X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Feditor%2Ff_main.pas;h=225daecbb528255b4ad1c689dcdb14b2e59d705d;hb=fd99178e87f17fe1416ef9c73278e8a877f8f925;hp=99820355f52210d9bc9db7cdf758a2ec5a50502b;hpb=fa946f8b1475bf5331fa0376394900b70de78a40;p=d2df-editor.git diff --git a/src/editor/f_main.pas b/src/editor/f_main.pas index 9982035..225daec 100644 --- a/src/editor/f_main.pas +++ b/src/editor/f_main.pas @@ -5,10 +5,10 @@ unit f_main; interface uses - LCLIntf, LCLType, LMessages, SysUtils, Variants, Classes, Graphics, - Controls, Forms, Dialogs, ImgList, StdCtrls, Buttons, - ComCtrls, ValEdit, Types, ToolWin, Menus, ExtCtrls, - CheckLst, Grids, OpenGLContext, utils, UTF8Process; + LCLIntf, LCLType, SysUtils, Variants, Classes, Graphics, + Controls, Forms, Dialogs, StdCtrls, Buttons, + ComCtrls, ValEdit, Types, Menus, ExtCtrls, + CheckLst, Grids, OpenGLContext, Utils, UTF8Process; type @@ -26,6 +26,7 @@ type miSaveMapAs: TMenuItem; miOpenWadMap: TMenuItem; miLine1: TMenuItem; + miReopenMap: TMenuItem; miSaveMiniMap: TMenuItem; miDeleteMap: TMenuItem; miPackMap: TMenuItem; @@ -204,15 +205,21 @@ type procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); + procedure FormDropFiles(Sender: TObject; const FileNames: array of String); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormResize(Sender: TObject); procedure lbTextureListClick(Sender: TObject); + procedure lbTextureListDrawItem(Control: TWinControl; Index: Integer; + ARect: TRect; State: TOwnerDrawState); + procedure miReopenMapClick(Sender: TObject); procedure RenderPanelMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure RenderPanelMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure RenderPanelMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure RenderPanelPaint(Sender: TObject); procedure RenderPanelResize(Sender: TObject); + procedure Splitter1Moved(Sender: TObject); procedure vleObjectPropertyEditButtonClick(Sender: TObject); + procedure vleObjectPropertyApply(Sender: TObject); procedure vleObjectPropertyGetPickList(Sender: TObject; const KeyName: String; Values: TStrings); procedure vleObjectPropertyKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); @@ -258,8 +265,9 @@ type procedure OnIdle(Sender: TObject; var Done: Boolean); public procedure RefreshRecentMenu(); - { procedure lbTextureListDrawItem(Control: TWinControl; Index: Integer; - Rect: TRect; State: TOwnerDrawState); } + procedure OpenMapFile(FileName: String); + function RenderMousePos(): TPoint; + procedure RecountSelectedObjects(); end; const @@ -284,13 +292,14 @@ var DotColor: TColor; DotEnable: Boolean; - DotStep: Byte; - DotStepOne, DotStepTwo: Byte; + DotStep: Word; + DotStepOne, DotStepTwo: Word; DotSize: Byte; DrawTexturePanel: Boolean; DrawPanelSize: Boolean; BackColor: TColor; PreviewColor: TColor; + UseCheckerboard: Boolean; Scale: Byte; RecentCount: Integer; RecentFiles: TStringList; @@ -304,12 +313,14 @@ var TestOptionsAllowExit: Boolean; TestOptionsWeaponStay: Boolean; TestOptionsMonstersDM: Boolean; - TestD2dExe: String; + TestD2dExe, TestD2DArgs: String; TestMapOnce: Boolean; LayerEnabled: Array [LAYER_BACK..LAYER_TRIGGERS] of Boolean = (True, True, True, True, True, True, True, True, True); - PreviewMode: Boolean = False; + ContourEnabled: Array [LAYER_BACK..LAYER_TRIGGERS] of Boolean = + (False, False, False, False, False, False, False, False, False); + PreviewMode: Byte = 0; gLanguage: String; FormCaption: String; @@ -323,14 +334,14 @@ procedure ChangeShownProperty(Name: String; NewValue: String); implementation uses - f_options, e_graphics, e_log, GL, GLExt, Math, + f_options, e_graphics, e_log, GL, Math, f_mapoptions, g_basic, f_about, f_mapoptimization, f_mapcheck, f_addresource_texture, g_textures, - f_activationtype, f_keys, MAPWRITER, MAPSTRUCT, - MAPREADER, f_selectmap, f_savemap, WADEDITOR, WADSTRUCT, MAPDEF, + f_activationtype, f_keys, wadreader, fileutil, + MAPREADER, f_selectmap, f_savemap, WADEDITOR, MAPDEF, g_map, f_saveminimap, f_addresource, CONFIG, f_packmap, f_addresource_sound, f_maptest, f_choosetype, - g_language, f_selectlang, ClipBrd; + g_language, f_selectlang, ClipBrd, g_resources; const UNDO_DELETE_PANEL = 1; @@ -380,7 +391,7 @@ const SELECTFLAG_SHOTPANEL = 7; SELECTFLAG_SELECTED = 8; - RECENT_FILES_MENU_START = 11; + RECENT_FILES_MENU_START = 12; CLIPBOARD_SIG = 'DF:ED'; @@ -431,8 +442,10 @@ var LastMovePoint: Types.TPoint; MouseLDown: Boolean; MouseRDown: Boolean; + MouseMDown: Boolean; MouseLDownPos: Types.TPoint; MouseRDownPos: Types.TPoint; + MouseMDownPos: Types.TPoint; SelectFlag: Byte = SELECTFLAG_NONE; MouseAction: Byte = MOUSEACTION_NONE; @@ -683,10 +696,10 @@ begin begin ScaleSz := 16 div Scale; // Размер видимой части карты: - rx := min(Normalize16(Width), Normalize16(gMapInfo.Width)) div 2; - ry := min(Normalize16(Height), Normalize16(gMapInfo.Height)) div 2; + rx := Min(Normalize16(Width), Normalize16(gMapInfo.Width)) div 2; + ry := Min(Normalize16(Height), Normalize16(gMapInfo.Height)) div 2; // Место клика на мини-карте: - MapOffset.X := X - (Width-max(gMapInfo.Width div ScaleSz, 1)-1); + MapOffset.X := X - (Width - Max(gMapInfo.Width div ScaleSz, 1) - 1); MapOffset.Y := Y - 1; // Это же место на "большой" карте: MapOffset.X := MapOffset.X * ScaleSz; @@ -695,17 +708,11 @@ begin MapOffset.X := MapOffset.X - rx; MapOffset.Y := MapOffset.Y - ry; // Выход за границы: - if MapOffset.X < 0 then - MapOffset.X := 0; - if MapOffset.Y < 0 then - MapOffset.Y := 0; - if MapOffset.X > MainForm.sbHorizontal.Max then - MapOffset.X := MainForm.sbHorizontal.Max; - if MapOffset.Y > MainForm.sbVertical.Max then - MapOffset.Y := MainForm.sbVertical.Max; + MapOffset.X := EnsureRange(MapOffset.X, MainForm.sbHorizontal.Min, MainForm.sbHorizontal.Max); + MapOffset.Y := EnsureRange(MapOffset.Y, MainForm.sbVertical.Min, MainForm.sbVertical.Max); // Кратно 16: - MapOffset.X := Normalize16(MapOffset.X); - MapOffset.Y := Normalize16(MapOffset.Y); + // MapOffset.X := Normalize16(MapOffset.X); + // MapOffset.Y := Normalize16(MapOffset.Y); end; MainForm.sbHorizontal.Position := MapOffset.X; @@ -730,6 +737,7 @@ var str: String; begin MainForm.vleObjectProperty.Strings.Clear(); + MainForm.RecountSelectedObjects(); // Отображаем свойства если выделен только один объект: if SelectedObjectCount() <> 1 then @@ -951,7 +959,8 @@ begin case TriggerType of TRIGGER_EXIT: begin - with ItemProps[InsertRow(_lc[I_PROP_TR_NEXT_MAP], Data.MapName, True)] do + str := win2utf(Data.MapName); + with ItemProps[InsertRow(_lc[I_PROP_TR_NEXT_MAP], str, True)] do begin EditStyle := esEllipsis; ReadOnly := True; @@ -1105,7 +1114,8 @@ begin TRIGGER_SOUND: begin - with ItemProps[InsertRow(_lc[I_PROP_TR_SOUND_NAME], Data.SoundName, True)] do + str := win2utf(Data.SoundName); + with ItemProps[InsertRow(_lc[I_PROP_TR_SOUND_NAME], str, True)] do begin EditStyle := esEllipsis; ReadOnly := True; @@ -1268,7 +1278,8 @@ begin TRIGGER_MUSIC: begin - with ItemProps[InsertRow(_lc[I_PROP_TR_MUSIC_NAME], Data.MusicName, True)] do + str := win2utf(Data.MusicName); + with ItemProps[InsertRow(_lc[I_PROP_TR_MUSIC_NAME], str, True)] do begin EditStyle := esEllipsis; ReadOnly := True; @@ -1370,7 +1381,8 @@ begin EditStyle := esPickList; ReadOnly := True; end; - with ItemProps[InsertRow(_lc[I_PROP_TR_MESSAGE_TEXT], Data.MessageText, True)] do + str := win2utf(Data.MessageText); + with ItemProps[InsertRow(_lc[I_PROP_TR_MESSAGE_TEXT], str, True)] do begin EditStyle := esSimple; MaxLength := 100; @@ -1394,6 +1406,20 @@ begin EditStyle := esSimple; MaxLength := 5; end; + case Data.DamageKind of + 3: str := _lc[I_PROP_TR_DAMAGE_KIND_3]; + 4: str := _lc[I_PROP_TR_DAMAGE_KIND_4]; + 5: str := _lc[I_PROP_TR_DAMAGE_KIND_5]; + 6: str := _lc[I_PROP_TR_DAMAGE_KIND_6]; + 7: str := _lc[I_PROP_TR_DAMAGE_KIND_7]; + 8: str := _lc[I_PROP_TR_DAMAGE_KIND_8]; + else str := _lc[I_PROP_TR_DAMAGE_KIND_0]; + end; + with ItemProps[InsertRow(_lc[I_PROP_TR_DAMAGE_KIND], str, True)] do + begin + EditStyle := esPickList; + ReadOnly := True; + end; end; TRIGGER_HEALTH: @@ -1467,7 +1493,7 @@ begin 3: str := _lc[I_PROP_TR_SHOT_AIM_3]; else str := _lc[I_PROP_TR_SHOT_AIM_0]; end; - with ItemProps[InsertRow(_lc[I_PROP_TR_SHOT_AIM], str, True)-1] do + with ItemProps[InsertRow(_lc[I_PROP_TR_SHOT_AIM], str, True)] do begin EditStyle := esPickList; ReadOnly := True; @@ -1761,6 +1787,7 @@ begin RemoveSelectFromObjects(); MainForm.miUndo.Enabled := UndoBuffer <> nil; + MainForm.RecountSelectedObjects(); end; procedure Undo_Add(ObjectType: Byte; ID: DWORD; Group: Boolean = False); @@ -1881,18 +1908,25 @@ var ok: Boolean; FileName: String; ResourceName: String; - UResourceName: String; FullResourceName: String; SectionName: String; Data: Pointer; Width, Height: Word; fn: String; begin + Data := nil; + FrameLen := 0; + Width := 0; + Height := 0; + if aSection = '..' then SectionName := '' else SectionName := aSection; + if aWAD = '' then + aWAD := _lc[I_WAD_SPECIAL_MAP]; + if aWAD = _lc[I_WAD_SPECIAL_MAP] then begin // Файл карты g_ProcessResourceStr(OpenedMap, @fn, nil, nil); @@ -1913,15 +1947,14 @@ begin end; ok := True; - UResourceName := win2utf(ResourceName); // Есть ли уже такая текстура: for a := 0 to MainForm.lbTextureList.Items.Count-1 do - if UResourceName = MainForm.lbTextureList.Items[a] then + if ResourceName = MainForm.lbTextureList.Items[a] then begin if not silent then ErrorMessageBox(Format(_lc[I_MSG_TEXTURE_ALREADY], - [UResourceName])); + [ResourceName])); ok := False; end; @@ -1930,7 +1963,7 @@ begin begin if not silent then ErrorMessageBox(Format(_lc[I_MSG_RES_NAME_64], - [UResourceName])); + [ResourceName])); ok := False; end; @@ -1939,7 +1972,7 @@ begin a := -1; if aWAD = _lc[I_WAD_SPECIAL_TEXS] then begin - a := MainForm.lbTextureList.Items.Add(UResourceName); + a := MainForm.lbTextureList.Items.Add(ResourceName); if not silent then SelectTexture(a); Result := True; @@ -1952,14 +1985,21 @@ begin begin // Аним. текстура GetFrame(FullResourceName, Data, FrameLen, Width, Height); - if g_CreateTextureMemorySize(Data, FrameLen, ResourceName, 0, 0, Width, Height, 1) then - a := MainForm.lbTextureList.Items.Add(UResourceName); + if not g_CreateTextureMemorySize(Data, FrameLen, ResourceName, 0, 0, Width, Height, 1) then + ok := False; + a := MainForm.lbTextureList.Items.Add(ResourceName); end else // Обычная текстура begin - if g_CreateTextureWAD(ResourceName, FullResourceName) then - a := MainForm.lbTextureList.Items.Add(UResourceName); + if not g_CreateTextureWAD(ResourceName, FullResourceName) then + ok := False; + a := MainForm.lbTextureList.Items.Add(ResourceName); end; + if (not ok) and (slInvalidTextures.IndexOf(ResourceName) = -1) then + begin + slInvalidTextures.Add(ResourceName); + ok := True; + end; if (a > -1) and (not silent) then SelectTexture(a); end; @@ -1987,6 +2027,7 @@ var MapName: String; idx: Integer; begin + SelectMapForm.Caption := _lc[I_CAP_OPEN]; SelectMapForm.GetMaps(FileName); if (FileName = OpenedWAD) and @@ -2213,7 +2254,7 @@ end; function SelectedTexture(): String; begin if MainForm.lbTextureList.ItemIndex <> -1 then - Result := utf2win(MainForm.lbTextureList.Items[MainForm.lbTextureList.ItemIndex]) + Result := MainForm.lbTextureList.Items[MainForm.lbTextureList.ItemIndex] else Result := ''; end; @@ -2221,7 +2262,7 @@ end; function IsSpecialTextureSel(): Boolean; begin Result := (MainForm.lbTextureList.ItemIndex <> -1) and - IsSpecialTexture(utf2win(MainForm.lbTextureList.Items[MainForm.lbTextureList.ItemIndex])); + IsSpecialTexture(MainForm.lbTextureList.Items[MainForm.lbTextureList.ItemIndex]); end; function CopyBufferToString(var CopyBuf: TCopyRecArray): String; @@ -2317,7 +2358,8 @@ begin Result := Res; end; -procedure StringToCopyBuffer(Str: String; var CopyBuf: TCopyRecArray); +procedure StringToCopyBuffer(Str: String; var CopyBuf: TCopyRecArray; + var pmin: TPoint); var i, j, t: Integer; @@ -2399,6 +2441,8 @@ begin PanelType := StrToIntDef(GetNext(), PANEL_WALL); X := StrToIntDef(GetNext(), 0); Y := StrToIntDef(GetNext(), 0); + pmin.X := Min(X, pmin.X); + pmin.Y := Min(Y, pmin.Y); Width := StrToIntDef(GetNext(), 16); Height := StrToIntDef(GetNext(), 16); TextureName := GetNext(); @@ -2413,6 +2457,8 @@ begin ItemType := StrToIntDef(GetNext(), ITEM_MEDKIT_SMALL); X := StrToIntDef(GetNext(), 0); Y := StrToIntDef(GetNext(), 0); + pmin.X := Min(X, pmin.X); + pmin.Y := Min(Y, pmin.Y); OnlyDM := (GetNext() = '1'); Fall := (GetNext() = '1'); end; @@ -2423,6 +2469,8 @@ begin MonsterType := StrToIntDef(GetNext(), MONSTER_DEMON); X := StrToIntDef(GetNext(), 0); Y := StrToIntDef(GetNext(), 0); + pmin.X := Min(X, pmin.X); + pmin.Y := Min(Y, pmin.Y); if GetNext() = '1' then Direction := D_LEFT @@ -2436,6 +2484,8 @@ begin AreaType := StrToIntDef(GetNext(), AREA_PLAYERPOINT1); X := StrToIntDef(GetNext(), 0); Y := StrToIntDef(GetNext(), 0); + pmin.X := Min(X, pmin.X); + pmin.Y := Min(Y, pmin.Y); if GetNext() = '1' then Direction := D_LEFT else @@ -2448,6 +2498,8 @@ begin TriggerType := StrToIntDef(GetNext(), TRIGGER_EXIT); X := StrToIntDef(GetNext(), 0); Y := StrToIntDef(GetNext(), 0); + pmin.X := Min(X, pmin.X); + pmin.Y := Min(Y, pmin.Y); Width := StrToIntDef(GetNext(), 16); Height := StrToIntDef(GetNext(), 16); ActivateType := StrToIntDef(GetNext(), 0); @@ -2457,6 +2509,34 @@ begin for j := 0 to 127 do Data.Default[j] := StrToIntDef(GetNext(), 0); + + case TriggerType of + TRIGGER_TELEPORT: + begin + pmin.X := Min(Data.TargetPoint.X, pmin.X); + pmin.Y := Min(Data.TargetPoint.Y, pmin.Y); + end; + TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF: + begin + pmin.X := Min(Data.tX, pmin.X); + pmin.Y := Min(Data.tY, pmin.Y); + end; + TRIGGER_SPAWNMONSTER: + begin + pmin.X := Min(Data.MonPos.X, pmin.X); + pmin.Y := Min(Data.MonPos.Y, pmin.Y); + end; + TRIGGER_SPAWNITEM: + begin + pmin.X := Min(Data.ItemPos.X, pmin.X); + pmin.Y := Min(Data.ItemPos.Y, pmin.Y); + end; + TRIGGER_SHOT: + begin + pmin.X := Min(Data.ShotPos.X, pmin.X); + pmin.Y := Min(Data.ShotPos.Y, pmin.Y); + end; + end; end; end; end; @@ -2499,30 +2579,27 @@ end; procedure TMainForm.aRecentFileExecute(Sender: TObject); var - n, pw: Integer; - s, fn: String; + n: Integer; + fn, s: String; begin s := LowerCase((Sender as TMenuItem).Caption); Delete(s, Pos('&', s), 1); s := Trim(Copy(s, 1, 2)); n := StrToIntDef(s, 0) - 1; - - if (n < 0) or (n >= RecentFiles.Count) then - Exit; - - s := RecentFiles[n]; - pw := Pos('.wad:\', LowerCase(s)); - - if pw > 0 then - begin // Map name included - fn := Copy(s, 1, pw + 3); - Delete(s, 1, pw + 5); - if (FileExists(fn)) then - OpenMap(fn, s); + if (n >= 0) and (n <= RecentFiles.Count) then + begin + fn := g_ExtractWadName(RecentFiles[n]); + if FileExists(fn) then + begin + s := g_ExtractFilePathName(RecentFiles[n]); + OpenMap(fn, s) + end + else if MessageBox(0, PChar(_lc[I_MSG_DEL_RECENT_PROMT]), PChar(_lc[I_MSG_DEL_RECENT]), MB_ICONQUESTION or MB_YESNO) = idYes then + begin + RecentFiles.Delete(n); + RefreshRecentMenu(); end - else // Only wad name - if (FileExists(s)) then - OpenMap(s, ''); + end end; procedure TMainForm.aEditorOptionsExecute(Sender: TObject); @@ -2535,21 +2612,15 @@ var cwdt, chgt: Byte; spc: ShortInt; ID: DWORD; - wad: TWADEditor_1; cfgdata: Pointer; cfglen: Integer; config: TConfig; begin - cfglen := 0; - - wad := TWADEditor_1.Create; - if wad.ReadFile(EditorDir+'data/Game.wad') then - wad.GetResource('FONTS', cfgres, cfgdata, cfglen); - wad.Free(); - - if cfglen <> 0 then + ID := 0; + g_ReadResource(EditorDir + 'data/game.wad', 'FONTS', cfgres, cfgdata, cfglen); + if cfgdata <> nil then begin - if not g_CreateTextureWAD('FONT_STD', EditorDir+'data/Game.wad:FONTS\'+texture) then + if not g_CreateTextureWAD('FONT_STD', EditorDir + 'data/game.wad:FONTS\' + texture) then e_WriteLog('ERROR ERROR ERROR', MSG_WARNING); config := TConfig.CreateMem(cfgdata, cfglen); @@ -2558,14 +2629,15 @@ begin spc := Min(Max(config.ReadInt('FontMap', 'Kerning', 0), -128), 127); if g_GetTexture('FONT_STD', ID) then - e_TextureFontBuild(ID, FontID, cwdt, chgt, spc-2); + e_TextureFontBuild(ID, FontID, cwdt, chgt, spc - 2); config.Free(); + FreeMem(cfgdata) end else - e_WriteLog('Could not load FONT_STD', MSG_WARNING); - - if cfglen <> 0 then FreeMem(cfgdata); + begin + e_WriteLog('Could not load FONT_STD', MSG_WARNING) + end end; procedure TMainForm.FormCreate(Sender: TObject); @@ -2579,6 +2651,10 @@ begin EditorDir := ExtractFilePath(Application.ExeName); e_InitLog(EditorDir+'Editor.log', WM_NEWFILE); + e_WriteLog('Doom 2D: Forever Editor version ' + EDITOR_VERSION, MSG_NOTIFY); + e_WriteLog('Build date: ' + EDITOR_BUILDDATE + ' ' + EDITOR_BUILDTIME, MSG_NOTIFY); + e_WriteLog('Build hash: ' + g_GetBuildHash(), MSG_NOTIFY); + e_WriteLog('Build by: ' + g_GetBuilderName(), MSG_NOTIFY); slInvalidTextures := TStringList.Create; @@ -2625,6 +2701,7 @@ begin DrawPanelSize := config.ReadBool('Editor', 'DrawPanelSize', True); BackColor := config.ReadInt('Editor', 'BackColor', $7F6040); PreviewColor := config.ReadInt('Editor', 'PreviewColor', $00FF00); + UseCheckerboard := config.ReadBool('Editor', 'UseCheckerboard', True); gColorEdge := config.ReadInt('Editor', 'EdgeColor', COLOR_EDGE); gAlphaEdge := config.ReadInt('Editor', 'EdgeAlpha', ALPHA_EDGE); if gAlphaEdge = 255 then @@ -2642,6 +2719,8 @@ begin gAlphaTriggerArea := config.ReadInt('Editor', 'TriggerAlpha', ALPHA_AREA); if gAlphaTriggerArea = 255 then gAlphaTriggerArea := ALPHA_AREA; + gAlphaMonsterRect := config.ReadInt('Editor', 'MonsterRectAlpha', 0); + gAlphaAreaRect := config.ReadInt('Editor', 'AreaRectAlpha', 0); if config.ReadInt('Editor', 'Scale', 0) = 1 then Scale := 2 else @@ -2656,6 +2735,9 @@ begin s := config.ReadStr('Editor', 'Language', ''); gLanguage := s; + Compress := config.ReadBool('Editor', 'Compress', True); + Backup := config.ReadBool('Editor', 'Backup', True); + RecentCount := config.ReadInt('Editor', 'RecentCount', 5); if RecentCount > 10 then RecentCount := 10; @@ -2697,6 +2779,11 @@ var ObjCount: Word; aX, aY, aX2, aY2, XX, ScaleSz: Integer; begin + ID := 0; + PID := 0; + Width := 0; + Height := 0; + e_BeginRender(); e_Clear(GL_COLOR_BUFFER_BIT, @@ -2741,30 +2828,46 @@ begin end; // Рисуем сетку: - if DotEnable and (not PreviewMode) then + if DotEnable and (PreviewMode = 0) then begin if DotSize = 2 then a := -1 else a := 0; - for x := 0 to (RenderPanel.Width div DotStep) do - for y := 0 to (RenderPanel.Height div DotStep) do - e_DrawPoint(DotSize, x*DotStep + a, y*DotStep + a, + x := MapOffset.X mod DotStep; + y := MapOffset.Y mod DotStep; + + while x < RenderPanel.Width do + begin + while y < RenderPanel.Height do + begin + e_DrawPoint(DotSize, x + a, y + a, GetRValue(DotColor), GetGValue(DotColor), GetBValue(DotColor)); + y += DotStep; + end; + x += DotStep; + y := MapOffset.Y mod DotStep; + end; end; // Превью текстуры: if (lbTextureList.ItemIndex <> -1) and (cbPreview.Checked) and - (not IsSpecialTextureSel()) and (not PreviewMode) then + (not IsSpecialTextureSel()) and (PreviewMode = 0) then begin if not g_GetTexture(SelectedTexture(), ID) then g_GetTexture('NOTEXTURE', ID); g_GetTextureSizeByID(ID, Width, Height); - if g_GetTexture('PREVIEW', PID) then - e_DrawFill(PID, RenderPanel.Width-Width, RenderPanel.Height-Height, Width div 16 + 1, Height div 16 + 1, 0, True, False); + if UseCheckerboard then + begin + if g_GetTexture('PREVIEW', PID) then + e_DrawFill(PID, RenderPanel.Width-Width, RenderPanel.Height-Height, Width div 16 + 1, Height div 16 + 1, 0, True, False); + end else + e_DrawFillQuad(RenderPanel.Width-Width-2, RenderPanel.Height-Height-2, + RenderPanel.Width-1, RenderPanel.Height-1, + GetRValue(PreviewColor), GetGValue(PreviewColor), GetBValue(PreviewColor), 0); e_Draw(ID, RenderPanel.Width-Width, RenderPanel.Height-Height, 0, True, False); end; @@ -2853,8 +2956,9 @@ begin g_GetTexture('NOTEXTURE', ID); g_GetTextureSizeByID(ID, Width, Height); with DrawRect^ do - e_DrawFill(ID, Min(Left, Right), Min(Top, Bottom), Abs(Right-Left) div Width, - Abs(Bottom-Top) div Height, 0, True, False); + if (Abs(Right-Left) >= Width) and (Abs(Bottom-Top) >= Height) then + e_DrawFill(ID, Min(Left, Right), Min(Top, Bottom), Abs(Right-Left) div Width, + Abs(Bottom-Top) div Height, 64, True, False); end; // Прямоугольник выделения: @@ -2863,7 +2967,8 @@ begin e_DrawQuad(Left, Top, Right-1, Bottom-1, 255, 255, 255); // Чертим мышью панель/триггер или меняем мышью их размер: - if (MouseAction in [MOUSEACTION_DRAWPANEL, MOUSEACTION_DRAWTRIGGER, MOUSEACTION_RESIZE]) and + if (((MouseAction in [MOUSEACTION_DRAWPANEL, MOUSEACTION_DRAWTRIGGER]) and + not(ssCtrl in GetKeyShiftState())) or (MouseAction = MOUSEACTION_RESIZE)) and (DrawPanelSize) then begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+88, MousePos.Y+33, 192, 192, 192, 127); @@ -2873,7 +2978,7 @@ begin begin // Чертим новый PrintBlack(MousePos.X+2, MousePos.Y+2, Format(_glc[I_HINT_WIDTH], [Abs(MousePos.X-MouseLDownPos.X)]), gEditorFont); - PrintBlack(MousePos.X+2, MousePos.Y+14, Format(_glc[I_HINT_HEIGHT], + PrintBlack(MousePos.X+2, MousePos.Y+16, Format(_glc[I_HINT_HEIGHT], [Abs(MousePos.Y-MouseLDownPos.Y)]), gEditorFont); end else // Растягиваем существующий @@ -2892,7 +2997,7 @@ begin PrintBlack(MousePos.X+2, MousePos.Y+2, Format(_glc[I_HINT_WIDTH], [Width]), gEditorFont); - PrintBlack(MousePos.X+2, MousePos.Y+14, Format(_glc[I_HINT_HEIGHT], [Height]), + PrintBlack(MousePos.X+2, MousePos.Y+16, Format(_glc[I_HINT_HEIGHT], [Height]), gEditorFont); end; end; @@ -2996,18 +3101,13 @@ procedure TMainForm.FormResize(Sender: TObject); begin e_SetViewPort(0, 0, RenderPanel.Width, RenderPanel.Height); - if gMapInfo.Width >= RenderPanel.Width then - sbHorizontal.Max := Normalize16(gMapInfo.Width-RenderPanel.Width+16) - else - sbHorizontal.Max := 0; + sbHorizontal.Min := Min(gMapInfo.Width - RenderPanel.Width, -RenderPanel.Width div 2); + sbHorizontal.Max := Max(0, gMapInfo.Width - RenderPanel.Width div 2); + sbVertical.Min := Min(gMapInfo.Height - RenderPanel.Height, -RenderPanel.Height div 2); + sbVertical.Max := Max(0, gMapInfo.Height - RenderPanel.Height div 2); - if gMapInfo.Height >= RenderPanel.Height then - sbVertical.Max := Normalize16(gMapInfo.Height-RenderPanel.Height+16) - else - sbVertical.Max := 0; - - MapOffset.X := -Normalize16(sbHorizontal.Position); - MapOffset.Y := -Normalize16(sbVertical.Position); + MapOffset.X := -sbHorizontal.Position; + MapOffset.Y := -sbVertical.Position; end; procedure SelectNextObject(X, Y: Integer; ObjectType: Byte; ID: DWORD); @@ -3498,6 +3598,16 @@ begin end; end; // if Button = mbRight + if Button = mbMiddle then // Middle Mouse Button + begin + SetCapture(RenderPanel.Handle); + RenderPanel.Cursor := crSize; + end; + + MouseMDown := Button = mbMiddle; + if MouseMDown then + MouseMDownPos := Mouse.CursorPos; + MouseRDown := Button = mbRight; if MouseRDown then MouseRDownPos := MousePos; @@ -3512,26 +3622,46 @@ procedure TMainForm.RenderPanelMouseUp(Sender: TObject; var panel: TPanel; trigger: TTrigger; - i: Integer; - IDArray: DWArray; rRect: TRectWH; rSelectRect: Boolean; + wWidth, wHeight: Word; + TextureID: DWORD; + + procedure SelectObjects(ObjectType: Byte); + var + i: Integer; + IDArray: DWArray; + begin + IDArray := ObjectInRect(rRect.X, rRect.Y, + rRect.Width, rRect.Height, + ObjectType, rSelectRect); + + if IDArray <> nil then + for i := 0 to High(IDArray) do + SelectObject(ObjectType, IDArray[i], (ssCtrl in Shift) or rSelectRect); + end; begin if Button = mbLeft then MouseLDown := False; if Button = mbRight then MouseRDown := False; + if Button = mbMiddle then + MouseMDown := False; DrawRect := nil; ResizeType := RESIZETYPE_NONE; + TextureID := 0; if Button = mbLeft then // Left Mouse Button begin if MouseAction <> MOUSEACTION_NONE then begin // Было действие мышью - // Мышь сдвинулась во время удержания клавиши: - if (MousePos.X <> MouseLDownPos.X) and - (MousePos.Y <> MouseLDownPos.Y) then + // Мышь сдвинулась во время удержания клавиши, + // либо активирован режим быстрого рисования: + if ((MousePos.X <> MouseLDownPos.X) and + (MousePos.Y <> MouseLDownPos.Y)) or + ((MouseAction in [MOUSEACTION_DRAWPANEL, MOUSEACTION_DRAWTRIGGER]) and + (ssCtrl in Shift)) then case MouseAction of // Рисовали панель: MOUSEACTION_DRAWPANEL: @@ -3561,8 +3691,25 @@ begin Panel.X := Min(MousePos.X-MapOffset.X, MouseLDownPos.X-MapOffset.X); Panel.Y := Min(MousePos.Y-MapOffset.Y, MouseLDownPos.Y-MapOffset.Y); - Panel.Width := Abs(MousePos.X-MouseLDownPos.X); - Panel.Height := Abs(MousePos.Y-MouseLDownPos.Y); + if ssCtrl in Shift then + begin + wWidth := DotStep; + wHeight := DotStep; + if (lbTextureList.ItemIndex <> -1) and + (not IsSpecialTextureSel()) then + begin + if not g_GetTexture(SelectedTexture(), TextureID) then + g_GetTexture('NOTEXTURE', TextureID); + g_GetTextureSizeByID(TextureID, wWidth, wHeight); + end; + Panel.Width := wWidth; + Panel.Height := wHeight; + end + else + begin + Panel.Width := Abs(MousePos.X-MouseLDownPos.X); + Panel.Height := Abs(MousePos.Y-MouseLDownPos.Y); + end; // Лифты, блокМон или отсутствие текстуры - пустая текстура: if (lbPanelType.ItemIndex in [9, 10, 11, 12, 13]) or @@ -3604,8 +3751,18 @@ begin begin trigger.X := Min(MousePos.X-MapOffset.X, MouseLDownPos.X-MapOffset.X); trigger.Y := Min(MousePos.Y-MapOffset.Y, MouseLDownPos.Y-MapOffset.Y); - trigger.Width := Abs(MousePos.X-MouseLDownPos.X); - trigger.Height := Abs(MousePos.Y-MouseLDownPos.Y); + if ssCtrl in Shift then + begin + wWidth := DotStep; + wHeight := DotStep; + trigger.Width := wWidth; + trigger.Height := wHeight; + end + else + begin + trigger.Width := Abs(MousePos.X-MouseLDownPos.X); + trigger.Height := Abs(MousePos.Y-MouseLDownPos.Y); + end; trigger.Enabled := True; trigger.TriggerType := lbTriggersList.ItemIndex+1; @@ -3799,7 +3956,7 @@ begin MouseAction := MOUSEACTION_NONE; end; end // if Button = mbLeft... - else // Right Mouse Button: + else if Button = mbRight then // Right Mouse Button: begin if MouseAction = MOUSEACTION_NOACTION then begin @@ -3810,6 +3967,7 @@ begin // Объект передвинут или изменен в размере: if MouseAction in [MOUSEACTION_MOVEOBJ, MOUSEACTION_RESIZE] then begin + RenderPanel.Cursor := crDefault; MouseAction := MOUSEACTION_NONE; FillProperty(); Exit; @@ -3850,16 +4008,24 @@ begin RemoveSelectFromObjects(); // Выделяем всё в выбранном прямоугольнике: - IDArray := ObjectInRect(rRect.X, rRect.Y, - rRect.Width, rRect.Height, - pcObjects.ActivePageIndex+1, rSelectRect); - - if IDArray <> nil then - for i := 0 to High(IDArray) do - SelectObject(pcObjects.ActivePageIndex+1, IDArray[i], - (ssCtrl in Shift) or rSelectRect); + if (ssCtrl in Shift) and (ssAlt in Shift) then + begin + SelectObjects(OBJECT_PANEL); + SelectObjects(OBJECT_ITEM); + SelectObjects(OBJECT_MONSTER); + SelectObjects(OBJECT_AREA); + SelectObjects(OBJECT_TRIGGER); + end + else + SelectObjects(pcObjects.ActivePageIndex+1); FillProperty(); + end + + else // Middle Mouse Button + begin + RenderPanel.Cursor := crDefault; + ReleaseCapture(); end; end; @@ -3868,14 +4034,30 @@ begin Draw(); end; +function TMainForm.RenderMousePos(): Types.TPoint; +begin + Result := RenderPanel.ScreenToClient(Mouse.CursorPos); +end; + +procedure TMainForm.RecountSelectedObjects(); +begin + if SelectedObjectCount() = 0 then + StatusBar.Panels[0].Text := '' + else + StatusBar.Panels[0].Text := Format(_lc[I_CAP_STAT_SELECTED], [SelectedObjectCount()]); +end; + procedure TMainForm.RenderPanelMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var sX, sY: Integer; dWidth, dHeight: Integer; _id: Integer; + TextureID: DWORD; + wWidth, wHeight: Word; begin _id := GetFirstSelected(); + TextureID := 0; // Рисуем панель с текстурой, сетка - размеры текстуры: if (MouseAction = MOUSEACTION_DRAWPANEL) and @@ -3924,16 +4106,12 @@ begin end else begin // Кнопки мыши не зажаты - MousePos.X := (Round(X/sX)*sX); - MousePos.Y := (Round(Y/sY)*sY); + MousePos.X := Round((-MapOffset.X + X) / sX) * sX + MapOffset.X; + MousePos.Y := Round((-MapOffset.Y + Y) / sY) * sY + MapOffset.Y; end; -// Изменение размера закончилось - ставим обычный курсор: - if ResizeType = RESIZETYPE_NONE then - RenderPanel.Cursor := crDefault; - // Зажата только правая кнопка мыши: - if (not MouseLDown) and (MouseRDown) then + if (not MouseLDown) and (MouseRDown) and (not MouseMDown) then begin // Рисуем прямоугольник выделения: if MouseAction = MOUSEACTION_NONE then @@ -3973,17 +4151,16 @@ begin RESIZEDIR_LEFT: dWidth := -dWidth; end; - ResizeObject(SelectedObjects[GetFirstSelected].ObjectType, - SelectedObjects[GetFirstSelected].ID, - dWidth, dHeight, ResizeDirection); - - LastMovePoint := MousePos; + if ResizeObject(SelectedObjects[GetFirstSelected].ObjectType, + SelectedObjects[GetFirstSelected].ID, + dWidth, dHeight, ResizeDirection) then + LastMovePoint := MousePos; end; end; end; // Зажата только левая кнопка мыши: - if (not MouseRDown) and (MouseLDown) then + if (not MouseRDown) and (MouseLDown) and (not MouseMDown) then begin // Рисуем прямоугольник планирования панели: if MouseAction in [MOUSEACTION_DRAWPANEL, @@ -3992,10 +4169,29 @@ begin begin if DrawRect = nil then New(DrawRect); - DrawRect.Top := MouseLDownPos.y; - DrawRect.Left := MouseLDownPos.x; - DrawRect.Bottom := MousePos.y; - DrawRect.Right := MousePos.x; + if ssCtrl in Shift then + begin + wWidth := DotStep; + wHeight := DotStep; + if (lbTextureList.ItemIndex <> -1) and (not IsSpecialTextureSel()) and + (MouseAction = MOUSEACTION_DRAWPANEL) then + begin + if not g_GetTexture(SelectedTexture(), TextureID) then + g_GetTexture('NOTEXTURE', TextureID); + g_GetTextureSizeByID(TextureID, wWidth, wHeight); + end; + DrawRect.Top := MouseLDownPos.y; + DrawRect.Left := MouseLDownPos.x; + DrawRect.Bottom := DrawRect.Top + wHeight; + DrawRect.Right := DrawRect.Left + wWidth; + end + else + begin + DrawRect.Top := MouseLDownPos.y; + DrawRect.Left := MouseLDownPos.x; + DrawRect.Bottom := MousePos.y; + DrawRect.Right := MousePos.x; + end; end else // Двигаем карту: if MouseAction = MOUSEACTION_MOVEMAP then @@ -4004,6 +4200,18 @@ begin end; end; +// Only Middle Mouse Button is pressed + if (not MouseLDown) and (not MouseRDown) and (MouseMDown) then + begin + MapOffset.X := -EnsureRange(-MapOffset.X + MouseMDownPos.X - Mouse.CursorPos.X, + sbHorizontal.Min, sbHorizontal.Max); + sbHorizontal.Position := -MapOffset.X; + MapOffset.Y := -EnsureRange(-MapOffset.Y + MouseMDownPos.Y - Mouse.CursorPos.Y, + sbVertical.Min, sbVertical.Max); + sbVertical.Position := -MapOffset.Y; + MouseMDownPos := Mouse.CursorPos; + end; + // Клавиши мыши не зажаты: if (not MouseRDown) and (not MouseLDown) then DrawRect := nil; @@ -4060,6 +4268,8 @@ begin config.WriteInt('Editor', 'EdgeAlpha', gAlphaEdge); config.WriteInt('Editor', 'LineAlpha', gAlphaTriggerLine); config.WriteInt('Editor', 'TriggerAlpha', gAlphaTriggerArea); + config.WriteInt('Editor', 'MonsterRectAlpha', gAlphaMonsterRect); + config.WriteInt('Editor', 'AreaRectAlpha', gAlphaAreaRect); for i := 0 to RecentCount-1 do if i < RecentFiles.Count then @@ -4074,12 +4284,26 @@ begin slInvalidTextures.Free; end; +procedure TMainForm.FormDropFiles(Sender: TObject; + const FileNames: array of String); +begin + if Length(FileNames) <> 1 then + Exit; + + OpenMapFile(FileNames[0]); +end; + procedure TMainForm.RenderPanelResize(Sender: TObject); begin if MainForm.Visible then MainForm.Resize(); end; +procedure TMainForm.Splitter1Moved(Sender: TObject); +begin + FormResize(Sender); +end; + procedure TMainForm.aMapOptionsExecute(Sender: TObject); var ResName: String; @@ -4098,34 +4322,52 @@ begin AboutForm.ShowModal(); end; -procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word; - Shift: TShiftState); +procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var dx, dy, i: Integer; FileName: String; + ok: Boolean; begin if (not EditingProperties) then begin - if Key = Ord('1') then - SwitchLayer(LAYER_BACK); - if Key = Ord('2') then - SwitchLayer(LAYER_WALLS); - if Key = Ord('3') then - SwitchLayer(LAYER_FOREGROUND); - if Key = Ord('4') then - SwitchLayer(LAYER_STEPS); - if Key = Ord('5') then - SwitchLayer(LAYER_WATER); - if Key = Ord('6') then - SwitchLayer(LAYER_ITEMS); - if Key = Ord('7') then - SwitchLayer(LAYER_MONSTERS); - if Key = Ord('8') then - SwitchLayer(LAYER_AREAS); - if Key = Ord('9') then - SwitchLayer(LAYER_TRIGGERS); - if Key = Ord('0') then - tbShowClick(tbShow); + if ssCtrl in Shift then + begin + case Chr(Key) of + '1': ContourEnabled[LAYER_BACK] := not ContourEnabled[LAYER_BACK]; + '2': ContourEnabled[LAYER_WALLS] := not ContourEnabled[LAYER_WALLS]; + '3': ContourEnabled[LAYER_FOREGROUND] := not ContourEnabled[LAYER_FOREGROUND]; + '4': ContourEnabled[LAYER_STEPS] := not ContourEnabled[LAYER_STEPS]; + '5': ContourEnabled[LAYER_WATER] := not ContourEnabled[LAYER_WATER]; + '6': ContourEnabled[LAYER_ITEMS] := not ContourEnabled[LAYER_ITEMS]; + '7': ContourEnabled[LAYER_MONSTERS] := not ContourEnabled[LAYER_MONSTERS]; + '8': ContourEnabled[LAYER_AREAS] := not ContourEnabled[LAYER_AREAS]; + '9': ContourEnabled[LAYER_TRIGGERS] := not ContourEnabled[LAYER_TRIGGERS]; + '0': + begin + ok := False; + for i := Low(ContourEnabled) to High(ContourEnabled) do + if ContourEnabled[i] then + ok := True; + for i := Low(ContourEnabled) to High(ContourEnabled) do + ContourEnabled[i] := not ok + end + end + end + else + begin + case Chr(key) of + '1': SwitchLayer(LAYER_BACK); + '2': SwitchLayer(LAYER_WALLS); + '3': SwitchLayer(LAYER_FOREGROUND); + '4': SwitchLayer(LAYER_STEPS); + '5': SwitchLayer(LAYER_WATER); + '6': SwitchLayer(LAYER_ITEMS); + '7': SwitchLayer(LAYER_MONSTERS); + '8': SwitchLayer(LAYER_AREAS); + '9': SwitchLayer(LAYER_TRIGGERS); + '0': tbShowClick(tbShow); + end + end; if Key = Ord('V') then begin // Поворот монстров и областей: @@ -4166,19 +4408,54 @@ begin if not (ssCtrl in Shift) then begin + // Быстрое превью карты: + if Key = Ord('E') then + begin + if PreviewMode = 0 then + PreviewMode := 2; + end; + // Вертикальный скролл карты: with sbVertical do begin if Key = Ord('W') then begin - Position := IfThen(Position > DotStep, Position-DotStep, 0); - MapOffset.Y := -Round(Position/16) * 16; + dy := Position; + if ssShift in Shift then Position := EnsureRange(Position - DotStep * 4, Min, Max) + else Position := EnsureRange(Position - DotStep, Min, Max); + MapOffset.Y := -Position; + dy -= Position; + + if (MouseLDown or MouseRDown) then + begin + if DrawRect <> nil then + begin + Inc(MouseLDownPos.y, dy); + Inc(MouseRDownPos.y, dy); + end; + Inc(LastMovePoint.Y, dy); + RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y); + end; end; if Key = Ord('S') then begin - Position := IfThen(Position+DotStep < Max, Position+DotStep, Max); - MapOffset.Y := -Round(Position/16) * 16; + dy := Position; + if ssShift in Shift then Position := EnsureRange(Position + DotStep * 4, Min, Max) + else Position := EnsureRange(Position + DotStep, Min, Max); + MapOffset.Y := -Position; + dy -= Position; + + if (MouseLDown or MouseRDown) then + begin + if DrawRect <> nil then + begin + Inc(MouseLDownPos.y, dy); + Inc(MouseRDownPos.y, dy); + end; + Inc(LastMovePoint.Y, dy); + RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y); + end; end; end; @@ -4187,16 +4464,54 @@ begin begin if Key = Ord('A') then begin - Position := IfThen(Position > DotStep, Position-DotStep, 0); - MapOffset.X := -Round(Position/16) * 16; + dx := Position; + if ssShift in Shift then Position := EnsureRange(Position - DotStep * 4, Min, Max) + else Position := EnsureRange(Position - DotStep, Min, Max); + MapOffset.X := -Position; + dx -= Position; + + if (MouseLDown or MouseRDown) then + begin + if DrawRect <> nil then + begin + Inc(MouseLDownPos.x, dx); + Inc(MouseRDownPos.x, dx); + end; + Inc(LastMovePoint.X, dx); + RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y); + end; end; if Key = Ord('D') then begin - Position := IfThen(Position+DotStep < Max, Position+DotStep, Max); - MapOffset.X := -Round(Position/16) * 16; + dx := Position; + if ssShift in Shift then Position := EnsureRange(Position + DotStep * 4, Min, Max) + else Position := EnsureRange(Position + DotStep, Min, Max); + MapOffset.X := -Position; + dx -= Position; + + if (MouseLDown or MouseRDown) then + begin + if DrawRect <> nil then + begin + Inc(MouseLDownPos.x, dx); + Inc(MouseRDownPos.x, dx); + end; + Inc(LastMovePoint.X, dx); + RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y); + end; end; end; + end + else // ssCtrl in Shift + begin + if ssShift in Shift then + begin + // Вставка по абсолютному смещению: + if Key = Ord('V') then + aPasteObjectExecute(Sender); + end; + RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y); end; end; @@ -4255,6 +4570,7 @@ begin DrawPressRect := False; Exit; end; + i := -1; // Выбор области воздействия, в зависимости от типа триггера vleObjectProperty.FindRow(_lc[I_PROP_TR_EX_AREA], i); @@ -4295,6 +4611,7 @@ begin if i > 0 then begin g_ProcessResourceStr(OpenedMap, @FileName, nil, nil); + SelectMapForm.Caption := _lc[I_CAP_SELECT]; SelectMapForm.GetMaps(FileName); if SelectMapForm.ShowModal() = mrOK then @@ -4311,11 +4628,11 @@ begin begin AddSoundForm.OKFunction := nil; AddSoundForm.lbResourcesList.MultiSelect := False; - AddSoundForm.SetResource := utf2win(vleObjectProperty.Cells[1, i]); + AddSoundForm.SetResource := vleObjectProperty.Cells[1, i]; if (AddSoundForm.ShowModal() = mrOk) then begin - vleObjectProperty.Cells[1, i] := win2utf(AddSoundForm.ResourceName); + vleObjectProperty.Cells[1, i] := AddSoundForm.ResourceName; bApplyProperty.Click(); end; Exit; @@ -4355,6 +4672,9 @@ var TextureID: DWORD; TextureWidth, TextureHeight: Word; begin + TextureID := 0; + TextureWidth := 0; + TextureHeight := 0; if (lbTextureList.ItemIndex <> -1) and (not IsSpecialTextureSel()) then begin @@ -4377,6 +4697,42 @@ begin end; end; +procedure TMainForm.lbTextureListDrawItem(Control: TWinControl; Index: Integer; + ARect: TRect; State: TOwnerDrawState); +begin + with Control as TListBox do + begin + if LCLType.odSelected in State then + begin + Canvas.Brush.Color := clHighlight; + Canvas.Font.Color := clHighlightText; + end else + if (Items <> nil) and (Index >= 0) then + if slInvalidTextures.IndexOf(Items[Index]) > -1 then + begin + Canvas.Brush.Color := clRed; + Canvas.Font.Color := clWhite; + end; + Canvas.FillRect(ARect); + Canvas.TextRect(ARect, ARect.Left, ARect.Top, Items[Index]); + end; +end; + +procedure TMainForm.miReopenMapClick(Sender: TObject); +var + FileName, Resource: String; +begin + if OpenedMap = '' then + Exit; + + if MessageBox(0, PChar(_lc[I_MSG_REOPEN_MAP_PROMT]), + PChar(_lc[I_MENU_FILE_REOPEN]), MB_ICONQUESTION or MB_YESNO) <> idYes then + Exit; + + g_ProcessResourceStr(OpenedMap, @FileName, nil, @Resource); + OpenMap(FileName, Resource); +end; + procedure TMainForm.vleObjectPropertyGetPickList(Sender: TObject; const KeyName: String; Values: TStrings); begin @@ -4453,6 +4809,16 @@ begin Values.Add(_lc[I_PROP_TR_SHOT_AIM_2]); Values.Add(_lc[I_PROP_TR_SHOT_AIM_3]); end + else if KeyName = _lc[I_PROP_TR_DAMAGE_KIND] then + begin + Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_0]); + Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_3]); + Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_4]); + Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_5]); + Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_6]); + Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_7]); + Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_8]); + end else if (KeyName = _lc[I_PROP_PANEL_BLEND]) or (KeyName = _lc[I_PROP_DM_ONLY]) or (KeyName = _lc[I_PROP_ITEM_FALLS]) or @@ -4487,6 +4853,10 @@ var NoTextureID: DWORD; NW, NH: Word; begin + NoTextureID := 0; + NW := 0; + NH := 0; + if SelectedObjectCount() <> 1 then Exit; if not SelectedObjects[GetFirstSelected()].Live then @@ -4684,10 +5054,10 @@ begin case TriggerType of TRIGGER_EXIT: begin - s := vleObjectProperty.Values[_lc[I_PROP_TR_NEXT_MAP]]; + s := utf2win(vleObjectProperty.Values[_lc[I_PROP_TR_NEXT_MAP]]); FillByte(Data.MapName[0], 16, 0); if s <> '' then - Move(Data.MapName[0], s[1], Min(Length(s), 16)); + Move(s[1], Data.MapName[0], Min(Length(s), 16)); end; TRIGGER_TEXTURE: @@ -4723,10 +5093,10 @@ begin TRIGGER_SOUND: begin - s := vleObjectProperty.Values[_lc[I_PROP_TR_SOUND_NAME]]; + s := utf2win(vleObjectProperty.Values[_lc[I_PROP_TR_SOUND_NAME]]); FillByte(Data.SoundName[0], 64, 0); if s <> '' then - Move(Data.SoundName[0], s[1], Min(Length(s), 64)); + Move(s[1], Data.SoundName[0], Min(Length(s), 64)); Data.Volume := Min(StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_SOUND_VOLUME]], 0), 255); Data.Pan := Min(StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_SOUND_PAN]], 0), 255); @@ -4777,10 +5147,10 @@ begin TRIGGER_MUSIC: begin - s := vleObjectProperty.Values[_lc[I_PROP_TR_MUSIC_NAME]]; + s := utf2win(vleObjectProperty.Values[_lc[I_PROP_TR_MUSIC_NAME]]); FillByte(Data.MusicName[0], 64, 0); if s <> '' then - Move(Data.MusicName[0], s[1], Min(Length(s), 64)); + Move(s[1], Data.MusicName[0], Min(Length(s), 64)); if vleObjectProperty.Values[_lc[I_PROP_TR_MUSIC_ACT]] = _lc[I_PROP_TR_MUSIC_ON] then Data.MusicAction := 1 @@ -4837,10 +5207,10 @@ begin else if vleObjectProperty.Values[_lc[I_PROP_TR_MESSAGE_TO]] = _lc[I_PROP_TR_MESSAGE_TO_5] then Data.MessageSendTo := 5; - s := vleObjectProperty.Values[_lc[I_PROP_TR_MESSAGE_TEXT]]; + s := utf2win(vleObjectProperty.Values[_lc[I_PROP_TR_MESSAGE_TEXT]]); FillByte(Data.MessageText[0], 100, 0); if s <> '' then - Move(Data.MessageText[0], s[1], Min(Length(s), 100)); + Move(s[1], Data.MessageText[0], Min(Length(s), 100)); Data.MessageTime := Min(Max( StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_MESSAGE_TIME]], 0), 0), 65535); @@ -4852,6 +5222,21 @@ begin StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_DAMAGE_VALUE]], 0), 0), 65535); Data.DamageInterval := Min(Max( StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_INTERVAL]], 0), 0), 65535); + s := vleObjectProperty.Values[_lc[I_PROP_TR_DAMAGE_KIND]]; + if s = _lc[I_PROP_TR_DAMAGE_KIND_3] then + Data.DamageKind := 3 + else if s = _lc[I_PROP_TR_DAMAGE_KIND_4] then + Data.DamageKind := 4 + else if s = _lc[I_PROP_TR_DAMAGE_KIND_5] then + Data.DamageKind := 5 + else if s = _lc[I_PROP_TR_DAMAGE_KIND_6] then + Data.DamageKind := 6 + else if s = _lc[I_PROP_TR_DAMAGE_KIND_7] then + Data.DamageKind := 7 + else if s = _lc[I_PROP_TR_DAMAGE_KIND_8] then + Data.DamageKind := 8 + else + Data.DamageKind := 0; end; TRIGGER_HEALTH: @@ -5247,12 +5632,18 @@ procedure TMainForm.aPasteObjectExecute(Sender: TObject); var a, h: Integer; CopyBuffer: TCopyRecArray; - res: Boolean; + res, rel: Boolean; swad, ssec, sres: String; + NoTextureID: DWORD; + pmin: TPoint; begin CopyBuffer := nil; + NoTextureID := 0; + pmin.X := High(pmin.X); + pmin.Y := High(pmin.Y); - StringToCopyBuffer(ClipBoard.AsText, CopyBuffer); + StringToCopyBuffer(ClipBoard.AsText, CopyBuffer, pmin); + rel := not(ssShift in GetKeyShiftState()); if CopyBuffer = nil then Exit; @@ -5267,8 +5658,11 @@ begin OBJECT_PANEL: if Panel <> nil then begin - Panel^.X := Panel^.X + 16; - Panel^.Y := Panel^.Y + 16; + if rel then + begin + Panel^.X := Panel^.X - pmin.X - MapOffset.X + 32; + Panel^.Y := Panel^.Y - pmin.Y - MapOffset.Y + 32; + end; Panel^.TextureID := TEXTURE_SPECIAL_NONE; Panel^.TextureWidth := 1; @@ -5300,14 +5694,18 @@ begin g_GetTextureSizeByName(Panel^.TextureName, Panel^.TextureWidth, Panel^.TextureHeight) else - Panel^.TextureName := ''; + if g_GetTexture('NOTEXTURE', NoTextureID) then + begin + Panel^.TextureID := TEXTURE_SPECIAL_NOTEXTURE; + g_GetTextureSizeByID(NoTextureID, Panel^.TextureWidth, Panel^.TextureHeight); + end; end else // Спец.текстура: begin Panel^.TextureID := SpecialTextureID(Panel^.TextureName); with MainForm.lbTextureList.Items do - if IndexOf(win2utf(Panel^.TextureName)) = -1 then - Add(win2utf(Panel^.TextureName)); + if IndexOf(Panel^.TextureName) = -1 then + Add(Panel^.TextureName); end; end; @@ -5319,8 +5717,11 @@ begin OBJECT_ITEM: begin - Item.X := Item.X + 16; - Item.Y := Item.Y + 16; + if rel then + begin + Item.X := Item.X - pmin.X - MapOffset.X + 32; + Item.Y := Item.Y - pmin.Y - MapOffset.Y + 32; + end; ID := AddItem(Item); Undo_Add(OBJECT_ITEM, ID, a > 0); @@ -5329,8 +5730,11 @@ begin OBJECT_MONSTER: begin - Monster.X := Monster.X + 16; - Monster.Y := Monster.Y + 16; + if rel then + begin + Monster.X := Monster.X - pmin.X - MapOffset.X + 32; + Monster.Y := Monster.Y - pmin.Y - MapOffset.Y + 32; + end; ID := AddMonster(Monster); Undo_Add(OBJECT_MONSTER, ID, a > 0); @@ -5339,8 +5743,11 @@ begin OBJECT_AREA: begin - Area.X := Area.X + 16; - Area.Y := Area.Y + 16; + if rel then + begin + Area.X := Area.X - pmin.X - MapOffset.X + 32; + Area.Y := Area.Y - pmin.Y - MapOffset.Y + 32; + end; ID := AddArea(Area); Undo_Add(OBJECT_AREA, ID, a > 0); @@ -5349,8 +5756,48 @@ begin OBJECT_TRIGGER: begin - Trigger.X := Trigger.X + 16; - Trigger.Y := Trigger.Y + 16; + if rel then + with Trigger do + begin + X := X - pmin.X - MapOffset.X + 32; + Y := Y - pmin.Y - MapOffset.Y + 32; + + case TriggerType of + TRIGGER_TELEPORT: + begin + Data.TargetPoint.X := + Data.TargetPoint.X - pmin.X - MapOffset.X + 32; + Data.TargetPoint.Y := + Data.TargetPoint.Y - pmin.Y - MapOffset.Y + 32; + end; + TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF: + begin + Data.tX := Data.tX - pmin.X - MapOffset.X + 32; + Data.tY := Data.tY - pmin.Y - MapOffset.Y + 32; + end; + TRIGGER_SPAWNMONSTER: + begin + Data.MonPos.X := + Data.MonPos.X - pmin.X - MapOffset.X + 32; + Data.MonPos.Y := + Data.MonPos.Y - pmin.Y - MapOffset.Y + 32; + end; + TRIGGER_SPAWNITEM: + begin + Data.ItemPos.X := + Data.ItemPos.X - pmin.X - MapOffset.X + 32; + Data.ItemPos.Y := + Data.ItemPos.Y - pmin.Y - MapOffset.Y + 32; + end; + TRIGGER_SHOT: + begin + Data.ShotPos.X := + Data.ShotPos.X - pmin.X - MapOffset.X + 32; + Data.ShotPos.Y := + Data.ShotPos.Y - pmin.Y - MapOffset.Y + 32; + end; + end; + end; ID := AddTrigger(Trigger); Undo_Add(OBJECT_TRIGGER, ID, a > 0); @@ -5425,7 +5872,7 @@ begin begin b := lbTypeSelect.ItemIndex; Values[Key] := PANELNAMES[b]; - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; end end @@ -5455,12 +5902,13 @@ begin else if Key = _lc[I_PROP_TR_NEXT_MAP] then begin // Выбор следующей карты: g_ProcessResourceStr(OpenedMap, @FileName, nil, nil); + SelectMapForm.Caption := _lc[I_CAP_SELECT]; SelectMapForm.GetMaps(FileName); if SelectMapForm.ShowModal() = mrOK then begin vleObjectProperty.Values[Key] := SelectMapForm.lbMapList.Items[SelectMapForm.lbMapList.ItemIndex]; - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; end else if (Key = _lc[I_PROP_TR_SOUND_NAME]) or @@ -5468,12 +5916,12 @@ begin begin // Выбор файла звука/музыки: AddSoundForm.OKFunction := nil; AddSoundForm.lbResourcesList.MultiSelect := False; - AddSoundForm.SetResource := utf2win(vleObjectProperty.Values[Key]); + AddSoundForm.SetResource := vleObjectProperty.Values[Key]; if (AddSoundForm.ShowModal() = mrOk) then begin - vleObjectProperty.Values[Key] := utf2win(AddSoundForm.ResourceName); - bApplyProperty.Click(); + vleObjectProperty.Values[Key] := AddSoundForm.ResourceName; + vleObjectPropertyApply(Sender); end; end else if Key = _lc[I_PROP_TR_ACTIVATION] then @@ -5503,7 +5951,7 @@ begin b := b or ACTIVATE_NOMONSTER; Values[Key] := ActivateToStr(b); - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; end else if Key = _lc[I_PROP_TR_KEYS] then @@ -5530,7 +5978,7 @@ begin b := b or KEY_BLUETEAM; Values[Key] := KeyToStr(b); - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; end else if Key = _lc[I_PROP_TR_FX_TYPE] then @@ -5548,7 +5996,7 @@ begin begin b := lbTypeSelect.ItemIndex; Values[Key] := EffectToStr(b); - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; end else if Key = _lc[I_PROP_TR_MONSTER_TYPE] then @@ -5566,7 +6014,7 @@ begin begin b := lbTypeSelect.ItemIndex + MONSTER_DEMON; Values[Key] := MonsterToStr(b); - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; end else if Key = _lc[I_PROP_TR_ITEM_TYPE] then @@ -5595,7 +6043,7 @@ begin if b >= ITEM_WEAPON_KASTET then b := b + 2; Values[Key] := ItemToStr(b); - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; end else if Key = _lc[I_PROP_TR_SHOT_TYPE] then @@ -5613,7 +6061,7 @@ begin begin b := lbTypeSelect.ItemIndex; Values[Key] := ShotToStr(b); - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; end else if Key = _lc[I_PROP_TR_EFFECT_TYPE] then @@ -5636,7 +6084,7 @@ begin Values[Key] := _lc[I_PROP_TR_EFFECT_PARTICLE] else Values[Key] := _lc[I_PROP_TR_EFFECT_ANIMATION]; - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; end else if Key = _lc[I_PROP_TR_EFFECT_SUBTYPE] then @@ -5692,7 +6140,7 @@ begin Values[Key] := _lc[I_PROP_TR_EFFECT_BUBBLE]; end; - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; end else if Key = _lc[I_PROP_TR_EFFECT_COLOR] then @@ -5702,16 +6150,24 @@ begin if ColorDialog.Execute then begin Values[Key] := IntToStr(ColorDialog.Color); - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; end else if Key = _lc[I_PROP_PANEL_TEX] then begin // Смена текстуры: vleObjectProperty.Values[Key] := SelectedTexture(); - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; end; +procedure TMainForm.vleObjectPropertyApply(Sender: TObject); +begin + // hack to prevent empty ID in list + RenderPanel.SetFocus(); + bApplyProperty.Click(); + vleObjectProperty.SetFocus(); +end; + procedure TMainForm.aSaveMapExecute(Sender: TObject); var FileName, Section, Res: String; @@ -5733,31 +6189,35 @@ begin if OpenDialog.Execute() then begin - if (Pos('.ini', LowerCase(ExtractFileName(OpenDialog.FileName))) > 0) then - begin // INI карты: - FullClear(); + OpenMapFile(OpenDialog.FileName); + OpenDialog.InitialDir := ExtractFileDir(OpenDialog.FileName); + end; +end; - pLoadProgress.Left := (RenderPanel.Width div 2)-(pLoadProgress.Width div 2); - pLoadProgress.Top := (RenderPanel.Height div 2)-(pLoadProgress.Height div 2); - pLoadProgress.Show(); +procedure TMainForm.OpenMapFile(FileName: String); +begin + if (Pos('.ini', LowerCase(ExtractFileName(FileName))) > 0) then + begin // INI карты: + FullClear(); - OpenedMap := ''; - OpenedWAD := ''; + pLoadProgress.Left := (RenderPanel.Width div 2)-(pLoadProgress.Width div 2); + pLoadProgress.Top := (RenderPanel.Height div 2)-(pLoadProgress.Height div 2); + pLoadProgress.Show(); - LoadMapOld(OpenDialog.FileName); + OpenedMap := ''; + OpenedWAD := ''; - MainForm.Caption := Format('%s - %s', [FormCaption, ExtractFileName(OpenDialog.FileName)]); + LoadMapOld(FileName); - pLoadProgress.Hide(); - MainForm.FormResize(Self); - end - else // Карты из WAD: - begin - OpenMap(OpenDialog.FileName, ''); - end; + MainForm.Caption := Format('%s - %s', [FormCaption, ExtractFileName(FileName)]); - OpenDialog.InitialDir := ExtractFileDir(OpenDialog.FileName); - end; + pLoadProgress.Hide(); + MainForm.FormResize(Self); + end + else // Карты из WAD: + begin + OpenMap(FileName, ''); + end; end; procedure TMainForm.FormActivate(Sender: TObject); @@ -5789,75 +6249,55 @@ end; procedure TMainForm.aDeleteMap(Sender: TObject); var - WAD: TWADEditor_1; - MapList: SArray; - MapName: Char16; - a: Integer; - str: String; + res: Integer; + FileName: String; + MapName: String; begin OpenDialog.Filter := _lc[I_FILE_FILTER_WAD]; if not OpenDialog.Execute() then Exit; - WAD := TWADEditor_1.Create(); + FileName := OpenDialog.FileName; + SelectMapForm.Caption := _lc[I_CAP_REMOVE]; + SelectMapForm.lbMapList.Items.Clear(); + SelectMapForm.GetMaps(FileName); - if not WAD.ReadFile(OpenDialog.FileName) then - begin - WAD.Free(); + if SelectMapForm.ShowModal() <> mrOK then Exit; - end; - - WAD.CreateImage(); - MapList := WAD.GetResourcesList(''); - - SelectMapForm.lbMapList.Items.Clear(); - - if MapList <> nil then - for a := 0 to High(MapList) do - SelectMapForm.lbMapList.Items.Add(MapList[a]); + MapName := SelectMapForm.lbMapList.Items[SelectMapForm.lbMapList.ItemIndex]; + if MessageBox(0, PChar(Format(_lc[I_MSG_DELETE_MAP_PROMT], [MapName, OpenDialog.FileName])), PChar(_lc[I_MSG_DELETE_MAP]), MB_ICONQUESTION or MB_YESNO or MB_DEFBUTTON2) <> mrYes then + Exit; - if (SelectMapForm.ShowModal() = mrOK) then + g_DeleteResource(FileName, '', MapName, res); + if res <> 0 then begin - str := SelectMapForm.lbMapList.Items[SelectMapForm.lbMapList.ItemIndex]; - MapName := ''; - Move(MapName[0], str[1], Min(16, Length(str))); - - if MessageBox(0, PChar(Format(_lc[I_MSG_DELETE_MAP_PROMT], - [MapName, OpenDialog.FileName])), - PChar(_lc[I_MSG_DELETE_MAP]), - MB_ICONQUESTION or MB_YESNO or - MB_DEFBUTTON2) <> mrYes then - Exit; - - WAD.RemoveResource('', MapName); - - MessageBox(0, PChar(Format(_lc[I_MSG_MAP_DELETED_PROMT], - [MapName])), - PChar(_lc[I_MSG_MAP_DELETED]), - MB_ICONINFORMATION or MB_OK or - MB_DEFBUTTON1); + MessageBox(0, PChar('Cant delete map res=' + IntToStr(res)), PChar('Map not deleted!'), MB_ICONINFORMATION or MB_OK or MB_DEFBUTTON1); + Exit + end; - WAD.SaveTo(OpenDialog.FileName); + MessageBox( + 0, + PChar(Format(_lc[I_MSG_MAP_DELETED_PROMT], [MapName])), + PChar(_lc[I_MSG_MAP_DELETED]), + MB_ICONINFORMATION or MB_OK or MB_DEFBUTTON1 + ); // Удалили текущую карту - сохранять по старому ее нельзя: - if OpenedMap = (OpenDialog.FileName+':\'+MapName) then - begin - OpenedMap := ''; - OpenedWAD := ''; - MainForm.Caption := FormCaption; - end; - end; - - WAD.Free(); + if OpenedMap = (FileName + ':\' + MapName) then + begin + OpenedMap := ''; + OpenedWAD := ''; + MainForm.Caption := FormCaption + end end; procedure TMainForm.vleObjectPropertyKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_RETURN then - bApplyProperty.Click(); + vleObjectPropertyApply(Sender); end; procedure MovePanel(var ID: DWORD; MoveType: Byte); @@ -6065,6 +6505,8 @@ begin if gTriggers[a].TriggerType <> TRIGGER_NONE then SelectObject(OBJECT_TRIGGER, a, True); end; + + RecountSelectedObjects(); end; procedure TMainForm.tbGridOnClick(Sender: TObject); @@ -6093,7 +6535,10 @@ end; procedure TMainForm.miMapPreviewClick(Sender: TObject); begin - if not PreviewMode then + if PreviewMode = 2 then + Exit; + + if PreviewMode = 0 then begin Splitter2.Visible := False; Splitter1.Visible := False; @@ -6116,8 +6561,8 @@ begin sbVertical.Visible := True; end; - PreviewMode := not PreviewMode; - (Sender as TMenuItem).Checked := PreviewMode; + PreviewMode := PreviewMode xor 1; + (Sender as TMenuItem).Checked := PreviewMode > 0; FormResize(Self); end; @@ -6250,24 +6695,70 @@ begin MapTestForm.ShowModal(); end; +type SSArray = array of String; + +function ParseString (Str: AnsiString): SSArray; + function GetStr (var Str: AnsiString): AnsiString; + var a, b: Integer; + begin + Result := ''; + if Str[1] = '"' then + for b := 1 to Length(Str) do + if (b = Length(Str)) or (Str[b + 1] = '"') then + begin + Result := Copy(Str, 2, b - 1); + Delete(Str, 1, b + 1); + Str := Trim(Str); + Exit; + end; + for a := 1 to Length(Str) do + if (a = Length(Str)) or (Str[a + 1] = ' ') then + begin + Result := Copy(Str, 1, a); + Delete(Str, 1, a + 1); + Str := Trim(Str); + Exit; + end; + end; +begin + Result := nil; + Str := Trim(Str); + while Str <> '' do + begin + SetLength(Result, Length(Result)+1); + Result[High(Result)] := GetStr(Str); + end; +end; + procedure TMainForm.miTestMapClick(Sender: TObject); var - cmd, mapWAD, mapToRun: String; + newWAD, oldWAD, tempMap, ext: String; + args: SSArray; opt: LongWord; - time: Integer; + time, i: Integer; proc: TProcessUTF8; res: Boolean; begin // Сохраняем временную карту: time := 0; repeat - mapWAD := ExtractFilePath(TestD2dExe) + Format('maps/temp%.4d.wad', [time]); + newWAD := ExtractFilePath(TestD2dExe) + Format('maps/temp%.4d', [time]); Inc(time); - until not FileExists(mapWAD); - mapToRun := mapWAD + ':\' + TEST_MAP_NAME; - SaveMap(mapToRun); - - mapToRun := ExtractRelativePath(ExtractFilePath(TestD2dExe) + 'maps/', mapToRun); + until not FileExists(newWAD); + if OpenedMap <> '' then + begin + oldWad := g_ExtractWadName(OpenedMap); + newWad := newWad + ExtractFileExt(oldWad); + if CopyFile(oldWad, newWad) = false then + e_WriteLog('MapTest: unable to copy [' + oldWad + '] to [' + newWad + ']', MSG_WARNING) + end + else + begin + newWad := newWad + '.wad' + end; + tempMap := newWAD + ':\' + TEST_MAP_NAME; + SaveMap(tempMap); + tempMap := ExtractRelativePath(ExtractFilePath(TestD2dExe) + 'maps/', tempMap); // Опции игры: opt := 32 + 64; @@ -6282,23 +6773,27 @@ begin if TestOptionsMonstersDM then opt := opt + 16; -// Составляем командную строку: - cmd := ' -map "' + mapToRun + '"'; - cmd := cmd + ' -gm ' + TestGameMode; - cmd := cmd + ' -limt ' + TestLimTime; - cmd := cmd + ' -lims ' + TestLimScore; - cmd := cmd + ' -opt ' + IntToStr(opt); - - if TestMapOnce then - cmd := cmd + ' --close'; - - cmd := cmd + ' --debug'; - cmd := cmd + ' --tempdelete'; - // Запускаем: proc := TProcessUTF8.Create(nil); proc.Executable := TestD2dExe; - proc.Parameters.Add(cmd); + proc.Parameters.Add('-map'); + proc.Parameters.Add(tempMap); + proc.Parameters.Add('-gm'); + proc.Parameters.Add(TestGameMode); + proc.Parameters.Add('-limt'); + proc.Parameters.Add(TestLimTime); + proc.Parameters.Add('-lims'); + proc.Parameters.Add(TestLimScore); + proc.Parameters.Add('-opt'); + proc.Parameters.Add(IntToStr(opt)); + proc.Parameters.Add('--debug'); + if TestMapOnce then + proc.Parameters.Add('--close'); + + args := ParseString(TestD2DArgs); + for i := 0 to High(args) do + proc.Parameters.Add(args[i]); + res := True; try proc.Execute(); @@ -6318,20 +6813,20 @@ begin end; proc.Free(); - SysUtils.DeleteFile(mapWAD); + SysUtils.DeleteFile(newWAD); Application.Restore(); end; procedure TMainForm.sbVerticalScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer); begin - MapOffset.Y := -Normalize16(sbVertical.Position); + MapOffset.Y := -sbVertical.Position; end; procedure TMainForm.sbHorizontalScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer); begin - MapOffset.X := -Normalize16(sbHorizontal.Position); + MapOffset.X := -sbHorizontal.Position; end; procedure TMainForm.miOpenWadMapClick(Sender: TObject); @@ -6372,6 +6867,8 @@ begin for a := 0 to High(gTriggers) do if gTriggers[a].TriggerType <> TRIGGER_NONE then SelectObject(OBJECT_TRIGGER, a, True); + + RecountSelectedObjects(); end; procedure TMainForm.Splitter1CanResize(Sender: TObject; @@ -6396,8 +6893,7 @@ begin EditingProperties := False; end; -procedure TMainForm.FormKeyUp(Sender: TObject; var Key: Word; - Shift: TShiftState); +procedure TMainForm.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin // Объекты передвигались: if MainForm.ActiveControl = RenderPanel then @@ -6409,28 +6905,13 @@ begin (Key = Ord('V')) then FillProperty(); end; -end; - -{ -procedure TMainForm.lbTextureListDrawItem(Control: TWinControl; Index: Integer; - Rect: TRect; State: LCLType.TOwnerDrawState); -begin - with Control as TListBox do +// Быстрое превью карты: + if Key = Ord('E') then begin - if LCLType.odSelected in State then - begin - Canvas.Brush.Color := clHighlight; - Canvas.Font.Color := clHighlightText; - end else - if (Items <> nil) and (Index >= 0) then - if slInvalidTextures.IndexOf(Items[Index]) > -1 then - begin - Canvas.Brush.Color := clRed; - Canvas.Font.Color := clWhite; - end; - Canvas.FillRect(Rect); - Canvas.TextRect(Rect, Rect.Left, Rect.Top, Items[Index]); + if PreviewMode = 2 then + PreviewMode := 0; end; + RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y); end; -} + end.