X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Feditor%2Ff_main.pas;h=ef9e19d2ee9c59c7ffd0bdeae5e12aedfa9221cc;hb=71ef827e8608f2e426111ff0ddfb7019beba0e65;hp=d3193006eebd27184d3b0bc384de61a50d60962e;hpb=b72e164f0fb64e3301ae8ca217449daf6a9d301d;p=d2df-editor.git diff --git a/src/editor/f_main.pas b/src/editor/f_main.pas index d319300..ef9e19d 100644 --- a/src/editor/f_main.pas +++ b/src/editor/f_main.pas @@ -1,6 +1,6 @@ unit f_main; -{$MODE Delphi} +{$INCLUDE ../shared/a_modes.inc} interface @@ -8,10 +8,14 @@ uses LCLIntf, LCLType, LMessages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ImgList, StdCtrls, Buttons, ComCtrls, ValEdit, Types, ToolWin, Menus, ExtCtrls, - CheckLst, Grids; + CheckLst, Grids, OpenGLContext, utils, UTF8Process; type + + { TMainForm } + TMainForm = class(TForm) + lLoad: TLabel; // Главное меню: MainMenu: TMainMenu; // "Файл": @@ -77,6 +81,9 @@ type // Панель инструментов: MainToolBar: TToolBar; + pbLoad: TProgressBar; + pLoadProgress: TPanel; + RenderPanel: TOpenGLControl; tbNewMap: TToolButton; tbOpenMap: TToolButton; tbSaveMap: TToolButton; @@ -107,12 +114,6 @@ type // Панель карты: PanelMap: TPanel; - // Панель отображения карты: - RenderPanel: TPanel; - // Панель загрузки: - pLoadProgress: TPanel; - lLoad: TLabel; - pbLoad: TProgressBar; // Полосы прокрутки: sbHorizontal: TScrollBar; sbVertical: TScrollBar; @@ -206,9 +207,12 @@ type 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 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 vleObjectPropertyEditButtonClick(Sender: TObject); procedure vleObjectPropertyGetPickList(Sender: TObject; const KeyName: String; Values: TStrings); @@ -256,8 +260,6 @@ type procedure OnIdle(Sender: TObject; var Done: Boolean); public procedure RefreshRecentMenu(); - { procedure lbTextureListDrawItem(Control: TWinControl; Index: Integer; - Rect: TRect; State: TOwnerDrawState); } end; const @@ -321,14 +323,14 @@ procedure ChangeShownProperty(Name: String; NewValue: String); implementation uses - f_options, e_graphics, e_log, dglOpenGL, Math, + f_options, e_graphics, e_log, GL, GLExt, 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, MAPDEF, + MAPREADER, f_selectmap, f_savemap, WADEDITOR, WADSTRUCT, MAPDEF, g_map, f_saveminimap, f_addresource, CONFIG, f_packmap, f_addresource_sound, f_maptest, f_choosetype, - g_language, f_selectlang, ClipBrd, Windows; + g_language, f_selectlang, ClipBrd; const UNDO_DELETE_PANEL = 1; @@ -419,9 +421,8 @@ type TCopyRecArray = Array of TCopyRec; var - hDC: THandle; - hRC: THandle; gEditorFont: DWORD; + gDataLoaded: Boolean = False; ShowMap: Boolean = False; DrawRect: PRect = nil; SnapToGrid: Boolean = True; @@ -1460,7 +1461,13 @@ begin MaxLength := 3; end; - with ItemProps[InsertRow(_lc[I_PROP_TR_SHOT_ALLMAP], BoolNames[Data.ShotAllMap], True)] do + case Data.ShotAim of + 1: str := _lc[I_PROP_TR_SHOT_AIM_1]; + 2: str := _lc[I_PROP_TR_SHOT_AIM_2]; + 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 begin EditStyle := esPickList; ReadOnly := True; @@ -1788,6 +1795,7 @@ procedure FullClear(); begin RemoveSelectFromObjects(); ClearMap(); + LoadSky(gMapInfo.SkyName); UndoBuffer := nil; slInvalidTextures.Clear(); MapCheckForm.lbErrorList.Clear(); @@ -1869,10 +1877,11 @@ end; function AddTexture(aWAD, aSection, aTex: String; silent: Boolean): Boolean; var - a: Integer; + a, FrameLen: Integer; ok: Boolean; FileName: String; ResourceName: String; + UResourceName: String; FullResourceName: String; SectionName: String; Data: Pointer; @@ -1899,19 +1908,20 @@ begin end else begin // Внешний WAD - FileName := EditorDir+'wads\'+aWAD; - ResourceName := aWAD+':'+SectionName+'\'+aTex; + FileName := EditorDir+'wads/'+aWAD; + ResourceName := utf2win(aWAD)+':'+SectionName+'\'+aTex; end; ok := True; + UResourceName := win2utf(ResourceName); // Есть ли уже такая текстура: for a := 0 to MainForm.lbTextureList.Items.Count-1 do - if ResourceName = MainForm.lbTextureList.Items[a] then + if UResourceName = MainForm.lbTextureList.Items[a] then begin if not silent then ErrorMessageBox(Format(_lc[I_MSG_TEXTURE_ALREADY], - [ResourceName])); + [UResourceName])); ok := False; end; @@ -1920,7 +1930,7 @@ begin begin if not silent then ErrorMessageBox(Format(_lc[I_MSG_RES_NAME_64], - [ResourceName])); + [UResourceName])); ok := False; end; @@ -1929,7 +1939,7 @@ begin a := -1; if aWAD = _lc[I_WAD_SPECIAL_TEXS] then begin - a := MainForm.lbTextureList.Items.Add(ResourceName); + a := MainForm.lbTextureList.Items.Add(UResourceName); if not silent then SelectTexture(a); Result := True; @@ -1940,15 +1950,15 @@ begin if IsAnim(FullResourceName) then begin // Аним. текстура - GetFrame(FullResourceName, Data, Width, Height); + GetFrame(FullResourceName, Data, FrameLen, Width, Height); - if g_CreateTextureMemorySize(Data, ResourceName, 0, 0, Width, Height, 1) then - a := MainForm.lbTextureList.Items.Add(ResourceName); + if g_CreateTextureMemorySize(Data, FrameLen, ResourceName, 0, 0, Width, Height, 1) then + a := MainForm.lbTextureList.Items.Add(UResourceName); end else // Обычная текстура begin if g_CreateTextureWAD(ResourceName, FullResourceName) then - a := MainForm.lbTextureList.Items.Add(ResourceName); + a := MainForm.lbTextureList.Items.Add(UResourceName); end; if (a > -1) and (not silent) then SelectTexture(a); @@ -2037,7 +2047,7 @@ begin lbTextureList.Sorted := True; lbTextureList.Sorted := False; - UpdateCaption(gMapInfo.Name, ExtractFileName(FileName), MapName); + UpdateCaption(win2utf(gMapInfo.Name), ExtractFileName(FileName), MapName); end; end; @@ -2203,7 +2213,7 @@ end; function SelectedTexture(): String; begin if MainForm.lbTextureList.ItemIndex <> -1 then - Result := MainForm.lbTextureList.Items[MainForm.lbTextureList.ItemIndex] + Result := utf2win(MainForm.lbTextureList.Items[MainForm.lbTextureList.ItemIndex]) else Result := ''; end; @@ -2211,7 +2221,7 @@ end; function IsSpecialTextureSel(): Boolean; begin Result := (MainForm.lbTextureList.ItemIndex <> -1) and - IsSpecialTexture(MainForm.lbTextureList.Items[MainForm.lbTextureList.ItemIndex]); + IsSpecialTexture(utf2win(MainForm.lbTextureList.Items[MainForm.lbTextureList.ItemIndex])); end; function CopyBufferToString(var CopyBuf: TCopyRecArray): String; @@ -2491,6 +2501,7 @@ procedure TMainForm.aRecentFileExecute(Sender: TObject); var n, pw: Integer; s, fn: String; + b: Boolean; begin s := LowerCase((Sender as TMenuItem).Caption); Delete(s, Pos('&', s), 1); @@ -2502,17 +2513,31 @@ begin s := RecentFiles[n]; pw := Pos('.wad:\', LowerCase(s)); + b := False; if pw > 0 then begin // Map name included fn := Copy(s, 1, pw + 3); Delete(s, 1, pw + 5); if (FileExists(fn)) then + begin OpenMap(fn, s); + b := True; + end; end else // Only wad name if (FileExists(s)) then + begin OpenMap(s, ''); + b := True; + end; + + if (not b) and (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; end; procedure TMainForm.aEditorOptionsExecute(Sender: TObject); @@ -2520,51 +2545,57 @@ begin OptionsForm.ShowModal(); end; -procedure TMainForm.FormCreate(Sender: TObject); +procedure LoadStdFont(cfgres, texture: string; var FontID: DWORD); var - PixelFormat: GLuint; - pfd: TPIXELFORMATDESCRIPTOR; + cwdt, chgt: Byte; + spc: ShortInt; + ID: DWORD; + wad: TWADEditor_1; + cfgdata: Pointer; + cfglen: Integer; config: TConfig; - i: Integer; - s: String; begin - Randomize(); + cfglen := 0; - EditorDir := ExtractFilePath(Application.ExeName); + wad := TWADEditor_1.Create; + if wad.ReadFile(EditorDir+'data/Game.wad') then + wad.GetResource('FONTS', cfgres, cfgdata, cfglen); + wad.Free(); - e_InitLog(EditorDir+'Editor.log', WM_NEWFILE); + if cfglen <> 0 then + begin + if not g_CreateTextureWAD('FONT_STD', EditorDir+'data/Game.wad:FONTS\'+texture) then + e_WriteLog('ERROR ERROR ERROR', MSG_WARNING); - e_WriteLog('Init OpenGL', MSG_NOTIFY); + config := TConfig.CreateMem(cfgdata, cfglen); + cwdt := Min(Max(config.ReadInt('FontMap', 'CharWidth', 0), 0), 255); + chgt := Min(Max(config.ReadInt('FontMap', 'CharHeight', 0), 0), 255); + spc := Min(Max(config.ReadInt('FontMap', 'Kerning', 0), -128), 127); - InitOpenGL(); - hDC := GetDC(RenderPanel.Handle); + if g_GetTexture('FONT_STD', ID) then + e_TextureFontBuild(ID, FontID, cwdt, chgt, spc-2); - FillChar(pfd, SizeOf(pfd), 0); - with pfd do - begin - nSize := SizeOf(pfd); - nVersion := 1; - dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER; - dwLayerMask := PFD_MAIN_PLANE; - iPixelType := PFD_TYPE_RGBA; - cColorBits := 24; - cDepthBits := 32; - iLayerType := PFD_MAIN_PLANE; - end; - PixelFormat := ChoosePixelFormat (hDC, @pfd); - SetPixelFormat(hDC, PixelFormat, @pfd); + config.Free(); + end + else + e_WriteLog('Could not load FONT_STD', MSG_WARNING); - hRC := wglCreateContext(hDC); - ActivateRenderingContext(hDC, hRC); + if cfglen <> 0 then FreeMem(cfgdata); +end; - e_InitGL(False); +procedure TMainForm.FormCreate(Sender: TObject); +var + config: TConfig; + i: Integer; + s: String; +begin + Randomize(); - gEditorFont := e_SimpleFontCreate('Arial Cyr', 12, FW_BOLD, hDC); + EditorDir := ExtractFilePath(Application.ExeName); - slInvalidTextures := TStringList.Create; + e_InitLog(EditorDir+'Editor.log', WM_NEWFILE); - e_WriteLog('Loading data', MSG_NOTIFY); - LoadData(); + slInvalidTextures := TStringList.Create; ShowLayer(LAYER_BACK, True); ShowLayer(LAYER_WALLS, True); @@ -2582,8 +2613,16 @@ begin OpenedMap := ''; OpenedWAD := ''; - config := TConfig.CreateFile(EditorDir+'\Editor.cfg'); + config := TConfig.CreateFile(EditorDir+'Editor.cfg'); + if config.ReadInt('Editor', 'XPos', -1) = -1 then + Position := poDesktopCenter + else begin + Left := config.ReadInt('Editor', 'XPos', Left); + Top := config.ReadInt('Editor', 'YPos', Top); + Width := config.ReadInt('Editor', 'Width', Width); + Height := config.ReadInt('Editor', 'Height', Height); + end; if config.ReadBool('Editor', 'Maximize', False) then WindowState := wsMaximized; ShowMap := config.ReadBool('Editor', 'Minimap', False); @@ -2657,18 +2696,22 @@ begin Application.OnIdle := OnIdle; end; +procedure PrintBlack(X, Y: Integer; Text: string; FontID: DWORD); +begin + // NOTE: all the font printing routines assume CP1251 + e_TextureFontPrintEx(X, Y, Text, FontID, 0, 0, 0, 1.0); +end; + procedure TMainForm.Draw(); var - ps: TPaintStruct; x, y: Integer; a, b: Integer; - ID: DWORD; + ID, PID: DWORD; Width, Height: Word; Rect: TRectWH; ObjCount: Word; aX, aY, aX2, aY2, XX, ScaleSz: Integer; begin - BeginPaint(Handle, ps); e_BeginRender(); e_Clear(GL_COLOR_BUFFER_BIT, @@ -2735,10 +2778,9 @@ begin if not g_GetTexture(SelectedTexture(), ID) then g_GetTexture('NOTEXTURE', ID); g_GetTextureSizeByID(ID, Width, Height); - 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-1, RenderPanel.Height-Height-1, 0, True, False); + 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); + e_Draw(ID, RenderPanel.Width-Width, RenderPanel.Height-Height, 0, True, False); end; // Подсказка при выборе точки Телепорта: @@ -2755,7 +2797,7 @@ begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_TELEPORT]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_TELEPORT], gEditorFont); end; // Подсказка при выборе точки появления: @@ -2766,7 +2808,7 @@ begin 0, 0, 255); e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_SPAWN]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_SPAWN], gEditorFont); end; // Подсказка при выборе панели двери: @@ -2774,7 +2816,7 @@ begin begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_PANEL_DOOR]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_PANEL_DOOR], gEditorFont); end; // Подсказка при выборе панели с текстурой: @@ -2782,7 +2824,7 @@ begin begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+196, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+196, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_PANEL_TEXTURE]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_PANEL_TEXTURE], gEditorFont); end; // Подсказка при выборе панели индикации выстрела: @@ -2790,7 +2832,7 @@ begin begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+316, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+316, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_PANEL_SHOT]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_PANEL_SHOT], gEditorFont); end; // Подсказка при выборе панели лифта: @@ -2798,7 +2840,7 @@ begin begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_PANEL_LIFT]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_PANEL_LIFT], gEditorFont); end; // Подсказка при выборе монстра: @@ -2806,7 +2848,7 @@ begin begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+120, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+120, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_MONSTER]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_MONSTER], gEditorFont); end; // Подсказка при выборе области воздействия: @@ -2814,7 +2856,7 @@ begin begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+204, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+204, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_EXT_AREA]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_EXT_AREA], gEditorFont); end; // Рисуем текстуры, если чертим панель: @@ -2844,10 +2886,10 @@ begin if MouseAction in [MOUSEACTION_DRAWPANEL, MOUSEACTION_DRAWTRIGGER] then begin // Чертим новый - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(Format(_lc[I_HINT_WIDTH], - [Abs(MousePos.X-MouseLDownPos.X)])), gEditorFont, 0, 0, 0); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+28, PChar(Format(_lc[I_HINT_HEIGHT], - [Abs(MousePos.Y-MouseLDownPos.Y)])), gEditorFont, 0, 0, 0); + 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], + [Abs(MousePos.Y-MouseLDownPos.Y)]), gEditorFont); end else // Растягиваем существующий if SelectedObjects[GetFirstSelected].ObjectType in [OBJECT_PANEL, OBJECT_TRIGGER] then @@ -2863,10 +2905,10 @@ begin Height := gTriggers[SelectedObjects[GetFirstSelected].ID].Height; end; - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(Format(_lc[I_HINT_WIDTH], [Width])), - gEditorFont, 0, 0, 0); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+28, PChar(Format(_lc[I_HINT_HEIGHT], [Height])), - gEditorFont, 0, 0, 0); + 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]), + gEditorFont); end; end; @@ -2962,8 +3004,7 @@ begin end; // Мини-карта e_EndRender(); - SwapBuffers(hDC); - EndPaint(Handle, ps); + RenderPanel.SwapBuffers(); end; procedure TMainForm.FormResize(Sender: TObject); @@ -3616,7 +3657,7 @@ begin trigger.Key := Trigger.Key or KEY_BLUETEAM; // Параметры триггера: - ZeroMemory(@trigger.Data.Default[0], 128); + FillByte(trigger.Data.Default[0], 128, 0); case trigger.TriggerType of // Переключаемая панель: @@ -3725,7 +3766,7 @@ begin trigger.Data.ShotPanelID := -1; trigger.Data.ShotTarget := 0; trigger.Data.ShotIntSight := 0; - trigger.Data.ShotAllMap := False; + trigger.Data.ShotAim := TRIGGER_SHOT_AIM_DEFAULT; trigger.Data.ShotPos.X := trigger.X-64; trigger.Data.ShotPos.Y := trigger.Y-64; trigger.Data.ShotAngle := 0; @@ -3837,6 +3878,11 @@ begin end; end; +procedure TMainForm.RenderPanelPaint(Sender: TObject); +begin + Draw(); +end; + procedure TMainForm.RenderPanelMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var @@ -3909,8 +3955,10 @@ begin begin if DrawRect = nil then New(DrawRect); - DrawRect.TopLeft := MouseRDownPos; - DrawRect.BottomRight := MousePos; + DrawRect.Top := MouseRDownPos.y; + DrawRect.Left := MouseRDownPos.x; + DrawRect.Bottom := MousePos.y; + DrawRect.Right := MousePos.x; end else // Двигаем выделенные объекты: @@ -3959,8 +4007,10 @@ begin begin if DrawRect = nil then New(DrawRect); - DrawRect.TopLeft := MouseLDownPos; - DrawRect.BottomRight := MousePos; + DrawRect.Top := MouseLDownPos.y; + DrawRect.Left := MouseLDownPos.x; + DrawRect.Bottom := MousePos.y; + DrawRect.Right := MousePos.x; end else // Двигаем карту: if MouseAction = MOUSEACTION_MOVEMAP then @@ -3983,7 +4033,7 @@ begin CanClose := MessageBox(0, PChar(_lc[I_MSG_EXIT_PROMT]), PChar(_lc[I_MSG_EXIT]), MB_ICONQUESTION or MB_YESNO or - MB_TASKMODAL or MB_DEFBUTTON1) = idYes; + MB_DEFBUTTON1) = idYes; end; procedure TMainForm.aExitExecute(Sender: TObject); @@ -3996,8 +4046,22 @@ var config: TConfig; i: Integer; begin - config := TConfig.CreateFile(EditorDir+'\Editor.cfg'); + config := TConfig.CreateFile(EditorDir+'Editor.cfg'); + if WindowState <> wsMaximized then + begin + config.WriteInt('Editor', 'XPos', Left); + config.WriteInt('Editor', 'YPos', Top); + config.WriteInt('Editor', 'Width', Width); + config.WriteInt('Editor', 'Height', Height); + end + else + begin + config.WriteInt('Editor', 'XPos', RestoredLeft); + config.WriteInt('Editor', 'YPos', RestoredTop); + config.WriteInt('Editor', 'Width', RestoredWidth); + config.WriteInt('Editor', 'Height', RestoredHeight); + end; config.WriteBool('Editor', 'Maximize', WindowState = wsMaximized); config.WriteBool('Editor', 'Minimap', ShowMap); config.WriteInt('Editor', 'PanelProps', PanelProps.ClientWidth); @@ -4019,12 +4083,10 @@ begin config.WriteStr('RecentFiles', IntToStr(i+1), ''); RecentFiles.Free(); - config.SaveFile(EditorDir+'\Editor.cfg'); + config.SaveFile(EditorDir+'Editor.cfg'); config.Free(); slInvalidTextures.Free; - - wglDeleteContext(hRC); end; procedure TMainForm.RenderPanelResize(Sender: TObject); @@ -4043,7 +4105,7 @@ begin while (Pos(':\', ResName) > 0) do Delete(ResName, 1, Pos(':\', ResName) + 1); - UpdateCaption(gMapInfo.Name, ExtractFileName(OpenedWAD), ResName); + UpdateCaption(win2utf(gMapInfo.Name), ExtractFileName(OpenedWAD), ResName); end; procedure TMainForm.aAboutExecute(Sender: TObject); @@ -4264,11 +4326,11 @@ begin begin AddSoundForm.OKFunction := nil; AddSoundForm.lbResourcesList.MultiSelect := False; - AddSoundForm.SetResource := vleObjectProperty.Cells[1, i]; + AddSoundForm.SetResource := utf2win(vleObjectProperty.Cells[1, i]); if (AddSoundForm.ShowModal() = mrOk) then begin - vleObjectProperty.Cells[1, i] := AddSoundForm.ResourceName; + vleObjectProperty.Cells[1, i] := win2utf(AddSoundForm.ResourceName); bApplyProperty.Click(); end; Exit; @@ -4330,6 +4392,27 @@ 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.vleObjectPropertyGetPickList(Sender: TObject; const KeyName: String; Values: TStrings); begin @@ -4399,6 +4482,13 @@ begin Values.Add(_lc[I_PROP_TR_SHOT_TO_5]); Values.Add(_lc[I_PROP_TR_SHOT_TO_6]); end + else if KeyName = _lc[I_PROP_TR_SHOT_AIM] then + begin + Values.Add(_lc[I_PROP_TR_SHOT_AIM_0]); + Values.Add(_lc[I_PROP_TR_SHOT_AIM_1]); + 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_PANEL_BLEND]) or (KeyName = _lc[I_PROP_DM_ONLY]) or (KeyName = _lc[I_PROP_ITEM_FALLS]) or @@ -4416,7 +4506,6 @@ begin (KeyName = _lc[I_PROP_TR_SCORE_CON]) or (KeyName = _lc[I_PROP_TR_SCORE_MSG]) or (KeyName = _lc[I_PROP_TR_HEALTH_MAX]) or - (KeyName = _lc[I_PROP_TR_SHOT_ALLMAP]) or (KeyName = _lc[I_PROP_TR_SHOT_SOUND]) or (KeyName = _lc[I_PROP_TR_EFFECT_CENTER]) then begin @@ -4632,9 +4721,9 @@ begin TRIGGER_EXIT: begin s := vleObjectProperty.Values[_lc[I_PROP_TR_NEXT_MAP]]; - ZeroMemory(@Data.MapName[0], 16); + FillByte(Data.MapName[0], 16, 0); if s <> '' then - CopyMemory(@Data.MapName[0], @s[1], Min(Length(s), 16)); + Move(Data.MapName[0], s[1], Min(Length(s), 16)); end; TRIGGER_TEXTURE: @@ -4671,9 +4760,9 @@ begin TRIGGER_SOUND: begin s := vleObjectProperty.Values[_lc[I_PROP_TR_SOUND_NAME]]; - ZeroMemory(@Data.SoundName[0], 64); + FillByte(Data.SoundName[0], 64, 0); if s <> '' then - CopyMemory(@Data.SoundName[0], @s[1], Min(Length(s), 64)); + Move(Data.SoundName[0], s[1], 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); @@ -4725,9 +4814,9 @@ begin TRIGGER_MUSIC: begin s := vleObjectProperty.Values[_lc[I_PROP_TR_MUSIC_NAME]]; - ZeroMemory(@Data.MusicName[0], 64); + FillByte(Data.MusicName[0], 64, 0); if s <> '' then - CopyMemory(@Data.MusicName[0], @s[1], Min(Length(s), 64)); + Move(Data.MusicName[0], s[1], Min(Length(s), 64)); if vleObjectProperty.Values[_lc[I_PROP_TR_MUSIC_ACT]] = _lc[I_PROP_TR_MUSIC_ON] then Data.MusicAction := 1 @@ -4785,9 +4874,9 @@ begin Data.MessageSendTo := 5; s := vleObjectProperty.Values[_lc[I_PROP_TR_MESSAGE_TEXT]]; - ZeroMemory(@Data.MessageText[0], 100); + FillByte(Data.MessageText[0], 100, 0); if s <> '' then - CopyMemory(@Data.MessageText[0], @s[1], Min(Length(s), 100)); + Move(Data.MessageText[0], s[1], Min(Length(s), 100)); Data.MessageTime := Min(Max( StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_MESSAGE_TIME]], 0), 0), 65535); @@ -4830,7 +4919,13 @@ begin Data.ShotTarget := 6; Data.ShotIntSight := Min(Max( StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_SHOT_SIGHT]], 0), 0), 65535); - Data.ShotAllMap := NameToBool(vleObjectProperty.Values[_lc[I_PROP_TR_SHOT_ALLMAP]]); + Data.ShotAim := 0; + if vleObjectProperty.Values[_lc[I_PROP_TR_SHOT_AIM]] = _lc[I_PROP_TR_SHOT_AIM_1] then + Data.ShotAim := 1 + else if vleObjectProperty.Values[_lc[I_PROP_TR_SHOT_AIM]] = _lc[I_PROP_TR_SHOT_AIM_2] then + Data.ShotAim := 2 + else if vleObjectProperty.Values[_lc[I_PROP_TR_SHOT_AIM]] = _lc[I_PROP_TR_SHOT_AIM_3] then + Data.ShotAim := 3; Data.ShotAngle := Min( StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_SHOT_ANGLE]], 0), 360); Data.ShotWait := Min(Max( @@ -4915,7 +5010,7 @@ begin [SelectedTexture()])), PChar(_lc[I_MSG_DEL_TEXTURE]), MB_ICONQUESTION or MB_YESNO or - MB_TASKMODAL or MB_DEFBUTTON1) <> idYes then + MB_DEFBUTTON1) <> idYes then Exit; if gPanels <> nil then @@ -4940,7 +5035,7 @@ begin if (MessageBox(0, PChar(_lc[I_MSG_CLEAR_MAP_PROMT]), PChar(_lc[I_MSG_CLEAR_MAP]), MB_ICONQUESTION or MB_YESNO or - MB_TASKMODAL or MB_DEFBUTTON1) = mrYes) then + MB_DEFBUTTON1) = mrYes) then FullClear(); end; @@ -5247,8 +5342,8 @@ begin begin Panel^.TextureID := SpecialTextureID(Panel^.TextureName); with MainForm.lbTextureList.Items do - if IndexOf(Panel^.TextureName) = -1 then - Add(Panel^.TextureName); + if IndexOf(win2utf(Panel^.TextureName)) = -1 then + Add(win2utf(Panel^.TextureName)); end; end; @@ -5409,11 +5504,11 @@ begin begin // Выбор файла звука/музыки: AddSoundForm.OKFunction := nil; AddSoundForm.lbResourcesList.MultiSelect := False; - AddSoundForm.SetResource := vleObjectProperty.Values[Key]; + AddSoundForm.SetResource := utf2win(vleObjectProperty.Values[Key]); if (AddSoundForm.ShowModal() = mrOk) then begin - vleObjectProperty.Values[Key] := AddSoundForm.ResourceName; + vleObjectProperty.Values[Key] := utf2win(AddSoundForm.ResourceName); bApplyProperty.Click(); end; end @@ -5522,6 +5617,8 @@ begin lbTypeSelect.Items.Add(ItemToStr(ITEM_HELMET)); lbTypeSelect.Items.Add(ItemToStr(ITEM_JETPACK)); lbTypeSelect.Items.Add(ItemToStr(ITEM_INVIS)); + lbTypeSelect.Items.Add(ItemToStr(ITEM_WEAPON_FLAMETHROWER)); + lbTypeSelect.Items.Add(ItemToStr(ITEM_AMMO_FUELCAN)); b := StrToItem(Values[Key]); if b >= ITEM_BOTTLE then @@ -5715,9 +5812,9 @@ begin else gLanguage := LANGUAGE_RUSSIAN; end; - config := TConfig.CreateFile(EditorDir+'\Editor.cfg'); + config := TConfig.CreateFile(EditorDir+'Editor.cfg'); config.WriteStr('Editor', 'Language', gLanguage); - config.SaveFile(EditorDir+'\Editor.cfg'); + config.SaveFile(EditorDir+'Editor.cfg'); config.Free(); end; @@ -5761,13 +5858,13 @@ begin begin str := SelectMapForm.lbMapList.Items[SelectMapForm.lbMapList.ItemIndex]; MapName := ''; - CopyMemory(@MapName[0], @str[1], Min(16, Length(str))); + 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_TASKMODAL or MB_DEFBUTTON2) <> mrYes then + MB_DEFBUTTON2) <> mrYes then Exit; WAD.RemoveResource('', MapName); @@ -5776,7 +5873,7 @@ begin [MapName])), PChar(_lc[I_MSG_MAP_DELETED]), MB_ICONINFORMATION or MB_OK or - MB_TASKMODAL or MB_DEFBUTTON1); + MB_DEFBUTTON1); WAD.SaveTo(OpenDialog.FileName); @@ -5968,7 +6065,7 @@ begin gMapInfo.FileName := SaveDialog.FileName; gMapInfo.MapName := SaveMapForm.eMapName.Text; - UpdateCaption(gMapInfo.Name, ExtractFileName(gMapInfo.FileName), gMapInfo.MapName); + UpdateCaption(win2utf(gMapInfo.Name), ExtractFileName(gMapInfo.FileName), gMapInfo.MapName); end; procedure TMainForm.aSelectAllExecute(Sender: TObject); @@ -6014,6 +6111,19 @@ end; procedure TMainForm.OnIdle(Sender: TObject; var Done: Boolean); begin + // FIXME: this is a shitty hack + if not gDataLoaded then + begin + e_WriteLog('Init OpenGL', MSG_NOTIFY); + e_InitGL(); + e_WriteLog('Loading data', MSG_NOTIFY); + LoadStdFont('STDTXT', 'STDFONT', gEditorFont); + e_WriteLog('Loading more data', MSG_NOTIFY); + LoadData(); + e_WriteLog('Loading even more data', MSG_NOTIFY); + gDataLoaded := True; + MainForm.FormResize(nil); + end; Draw(); end; @@ -6044,6 +6154,8 @@ begin PreviewMode := not PreviewMode; (Sender as TMenuItem).Checked := PreviewMode; + + FormResize(Self); end; procedure TMainForm.miLayer1Click(Sender: TObject); @@ -6176,21 +6288,33 @@ end; procedure TMainForm.miTestMapClick(Sender: TObject); var - cmd, mapWAD, mapToRun: String; + cmd, mapWAD, mapToRun, tempWAD: String; opt: LongWord; time: Integer; - lpMsgBuf: PChar; + proc: TProcessUTF8; + res: Boolean; begin + mapToRun := ''; + if OpenedMap <> '' then + begin + // Указываем текущую карту для теста: + g_ProcessResourceStr(OpenedMap, @mapWAD, nil, @mapToRun); + mapToRun := mapWAD + ':\' + mapToRun; + mapToRun := ExtractRelativePath(ExtractFilePath(TestD2dExe) + 'maps/', mapToRun); + end; // Сохраняем временную карту: time := 0; repeat - mapWAD := ExtractFilePath(TestD2dExe) + Format('maps\temp%.4d.wad', [time]); + mapWAD := ExtractFilePath(TestD2dExe) + Format('maps/temp%.4d.wad', [time]); Inc(time); until not FileExists(mapWAD); - mapToRun := mapWAD + ':\' + TEST_MAP_NAME; - SaveMap(mapToRun); + tempWAD := mapWAD + ':\' + TEST_MAP_NAME; + SaveMap(tempWAD); - mapToRun := ExtractRelativePath(ExtractFilePath(TestD2dExe) + 'maps\', mapToRun); + tempWAD := ExtractRelativePath(ExtractFilePath(TestD2dExe) + 'maps/', tempWAD); +// Если карта не была открыта, указываем временную в качестве текущей: + if mapToRun = '' then + mapToRun := tempWAD; // Опции игры: opt := 32 + 64; @@ -6206,7 +6330,8 @@ begin opt := opt + 16; // Составляем командную строку: - cmd := ' -map "' + mapToRun + '"'; + cmd := '-map "' + mapToRun + '"'; + cmd := cmd + ' -testmap "' + tempWAD + '"'; cmd := cmd + ' -gm ' + TestGameMode; cmd := cmd + ' -limt ' + TestLimTime; cmd := cmd + ' -lims ' + TestLimScore; @@ -6216,19 +6341,29 @@ begin cmd := cmd + ' --close'; cmd := cmd + ' --debug'; - cmd := cmd + ' --tempdelete'; // Запускаем: - Application.Minimize(); - if ExecuteProcess(TestD2dExe, cmd) < 0 then + proc := TProcessUTF8.Create(nil); + proc.Executable := TestD2dExe; + proc.Parameters.Add(cmd); + res := True; + try + proc.Execute(); + except + res := False; + end; + if res then + begin + Application.Minimize(); + proc.WaitOnExit(); + end; + if (not res) or (proc.ExitCode < 0) then begin - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM, - nil, GetLastError(), LANG_SYSTEM_DEFAULT, - @lpMsgBuf, 0, nil); - MessageBox(0, lpMsgBuf, + MessageBox(0, 'FIXME', PChar(_lc[I_MSG_EXEC_ERROR]), MB_OK or MB_ICONERROR); end; + proc.Free(); SysUtils.DeleteFile(mapWAD); Application.Restore(); @@ -6323,26 +6458,4 @@ begin end; end; -{ -procedure TMainForm.lbTextureListDrawItem(Control: TWinControl; Index: Integer; - Rect: TRect; State: LCLType.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(Rect); - Canvas.TextRect(Rect, Rect.Left, Rect.Top, Items[Index]); - end; -end; -} end.