3 {$INCLUDE ../shared/a_modes.inc}
8 LCLIntf
, LCLType
, SysUtils
, Variants
, Classes
, Graphics
,
9 Controls
, Forms
, Dialogs
, StdCtrls
, Buttons
,
10 ComCtrls
, ValEdit
, Types
, Menus
, ExtCtrls
,
11 CheckLst
, Grids
, OpenGLContext
, Utils
, UTF8Process
;
17 TMainForm
= class(TForm
)
22 StatusBar
: TStatusBar
;
23 OpenDialog
: TOpenDialog
;
24 SaveDialog
: TSaveDialog
;
25 ColorDialog
: TColorDialog
;
29 ImageList
: TImageList
;
32 miAppleAbout
: TMenuItem
;
33 miAppleLine0
: TMenuItem
;
34 miApplePref
: TMenuItem
;
35 miAppleLine1
: TMenuItem
;
37 miMenuFile
: TMenuItem
;
40 miMacRecentSubMenu
: TMenuItem
;
41 miMacRecentEnd
: TMenuItem
;
42 miMacRecentClear
: TMenuItem
;
43 Separator1
: TMenuItem
;
45 miSaveMapAs
: TMenuItem
;
46 miOpenWadMap
: TMenuItem
;
48 miReopenMap
: TMenuItem
;
49 miSaveMiniMap
: TMenuItem
;
50 miDeleteMap
: TMenuItem
;
52 miWinRecentStart
: TMenuItem
;
53 miWinRecent
: TMenuItem
;
57 miMenuEdit
: TMenuItem
;
64 miSelectAll
: TMenuItem
;
66 miSnapToGrid
: TMenuItem
;
67 miSwitchGrid
: TMenuItem
;
68 Separator2
: TMenuItem
;
72 miMapOptions
: TMenuItem
;
75 miMenuView
: TMenuItem
;
77 miLayerBackground
: TMenuItem
;
78 miLayerForeground
: TMenuItem
;
79 miLayerWalls
: TMenuItem
;
80 miLayerDoors
: TMenuItem
;
81 miLayersSep1
: TMenuItem
;
82 miLayerLadders
: TMenuItem
;
83 miLayerLiquids
: TMenuItem
;
84 miLayerStreams
: TMenuItem
;
85 miLayerZones
: TMenuItem
;
86 miLayersSep2
: TMenuItem
;
87 miLayerMonsters
: TMenuItem
;
88 miLayerAreas
: TMenuItem
;
89 miLayerItems
: TMenuItem
;
90 miLayerTriggers
: TMenuItem
;
91 miViewLine1
: TMenuItem
;
93 miShowEdges
: TMenuItem
;
94 miViewLine2
: TMenuItem
;
95 miMapPreview
: TMenuItem
;
97 miMenuService
: TMenuItem
;
98 miCheckMap
: TMenuItem
;
99 miOptimmization
: TMenuItem
;
100 miTestMap
: TMenuItem
;
102 miMenuWindow
: TMenuItem
;
103 miMacMinimize
: TMenuItem
;
104 miMacZoom
: TMenuItem
;
106 miMenuHelp
: TMenuItem
;
109 miMenuHidden
: TMenuItem
;
110 minexttab
: TMenuItem
;
111 selectall1
: TMenuItem
;
114 ilToolbar
: TImageList
;
115 MainToolBar
: TToolBar
;
116 tbNewMap
: TToolButton
;
117 tbOpenMap
: TToolButton
;
118 tbSaveMap
: TToolButton
;
119 tbOpenWadMap
: TToolButton
;
120 tbLine1
: TToolButton
;
121 tbShowMap
: TToolButton
;
122 tbLine2
: TToolButton
;
124 tbLine3
: TToolButton
;
125 tbGridOn
: TToolButton
;
127 tbLine4
: TToolButton
;
128 tbTestMap
: TToolButton
;
131 pLoadProgress
: TPanel
;
133 pbLoad
: TProgressBar
;
137 RenderPanel
: TOpenGLControl
;
138 sbHorizontal
: TScrollBar
;
139 sbVertical
: TScrollBar
;
141 // Object propertiy editor:
143 PanelPropApply
: TPanel
;
144 bApplyProperty
: TButton
;
145 vleObjectProperty
: TValueListEditor
;
149 pcObjects
: TPageControl
;
152 PanelPanelType
: TPanel
;
153 lbPanelType
: TListBox
;
154 lbTextureList
: TListBox
;
155 PanelTextures
: TPanel
;
157 lTextureWidth
: TLabel
;
159 lTextureHeight
: TLabel
;
160 cbPreview
: TCheckBox
;
161 bbAddTexture
: TBitBtn
;
162 bbRemoveTexture
: TBitBtn
;
163 bClearTexture
: TButton
;
166 lbItemList
: TListBox
;
170 tsMonsters
: TTabSheet
;
171 lbMonsterList
: TListBox
;
172 rbMonsterLeft
: TRadioButton
;
173 rbMonsterRight
: TRadioButton
;
176 lbAreasList
: TListBox
;
177 rbAreaLeft
: TRadioButton
;
178 rbAreaRight
: TRadioButton
;
180 tsTriggers
: TTabSheet
;
181 lbTriggersList
: TListBox
;
182 clbActivationType
: TCheckListBox
;
183 clbKeys
: TCheckListBox
;
185 procedure aAboutExecute(Sender
: TObject
);
186 procedure aCheckMapExecute(Sender
: TObject
);
187 procedure aMoveToFore(Sender
: TObject
);
188 procedure aMoveToBack(Sender
: TObject
);
189 procedure aCopyObjectExecute(Sender
: TObject
);
190 procedure aCutObjectExecute(Sender
: TObject
);
191 procedure aEditorOptionsExecute(Sender
: TObject
);
192 procedure aExitExecute(Sender
: TObject
);
193 procedure aMapOptionsExecute(Sender
: TObject
);
194 procedure aNewMapExecute(Sender
: TObject
);
195 procedure aOpenMapExecute(Sender
: TObject
);
196 procedure aOptimizeExecute(Sender
: TObject
);
197 procedure aPasteObjectExecute(Sender
: TObject
);
198 procedure aSelectAllExecute(Sender
: TObject
);
199 procedure aSaveMapExecute(Sender
: TObject
);
200 procedure aSaveMapAsExecute(Sender
: TObject
);
201 procedure aUndoExecute(Sender
: TObject
);
202 procedure aDeleteMap(Sender
: TObject
);
203 procedure bApplyPropertyClick(Sender
: TObject
);
204 procedure bbAddTextureClick(Sender
: TObject
);
205 procedure bbRemoveTextureClick(Sender
: TObject
);
206 procedure FormActivate(Sender
: TObject
);
207 procedure FormCloseQuery(Sender
: TObject
; var CanClose
: Boolean);
208 procedure FormCreate(Sender
: TObject
);
209 procedure FormDestroy(Sender
: TObject
);
210 procedure FormDropFiles(Sender
: TObject
; const FileNames
: array of String);
211 procedure FormKeyDown(Sender
: TObject
; var Key
: Word; Shift
: TShiftState
);
212 procedure FormResize(Sender
: TObject
);
213 procedure FormWindowStateChange(Sender
: TObject
);
214 procedure miRecentFileExecute(Sender
: TObject
);
215 procedure miMacRecentClearClick(Sender
: TObject
);
216 procedure miMacZoomClick(Sender
: TObject
);
217 procedure lbTextureListClick(Sender
: TObject
);
218 procedure lbTextureListDrawItem(Control
: TWinControl
; Index
: Integer;
219 ARect
: TRect
; State
: TOwnerDrawState
);
220 procedure miMacMinimizeClick(Sender
: TObject
);
221 procedure miReopenMapClick(Sender
: TObject
);
222 procedure RenderPanelMouseDown(Sender
: TObject
; Button
: TMouseButton
; Shift
: TShiftState
; X
, Y
: Integer);
223 procedure RenderPanelMouseMove(Sender
: TObject
; Shift
: TShiftState
; X
, Y
: Integer);
224 procedure RenderPanelMouseUp(Sender
: TObject
; Button
: TMouseButton
; Shift
: TShiftState
; X
, Y
: Integer);
225 procedure RenderPanelPaint(Sender
: TObject
);
226 procedure RenderPanelResize(Sender
: TObject
);
227 procedure Splitter1Moved(Sender
: TObject
);
228 procedure MapTestCheck(Sender
: TObject
);
229 procedure vleObjectPropertyEditButtonClick(Sender
: TObject
);
230 procedure vleObjectPropertyApply(Sender
: TObject
);
231 procedure vleObjectPropertyGetPickList(Sender
: TObject
; const KeyName
: String; Values
: TStrings
);
232 procedure vleObjectPropertyKeyDown(Sender
: TObject
; var Key
: Word;
234 procedure tbGridOnClick(Sender
: TObject
);
235 procedure miMapPreviewClick(Sender
: TObject
);
236 procedure miLayerClick(Sender
: TObject
);
237 procedure tbShowClick(Sender
: TObject
);
238 procedure miSnapToGridClick(Sender
: TObject
);
239 procedure miMiniMapClick(Sender
: TObject
);
240 procedure miSwitchGridClick(Sender
: TObject
);
241 procedure miShowEdgesClick(Sender
: TObject
);
242 procedure minexttabClick(Sender
: TObject
);
243 procedure miSaveMiniMapClick(Sender
: TObject
);
244 procedure bClearTextureClick(Sender
: TObject
);
245 procedure miPackMapClick(Sender
: TObject
);
246 procedure miTestMapClick(Sender
: TObject
);
247 procedure sbVerticalScroll(Sender
: TObject
; ScrollCode
: TScrollCode
;
248 var ScrollPos
: Integer);
249 procedure sbHorizontalScroll(Sender
: TObject
; ScrollCode
: TScrollCode
;
250 var ScrollPos
: Integer);
251 procedure miOpenWadMapClick(Sender
: TObject
);
252 procedure selectall1Click(Sender
: TObject
);
253 procedure Splitter1CanResize(Sender
: TObject
; var NewSize
: Integer;
254 var Accept
: Boolean);
255 procedure Splitter2CanResize(Sender
: TObject
; var NewSize
: Integer;
256 var Accept
: Boolean);
257 procedure vleObjectPropertyEnter(Sender
: TObject
);
258 procedure vleObjectPropertyExit(Sender
: TObject
);
259 procedure FormKeyUp(Sender
: TObject
; var Key
: Word;
262 LastDrawTime
: UInt64
;
264 procedure OnIdle(Sender
: TObject
; var Done
: Boolean);
265 procedure RefillRecentMenu (menu
: TMenuItem
; start
: Integer; fmt
: AnsiString
);
266 procedure MoveMap(X
, Y
: Integer);
267 procedure FillProperty();
268 procedure SelectObject(fObjectType
: Byte; fID
: DWORD
; Multi
: Boolean);
269 procedure DeleteSelectedObjects();
270 procedure Undo_Add(ObjectType
: Byte; ID
: DWORD
; Group
: Boolean = False);
271 procedure FullClear();
272 function CheckProperty(): Boolean;
273 procedure SelectTexture(ID
: Integer);
274 procedure UpdateCaption(sMap
, sFile
, sRes
: String);
275 procedure SwitchMap();
276 procedure ShowEdges();
277 function SelectedTexture(): String;
278 function IsSpecialTextureSel(): Boolean;
279 procedure InitGraphics();
280 procedure SelectNextObject(X
, Y
: Integer; ObjectType
: Byte; ID
: DWORD
);
282 procedure RefreshRecentMenu();
283 procedure OpenMapFile(FileName
: String);
284 function RenderMousePos(): TPoint
;
285 procedure RecountSelectedObjects();
286 procedure OpenMap(FileName
: String; mapN
: String);
287 function AddTexture(aWAD
, aSection
, aTex
: String; silent
: Boolean): Boolean;
288 procedure RemoveSelectFromObjects();
289 procedure ChangeShownProperty(Name
: String; NewValue
: String);
293 TEST_MAP_NAME
= '$$$_TEST_$$$';
294 LANGUAGE_FILE_NAME
= '_Editor.txt';
297 MainForm
: TMainForm
; // TODO: move to Editor.lpr and rename 'f_main' to 'Main'?
305 DotStepOne
, DotStepTwo
: Word;
307 DrawTexturePanel
: Boolean;
308 DrawPanelSize
: Boolean;
310 PreviewColor
: TColor
;
311 UseCheckerboard
: Boolean;
313 RecentCount
: Integer;
314 RecentFiles
: TStringList
;
315 slInvalidTextures
: TStringList
;
317 TestGameMode
: String;
319 TestLimScore
: String;
320 TestOptionsTwoPlayers
: Boolean;
321 TestOptionsTeamDamage
: Boolean;
322 TestOptionsAllowExit
: Boolean;
323 TestOptionsWeaponStay
: Boolean;
324 TestOptionsMonstersDM
: Boolean;
325 TestD2dExe
, TestD2dArgs
: String;
326 TestMapOnce
: Boolean;
328 PreviewMode
: Byte = 0;
336 f_options
, e_graphics
, e_log
, GL
, Math
,
337 f_mapoptions
, g_basic
, f_about
, f_mapoptimization
,
338 f_mapcheck
, f_addresource_texture
, g_textures
,
339 f_activationtype
, f_keys
, wadreader
, fileutil
,
340 MAPREADER
, f_selectmap
, f_savemap
, WADEDITOR
, WADSTRUCT
, MAPDEF
,
341 g_map
, f_saveminimap
, f_addresource
, CONFIG
, f_packmap
,
342 f_addresource_sound
, f_choosetype
,
343 g_language
, ClipBrd
, g_options
;
346 UNDO_DELETE_PANEL
= 1;
347 UNDO_DELETE_ITEM
= 2;
348 UNDO_DELETE_AREA
= 3;
349 UNDO_DELETE_MONSTER
= 4;
350 UNDO_DELETE_TRIGGER
= 5;
354 UNDO_ADD_MONSTER
= 9;
355 UNDO_ADD_TRIGGER
= 10;
356 UNDO_MOVE_PANEL
= 11;
359 UNDO_MOVE_MONSTER
= 14;
360 UNDO_MOVE_TRIGGER
= 15;
361 UNDO_RESIZE_PANEL
= 16;
362 UNDO_RESIZE_TRIGGER
= 17;
364 MOUSEACTION_NONE
= 0;
365 MOUSEACTION_DRAWPANEL
= 1;
366 MOUSEACTION_DRAWTRIGGER
= 2;
367 MOUSEACTION_MOVEOBJ
= 3;
368 MOUSEACTION_RESIZE
= 4;
369 MOUSEACTION_MOVEMAP
= 5;
370 MOUSEACTION_DRAWPRESS
= 6;
371 MOUSEACTION_NOACTION
= 7;
374 RESIZETYPE_VERTICAL
= 1;
375 RESIZETYPE_HORIZONTAL
= 2;
384 SELECTFLAG_TELEPORT
= 1;
386 SELECTFLAG_TEXTURE
= 3;
388 SELECTFLAG_MONSTER
= 5;
389 SELECTFLAG_SPAWNPOINT
= 6;
390 SELECTFLAG_SHOTPANEL
= 7;
391 SELECTFLAG_SELECTED
= 8;
393 RECENT_FILES_MENU_START
= 12;
395 CLIPBOARD_SIG
= 'DF:ED';
399 case UndoType
: Byte of
400 UNDO_DELETE_PANEL
: (Panel
: ^TPanel
);
401 UNDO_DELETE_ITEM
: (Item
: TItem
);
402 UNDO_DELETE_AREA
: (Area
: TArea
);
403 UNDO_DELETE_MONSTER
: (Monster
: TMonster
);
404 UNDO_DELETE_TRIGGER
: (Trigger
: TTrigger
);
409 UNDO_ADD_TRIGGER
: (AddID
: DWORD
);
414 UNDO_MOVE_TRIGGER
: (MoveID
: DWORD
; dX
, dY
: Integer);
416 UNDO_RESIZE_TRIGGER
: (ResizeID
: DWORD
; dW
, dH
: Integer);
421 case ObjectType
: Byte of
422 OBJECT_PANEL
: (Panel
: ^TPanel
);
423 OBJECT_ITEM
: (Item
: TItem
);
424 OBJECT_AREA
: (Area
: TArea
);
425 OBJECT_MONSTER
: (Monster
: TMonster
);
426 OBJECT_TRIGGER
: (Trigger
: TTrigger
);
429 TCopyRecArray
= Array of TCopyRec
;
433 gDataLoaded
: Boolean = False;
434 ShowMap
: Boolean = False;
435 DrawRect
: PRect
= nil;
436 SnapToGrid
: Boolean = True;
438 MousePos
: Types
.TPoint
;
439 LastMovePoint
: Types
.TPoint
;
443 MouseLDownPos
: Types
.TPoint
;
444 MouseRDownPos
: Types
.TPoint
;
445 MouseMDownPos
: Types
.TPoint
;
447 SelectFlag
: Byte = SELECTFLAG_NONE
;
448 MouseAction
: Byte = MOUSEACTION_NONE
;
449 ResizeType
: Byte = RESIZETYPE_NONE
;
450 ResizeDirection
: Byte = RESIZEDIR_NONE
;
452 DrawPressRect
: Boolean = False;
453 EditingProperties
: Boolean = False;
455 UndoBuffer
: Array of Array of TUndoRec
= nil;
457 MapTestProcess
: TProcessUTF8
;
462 //----------------------------------------
463 //Далее идут вспомогательные процедуры
464 //----------------------------------------
466 function NameToBool(Name
: String): Boolean;
468 if Name
= BoolNames
[True] then
474 function NameToDir(Name
: String): TDirection
;
476 if Name
= DirNames
[D_LEFT
] then
482 function NameToDirAdv(Name
: String): Byte;
484 if Name
= DirNamesAdv
[1] then
487 if Name
= DirNamesAdv
[2] then
490 if Name
= DirNamesAdv
[3] then
496 function ActivateToStr(ActivateType
: Byte): String;
500 if ByteBool(ACTIVATE_PLAYERCOLLIDE
and ActivateType
) then
501 Result
:= Result
+ '+PC';
502 if ByteBool(ACTIVATE_MONSTERCOLLIDE
and ActivateType
) then
503 Result
:= Result
+ '+MC';
504 if ByteBool(ACTIVATE_PLAYERPRESS
and ActivateType
) then
505 Result
:= Result
+ '+PP';
506 if ByteBool(ACTIVATE_MONSTERPRESS
and ActivateType
) then
507 Result
:= Result
+ '+MP';
508 if ByteBool(ACTIVATE_SHOT
and ActivateType
) then
509 Result
:= Result
+ '+SH';
510 if ByteBool(ACTIVATE_NOMONSTER
and ActivateType
) then
511 Result
:= Result
+ '+NM';
513 if (Result
<> '') and (Result
[1] = '+') then
514 Delete(Result
, 1, 1);
517 function StrToActivate(Str
: String): Byte;
521 if Pos('PC', Str
) > 0 then
522 Result
:= ACTIVATE_PLAYERCOLLIDE
;
523 if Pos('MC', Str
) > 0 then
524 Result
:= Result
or ACTIVATE_MONSTERCOLLIDE
;
525 if Pos('PP', Str
) > 0 then
526 Result
:= Result
or ACTIVATE_PLAYERPRESS
;
527 if Pos('MP', Str
) > 0 then
528 Result
:= Result
or ACTIVATE_MONSTERPRESS
;
529 if Pos('SH', Str
) > 0 then
530 Result
:= Result
or ACTIVATE_SHOT
;
531 if Pos('NM', Str
) > 0 then
532 Result
:= Result
or ACTIVATE_NOMONSTER
;
535 function KeyToStr(Key
: Byte): String;
539 if ByteBool(KEY_RED
and Key
) then
540 Result
:= Result
+ '+RK';
541 if ByteBool(KEY_GREEN
and Key
) then
542 Result
:= Result
+ '+GK';
543 if ByteBool(KEY_BLUE
and Key
) then
544 Result
:= Result
+ '+BK';
545 if ByteBool(KEY_REDTEAM
and Key
) then
546 Result
:= Result
+ '+RT';
547 if ByteBool(KEY_BLUETEAM
and Key
) then
548 Result
:= Result
+ '+BT';
550 if (Result
<> '') and (Result
[1] = '+') then
551 Delete(Result
, 1, 1);
554 function StrToKey(Str
: String): Byte;
558 if Pos('RK', Str
) > 0 then
560 if Pos('GK', Str
) > 0 then
561 Result
:= Result
or KEY_GREEN
;
562 if Pos('BK', Str
) > 0 then
563 Result
:= Result
or KEY_BLUE
;
564 if Pos('RT', Str
) > 0 then
565 Result
:= Result
or KEY_REDTEAM
;
566 if Pos('BT', Str
) > 0 then
567 Result
:= Result
or KEY_BLUETEAM
;
570 function EffectToStr(Effect
: Byte): String;
572 if Effect
in [EFFECT_TELEPORT
..EFFECT_FIRE
] then
573 Result
:= EffectNames
[Effect
]
575 Result
:= EffectNames
[EFFECT_NONE
];
578 function StrToEffect(Str
: String): Byte;
582 Result
:= EFFECT_NONE
;
583 for i
:= EFFECT_TELEPORT
to EFFECT_FIRE
do
584 if EffectNames
[i
] = Str
then
591 function MonsterToStr(MonType
: Byte): String;
593 if MonType
in [MONSTER_DEMON
..MONSTER_MAN
] then
594 Result
:= MonsterNames
[MonType
]
596 Result
:= MonsterNames
[MONSTER_ZOMBY
];
599 function StrToMonster(Str
: String): Byte;
603 Result
:= MONSTER_ZOMBY
;
604 for i
:= MONSTER_DEMON
to MONSTER_MAN
do
605 if MonsterNames
[i
] = Str
then
612 function ItemToStr(ItemType
: Byte): String;
614 if ItemType
in [ITEM_MEDKIT_SMALL
..ITEM_MAX
] then
615 Result
:= ItemNames
[ItemType
]
617 Result
:= ItemNames
[ITEM_AMMO_BULLETS
];
620 function StrToItem(Str
: String): Byte;
624 Result
:= ITEM_AMMO_BULLETS
;
625 for i
:= ITEM_MEDKIT_SMALL
to ITEM_MAX
do
626 if ItemNames
[i
] = Str
then
633 function ShotToStr(ShotType
: Byte): String;
635 if ShotType
in [TRIGGER_SHOT_PISTOL
..TRIGGER_SHOT_MAX
] then
636 Result
:= ShotNames
[ShotType
]
638 Result
:= ShotNames
[TRIGGER_SHOT_PISTOL
];
641 function StrToShot(Str
: String): Byte;
645 Result
:= TRIGGER_SHOT_PISTOL
;
646 for i
:= TRIGGER_SHOT_PISTOL
to TRIGGER_SHOT_MAX
do
647 if ShotNames
[i
] = Str
then
654 function SelectedObjectCount(): Word;
660 if SelectedObjects
= nil then
663 for a
:= 0 to High(SelectedObjects
) do
664 if SelectedObjects
[a
].Live
then
665 Result
:= Result
+ 1;
668 function GetFirstSelected(): Integer;
674 if SelectedObjects
= nil then
677 for a
:= 0 to High(SelectedObjects
) do
678 if SelectedObjects
[a
].Live
then
685 function Normalize16(x
: Integer): Integer;
687 Result
:= (x
div 16) * 16;
690 procedure TMainForm
.MoveMap(X
, Y
: Integer);
692 rx
, ry
, ScaleSz
: Integer;
696 ScaleSz
:= 16 div Scale
;
697 // Размер видимой части карты:
698 rx
:= Min(Normalize16(Width
), Normalize16(gMapInfo
.Width
)) div 2;
699 ry
:= Min(Normalize16(Height
), Normalize16(gMapInfo
.Height
)) div 2;
700 // Место клика на мини-карте:
701 MapOffset
.X
:= X
- (Width
- Max(gMapInfo
.Width
div ScaleSz
, 1) - 1);
702 MapOffset
.Y
:= Y
- 1;
703 // Это же место на "большой" карте:
704 MapOffset
.X
:= MapOffset
.X
* ScaleSz
;
705 MapOffset
.Y
:= MapOffset
.Y
* ScaleSz
;
706 // Левый верхний угол новой видимой части карты:
707 MapOffset
.X
:= MapOffset
.X
- rx
;
708 MapOffset
.Y
:= MapOffset
.Y
- ry
;
710 MapOffset
.X
:= EnsureRange(MapOffset
.X
, sbHorizontal
.Min
, sbHorizontal
.Max
);
711 MapOffset
.Y
:= EnsureRange(MapOffset
.Y
, sbVertical
.Min
, sbVertical
.Max
);
713 // MapOffset.X := Normalize16(MapOffset.X);
714 // MapOffset.Y := Normalize16(MapOffset.Y);
717 sbHorizontal
.Position
:= MapOffset
.X
;
718 sbVertical
.Position
:= MapOffset
.Y
;
720 MapOffset
.X
:= -MapOffset
.X
;
721 MapOffset
.Y
:= -MapOffset
.Y
;
726 function IsTexturedPanel(PanelType
: Word): Boolean;
728 Result
:= WordBool(PanelType
and (PANEL_WALL
or PANEL_BACK
or PANEL_FORE
or
729 PANEL_LADDER
or PANEL_OPENDOOR
or PANEL_CLOSEDOOR
or
730 PANEL_WATER
or PANEL_ACID1
or PANEL_ACID2
));
733 procedure TMainForm
.FillProperty();
738 vleObjectProperty
.Strings
.Clear();
739 RecountSelectedObjects();
741 // Отображаем свойства если выделен только один объект:
742 if SelectedObjectCount() <> 1 then
745 _id
:= GetFirstSelected();
746 if not SelectedObjects
[_id
].Live
then
749 with vleObjectProperty
do
750 with ItemProps
[InsertRow(MsgPropId
, IntToStr(SelectedObjects
[_id
].ID
), True)] do
752 EditStyle
:= esSimple
;
756 case SelectedObjects
[0].ObjectType
of
759 with vleObjectProperty
,
760 gPanels
[SelectedObjects
[_id
].ID
] do
762 with ItemProps
[InsertRow(MsgPropX
, IntToStr(X
), True)] do
764 EditStyle
:= esSimple
;
768 with ItemProps
[InsertRow(MsgPropY
, IntToStr(Y
), True)] do
770 EditStyle
:= esSimple
;
774 with ItemProps
[InsertRow(MsgPropWidth
, IntToStr(Width
), True)] do
776 EditStyle
:= esSimple
;
780 with ItemProps
[InsertRow(MsgPropHeight
, IntToStr(Height
), True)] do
782 EditStyle
:= esSimple
;
786 with ItemProps
[InsertRow(MsgPropPanelType
, GetPanelName(PanelType
), True)] do
788 EditStyle
:= esEllipsis
;
792 if IsTexturedPanel(PanelType
) then
793 begin // Может быть текстура
794 with ItemProps
[InsertRow(MsgPropPanelTex
, TextureName
, True)] do
796 EditStyle
:= esEllipsis
;
800 if TextureName
<> '' then
801 begin // Есть текстура
802 with ItemProps
[InsertRow(MsgPropPanelAlpha
, IntToStr(Alpha
), True)] do
804 EditStyle
:= esSimple
;
808 with ItemProps
[InsertRow(MsgPropPanelBlend
, BoolNames
[Blending
], True)] do
810 EditStyle
:= esPickList
;
820 with vleObjectProperty
,
821 gItems
[SelectedObjects
[_id
].ID
] do
823 with ItemProps
[InsertRow(MsgPropX
, IntToStr(X
), True)] do
825 EditStyle
:= esSimple
;
829 with ItemProps
[InsertRow(MsgPropY
, IntToStr(Y
), True)] do
831 EditStyle
:= esSimple
;
835 with ItemProps
[InsertRow(MsgPropDmOnly
, BoolNames
[OnlyDM
], True)] do
837 EditStyle
:= esPickList
;
841 with ItemProps
[InsertRow(MsgPropItemFalls
, BoolNames
[Fall
], True)] do
843 EditStyle
:= esPickList
;
851 with vleObjectProperty
,
852 gMonsters
[SelectedObjects
[_id
].ID
] do
854 with ItemProps
[InsertRow(MsgPropX
, IntToStr(X
), True)] do
856 EditStyle
:= esSimple
;
860 with ItemProps
[InsertRow(MsgPropY
, IntToStr(Y
), True)] do
862 EditStyle
:= esSimple
;
866 with ItemProps
[InsertRow(MsgPropDirection
, DirNames
[Direction
], True)] do
868 EditStyle
:= esPickList
;
876 with vleObjectProperty
,
877 gAreas
[SelectedObjects
[_id
].ID
] do
879 with ItemProps
[InsertRow(MsgPropX
, IntToStr(X
), True)] do
881 EditStyle
:= esSimple
;
885 with ItemProps
[InsertRow(MsgPropY
, IntToStr(Y
), True)] do
887 EditStyle
:= esSimple
;
891 with ItemProps
[InsertRow(MsgPropDirection
, DirNames
[Direction
], True)] do
893 EditStyle
:= esPickList
;
901 with vleObjectProperty
,
902 gTriggers
[SelectedObjects
[_id
].ID
] do
904 with ItemProps
[InsertRow(MsgPropTrType
, GetTriggerName(TriggerType
), True)] do
906 EditStyle
:= esSimple
;
910 with ItemProps
[InsertRow(MsgPropX
, IntToStr(X
), True)] do
912 EditStyle
:= esSimple
;
916 with ItemProps
[InsertRow(MsgPropY
, IntToStr(Y
), True)] do
918 EditStyle
:= esSimple
;
922 with ItemProps
[InsertRow(MsgPropWidth
, IntToStr(Width
), True)] do
924 EditStyle
:= esSimple
;
928 with ItemProps
[InsertRow(MsgPropHeight
, IntToStr(Height
), True)] do
930 EditStyle
:= esSimple
;
934 with ItemProps
[InsertRow(MsgPropTrEnabled
, BoolNames
[Enabled
], True)] do
936 EditStyle
:= esPickList
;
940 with ItemProps
[InsertRow(MsgPropTrTexturePanel
, IntToStr(TexturePanel
), True)] do
942 EditStyle
:= esEllipsis
;
946 with ItemProps
[InsertRow(MsgPropTrActivation
, ActivateToStr(ActivateType
), True)] do
948 EditStyle
:= esEllipsis
;
952 with ItemProps
[InsertRow(MsgPropTrKeys
, KeyToStr(Key
), True)] do
954 EditStyle
:= esEllipsis
;
961 str
:= win2utf(Data
.MapName
);
962 with ItemProps
[InsertRow(MsgPropTrNextMap
, str
, True)] do
964 EditStyle
:= esEllipsis
;
971 with ItemProps
[InsertRow(MsgPropTrTeleportTo
, Format('(%d:%d)', [Data
.TargetPoint
.X
, Data
.TargetPoint
.Y
]), True)] do
973 EditStyle
:= esEllipsis
;
977 with ItemProps
[InsertRow(MsgPropTrD2d
, BoolNames
[Data
.d2d_teleport
], True)] do
979 EditStyle
:= esPickList
;
983 with ItemProps
[InsertRow(MsgPropTrTeleportSilent
, BoolNames
[Data
.silent_teleport
], True)] do
985 EditStyle
:= esPickList
;
989 with ItemProps
[InsertRow(MsgPropTrTeleportDir
, DirNamesAdv
[Data
.TlpDir
], True)] do
991 EditStyle
:= esPickList
;
996 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
,
997 TRIGGER_DOOR
, TRIGGER_DOOR5
:
999 with ItemProps
[InsertRow(MsgPropTrDoorPanel
, IntToStr(Data
.PanelID
), True)] do
1001 EditStyle
:= esEllipsis
;
1005 with ItemProps
[InsertRow(MsgPropTrSilent
, BoolNames
[Data
.NoSound
], True)] do
1007 EditStyle
:= esPickList
;
1011 with ItemProps
[InsertRow(MsgPropTrD2d
, BoolNames
[Data
.d2d_doors
], True)] do
1013 EditStyle
:= esPickList
;
1018 TRIGGER_CLOSETRAP
, TRIGGER_TRAP
:
1020 with ItemProps
[InsertRow(MsgPropTrTrapPanel
, IntToStr(Data
.PanelID
), True)] do
1022 EditStyle
:= esEllipsis
;
1026 with ItemProps
[InsertRow(MsgPropTrSilent
, BoolNames
[Data
.NoSound
], True)] do
1028 EditStyle
:= esPickList
;
1032 with ItemProps
[InsertRow(MsgPropTrD2d
, BoolNames
[Data
.d2d_doors
], True)] do
1034 EditStyle
:= esPickList
;
1039 TRIGGER_PRESS
, TRIGGER_ON
, TRIGGER_OFF
,
1042 with ItemProps
[InsertRow(MsgPropTrExArea
,
1043 Format('(%d:%d %d:%d)', [Data
.tX
, Data
.tY
, Data
.tWidth
, Data
.tHeight
]), True)] do
1045 EditStyle
:= esEllipsis
;
1049 with ItemProps
[InsertRow(MsgPropTrExDelay
, IntToStr(Data
.Wait
), True)] do
1051 EditStyle
:= esSimple
;
1055 with ItemProps
[InsertRow(MsgPropTrExCount
, IntToStr(Data
.Count
), True)] do
1057 EditStyle
:= esSimple
;
1061 with ItemProps
[InsertRow(MsgPropTrExMonster
, IntToStr(Data
.MonsterID
-1), True)] do
1063 EditStyle
:= esEllipsis
;
1067 if TriggerType
= TRIGGER_PRESS
then
1068 with ItemProps
[InsertRow(MsgPropTrExRandom
, BoolNames
[Data
.ExtRandom
], True)] do
1070 EditStyle
:= esPickList
;
1078 TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
:
1080 with ItemProps
[InsertRow(MsgPropTrLiftPanel
, IntToStr(Data
.PanelID
), True)] do
1082 EditStyle
:= esEllipsis
;
1086 with ItemProps
[InsertRow(MsgPropTrSilent
, BoolNames
[Data
.NoSound
], True)] do
1088 EditStyle
:= esPickList
;
1092 with ItemProps
[InsertRow(MsgPropTrD2d
, BoolNames
[Data
.d2d_doors
], True)] do
1094 EditStyle
:= esPickList
;
1101 with ItemProps
[InsertRow(MsgPropTrTextureOnce
, BoolNames
[Data
.ActivateOnce
], True)] do
1103 EditStyle
:= esPickList
;
1107 with ItemProps
[InsertRow(MsgPropTrTextureAnimOnce
, BoolNames
[Data
.AnimOnce
], True)] do
1109 EditStyle
:= esPickList
;
1116 str
:= win2utf(Data
.SoundName
);
1117 with ItemProps
[InsertRow(MsgPropTrSoundName
, str
, True)] do
1119 EditStyle
:= esEllipsis
;
1123 with ItemProps
[InsertRow(MsgPropTrSoundVolume
, IntToStr(Data
.Volume
), True)] do
1125 EditStyle
:= esSimple
;
1129 with ItemProps
[InsertRow(MsgPropTrSoundPan
, IntToStr(Data
.Pan
), True)] do
1131 EditStyle
:= esSimple
;
1135 with ItemProps
[InsertRow(MsgPropTrSoundCount
, IntToStr(Data
.PlayCount
), True)] do
1137 EditStyle
:= esSimple
;
1141 with ItemProps
[InsertRow(MsgPropTrSoundLocal
, BoolNames
[Data
.Local
], True)] do
1143 EditStyle
:= esPickList
;
1147 with ItemProps
[InsertRow(MsgPropTrSoundSwitch
, BoolNames
[Data
.SoundSwitch
], True)] do
1149 EditStyle
:= esPickList
;
1154 TRIGGER_SPAWNMONSTER
:
1156 with ItemProps
[InsertRow(MsgPropTrMonsterType
, MonsterToStr(Data
.MonType
), True)] do
1158 EditStyle
:= esEllipsis
;
1162 with ItemProps
[InsertRow(MsgPropTrSpawnTo
,
1163 Format('(%d:%d)', [Data
.MonPos
.X
, Data
.MonPos
.Y
]), True)] do
1165 EditStyle
:= esEllipsis
;
1169 with ItemProps
[InsertRow(MsgPropDirection
, DirNames
[TDirection(Data
.MonDir
)], True)] do
1171 EditStyle
:= esPickList
;
1175 with ItemProps
[InsertRow(MsgPropTrHealth
, IntToStr(Data
.MonHealth
), True)] do
1177 EditStyle
:= esSimple
;
1181 with ItemProps
[InsertRow(MsgPropTrMonsterActive
, BoolNames
[Data
.MonActive
], True)] do
1183 EditStyle
:= esPickList
;
1187 with ItemProps
[InsertRow(MsgPropTrCount
, IntToStr(Data
.MonCount
), True)] do
1189 EditStyle
:= esSimple
;
1193 with ItemProps
[InsertRow(MsgPropTrFxType
, EffectToStr(Data
.MonEffect
), True)] do
1195 EditStyle
:= esEllipsis
;
1199 with ItemProps
[InsertRow(MsgPropTrSpawnMax
, IntToStr(Data
.MonMax
), True)] do
1201 EditStyle
:= esSimple
;
1205 with ItemProps
[InsertRow(MsgPropTrSpawnDelay
, IntToStr(Data
.MonDelay
), True)] do
1207 EditStyle
:= esSimple
;
1211 case Data
.MonBehav
of
1212 1: str
:= MsgPropTrMonsterBehaviour1
;
1213 2: str
:= MsgPropTrMonsterBehaviour2
;
1214 3: str
:= MsgPropTrMonsterBehaviour3
;
1215 4: str
:= MsgPropTrMonsterBehaviour4
;
1216 5: str
:= MsgPropTrMonsterBehaviour5
;
1217 else str
:= MsgPropTrMonsterBehaviour0
;
1219 with ItemProps
[InsertRow(MsgPropTrMonsterBehaviour
, str
, True)] do
1221 EditStyle
:= esPickList
;
1228 with ItemProps
[InsertRow(MsgPropTrItemType
, ItemToStr(Data
.ItemType
), True)] do
1230 EditStyle
:= esEllipsis
;
1234 with ItemProps
[InsertRow(MsgPropTrSpawnTo
,
1235 Format('(%d:%d)', [Data
.ItemPos
.X
, Data
.ItemPos
.Y
]), True)] do
1237 EditStyle
:= esEllipsis
;
1241 with ItemProps
[InsertRow(MsgPropDmOnly
, BoolNames
[Data
.ItemOnlyDM
], True)] do
1243 EditStyle
:= esPickList
;
1247 with ItemProps
[InsertRow(MsgPropItemFalls
, BoolNames
[Data
.ItemFalls
], True)] do
1249 EditStyle
:= esPickList
;
1253 with ItemProps
[InsertRow(MsgPropTrCount
, IntToStr(Data
.ItemCount
), True)] do
1255 EditStyle
:= esSimple
;
1259 with ItemProps
[InsertRow(MsgPropTrFxType
, EffectToStr(Data
.ItemEffect
), True)] do
1261 EditStyle
:= esEllipsis
;
1265 with ItemProps
[InsertRow(MsgPropTrSpawnMax
, IntToStr(Data
.ItemMax
), True)] do
1267 EditStyle
:= esSimple
;
1271 with ItemProps
[InsertRow(MsgPropTrSpawnDelay
, IntToStr(Data
.ItemDelay
), True)] do
1273 EditStyle
:= esSimple
;
1280 str
:= win2utf(Data
.MusicName
);
1281 with ItemProps
[InsertRow(MsgPropTrMusicName
, str
, True)] do
1283 EditStyle
:= esEllipsis
;
1287 if Data
.MusicAction
= 1 then
1288 str
:= MsgPropTrMusicOn
1290 str
:= MsgPropTrMusicOff
;
1292 with ItemProps
[InsertRow(MsgPropTrMusicAct
, str
, True)] do
1294 EditStyle
:= esPickList
;
1301 with ItemProps
[InsertRow(MsgPropTrPushAngle
, IntToStr(Data
.PushAngle
), True)] do
1303 EditStyle
:= esSimple
;
1306 with ItemProps
[InsertRow(MsgPropTrPushForce
, IntToStr(Data
.PushForce
), True)] do
1308 EditStyle
:= esSimple
;
1311 with ItemProps
[InsertRow(MsgPropTrPushReset
, BoolNames
[Data
.ResetVel
], True)] do
1313 EditStyle
:= esPickList
;
1320 case Data
.ScoreAction
of
1321 1: str
:= MsgPropTrScoreAct1
;
1322 2: str
:= MsgPropTrScoreAct2
;
1323 3: str
:= MsgPropTrScoreAct3
;
1324 else str
:= MsgPropTrScoreAct0
;
1326 with ItemProps
[InsertRow(MsgPropTrScoreAct
, str
, True)] do
1328 EditStyle
:= esPickList
;
1331 with ItemProps
[InsertRow(MsgPropTrCount
, IntToStr(Data
.ScoreCount
), True)] do
1333 EditStyle
:= esSimple
;
1336 case Data
.ScoreTeam
of
1337 1: str
:= MsgPropTrScoreTeam1
;
1338 2: str
:= MsgPropTrScoreTeam2
;
1339 3: str
:= MsgPropTrScoreTeam3
;
1340 else str
:= MsgPropTrScoreTeam0
;
1342 with ItemProps
[InsertRow(MsgPropTrScoreTeam
, str
, True)] do
1344 EditStyle
:= esPickList
;
1347 with ItemProps
[InsertRow(MsgPropTrScoreCon
, BoolNames
[Data
.ScoreCon
], True)] do
1349 EditStyle
:= esPickList
;
1352 with ItemProps
[InsertRow(MsgPropTrScoreMsg
, BoolNames
[Data
.ScoreMsg
], True)] do
1354 EditStyle
:= esPickList
;
1361 case Data
.MessageKind
of
1362 1: str
:= MsgPropTrMessageKind1
;
1363 else str
:= MsgPropTrMessageKind0
;
1365 with ItemProps
[InsertRow(MsgPropTrMessageKind
, str
, True)] do
1367 EditStyle
:= esPickList
;
1370 case Data
.MessageSendTo
of
1371 1: str
:= MsgPropTrMessageTo1
;
1372 2: str
:= MsgPropTrMessageTo2
;
1373 3: str
:= MsgPropTrMessageTo3
;
1374 4: str
:= MsgPropTrMessageTo4
;
1375 5: str
:= MsgPropTrMessageTo5
;
1376 else str
:= MsgPropTrMessageTo0
;
1378 with ItemProps
[InsertRow(MsgPropTrMessageTo
, str
, True)] do
1380 EditStyle
:= esPickList
;
1383 str
:= win2utf(Data
.MessageText
);
1384 with ItemProps
[InsertRow(MsgPropTrMessageText
, str
, True)] do
1386 EditStyle
:= esSimple
;
1389 with ItemProps
[InsertRow(MsgPropTrMessageTime
, IntToStr(Data
.MessageTime
), True)] do
1391 EditStyle
:= esSimple
;
1398 with ItemProps
[InsertRow(MsgPropTrDamageValue
, IntToStr(Data
.DamageValue
), True)] do
1400 EditStyle
:= esSimple
;
1403 with ItemProps
[InsertRow(MsgPropTrInterval
, IntToStr(Data
.DamageInterval
), True)] do
1405 EditStyle
:= esSimple
;
1408 case Data
.DamageKind
of
1409 3: str
:= MsgPropTrDamageKind3
;
1410 4: str
:= MsgPropTrDamageKind4
;
1411 5: str
:= MsgPropTrDamageKind5
;
1412 6: str
:= MsgPropTrDamageKind6
;
1413 7: str
:= MsgPropTrDamageKind7
;
1414 8: str
:= MsgPropTrDamageKind8
;
1415 else str
:= MsgPropTrDamageKind0
;
1417 with ItemProps
[InsertRow(MsgPropTrDamageKind
, str
, True)] do
1419 EditStyle
:= esPickList
;
1426 with ItemProps
[InsertRow(MsgPropTrHealth
, IntToStr(Data
.HealValue
), True)] do
1428 EditStyle
:= esSimple
;
1431 with ItemProps
[InsertRow(MsgPropTrInterval
, IntToStr(Data
.HealInterval
), True)] do
1433 EditStyle
:= esSimple
;
1436 with ItemProps
[InsertRow(MsgPropTrHealthMax
, BoolNames
[Data
.HealMax
], True)] do
1438 EditStyle
:= esPickList
;
1441 with ItemProps
[InsertRow(MsgPropTrSilent
, BoolNames
[Data
.HealSilent
], True)] do
1443 EditStyle
:= esPickList
;
1450 with ItemProps
[InsertRow(MsgPropTrShotType
, ShotToStr(Data
.ShotType
), True)] do
1452 EditStyle
:= esEllipsis
;
1456 with ItemProps
[InsertRow(MsgPropTrShotSound
, BoolNames
[Data
.ShotSound
], True)] do
1458 EditStyle
:= esPickList
;
1462 with ItemProps
[InsertRow(MsgPropTrShotPanel
, IntToStr(Data
.ShotPanelID
), True)] do
1464 EditStyle
:= esEllipsis
;
1468 case Data
.ShotTarget
of
1469 1: str
:= MsgPropTrShotTo1
;
1470 2: str
:= MsgPropTrShotTo2
;
1471 3: str
:= MsgPropTrShotTo3
;
1472 4: str
:= MsgPropTrShotTo4
;
1473 5: str
:= MsgPropTrShotTo5
;
1474 6: str
:= MsgPropTrShotTo6
;
1475 else str
:= MsgPropTrShotTo0
;
1477 with ItemProps
[InsertRow(MsgPropTrShotTo
, str
, True)] do
1479 EditStyle
:= esPickList
;
1483 with ItemProps
[InsertRow(MsgPropTrShotSight
, IntToStr(Data
.ShotIntSight
), True)] do
1485 EditStyle
:= esSimple
;
1489 case Data
.ShotAim
of
1490 1: str
:= MsgPropTrShotAim1
;
1491 2: str
:= MsgPropTrShotAim2
;
1492 3: str
:= MsgPropTrShotAim3
;
1493 else str
:= MsgPropTrShotAim0
;
1495 with ItemProps
[InsertRow(MsgPropTrShotAim
, str
, True)] do
1497 EditStyle
:= esPickList
;
1501 with ItemProps
[InsertRow(MsgPropTrSpawnTo
,
1502 Format('(%d:%d)', [Data
.ShotPos
.X
, Data
.ShotPos
.Y
]), True)] do
1504 EditStyle
:= esEllipsis
;
1508 with ItemProps
[InsertRow(MsgPropTrShotAngle
, IntToStr(Data
.ShotAngle
), True)] do
1510 EditStyle
:= esSimple
;
1514 with ItemProps
[InsertRow(MsgPropTrExDelay
, IntToStr(Data
.ShotWait
), True)] do
1516 EditStyle
:= esSimple
;
1520 with ItemProps
[InsertRow(MsgPropTrShotAcc
, IntToStr(Data
.ShotAccuracy
), True)] do
1522 EditStyle
:= esSimple
;
1526 with ItemProps
[InsertRow(MsgPropTrShotAmmo
, IntToStr(Data
.ShotAmmo
), True)] do
1528 EditStyle
:= esSimple
;
1532 with ItemProps
[InsertRow(MsgPropTrShotReload
, IntToStr(Data
.ShotIntReload
), True)] do
1534 EditStyle
:= esSimple
;
1541 with ItemProps
[InsertRow(MsgPropTrCount
, IntToStr(Data
.FXCount
), True)] do
1543 EditStyle
:= esSimple
;
1547 if Data
.FXType
= 0 then
1548 str
:= MsgPropTrEffectParticle
1550 str
:= MsgPropTrEffectAnimation
;
1551 with ItemProps
[InsertRow(MsgPropTrEffectType
, str
, True)] do
1553 EditStyle
:= esEllipsis
;
1558 if Data
.FXType
= 0 then
1559 case Data
.FXSubType
of
1560 TRIGGER_EFFECT_SLIQUID
:
1561 str
:= MsgPropTrEffectSliquid
;
1562 TRIGGER_EFFECT_LLIQUID
:
1563 str
:= MsgPropTrEffectLliquid
;
1564 TRIGGER_EFFECT_DLIQUID
:
1565 str
:= MsgPropTrEffectDliquid
;
1566 TRIGGER_EFFECT_BLOOD
:
1567 str
:= MsgPropTrEffectBlood
;
1568 TRIGGER_EFFECT_SPARK
:
1569 str
:= MsgPropTrEffectSpark
;
1570 TRIGGER_EFFECT_BUBBLE
:
1571 str
:= MsgPropTrEffectBubble
;
1573 if Data
.FXType
= 1 then
1575 if (Data
.FXSubType
= 0) or (Data
.FXSubType
> EFFECT_FIRE
) then
1576 Data
.FXSubType
:= EFFECT_TELEPORT
;
1577 str
:= EffectToStr(Data
.FXSubType
);
1579 with ItemProps
[InsertRow(MsgPropTrEffectSubtype
, str
, True)] do
1581 EditStyle
:= esEllipsis
;
1585 with ItemProps
[InsertRow(MsgPropTrEffectColor
, IntToStr(Data
.FXColorR
or (Data
.FXColorG
shl 8) or (Data
.FXColorB
shl 16)), True)] do
1587 EditStyle
:= esEllipsis
;
1591 with ItemProps
[InsertRow(MsgPropTrEffectCenter
, BoolNames
[Data
.FXPos
= 0], True)] do
1593 EditStyle
:= esPickList
;
1597 with ItemProps
[InsertRow(MsgPropTrExDelay
, IntToStr(Data
.FXWait
), True)] do
1599 EditStyle
:= esSimple
;
1603 with ItemProps
[InsertRow(MsgPropTrEffectVelx
, IntToStr(Data
.FXVelX
), True)] do
1605 EditStyle
:= esSimple
;
1609 with ItemProps
[InsertRow(MsgPropTrEffectVely
, IntToStr(Data
.FXVelY
), True)] do
1611 EditStyle
:= esSimple
;
1615 with ItemProps
[InsertRow(MsgPropTrEffectSpl
, IntToStr(Data
.FXSpreadL
), True)] do
1617 EditStyle
:= esSimple
;
1621 with ItemProps
[InsertRow(MsgPropTrEffectSpr
, IntToStr(Data
.FXSpreadR
), True)] do
1623 EditStyle
:= esSimple
;
1627 with ItemProps
[InsertRow(MsgPropTrEffectSpu
, IntToStr(Data
.FXSpreadU
), True)] do
1629 EditStyle
:= esSimple
;
1633 with ItemProps
[InsertRow(MsgPropTrEffectSpd
, IntToStr(Data
.FXSpreadD
), True)] do
1635 EditStyle
:= esSimple
;
1639 end; //case TriggerType
1641 end; // OBJECT_TRIGGER:
1645 procedure TMainForm
.ChangeShownProperty(Name
: String; NewValue
: String);
1649 if SelectedObjectCount() <> 1 then
1651 if not SelectedObjects
[GetFirstSelected()].Live
then
1654 // Есть ли такой ключ:
1655 if vleObjectProperty
.FindRow(Name
, row
) then
1656 vleObjectProperty
.Values
[Name
] := NewValue
;
1659 procedure TMainForm
.SelectObject(fObjectType
: Byte; fID
: DWORD
; Multi
: Boolean);
1668 // Уже выделен - убираем:
1669 if SelectedObjects
<> nil then
1670 for a
:= 0 to High(SelectedObjects
) do
1671 with SelectedObjects
[a
] do
1672 if Live
and (ID
= fID
) and
1673 (ObjectType
= fObjectType
) then
1682 SetLength(SelectedObjects
, Length(SelectedObjects
)+1);
1684 with SelectedObjects
[High(SelectedObjects
)] do
1686 ObjectType
:= fObjectType
;
1693 SetLength(SelectedObjects
, 1);
1695 with SelectedObjects
[0] do
1697 ObjectType
:= fObjectType
;
1703 miCopy
.Enabled
:= True;
1704 miCut
.Enabled
:= True;
1706 if fObjectType
= OBJECT_PANEL
then
1708 miToFore
.Enabled
:= True;
1709 miToBack
.Enabled
:= True;
1713 procedure TMainForm
.RemoveSelectFromObjects();
1715 SelectedObjects
:= nil;
1716 DrawPressRect
:= False;
1717 MouseLDown
:= False;
1718 MouseRDown
:= False;
1719 MouseAction
:= MOUSEACTION_NONE
;
1720 SelectFlag
:= SELECTFLAG_NONE
;
1721 ResizeType
:= RESIZETYPE_NONE
;
1722 ResizeDirection
:= RESIZEDIR_NONE
;
1724 vleObjectProperty
.Strings
.Clear();
1725 miCopy
.Enabled
:= False;
1726 miCut
.Enabled
:= False;
1727 miToFore
.Enabled
:= False;
1728 miToBack
.Enabled
:= False;
1731 procedure TMainForm
.DeleteSelectedObjects();
1736 if SelectedObjects
= nil then
1742 for a
:= 0 to High(SelectedObjects
) do
1743 with SelectedObjects
[a
] do
1748 SetLength(UndoBuffer
, Length(UndoBuffer
)+1);
1749 i
:= High(UndoBuffer
);
1753 SetLength(UndoBuffer
[i
], Length(UndoBuffer
[i
])+1);
1754 ii
:= High(UndoBuffer
[i
]);
1759 UndoBuffer
[i
, ii
].UndoType
:= UNDO_DELETE_PANEL
;
1760 New(UndoBuffer
[i
, ii
].Panel
);
1761 UndoBuffer
[i
, ii
].Panel
^ := gPanels
[ID
];
1765 UndoBuffer
[i
, ii
].UndoType
:= UNDO_DELETE_ITEM
;
1766 UndoBuffer
[i
, ii
].Item
:= gItems
[ID
];
1770 UndoBuffer
[i
, ii
].UndoType
:= UNDO_DELETE_AREA
;
1771 UndoBuffer
[i
, ii
].Area
:= gAreas
[ID
];
1775 UndoBuffer
[i
, ii
].UndoType
:= UNDO_DELETE_TRIGGER
;
1776 UndoBuffer
[i
, ii
].Trigger
:= gTriggers
[ID
];
1780 RemoveObject(ID
, ObjectType
);
1783 RemoveSelectFromObjects();
1785 miUndo
.Enabled
:= UndoBuffer
<> nil;
1786 RecountSelectedObjects();
1789 procedure TMainForm
.Undo_Add(ObjectType
: Byte; ID
: DWORD
; Group
: Boolean);
1793 if (not Group
) or (Length(UndoBuffer
) = 0) then
1794 SetLength(UndoBuffer
, Length(UndoBuffer
)+1);
1795 SetLength(UndoBuffer
[High(UndoBuffer
)], Length(UndoBuffer
[High(UndoBuffer
)])+1);
1796 i
:= High(UndoBuffer
);
1797 ii
:= High(UndoBuffer
[i
]);
1801 UndoBuffer
[i
, ii
].UndoType
:= UNDO_ADD_PANEL
;
1803 UndoBuffer
[i
, ii
].UndoType
:= UNDO_ADD_ITEM
;
1805 UndoBuffer
[i
, ii
].UndoType
:= UNDO_ADD_MONSTER
;
1807 UndoBuffer
[i
, ii
].UndoType
:= UNDO_ADD_AREA
;
1809 UndoBuffer
[i
, ii
].UndoType
:= UNDO_ADD_TRIGGER
;
1812 UndoBuffer
[i
, ii
].AddID
:= ID
;
1813 miUndo
.Enabled
:= UndoBuffer
<> nil;
1816 procedure DiscardUndoBuffer();
1820 for i
:= 0 to High(UndoBuffer
) do
1821 for k
:= 0 to High(UndoBuffer
[i
]) do
1822 with UndoBuffer
[i
][k
] do
1823 if UndoType
= UNDO_DELETE_PANEL
then
1829 procedure TMainForm
.FullClear();
1831 RemoveSelectFromObjects();
1833 LoadSky(gMapInfo
.SkyName
);
1834 DiscardUndoBuffer();
1835 slInvalidTextures
.Clear();
1836 MapCheckForm
.lbErrorList
.Clear();
1837 MapCheckForm
.mErrorDescription
.Clear();
1839 miUndo
.Enabled
:= False;
1840 sbHorizontal
.Position
:= 0;
1841 sbVertical
.Position
:= 0;
1843 Caption
:= FormCaption
;
1848 procedure ErrorMessageBox(str
: String);
1850 Application
.MessageBox(PChar(str
), PChar(MsgMsgError
),
1851 MB_ICONINFORMATION
or MB_OK
or MB_DEFBUTTON1
);
1854 function TMainForm
.CheckProperty(): Boolean;
1860 _id
:= GetFirstSelected();
1862 if SelectedObjects
[_id
].ObjectType
= OBJECT_PANEL
then
1863 with gPanels
[SelectedObjects
[_id
].ID
] do
1865 if TextureWidth
<> 0 then
1866 if StrToIntDef(vleObjectProperty
.Values
[MsgPropWidth
], 1) mod TextureWidth
<> 0 then
1868 ErrorMessageBox(Format(MsgMsgWrongTexwidth
,
1873 if TextureHeight
<> 0 then
1874 if StrToIntDef(Trim(vleObjectProperty
.Values
[MsgPropHeight
]), 1) mod TextureHeight
<> 0 then
1876 ErrorMessageBox(Format(MsgMsgWrongTexheight
,
1881 if IsTexturedPanel(PanelType
) and (TextureName
<> '') then
1882 if not (StrToIntDef(vleObjectProperty
.Values
[MsgPropPanelAlpha
], -1) in [0..255]) then
1884 ErrorMessageBox(MsgMsgWrongAlpha
);
1889 if SelectedObjects
[_id
].ObjectType
in [OBJECT_PANEL
, OBJECT_TRIGGER
] then
1890 if (StrToIntDef(vleObjectProperty
.Values
[MsgPropWidth
], 0) <= 0) or
1891 (StrToIntDef(vleObjectProperty
.Values
[MsgPropHeight
], 0) <= 0) then
1893 ErrorMessageBox(MsgMsgWrongSize
);
1897 if (Trim(vleObjectProperty
.Values
[MsgPropX
]) = '') or
1898 (Trim(vleObjectProperty
.Values
[MsgPropY
]) = '') then
1900 ErrorMessageBox(MsgMsgWrongXy
);
1907 procedure TMainForm
.SelectTexture(ID
: Integer);
1909 lbTextureList
.ItemIndex
:= ID
;
1910 lbTextureListClick(nil);
1913 function TMainForm
.AddTexture(aWAD
, aSection
, aTex
: String; silent
: Boolean): Boolean;
1915 a
, FrameLen
: Integer;
1918 ResourceName
: String;
1919 FullResourceName
: String;
1920 SectionName
: String;
1922 Width
, Height
: Word;
1930 if aSection
= '..' then
1933 SectionName
:= aSection
;
1936 aWAD
:= MsgWadSpecialMap
;
1938 if aWAD
= MsgWadSpecialMap
then
1940 g_ProcessResourceStr(OpenedMap
, @fn
, nil, nil);
1942 ResourceName
:= ':'+SectionName
+'\'+aTex
;
1945 if aWAD
= MsgWadSpecialTexs
then
1946 begin // Спец. текстуры
1948 ResourceName
:= aTex
;
1951 begin // Внешний WAD
1952 FileName
:= WadsDir
+ DirectorySeparator
+ aWAD
;
1953 ResourceName
:= aWAD
+':'+SectionName
+'\'+aTex
;
1958 // Есть ли уже такая текстура:
1959 for a
:= 0 to lbTextureList
.Items
.Count
-1 do
1960 if ResourceName
= lbTextureList
.Items
[a
] then
1963 ErrorMessageBox(Format(MsgMsgTextureAlready
,
1968 // Название ресурса <= 64 символов:
1969 if Length(ResourceName
) > 64 then
1972 ErrorMessageBox(Format(MsgMsgResName64
,
1980 if aWAD
= MsgWadSpecialTexs
then
1982 a
:= lbTextureList
.Items
.Add(ResourceName
);
1989 FullResourceName
:= FileName
+':'+SectionName
+'\'+aTex
;
1991 if IsAnim(FullResourceName
) then
1992 begin // Аним. текстура
1993 GetFrame(FullResourceName
, Data
, FrameLen
, Width
, Height
);
1995 if not g_CreateTextureMemorySize(Data
, FrameLen
, ResourceName
, 0, 0, Width
, Height
, 1) then
1997 a
:= lbTextureList
.Items
.Add(ResourceName
);
1999 else // Обычная текстура
2001 if not g_CreateTextureWAD(ResourceName
, FullResourceName
) then
2003 a
:= lbTextureList
.Items
.Add(ResourceName
);
2005 if (not ok
) and (slInvalidTextures
.IndexOf(ResourceName
) = -1) then
2007 slInvalidTextures
.Add(ResourceName
);
2010 if (a
> -1) and (not silent
) then
2017 procedure TMainForm
.UpdateCaption(sMap
, sFile
, sRes
: String);
2019 if (sFile
= '') and (sRes
= '') and (sMap
= '') then
2020 Caption
:= FormCaption
2023 Caption
:= Format('%s - %s:%s', [FormCaption
, sFile
, sRes
])
2025 if (sFile
<> '') and (sRes
<> '') then
2026 Caption
:= Format('%s - %s (%s:%s)', [FormCaption
, sMap
, sFile
, sRes
])
2028 Caption
:= Format('%s - %s', [FormCaption
, sMap
]);
2031 procedure TMainForm
.OpenMap(FileName
: String; mapN
: String);
2036 SelectMapForm
.Caption
:= MsgCapOpen
;
2037 SelectMapForm
.GetMaps(FileName
);
2039 if (FileName
= OpenedWAD
) and
2040 (OpenedMap
<> '') then
2042 MapName
:= OpenedMap
;
2043 while (Pos(':\', MapName
) > 0) do
2044 Delete(MapName
, 1, Pos(':\', MapName
) + 1);
2046 idx
:= SelectMapForm
.lbMapList
.Items
.IndexOf(MapName
);
2047 SelectMapForm
.lbMapList
.ItemIndex
:= idx
;
2050 if SelectMapForm
.lbMapList
.Count
> 0 then
2051 SelectMapForm
.lbMapList
.ItemIndex
:= 0
2053 SelectMapForm
.lbMapList
.ItemIndex
:= -1;
2058 idx
:= SelectMapForm
.lbMapList
.Items
.IndexOf(mapN
);
2062 if (SelectMapForm
.ShowModal() = mrOK
) and
2063 (SelectMapForm
.lbMapList
.ItemIndex
<> -1) then
2064 idx
:= SelectMapForm
.lbMapList
.ItemIndex
2069 MapName
:= SelectMapForm
.lbMapList
.Items
[idx
];
2073 pLoadProgress
.Left
:= (RenderPanel
.Width
div 2)-(pLoadProgress
.Width
div 2);
2074 pLoadProgress
.Top
:= (RenderPanel
.Height
div 2)-(pLoadProgress
.Height
div 2);
2075 pLoadProgress
.Show();
2077 OpenedMap
:= FileName
+':\'+MapName
;
2078 OpenedWAD
:= FileName
;
2080 idx
:= RecentFiles
.IndexOf(OpenedMap
);
2081 // Такая карта уже недавно открывалась:
2083 RecentFiles
.Delete(idx
);
2084 RecentFiles
.Insert(0, OpenedMap
);
2085 RefreshRecentMenu();
2089 pLoadProgress
.Hide();
2092 lbTextureList
.Sorted
:= True;
2093 lbTextureList
.Sorted
:= False;
2095 UpdateCaption(gMapInfo
.Name
, ExtractFileName(FileName
), MapName
);
2098 procedure MoveSelectedObjects(Wall
, alt
: Boolean; dx
, dy
: Integer);
2103 if SelectedObjects
= nil then
2110 for a
:= 0 to High(SelectedObjects
) do
2111 if SelectedObjects
[a
].Live
then
2113 if ObjectCollideLevel(SelectedObjects
[a
].ID
, SelectedObjects
[a
].ObjectType
, dx
, 0) then
2116 if ObjectCollideLevel(SelectedObjects
[a
].ID
, SelectedObjects
[a
].ObjectType
, 0, dy
) then
2119 if (not okX
) or (not okY
) then
2125 for a
:= 0 to High(SelectedObjects
) do
2126 if SelectedObjects
[a
].Live
then
2129 MoveObject(SelectedObjects
[a
].ObjectType
, SelectedObjects
[a
].ID
, dx
, 0);
2132 MoveObject(SelectedObjects
[a
].ObjectType
, SelectedObjects
[a
].ID
, 0, dy
);
2134 if alt
and (SelectedObjects
[a
].ObjectType
= OBJECT_TRIGGER
) then
2136 if gTriggers
[SelectedObjects
[a
].ID
].TriggerType
in [TRIGGER_PRESS
,
2137 TRIGGER_ON
, TRIGGER_OFF
, TRIGGER_ONOFF
] then
2138 begin // Двигаем зону Расширителя
2140 gTriggers
[SelectedObjects
[a
].ID
].Data
.tX
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.tX
+dx
;
2142 gTriggers
[SelectedObjects
[a
].ID
].Data
.tY
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.tY
+dy
;
2145 if gTriggers
[SelectedObjects
[a
].ID
].TriggerType
in [TRIGGER_TELEPORT
] then
2146 begin // Двигаем точку назначения Телепорта
2148 gTriggers
[SelectedObjects
[a
].ID
].Data
.TargetPoint
.X
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.TargetPoint
.X
+dx
;
2150 gTriggers
[SelectedObjects
[a
].ID
].Data
.TargetPoint
.Y
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.TargetPoint
.Y
+dy
;
2153 if gTriggers
[SelectedObjects
[a
].ID
].TriggerType
in [TRIGGER_SPAWNMONSTER
] then
2154 begin // Двигаем точку создания монстра
2156 gTriggers
[SelectedObjects
[a
].ID
].Data
.MonPos
.X
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.MonPos
.X
+dx
;
2158 gTriggers
[SelectedObjects
[a
].ID
].Data
.MonPos
.Y
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.MonPos
.Y
+dy
;
2161 if gTriggers
[SelectedObjects
[a
].ID
].TriggerType
in [TRIGGER_SPAWNITEM
] then
2162 begin // Двигаем точку создания предмета
2164 gTriggers
[SelectedObjects
[a
].ID
].Data
.ItemPos
.X
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.ItemPos
.X
+dx
;
2166 gTriggers
[SelectedObjects
[a
].ID
].Data
.ItemPos
.Y
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.ItemPos
.Y
+dy
;
2169 if gTriggers
[SelectedObjects
[a
].ID
].TriggerType
in [TRIGGER_SHOT
] then
2170 begin // Двигаем точку создания выстрела
2172 gTriggers
[SelectedObjects
[a
].ID
].Data
.ShotPos
.X
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.ShotPos
.X
+dx
;
2174 gTriggers
[SelectedObjects
[a
].ID
].Data
.ShotPos
.Y
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.ShotPos
.Y
+dy
;
2179 LastMovePoint
:= MousePos
;
2183 procedure TMainForm
.SwitchMap();
2185 ShowMap
:= not ShowMap
;
2186 tbShowMap
.Down
:= ShowMap
;
2187 miMiniMap
.Checked
:= ShowMap
;
2190 procedure TMainForm
.ShowEdges();
2192 if drEdge
[3] < 255 then
2195 drEdge
[3] := gAlphaEdge
;
2196 miShowEdges
.Checked
:= drEdge
[3] <> 255;
2199 function TMainForm
.SelectedTexture(): String;
2201 if lbTextureList
.ItemIndex
<> -1 then
2202 Result
:= lbTextureList
.Items
[lbTextureList
.ItemIndex
]
2207 function TMainForm
.IsSpecialTextureSel(): Boolean;
2209 Result
:= (lbTextureList
.ItemIndex
<> -1) and
2210 IsSpecialTexture(lbTextureList
.Items
[lbTextureList
.ItemIndex
]);
2213 function CopyBufferToString(var CopyBuf
: TCopyRecArray
): String;
2218 procedure AddInt(x
: Integer);
2220 Res
:= Res
+ IntToStr(x
) + ' ';
2226 if Length(CopyBuf
) = 0 then
2229 Res
:= CLIPBOARD_SIG
+ ' ';
2231 for i
:= 0 to High(CopyBuf
) do
2233 if (CopyBuf
[i
].ObjectType
= OBJECT_PANEL
) and
2234 (CopyBuf
[i
].Panel
= nil) then
2238 AddInt(CopyBuf
[i
].ObjectType
);
2241 // Свойства объекта:
2242 case CopyBuf
[i
].ObjectType
of
2244 with CopyBuf
[i
].Panel
^ do
2251 Res
:= Res
+ '"' + TextureName
+ '" ';
2253 AddInt(IfThen(Blending
, 1, 0));
2257 with CopyBuf
[i
].Item
do
2262 AddInt(IfThen(OnlyDM
, 1, 0));
2263 AddInt(IfThen(Fall
, 1, 0));
2267 with CopyBuf
[i
].Monster
do
2269 AddInt(MonsterType
);
2272 AddInt(IfThen(Direction
= D_LEFT
, 1, 0));
2276 with CopyBuf
[i
].Area
do
2281 AddInt(IfThen(Direction
= D_LEFT
, 1, 0));
2285 with CopyBuf
[i
].Trigger
do
2287 AddInt(TriggerType
);
2292 AddInt(ActivateType
);
2294 AddInt(IfThen(Enabled
, 1, 0));
2295 AddInt(TexturePanel
);
2297 for j
:= 0 to 127 do
2298 AddInt(Data
.Default
[j
]);
2306 procedure StringToCopyBuffer(Str
: String; var CopyBuf
: TCopyRecArray
; var pmin
: TPoint
);
2309 minArea
, newArea
, newX
, newY
: LongInt;
2311 function GetNext(): String;
2316 if Str
[1] = '"' then
2328 Result
:= Copy(Str
, 1, p
-1);
2344 Result
:= Copy(Str
, 1, p
-1);
2352 minArea
:= High(minArea
);
2355 if GetNext() <> CLIPBOARD_SIG
then
2361 t
:= StrToIntDef(GetNext(), 0);
2363 if (t
< OBJECT_PANEL
) or (t
> OBJECT_TRIGGER
) or (GetNext() <> ';') then
2364 begin // Что-то не то => пропускаем:
2372 i
:= Length(CopyBuf
);
2373 SetLength(CopyBuf
, i
+ 1);
2375 CopyBuf
[i
].ObjectType
:= t
;
2376 CopyBuf
[i
].Panel
:= nil;
2378 // Свойства объекта:
2382 New(CopyBuf
[i
].Panel
);
2384 with CopyBuf
[i
].Panel
^ do
2386 PanelType
:= StrToIntDef(GetNext(), PANEL_WALL
);
2387 X
:= StrToIntDef(GetNext(), 0);
2388 Y
:= StrToIntDef(GetNext(), 0);
2389 Width
:= StrToIntDef(GetNext(), 16);
2390 Height
:= StrToIntDef(GetNext(), 16);
2391 TextureName
:= GetNext();
2392 Alpha
:= StrToIntDef(GetNext(), 0);
2393 Blending
:= (GetNext() = '1');
2394 newArea
:= X
* Y
- Width
* Height
;
2401 with CopyBuf
[i
].Item
do
2403 ItemType
:= StrToIntDef(GetNext(), ITEM_MEDKIT_SMALL
);
2404 X
:= StrToIntDef(GetNext(), 0);
2405 Y
:= StrToIntDef(GetNext(), 0);
2406 OnlyDM
:= (GetNext() = '1');
2407 Fall
:= (GetNext() = '1');
2414 with CopyBuf
[i
].Monster
do
2416 MonsterType
:= StrToIntDef(GetNext(), MONSTER_DEMON
);
2417 X
:= StrToIntDef(GetNext(), 0);
2418 Y
:= StrToIntDef(GetNext(), 0);
2420 then Direction
:= D_LEFT
2421 else Direction
:= D_RIGHT
;
2428 with CopyBuf
[i
].Area
do
2430 AreaType
:= StrToIntDef(GetNext(), AREA_PLAYERPOINT1
);
2431 X
:= StrToIntDef(GetNext(), 0);
2432 Y
:= StrToIntDef(GetNext(), 0);
2434 then Direction
:= D_LEFT
2435 else Direction
:= D_RIGHT
;
2442 with CopyBuf
[i
].Trigger
do
2444 TriggerType
:= StrToIntDef(GetNext(), TRIGGER_EXIT
);
2445 X
:= StrToIntDef(GetNext(), 0);
2446 Y
:= StrToIntDef(GetNext(), 0);
2447 Width
:= StrToIntDef(GetNext(), 16);
2448 Height
:= StrToIntDef(GetNext(), 16);
2449 ActivateType
:= StrToIntDef(GetNext(), 0);
2450 Key
:= StrToIntDef(GetNext(), 0);
2451 Enabled
:= (GetNext() = '1');
2452 TexturePanel
:= StrToIntDef(GetNext(), 0);
2454 do Data
.Default
[j
] := StrToIntDef(GetNext(), 0);
2455 newArea
:= X
* Y
- Width
* Height
;
2461 if newArea
< minArea
then
2470 //----------------------------------------
2471 //Закончились вспомогательные процедуры
2472 //----------------------------------------
2474 procedure TMainForm
.miRecentFileExecute (Sender
: TObject
);
2479 n
:= (Sender
as TMenuItem
).Tag
;
2480 s
:= RecentFiles
[n
];
2481 fn
:= g_ExtractWadName(s
);
2482 if FileExists(fn
) then
2483 OpenMap(fn
, g_ExtractFilePathName(s
))
2485 Application
.MessageBox('File not available anymore', '', MB_OK
);
2486 // if Application.MessageBox(PChar(MsgMsgDelRecentPrompt), PChar(MsgMsgDelRecent), MB_ICONQUESTION or MB_YESNO) = idYes then
2488 // RecentFiles.Delete(n);
2489 // RefreshRecentMenu();
2493 procedure TMainForm
.RefillRecentMenu (menu
: TMenuItem
; start
: Integer; fmt
: AnsiString
);
2494 var i
: Integer; MI
: TMenuItem
; s
: AnsiString
;
2496 Assert(menu
<> nil);
2498 Assert(start
<= menu
.Count
);
2500 // clear all the recent entries from menu
2502 while i
< menu
.Count
do
2504 MI
:= menu
.Items
[i
];
2505 if @MI
.OnClick
<> @TMainForm
.miRecentFileExecute
then
2510 Application
.ReleaseComponent(MI
);
2514 // fill with a new ones
2515 for i
:= 0 to RecentFiles
.Count
-1 do
2517 MI
:= TMenuItem
.Create(menu
);
2518 s
:= RecentFiles
[i
];
2519 MI
.Caption
:= Format(fmt
, [i
+1, g_ExtractWadNameNoPath(s
), g_ExtractFilePathName(s
)]);
2520 MI
.OnClick
:= miRecentFileExecute
;
2522 menu
.Insert(start
+ i
, MI
); // transfers ownership
2526 procedure TMainForm
.RefreshRecentMenu();
2529 while RecentFiles
.Count
> RecentCount
do
2530 RecentFiles
.Delete(RecentFiles
.Count
- 1);
2532 if miMacRecentSubMenu
.Visible
then
2534 // Reconstruct OSX-like recent list
2535 RefillRecentMenu(miMacRecentSubMenu
, 0, '%1:s - %2:s');
2536 miMacRecentEnd
.Enabled
:= RecentFiles
.Count
<> 0;
2537 miMacRecentEnd
.Visible
:= RecentFiles
.Count
<> 0;
2540 if miWinRecentStart
.Visible
then
2542 // Reconstruct Windows-like recent list
2543 start
:= miMenuFile
.IndexOf(miWinRecent
);
2544 if start
< 0 then start
:= miMenuFile
.Count
else start
+= 1;
2545 RefillRecentMenu(miMenuFile
, start
, '%0:d %1:s:%2:s');
2546 miWinRecent
.Enabled
:= False;
2547 miWinRecent
.Visible
:= RecentFiles
.Count
= 0;
2551 procedure TMainForm
.miMacRecentClearClick(Sender
: TObject
);
2553 RecentFiles
.Clear();
2554 RefreshRecentMenu();
2557 procedure TMainForm
.aEditorOptionsExecute(Sender
: TObject
);
2559 OptionsForm
.ShowModal();
2562 procedure LoadStdFont(cfgres
, texture
: string; var FontID
: DWORD
);
2576 wad
:= TWADEditor_1
.Create
;
2577 if wad
.ReadFile(GameWad
) then
2578 wad
.GetResource('FONTS', cfgres
, cfgdata
, cfglen
);
2583 if not g_CreateTextureWAD('FONT_STD', GameWad
+ ':FONTS\' + texture
) then
2584 e_WriteLog('ERROR ERROR ERROR', MSG_WARNING
);
2586 config
:= TConfig
.CreateMem(cfgdata
, cfglen
);
2587 cwdt
:= Min(Max(config
.ReadInt('FontMap', 'CharWidth', 0), 0), 255);
2588 chgt
:= Min(Max(config
.ReadInt('FontMap', 'CharHeight', 0), 0), 255);
2589 spc
:= Min(Max(config
.ReadInt('FontMap', 'Kerning', 0), -128), 127);
2591 if g_GetTexture('FONT_STD', ID
) then
2592 e_TextureFontBuild(ID
, FontID
, cwdt
, chgt
, spc
-2);
2597 e_WriteLog('Could not load FONT_STD', MSG_WARNING
);
2599 if cfglen
<> 0 then FreeMem(cfgdata
);
2602 procedure TMainForm
.FormCreate(Sender
: TObject
);
2612 miApple
.Enabled
:= True;
2613 miApple
.Visible
:= True;
2614 miMacRecentSubMenu
.Enabled
:= True;
2615 miMacRecentSubMenu
.Visible
:= True;
2616 miWinRecentStart
.Enabled
:= False;
2617 miWinRecentStart
.Visible
:= False;
2618 miWinRecent
.Enabled
:= False;
2619 miWinRecent
.Visible
:= False;
2620 miLine2
.Enabled
:= False;
2621 miLine2
.Visible
:= False;
2622 miExit
.Enabled
:= False;
2623 miExit
.Visible
:= False;
2624 miOptions
.Enabled
:= False;
2625 miOptions
.Visible
:= False;
2626 miMenuWindow
.Enabled
:= True;
2627 miMenuWindow
.Visible
:= True;
2628 miAbout
.Enabled
:= False;
2629 miAbout
.Visible
:= False;
2631 miApple
.Enabled
:= False;
2632 miApple
.Visible
:= False;
2633 miMacRecentSubMenu
.Enabled
:= False;
2634 miMacRecentSubMenu
.Visible
:= False;
2635 miWinRecentStart
.Enabled
:= True;
2636 miWinRecentStart
.Visible
:= True;
2637 miWinRecent
.Enabled
:= True;
2638 miWinRecent
.Visible
:= True;
2639 miLine2
.Enabled
:= True;
2640 miLine2
.Visible
:= True;
2641 miExit
.Enabled
:= True;
2642 miExit
.Visible
:= True;
2643 miOptions
.Enabled
:= True;
2644 miOptions
.Visible
:= True;
2645 miMenuWindow
.Enabled
:= False;
2646 miMenuWindow
.Visible
:= False;
2647 miAbout
.Enabled
:= True;
2648 miAbout
.Visible
:= True;
2651 miNewMap
.ShortCut
:= ShortCut(VK_N
, [ssModifier
]);
2652 miOpenMap
.ShortCut
:= ShortCut(VK_O
, [ssModifier
]);
2653 miSaveMap
.ShortCut
:= ShortCut(VK_S
, [ssModifier
]);
2655 miSaveMapAs
.ShortCut
:= ShortCut(VK_S
, [ssModifier
, ssShift
]);
2656 miReopenMap
.ShortCut
:= ShortCut(VK_F5
, [ssModifier
]);
2658 miUndo
.ShortCut
:= ShortCut(VK_Z
, [ssModifier
]);
2659 miCopy
.ShortCut
:= ShortCut(VK_C
, [ssModifier
]);
2660 miCut
.ShortCut
:= ShortCut(VK_X
, [ssModifier
]);
2661 miPaste
.ShortCut
:= ShortCut(VK_V
, [ssModifier
]);
2662 miSelectAll
.ShortCut
:= ShortCut(VK_A
, [ssModifier
]);
2663 miToFore
.ShortCut
:= ShortCut(VK_LCL_CLOSE_BRACKET
, [ssModifier
]);
2664 miToBack
.ShortCut
:= ShortCut(VK_LCL_OPEN_BRACKET
, [ssModifier
]);
2666 miMapOptions
.Shortcut
:= ShortCut(VK_P
, [ssModifier
, ssAlt
]);
2667 selectall1
.Shortcut
:= ShortCut(VK_A
, [ssModifier
, ssAlt
]);
2670 e_WriteLog('Doom 2D: Forever Editor version ' + EDITOR_VERSION
, MSG_NOTIFY
);
2671 e_WriteLog('Build date: ' + EDITOR_BUILDDATE
+ ' ' + EDITOR_BUILDTIME
, MSG_NOTIFY
);
2672 e_WriteLog('Build hash: ' + g_GetBuildHash(), MSG_NOTIFY
);
2673 e_WriteLog('Build by: ' + g_GetBuilderName(), MSG_NOTIFY
);
2675 slInvalidTextures
:= TStringList
.Create
;
2679 FormCaption
:= Caption
;
2683 config
:= TConfig
.CreateFile(CfgFileName
);
2685 gWADEditorLogLevel
:= config
.ReadInt('WADEditor', 'LogLevel', DFWAD_LOG_DEFAULT
);
2687 if config
.ReadInt('Editor', 'XPos', -1) = -1 then
2688 Position
:= poDesktopCenter
2690 Left
:= config
.ReadInt('Editor', 'XPos', Left
);
2691 Top
:= config
.ReadInt('Editor', 'YPos', Top
);
2692 Width
:= config
.ReadInt('Editor', 'Width', Width
);
2693 Height
:= config
.ReadInt('Editor', 'Height', Height
);
2695 if config
.ReadBool('Editor', 'Maximize', False) then
2696 WindowState
:= wsMaximized
;
2697 ShowMap
:= config
.ReadBool('Editor', 'Minimap', False);
2698 PanelProps
.Width
:= config
.ReadInt('Editor', 'PanelProps', PanelProps
.ClientWidth
);
2699 Splitter1
.Left
:= PanelProps
.Left
;
2700 PanelObjs
.Height
:= config
.ReadInt('Editor', 'PanelObjs', PanelObjs
.ClientHeight
);
2701 Splitter2
.Top
:= PanelObjs
.Top
;
2702 StatusBar
.Top
:= PanelObjs
.BoundsRect
.Bottom
;
2703 DotEnable
:= config
.ReadBool('Editor', 'DotEnable', True);
2704 DotColor
:= config
.ReadInt('Editor', 'DotColor', $FFFFFF);
2705 DotStepOne
:= config
.ReadInt('Editor', 'DotStepOne', 16);
2706 DotStepTwo
:= config
.ReadInt('Editor', 'DotStepTwo', 8);
2707 DotStep
:= config
.ReadInt('Editor', 'DotStep', DotStepOne
);
2708 DrawTexturePanel
:= config
.ReadBool('Editor', 'DrawTexturePanel', True);
2709 DrawPanelSize
:= config
.ReadBool('Editor', 'DrawPanelSize', True);
2710 BackColor
:= config
.ReadInt('Editor', 'BackColor', $7F6040);
2711 PreviewColor
:= config
.ReadInt('Editor', 'PreviewColor', $00FF00);
2712 UseCheckerboard
:= config
.ReadBool('Editor', 'UseCheckerboard', True);
2713 gColorEdge
:= config
.ReadInt('Editor', 'EdgeColor', COLOR_EDGE
);
2714 gAlphaEdge
:= config
.ReadInt('Editor', 'EdgeAlpha', ALPHA_EDGE
);
2715 if gAlphaEdge
= 255 then
2716 gAlphaEdge
:= ALPHA_EDGE
;
2717 drEdge
[0] := GetRValue(gColorEdge
);
2718 drEdge
[1] := GetGValue(gColorEdge
);
2719 drEdge
[2] := GetBValue(gColorEdge
);
2720 if not config
.ReadBool('Editor', 'EdgeShow', True) then
2723 drEdge
[3] := gAlphaEdge
;
2724 gAlphaTriggerLine
:= config
.ReadInt('Editor', 'LineAlpha', ALPHA_LINE
);
2725 if gAlphaTriggerLine
= 255 then
2726 gAlphaTriggerLine
:= ALPHA_LINE
;
2727 gAlphaTriggerArea
:= config
.ReadInt('Editor', 'TriggerAlpha', ALPHA_AREA
);
2728 if gAlphaTriggerArea
= 255 then
2729 gAlphaTriggerArea
:= ALPHA_AREA
;
2730 gAlphaMonsterRect
:= config
.ReadInt('Editor', 'MonsterRectAlpha', 0);
2731 gAlphaAreaRect
:= config
.ReadInt('Editor', 'AreaRectAlpha', 0);
2732 Scale
:= Max(config
.ReadInt('Editor', 'Scale', 1), 1);
2733 DotSize
:= Max(config
.ReadInt('Editor', 'DotSize', 1), 1);
2734 OpenDialog
.InitialDir
:= config
.ReadStr('Editor', 'LastOpenDir', MapsDir
);
2735 SaveDialog
.InitialDir
:= config
.ReadStr('Editor', 'LastSaveDir', MapsDir
);
2737 s
:= config
.ReadStr('Editor', 'Language', '');
2740 TestGameMode
:= config
.ReadStr('TestRun', 'GameMode', 'DM');
2741 TestLimTime
:= config
.ReadStr('TestRun', 'LimTime', '0');
2742 TestLimScore
:= config
.ReadStr('TestRun', 'LimScore', '0');
2743 TestOptionsTwoPlayers
:= config
.ReadBool('TestRun', 'TwoPlayers', False);
2744 TestOptionsTeamDamage
:= config
.ReadBool('TestRun', 'TeamDamage', False);
2745 TestOptionsAllowExit
:= config
.ReadBool('TestRun', 'AllowExit', True);
2746 TestOptionsWeaponStay
:= config
.ReadBool('TestRun', 'WeaponStay', False);
2747 TestOptionsMonstersDM
:= config
.ReadBool('TestRun', 'MonstersDM', False);
2748 TestMapOnce
:= config
.ReadBool('TestRun', 'MapOnce', False);
2749 {$IF DEFINED(DARWIN)}
2750 TestD2dExe
:= config
.ReadStr('TestRun', 'ExeDrawin', GameExeFile
);
2751 {$ELSEIF DEFINED(WINDOWS)}
2752 TestD2dExe
:= config
.ReadStr('TestRun', 'ExeWindows', GameExeFile
);
2754 TestD2dExe
:= config
.ReadStr('TestRun', 'ExeUnix', GameExeFile
);
2756 TestD2dArgs
:= config
.ReadStr('TestRun', 'Args', '');
2758 RecentCount
:= config
.ReadInt('Editor', 'RecentCount', 5);
2759 if RecentCount
> 10 then
2761 if RecentCount
< 2 then
2764 RecentFiles
:= TStringList
.Create();
2765 for i
:= 0 to RecentCount
-1 do
2768 s
:= config
.ReadStr('RecentFilesWin', IntToStr(i
), '');
2770 s
:= config
.ReadStr('RecentFilesUnix', IntToStr(i
), '');
2775 RefreshRecentMenu();
2779 // Fixes an LCL issue with TToolButton.ImageIndex forcibly assigned,
2780 // even when using a different ImageList, if TToolButton.MenuItem is set.
2781 // https://forum.lazarus.freepascal.org/index.php?topic=19260.0
2782 tbShow
.ImageIndex
:= 4;
2784 tbShowMap
.Down
:= ShowMap
;
2785 tbGridOn
.Down
:= DotEnable
;
2786 pcObjects
.ActivePageIndex
:= 0;
2787 Application
.Title
:= MsgEditorTitle
;
2789 Application
.OnIdle
:= OnIdle
;
2792 procedure PrintBlack(X
, Y
: Integer; Text: string; FontID
: DWORD
);
2794 // NOTE: all the font printing routines assume CP1251
2795 e_TextureFontPrintEx(X
, Y
, Text, FontID
, 0, 0, 0, 1.0);
2798 procedure TMainForm
.InitGraphics();
2800 // FIXME: this is a shitty hack
2801 if not gDataLoaded
then
2803 e_WriteLog('Init OpenGL', MSG_NOTIFY
);
2805 e_WriteLog('Loading data', MSG_NOTIFY
);
2806 LoadStdFont('STDTXT', 'STDFONT', gEditorFont
);
2807 e_WriteLog('Loading more data', MSG_NOTIFY
);
2809 e_WriteLog('Loading even more data', MSG_NOTIFY
);
2810 gDataLoaded
:= True;
2815 procedure TMainForm
.Draw();
2820 Width
, Height
: Word;
2823 aX
, aY
, aX2
, aY2
, XX
, ScaleSz
: Integer;
2825 LastDrawTime
:= GetTickCount64();
2835 e_Clear(GL_COLOR_BUFFER_BIT
,
2836 GetRValue(BackColor
)/255,
2837 GetGValue(BackColor
)/255,
2838 GetBValue(BackColor
)/255);
2842 ObjCount
:= SelectedObjectCount();
2844 // Обводим выделенные объекты красной рамкой:
2845 if ObjCount
> 0 then
2847 for a
:= 0 to High(SelectedObjects
) do
2848 if SelectedObjects
[a
].Live
then
2850 Rect
:= ObjectGetRect(SelectedObjects
[a
].ObjectType
, SelectedObjects
[a
].ID
);
2854 e_DrawQuad(X
+MapOffset
.X
, Y
+MapOffset
.Y
,
2855 X
+MapOffset
.X
+Width
-1, Y
+MapOffset
.Y
+Height
-1,
2858 // Рисуем точки изменения размеров:
2859 if (ObjCount
= 1) and
2860 (SelectedObjects
[GetFirstSelected
].ObjectType
in [OBJECT_PANEL
, OBJECT_TRIGGER
]) then
2862 e_DrawPoint(5, X
+MapOffset
.X
, Y
+MapOffset
.Y
+(Height
div 2), 255, 255, 255);
2863 e_DrawPoint(5, X
+MapOffset
.X
+Width
-1, Y
+MapOffset
.Y
+(Height
div 2), 255, 255, 255);
2864 e_DrawPoint(5, X
+MapOffset
.X
+(Width
div 2), Y
+MapOffset
.Y
, 255, 255, 255);
2865 e_DrawPoint(5, X
+MapOffset
.X
+(Width
div 2), Y
+MapOffset
.Y
+Height
-1, 255, 255, 255);
2867 e_DrawPoint(3, X
+MapOffset
.X
, Y
+MapOffset
.Y
+(Height
div 2), 255, 0, 0);
2868 e_DrawPoint(3, X
+MapOffset
.X
+Width
-1, Y
+MapOffset
.Y
+(Height
div 2), 255, 0, 0);
2869 e_DrawPoint(3, X
+MapOffset
.X
+(Width
div 2), Y
+MapOffset
.Y
, 255, 0, 0);
2870 e_DrawPoint(3, X
+MapOffset
.X
+(Width
div 2), Y
+MapOffset
.Y
+Height
-1, 255, 0, 0);
2877 if DotEnable
and (PreviewMode
= 0) then
2884 glDisable(GL_TEXTURE_2D
);
2885 glColor3ub(GetRValue(DotColor
), GetGValue(DotColor
), GetBValue(DotColor
));
2886 glPointSize(DotSize
);
2888 x
:= MapOffset
.X
mod DotStep
;
2889 while x
< RenderPanel
.Width
do
2891 y
:= MapOffset
.Y
mod DotStep
;
2892 while y
< RenderPanel
.Height
do
2894 glVertex2i(x
+ a
, y
+ a
);
2900 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
2904 if (lbTextureList
.ItemIndex
<> -1) and (cbPreview
.Checked
) and
2905 (not IsSpecialTextureSel()) and (PreviewMode
= 0) then
2907 if not g_GetTexture(SelectedTexture(), ID
) then
2908 g_GetTexture('NOTEXTURE', ID
);
2909 g_GetTextureSizeByID(ID
, Width
, Height
);
2910 if UseCheckerboard
then
2912 if g_GetTexture('PREVIEW', PID
) then
2913 e_DrawFill(PID
, RenderPanel
.Width
-Width
, RenderPanel
.Height
-Height
, Width
div 16 + 1, Height
div 16 + 1, 0, True, False);
2915 e_DrawFillQuad(RenderPanel
.Width
-Width
-2, RenderPanel
.Height
-Height
-2,
2916 RenderPanel
.Width
-1, RenderPanel
.Height
-1,
2917 GetRValue(PreviewColor
), GetGValue(PreviewColor
), GetBValue(PreviewColor
), 0);
2918 e_Draw(ID
, RenderPanel
.Width
-Width
, RenderPanel
.Height
-Height
, 0, True, False);
2921 // Подсказка при выборе точки Телепорта:
2922 if SelectFlag
= SELECTFLAG_TELEPORT
then
2924 with gTriggers
[SelectedObjects
[GetFirstSelected()].ID
] do
2925 if Data
.d2d_teleport
then
2926 e_DrawLine(2, MousePos
.X
-16, MousePos
.Y
-1,
2927 MousePos
.X
+16, MousePos
.Y
-1,
2930 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+AreaSize
[AREA_DMPOINT
].Width
-1,
2931 MousePos
.Y
+AreaSize
[AREA_DMPOINT
].Height
-1, 255, 255, 255);
2933 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 192, 192, 192, 127);
2934 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 255, 255, 255);
2935 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, utf8to1251(MsgHintTeleport
), gEditorFont
);
2938 // Подсказка при выборе точки появления:
2939 if SelectFlag
= SELECTFLAG_SPAWNPOINT
then
2941 e_DrawLine(2, MousePos
.X
-16, MousePos
.Y
-1,
2942 MousePos
.X
+16, MousePos
.Y
-1,
2944 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 192, 192, 192, 127);
2945 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 255, 255, 255);
2946 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, utf8to1251(MsgHintSpawn
), gEditorFont
);
2949 // Подсказка при выборе панели двери:
2950 if SelectFlag
= SELECTFLAG_DOOR
then
2952 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 192, 192, 192, 127);
2953 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 255, 255, 255);
2954 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, utf8to1251(MsgHintPanelDoor
), gEditorFont
);
2957 // Подсказка при выборе панели с текстурой:
2958 if SelectFlag
= SELECTFLAG_TEXTURE
then
2960 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+196, MousePos
.Y
+18, 192, 192, 192, 127);
2961 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+196, MousePos
.Y
+18, 255, 255, 255);
2962 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, utf8to1251(MsgHintPanelTexture
), gEditorFont
);
2965 // Подсказка при выборе панели индикации выстрела:
2966 if SelectFlag
= SELECTFLAG_SHOTPANEL
then
2968 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+316, MousePos
.Y
+18, 192, 192, 192, 127);
2969 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+316, MousePos
.Y
+18, 255, 255, 255);
2970 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, utf8to1251(MsgHintPanelShot
), gEditorFont
);
2973 // Подсказка при выборе панели лифта:
2974 if SelectFlag
= SELECTFLAG_LIFT
then
2976 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 192, 192, 192, 127);
2977 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 255, 255, 255);
2978 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, utf8to1251(MsgHintPanelLift
), gEditorFont
);
2981 // Подсказка при выборе монстра:
2982 if SelectFlag
= SELECTFLAG_MONSTER
then
2984 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+120, MousePos
.Y
+18, 192, 192, 192, 127);
2985 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+120, MousePos
.Y
+18, 255, 255, 255);
2986 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, utf8to1251(MsgHintMonster
), gEditorFont
);
2989 // Подсказка при выборе области воздействия:
2990 if DrawPressRect
then
2992 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+204, MousePos
.Y
+18, 192, 192, 192, 127);
2993 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+204, MousePos
.Y
+18, 255, 255, 255);
2994 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, utf8to1251(MsgHintExtArea
), gEditorFont
);
2997 // Рисуем текстуры, если чертим панель:
2998 if (MouseAction
= MOUSEACTION_DRAWPANEL
) and (DrawTexturePanel
) and
2999 (lbTextureList
.ItemIndex
<> -1) and (DrawRect
<> nil) and
3000 (lbPanelType
.ItemIndex
in [0..8]) and not IsSpecialTextureSel() then
3002 if not g_GetTexture(SelectedTexture(), ID
) then
3003 g_GetTexture('NOTEXTURE', ID
);
3004 g_GetTextureSizeByID(ID
, Width
, Height
);
3006 if (Abs(Right
-Left
) >= Width
) and (Abs(Bottom
-Top
) >= Height
) then
3007 e_DrawFill(ID
, Min(Left
, Right
), Min(Top
, Bottom
), Abs(Right
-Left
) div Width
,
3008 Abs(Bottom
-Top
) div Height
, 64, True, False);
3011 // Прямоугольник выделения:
3012 if DrawRect
<> nil then
3014 e_DrawQuad(Left
, Top
, Right
-1, Bottom
-1, 255, 255, 255);
3016 // Чертим мышью панель/триггер или меняем мышью их размер:
3017 if (((MouseAction
in [MOUSEACTION_DRAWPANEL
, MOUSEACTION_DRAWTRIGGER
]) and
3018 not(ssCtrl
in GetKeyShiftState())) or (MouseAction
= MOUSEACTION_RESIZE
)) and
3019 (DrawPanelSize
) then
3021 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+88, MousePos
.Y
+33, 192, 192, 192, 127);
3022 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+88, MousePos
.Y
+33, 255, 255, 255);
3024 if MouseAction
in [MOUSEACTION_DRAWPANEL
, MOUSEACTION_DRAWTRIGGER
] then
3025 begin // Чертим новый
3026 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, Format(utf8to1251(MsgHintWidth
),
3027 [Abs(MousePos
.X
-MouseLDownPos
.X
)]), gEditorFont
);
3028 PrintBlack(MousePos
.X
+2, MousePos
.Y
+16, Format(utf8to1251(MsgHintHeight
),
3029 [Abs(MousePos
.Y
-MouseLDownPos
.Y
)]), gEditorFont
);
3031 else // Растягиваем существующий
3032 if SelectedObjects
[GetFirstSelected
].ObjectType
in [OBJECT_PANEL
, OBJECT_TRIGGER
] then
3034 if SelectedObjects
[GetFirstSelected
].ObjectType
= OBJECT_PANEL
then
3036 Width
:= gPanels
[SelectedObjects
[GetFirstSelected
].ID
].Width
;
3037 Height
:= gPanels
[SelectedObjects
[GetFirstSelected
].ID
].Height
;
3041 Width
:= gTriggers
[SelectedObjects
[GetFirstSelected
].ID
].Width
;
3042 Height
:= gTriggers
[SelectedObjects
[GetFirstSelected
].ID
].Height
;
3045 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, Format(utf8to1251(MsgHintWidth
), [Width
]),
3047 PrintBlack(MousePos
.X
+2, MousePos
.Y
+16, Format(utf8to1251(MsgHintHeight
), [Height
]),
3052 // Ближайшая к курсору мыши точка на сетке:
3053 e_DrawPoint(3, MousePos
.X
, MousePos
.Y
, 0, 0, 255);
3058 // Сколько пикселов карты в 1 пикселе мини-карты:
3059 ScaleSz
:= 16 div Scale
;
3060 // Размеры мини-карты:
3061 aX
:= max(gMapInfo
.Width
div ScaleSz
, 1);
3062 aY
:= max(gMapInfo
.Height
div ScaleSz
, 1);
3063 // X-координата на RenderPanel нулевой x-координаты карты:
3064 XX
:= RenderPanel
.Width
- aX
- 1;
3066 e_DrawFillQuad(XX
-1, 0, RenderPanel
.Width
-1, aY
+1, 0, 0, 0, 0);
3067 e_DrawQuad(XX
-1, 0, RenderPanel
.Width
-1, aY
+1, 197, 197, 197);
3069 if gPanels
<> nil then
3072 for a
:= 0 to High(gPanels
) do
3074 if PanelType
<> 0 then
3076 // Левый верхний угол:
3077 aX
:= XX
+ (X
div ScaleSz
);
3078 aY
:= 1 + (Y
div ScaleSz
);
3080 aX2
:= max(Width
div ScaleSz
, 1);
3081 aY2
:= max(Height
div ScaleSz
, 1);
3082 // Правый нижний угол:
3083 aX2
:= aX
+ aX2
- 1;
3084 aY2
:= aY
+ aY2
- 1;
3087 PANEL_WALL
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 208, 208, 208, 0);
3088 PANEL_WATER
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 0, 0, 192, 0);
3089 PANEL_ACID1
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 0, 176, 0, 0);
3090 PANEL_ACID2
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 176, 0, 0, 0);
3091 PANEL_LADDER
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 128, 128, 128, 0);
3092 PANEL_LIFTUP
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 116, 72, 36, 0);
3093 PANEL_LIFTDOWN
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 116, 124, 96, 0);
3094 PANEL_LIFTLEFT
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 200, 80, 4, 0);
3095 PANEL_LIFTRIGHT
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 252, 140, 56, 0);
3096 PANEL_OPENDOOR
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 100, 220, 92, 0);
3097 PANEL_CLOSEDOOR
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 212, 184, 64, 0);
3098 PANEL_BLOCKMON
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 192, 0, 192, 0);
3102 // Рисуем красным выделенные панели:
3103 if SelectedObjects
<> nil then
3104 for b
:= 0 to High(SelectedObjects
) do
3105 with SelectedObjects
[b
] do
3106 if Live
and (ObjectType
= OBJECT_PANEL
) then
3107 with gPanels
[SelectedObjects
[b
].ID
] do
3108 if PanelType
and not(PANEL_BACK
or PANEL_FORE
) <> 0 then
3110 // Левый верхний угол:
3111 aX
:= XX
+ (X
div ScaleSz
);
3112 aY
:= 1 + (Y
div ScaleSz
);
3114 aX2
:= max(Width
div ScaleSz
, 1);
3115 aY2
:= max(Height
div ScaleSz
, 1);
3116 // Правый нижний угол:
3117 aX2
:= aX
+ aX2
- 1;
3118 aY2
:= aY
+ aY2
- 1;
3120 e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 255, 0, 0, 0)
3124 if (gMapInfo
.Width
> RenderPanel
.Width
) or
3125 (gMapInfo
.Height
> RenderPanel
.Height
) then
3127 // Окно, показывающее текущее положение экрана на карте:
3129 x
:= max(min(RenderPanel
.Width
, gMapInfo
.Width
) div ScaleSz
, 1);
3130 y
:= max(min(RenderPanel
.Height
, gMapInfo
.Height
) div ScaleSz
, 1);
3131 // Левый верхний угол:
3132 aX
:= XX
+ ((-MapOffset
.X
) div ScaleSz
);
3133 aY
:= 1 + ((-MapOffset
.Y
) div ScaleSz
);
3134 // Правый нижний угол:
3138 e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 127, 192, 127, 127, B_BLEND
);
3139 e_DrawQuad(aX
, aY
, aX2
, aY2
, 255, 0, 0);
3144 RenderPanel
.SwapBuffers();
3147 procedure TMainForm
.FormResize(Sender
: TObject
);
3149 e_SetViewPort(0, 0, RenderPanel
.Width
, RenderPanel
.Height
);
3151 sbHorizontal
.Min
:= Min(gMapInfo
.Width
- RenderPanel
.Width
, -RenderPanel
.Width
div 2);
3152 sbHorizontal
.Max
:= Max(0, gMapInfo
.Width
- RenderPanel
.Width
div 2);
3153 sbVertical
.Min
:= Min(gMapInfo
.Height
- RenderPanel
.Height
, -RenderPanel
.Height
div 2);
3154 sbVertical
.Max
:= Max(0, gMapInfo
.Height
- RenderPanel
.Height
div 2);
3156 MapOffset
.X
:= -sbHorizontal
.Position
;
3157 MapOffset
.Y
:= -sbVertical
.Position
;
3160 procedure TMainForm
.FormWindowStateChange(Sender
: TObject
);
3166 // deactivate all menus when main window minimized
3167 e
:= self
.WindowState
<> wsMinimized
;
3168 miMenuFile
.Enabled
:= e
;
3169 miMenuEdit
.Enabled
:= e
;
3170 miMenuView
.Enabled
:= e
;
3171 miMenuService
.Enabled
:= e
;
3172 miMenuWindow
.Enabled
:= e
;
3173 miMenuHelp
.Enabled
:= e
;
3174 miMenuHidden
.Enabled
:= e
;
3178 procedure TMainForm
.SelectNextObject(X
, Y
: Integer; ObjectType
: Byte; ID
: DWORD
);
3183 j_max
:= 0; // shut up compiler
3187 res
:= (gPanels
<> nil) and
3188 PanelInShownLayer(gPanels
[ID
].PanelType
) and
3189 g_CollidePoint(X
, Y
, gPanels
[ID
].X
, gPanels
[ID
].Y
,
3191 gPanels
[ID
].Height
);
3192 j_max
:= Length(gPanels
) - 1;
3197 res
:= (gItems
<> nil) and
3198 miLayerItems
.Checked
and
3199 g_CollidePoint(X
, Y
, gItems
[ID
].X
, gItems
[ID
].Y
,
3200 ItemSize
[gItems
[ID
].ItemType
][0],
3201 ItemSize
[gItems
[ID
].ItemType
][1]);
3202 j_max
:= Length(gItems
) - 1;
3207 res
:= (gMonsters
<> nil) and
3208 miLayerMonsters
.Checked
and
3209 g_CollidePoint(X
, Y
, gMonsters
[ID
].X
, gMonsters
[ID
].Y
,
3210 MonsterSize
[gMonsters
[ID
].MonsterType
].Width
,
3211 MonsterSize
[gMonsters
[ID
].MonsterType
].Height
);
3212 j_max
:= Length(gMonsters
) - 1;
3217 res
:= (gAreas
<> nil) and
3218 miLayerAreas
.Checked
and
3219 g_CollidePoint(X
, Y
, gAreas
[ID
].X
, gAreas
[ID
].Y
,
3220 AreaSize
[gAreas
[ID
].AreaType
].Width
,
3221 AreaSize
[gAreas
[ID
].AreaType
].Height
);
3222 j_max
:= Length(gAreas
) - 1;
3227 res
:= (gTriggers
<> nil) and
3228 miLayerTriggers
.Checked
and
3229 g_CollidePoint(X
, Y
, gTriggers
[ID
].X
, gTriggers
[ID
].Y
,
3230 gTriggers
[ID
].Width
,
3231 gTriggers
[ID
].Height
);
3232 j_max
:= Length(gTriggers
) - 1;
3242 // Перебор ID: от ID-1 до 0; потом от High до ID+1:
3251 if j
= Integer(ID
) then
3256 res
:= PanelInShownLayer(gPanels
[j
].PanelType
) and
3257 g_CollidePoint(X
, Y
, gPanels
[j
].X
, gPanels
[j
].Y
,
3261 res
:= (gItems
[j
].ItemType
<> ITEM_NONE
) and
3262 g_CollidePoint(X
, Y
, gItems
[j
].X
, gItems
[j
].Y
,
3263 ItemSize
[gItems
[j
].ItemType
][0],
3264 ItemSize
[gItems
[j
].ItemType
][1]);
3266 res
:= (gMonsters
[j
].MonsterType
<> MONSTER_NONE
) and
3267 g_CollidePoint(X
, Y
, gMonsters
[j
].X
, gMonsters
[j
].Y
,
3268 MonsterSize
[gMonsters
[j
].MonsterType
].Width
,
3269 MonsterSize
[gMonsters
[j
].MonsterType
].Height
);
3271 res
:= (gAreas
[j
].AreaType
<> AREA_NONE
) and
3272 g_CollidePoint(X
, Y
, gAreas
[j
].X
, gAreas
[j
].Y
,
3273 AreaSize
[gAreas
[j
].AreaType
].Width
,
3274 AreaSize
[gAreas
[j
].AreaType
].Height
);
3276 res
:= (gTriggers
[j
].TriggerType
<> TRIGGER_NONE
) and
3277 g_CollidePoint(X
, Y
, gTriggers
[j
].X
, gTriggers
[j
].Y
,
3279 gTriggers
[j
].Height
);
3286 SetLength(SelectedObjects
, 1);
3288 SelectedObjects
[0].ObjectType
:= ObjectType
;
3289 SelectedObjects
[0].ID
:= j
;
3290 SelectedObjects
[0].Live
:= True;
3298 procedure TMainForm
.RenderPanelMouseDown(Sender
: TObject
;
3299 Button
: TMouseButton
; Shift
: TShiftState
; X
, Y
: Integer);
3303 c1
, c2
, c3
, c4
: Boolean;
3309 ActiveControl
:= RenderPanel
;
3310 RenderPanel
.SetFocus();
3312 RenderPanelMouseMove(RenderPanel
, Shift
, X
, Y
);
3314 if Button
= mbLeft
then // Left Mouse Button
3316 // Двигаем карту с помощью мыши и мини-карты:
3318 g_CollidePoint(X
, Y
,
3319 RenderPanel
.Width
-max(gMapInfo
.Width
div (16 div Scale
), 1)-1,
3321 max(gMapInfo
.Width
div (16 div Scale
), 1),
3322 max(gMapInfo
.Height
div (16 div Scale
), 1) ) then
3325 MouseAction
:= MOUSEACTION_MOVEMAP
;
3327 else // Ставим предмет/монстра/область:
3328 if (pcObjects
.ActivePageIndex
in [1, 2, 3]) and
3329 (not (ssShift
in Shift
)) then
3331 case pcObjects
.ActivePageIndex
of
3333 if lbItemList
.ItemIndex
= -1 then
3334 ErrorMessageBox(MsgMsgChooseItem
)
3337 item
.ItemType
:= lbItemList
.ItemIndex
+ ITEM_MEDKIT_SMALL
;
3338 if item
.ItemType
>= ITEM_WEAPON_IRONFIST
then
3339 item
.ItemType
:= item
.ItemType
+ 2;
3340 item
.X
:= MousePos
.X
-MapOffset
.X
;
3341 item
.Y
:= MousePos
.Y
-MapOffset
.Y
;
3343 if not (ssCtrl
in Shift
) then
3345 item
.X
:= item
.X
- (ItemSize
[item
.ItemType
][0] div 2);
3346 item
.Y
:= item
.Y
- ItemSize
[item
.ItemType
][1];
3349 item
.OnlyDM
:= cbOnlyDM
.Checked
;
3350 item
.Fall
:= cbFall
.Checked
;
3351 Undo_Add(OBJECT_ITEM
, AddItem(item
));
3354 if lbMonsterList
.ItemIndex
= -1 then
3355 ErrorMessageBox(MsgMsgChooseMonster
)
3358 monster
.MonsterType
:= lbMonsterList
.ItemIndex
+ MONSTER_DEMON
;
3359 monster
.X
:= MousePos
.X
-MapOffset
.X
;
3360 monster
.Y
:= MousePos
.Y
-MapOffset
.Y
;
3362 if not (ssCtrl
in Shift
) then
3364 monster
.X
:= monster
.X
- (MonsterSize
[monster
.MonsterType
].Width
div 2);
3365 monster
.Y
:= monster
.Y
- MonsterSize
[monster
.MonsterType
].Height
;
3368 if rbMonsterLeft
.Checked
then
3369 monster
.Direction
:= D_LEFT
3371 monster
.Direction
:= D_RIGHT
;
3372 Undo_Add(OBJECT_MONSTER
, AddMonster(monster
));
3375 if lbAreasList
.ItemIndex
= -1 then
3376 ErrorMessageBox(MsgMsgChooseArea
)
3378 if (lbAreasList
.ItemIndex
+ 1) <> AREA_DOMFLAG
then
3380 area
.AreaType
:= lbAreasList
.ItemIndex
+ AREA_PLAYERPOINT1
;
3381 area
.X
:= MousePos
.X
-MapOffset
.X
;
3382 area
.Y
:= MousePos
.Y
-MapOffset
.Y
;
3384 if not (ssCtrl
in Shift
) then
3386 area
.X
:= area
.X
- (AreaSize
[area
.AreaType
].Width
div 2);
3387 area
.Y
:= area
.Y
- AreaSize
[area
.AreaType
].Height
;
3390 if rbAreaLeft
.Checked
then
3391 area
.Direction
:= D_LEFT
3393 area
.Direction
:= D_RIGHT
;
3394 Undo_Add(OBJECT_AREA
, AddArea(area
));
3400 i
:= GetFirstSelected();
3402 // Выбираем объект под текущим:
3403 if (SelectedObjects
<> nil) and
3404 (ssShift
in Shift
) and (i
>= 0) and
3405 (SelectedObjects
[i
].Live
) then
3407 if SelectedObjectCount() = 1 then
3408 SelectNextObject(X
-MapOffset
.X
, Y
-MapOffset
.Y
,
3409 SelectedObjects
[i
].ObjectType
,
3410 SelectedObjects
[i
].ID
);
3414 // Рисуем область триггера "Расширитель":
3415 if DrawPressRect
and (i
>= 0) and
3416 (SelectedObjects
[i
].ObjectType
= OBJECT_TRIGGER
) and
3417 (gTriggers
[SelectedObjects
[i
].ID
].TriggerType
in
3418 [TRIGGER_PRESS
, TRIGGER_ON
, TRIGGER_OFF
, TRIGGER_ONOFF
]) then
3419 MouseAction
:= MOUSEACTION_DRAWPRESS
3420 else // Рисуем панель:
3421 if pcObjects
.ActivePageIndex
= 0 then
3423 if (lbPanelType
.ItemIndex
>= 0) then
3424 MouseAction
:= MOUSEACTION_DRAWPANEL
3426 else // Рисуем триггер:
3427 if (lbTriggersList
.ItemIndex
>= 0) then
3429 MouseAction
:= MOUSEACTION_DRAWTRIGGER
;
3433 end; // if Button = mbLeft
3435 if Button
= mbRight
then // Right Mouse Button
3437 // Клик по мини-карте:
3439 g_CollidePoint(X
, Y
,
3440 RenderPanel
.Width
-max(gMapInfo
.Width
div (16 div Scale
), 1)-1,
3442 max(gMapInfo
.Width
div (16 div Scale
), 1),
3443 max(gMapInfo
.Height
div (16 div Scale
), 1) ) then
3445 MouseAction
:= MOUSEACTION_NOACTION
;
3447 else // Нужно что-то выбрать мышью:
3448 if SelectFlag
<> SELECTFLAG_NONE
then
3451 SELECTFLAG_TELEPORT
:
3452 // Точку назначения телепортации:
3453 with gTriggers
[SelectedObjects
[
3454 GetFirstSelected() ].ID
].Data
.TargetPoint
do
3456 X
:= MousePos
.X
-MapOffset
.X
;
3457 Y
:= MousePos
.Y
-MapOffset
.Y
;
3460 SELECTFLAG_SPAWNPOINT
:
3461 // Точку создания монстра:
3462 with gTriggers
[SelectedObjects
[GetFirstSelected()].ID
] do
3463 if TriggerType
= TRIGGER_SPAWNMONSTER
then
3465 Data
.MonPos
.X
:= MousePos
.X
-MapOffset
.X
;
3466 Data
.MonPos
.Y
:= MousePos
.Y
-MapOffset
.Y
;
3468 else if TriggerType
= TRIGGER_SPAWNITEM
then
3469 begin // Точка создания предмета:
3470 Data
.ItemPos
.X
:= MousePos
.X
-MapOffset
.X
;
3471 Data
.ItemPos
.Y
:= MousePos
.Y
-MapOffset
.Y
;
3473 else if TriggerType
= TRIGGER_SHOT
then
3474 begin // Точка создания выстрела:
3475 Data
.ShotPos
.X
:= MousePos
.X
-MapOffset
.X
;
3476 Data
.ShotPos
.Y
:= MousePos
.Y
-MapOffset
.Y
;
3482 IDArray
:= ObjectInRect(X
-MapOffset
.X
,
3484 2, 2, OBJECT_PANEL
, True);
3485 if IDArray
<> nil then
3487 for i
:= 0 to High(IDArray
) do
3488 if (gPanels
[IDArray
[i
]].PanelType
= PANEL_OPENDOOR
) or
3489 (gPanels
[IDArray
[i
]].PanelType
= PANEL_CLOSEDOOR
) then
3491 gTriggers
[SelectedObjects
[
3492 GetFirstSelected() ].ID
].Data
.PanelID
:= IDArray
[i
];
3497 gTriggers
[SelectedObjects
[
3498 GetFirstSelected() ].ID
].Data
.PanelID
:= -1;
3502 // Панель с текстурой:
3504 IDArray
:= ObjectInRect(X
-MapOffset
.X
,
3506 2, 2, OBJECT_PANEL
, True);
3507 if IDArray
<> nil then
3509 for i
:= 0 to High(IDArray
) do
3510 if ((gPanels
[IDArray
[i
]].PanelType
in
3511 [PANEL_WALL
, PANEL_BACK
, PANEL_FORE
,
3512 PANEL_WATER
, PANEL_ACID1
, PANEL_ACID2
,
3514 (gPanels
[IDArray
[i
]].PanelType
= PANEL_OPENDOOR
) or
3515 (gPanels
[IDArray
[i
]].PanelType
= PANEL_CLOSEDOOR
)) and
3516 (gPanels
[IDArray
[i
]].TextureName
<> '') then
3518 gTriggers
[SelectedObjects
[
3519 GetFirstSelected() ].ID
].TexturePanel
:= IDArray
[i
];
3524 gTriggers
[SelectedObjects
[
3525 GetFirstSelected() ].ID
].TexturePanel
:= -1;
3531 IDArray
:= ObjectInRect(X
-MapOffset
.X
,
3533 2, 2, OBJECT_PANEL
, True);
3534 if IDArray
<> nil then
3536 for i
:= 0 to High(IDArray
) do
3537 if (gPanels
[IDArray
[i
]].PanelType
= PANEL_LIFTUP
) or
3538 (gPanels
[IDArray
[i
]].PanelType
= PANEL_LIFTDOWN
) or
3539 (gPanels
[IDArray
[i
]].PanelType
= PANEL_LIFTLEFT
) or
3540 (gPanels
[IDArray
[i
]].PanelType
= PANEL_LIFTRIGHT
) then
3542 gTriggers
[SelectedObjects
[
3543 GetFirstSelected() ].ID
].Data
.PanelID
:= IDArray
[i
];
3548 gTriggers
[SelectedObjects
[
3549 GetFirstSelected() ].ID
].Data
.PanelID
:= -1;
3555 IDArray
:= ObjectInRect(X
-MapOffset
.X
,
3557 2, 2, OBJECT_MONSTER
, False);
3558 if IDArray
<> nil then
3559 gTriggers
[SelectedObjects
[
3560 GetFirstSelected() ].ID
].Data
.MonsterID
:= IDArray
[0]+1
3562 gTriggers
[SelectedObjects
[
3563 GetFirstSelected() ].ID
].Data
.MonsterID
:= 0;
3566 SELECTFLAG_SHOTPANEL
:
3567 // Панель индикации выстрела:
3569 if gTriggers
[SelectedObjects
[
3570 GetFirstSelected() ].ID
].TriggerType
= TRIGGER_SHOT
then
3572 IDArray
:= ObjectInRect(X
-MapOffset
.X
,
3574 2, 2, OBJECT_PANEL
, True);
3575 if IDArray
<> nil then
3577 for i
:= 0 to High(IDArray
) do
3578 if ((gPanels
[IDArray
[i
]].PanelType
in
3579 [PANEL_WALL
, PANEL_BACK
, PANEL_FORE
,
3580 PANEL_WATER
, PANEL_ACID1
, PANEL_ACID2
,
3582 (gPanels
[IDArray
[i
]].PanelType
= PANEL_OPENDOOR
) or
3583 (gPanels
[IDArray
[i
]].PanelType
= PANEL_CLOSEDOOR
)) and
3584 (gPanels
[IDArray
[i
]].TextureName
<> '') then
3586 gTriggers
[SelectedObjects
[
3587 GetFirstSelected() ].ID
].Data
.ShotPanelID
:= IDArray
[i
];
3592 gTriggers
[SelectedObjects
[
3593 GetFirstSelected() ].ID
].Data
.ShotPanelID
:= -1;
3598 SelectFlag
:= SELECTFLAG_SELECTED
;
3600 else // if SelectFlag <> SELECTFLAG_NONE...
3602 // Что уже выбрано и не нажат Ctrl:
3603 if (SelectedObjects
<> nil) and
3604 (not (ssCtrl
in Shift
)) then
3605 for i
:= 0 to High(SelectedObjects
) do
3606 with SelectedObjects
[i
] do
3609 if (ObjectType
in [OBJECT_PANEL
, OBJECT_TRIGGER
]) and
3610 (SelectedObjectCount() = 1) then
3612 Rect
:= ObjectGetRect(ObjectType
, ID
);
3614 c1
:= g_Collide(X
-MapOffset
.X
-1, Y
-MapOffset
.Y
-1, 2, 2,
3615 Rect
.X
-2, Rect
.Y
+(Rect
.Height
div 2)-2, 4, 4);
3616 c2
:= g_Collide(X
-MapOffset
.X
-1, Y
-MapOffset
.Y
-1, 2, 2,
3617 Rect
.X
+Rect
.Width
-3, Rect
.Y
+(Rect
.Height
div 2)-2, 4, 4);
3618 c3
:= g_Collide(X
-MapOffset
.X
-1, Y
-MapOffset
.Y
-1, 2, 2,
3619 Rect
.X
+(Rect
.Width
div 2)-2, Rect
.Y
-2, 4, 4);
3620 c4
:= g_Collide(X
-MapOffset
.X
-1, Y
-MapOffset
.Y
-1, 2, 2,
3621 Rect
.X
+(Rect
.Width
div 2)-2, Rect
.Y
+Rect
.Height
-3, 4, 4);
3623 // Меняем размер панели или триггера:
3624 if c1
or c2
or c3
or c4
then
3626 MouseAction
:= MOUSEACTION_RESIZE
;
3627 LastMovePoint
:= MousePos
;
3631 ResizeType
:= RESIZETYPE_HORIZONTAL
;
3633 ResizeDirection
:= RESIZEDIR_LEFT
3635 ResizeDirection
:= RESIZEDIR_RIGHT
;
3636 RenderPanel
.Cursor
:= crSizeWE
;
3640 ResizeType
:= RESIZETYPE_VERTICAL
;
3642 ResizeDirection
:= RESIZEDIR_UP
3644 ResizeDirection
:= RESIZEDIR_DOWN
;
3645 RenderPanel
.Cursor
:= crSizeNS
;
3652 // Перемещаем панель или триггер:
3653 if ObjectCollide(ObjectType
, ID
,
3655 Y
-MapOffset
.Y
-1, 2, 2) then
3657 MouseAction
:= MOUSEACTION_MOVEOBJ
;
3658 LastMovePoint
:= MousePos
;
3664 end; // if Button = mbRight
3666 if Button
= mbMiddle
then // Middle Mouse Button
3668 SetCapture(RenderPanel
.Handle
);
3669 RenderPanel
.Cursor
:= crSize
;
3672 MouseMDown
:= Button
= mbMiddle
;
3674 MouseMDownPos
:= Mouse
.CursorPos
;
3676 MouseRDown
:= Button
= mbRight
;
3678 MouseRDownPos
:= MousePos
;
3680 MouseLDown
:= Button
= mbLeft
;
3682 MouseLDownPos
:= MousePos
;
3685 procedure TMainForm
.RenderPanelMouseUp(Sender
: TObject
;
3686 Button
: TMouseButton
; Shift
: TShiftState
; X
, Y
: Integer);
3691 rSelectRect
: Boolean;
3692 wWidth
, wHeight
: Word;
3695 procedure SelectObjects(ObjectType
: Byte);
3700 IDArray
:= ObjectInRect(rRect
.X
, rRect
.Y
,
3701 rRect
.Width
, rRect
.Height
,
3702 ObjectType
, rSelectRect
);
3704 if IDArray
<> nil then
3705 for i
:= 0 to High(IDArray
) do
3706 SelectObject(ObjectType
, IDArray
[i
], (ssCtrl
in Shift
) or rSelectRect
);
3709 if Button
= mbLeft
then
3710 MouseLDown
:= False;
3711 if Button
= mbRight
then
3712 MouseRDown
:= False;
3713 if Button
= mbMiddle
then
3714 MouseMDown
:= False;
3716 if DrawRect
<> nil then
3722 ResizeType
:= RESIZETYPE_NONE
;
3725 if Button
= mbLeft
then // Left Mouse Button
3727 if MouseAction
<> MOUSEACTION_NONE
then
3728 begin // Было действие мышью
3729 // Мышь сдвинулась во время удержания клавиши,
3730 // либо активирован режим быстрого рисования:
3731 if ((MousePos
.X
<> MouseLDownPos
.X
) and
3732 (MousePos
.Y
<> MouseLDownPos
.Y
)) or
3733 ((MouseAction
in [MOUSEACTION_DRAWPANEL
, MOUSEACTION_DRAWTRIGGER
]) and
3734 (ssCtrl
in Shift
)) then
3737 MOUSEACTION_DRAWPANEL
:
3739 // Фон или передний план без текстуры - ошибка:
3740 if (lbPanelType
.ItemIndex
in [1, 2]) and
3741 (lbTextureList
.ItemIndex
= -1) then
3742 ErrorMessageBox(MsgMsgChooseTexture
)
3743 else // Назначаем параметры панели:
3745 case lbPanelType
.ItemIndex
of
3746 0: Panel
.PanelType
:= PANEL_WALL
;
3747 1: Panel
.PanelType
:= PANEL_BACK
;
3748 2: Panel
.PanelType
:= PANEL_FORE
;
3749 3: Panel
.PanelType
:= PANEL_OPENDOOR
;
3750 4: Panel
.PanelType
:= PANEL_CLOSEDOOR
;
3751 5: Panel
.PanelType
:= PANEL_LADDER
;
3752 6: Panel
.PanelType
:= PANEL_WATER
;
3753 7: Panel
.PanelType
:= PANEL_ACID1
;
3754 8: Panel
.PanelType
:= PANEL_ACID2
;
3755 9: Panel
.PanelType
:= PANEL_LIFTUP
;
3756 10: Panel
.PanelType
:= PANEL_LIFTDOWN
;
3757 11: Panel
.PanelType
:= PANEL_LIFTLEFT
;
3758 12: Panel
.PanelType
:= PANEL_LIFTRIGHT
;
3759 13: Panel
.PanelType
:= PANEL_BLOCKMON
;
3762 Panel
.X
:= Min(MousePos
.X
-MapOffset
.X
, MouseLDownPos
.X
-MapOffset
.X
);
3763 Panel
.Y
:= Min(MousePos
.Y
-MapOffset
.Y
, MouseLDownPos
.Y
-MapOffset
.Y
);
3764 if ssCtrl
in Shift
then
3768 if (lbTextureList
.ItemIndex
<> -1) and
3769 (not IsSpecialTextureSel()) then
3771 if not g_GetTexture(SelectedTexture(), TextureID
) then
3772 g_GetTexture('NOTEXTURE', TextureID
);
3773 g_GetTextureSizeByID(TextureID
, wWidth
, wHeight
);
3775 Panel
.Width
:= wWidth
;
3776 Panel
.Height
:= wHeight
;
3780 Panel
.Width
:= Abs(MousePos
.X
-MouseLDownPos
.X
);
3781 Panel
.Height
:= Abs(MousePos
.Y
-MouseLDownPos
.Y
);
3784 // Лифты, блокМон или отсутствие текстуры - пустая текстура:
3785 if (lbPanelType
.ItemIndex
in [9, 10, 11, 12, 13]) or
3786 (lbTextureList
.ItemIndex
= -1) then
3788 Panel
.TextureHeight
:= 1;
3789 Panel
.TextureWidth
:= 1;
3790 Panel
.TextureName
:= '';
3791 Panel
.TextureID
:= TEXTURE_SPECIAL_NONE
;
3793 else // Есть текстура:
3795 Panel
.TextureName
:= SelectedTexture();
3797 // Обычная текстура:
3798 if not IsSpecialTextureSel() then
3800 g_GetTextureSizeByName(Panel
.TextureName
,
3801 Panel
.TextureWidth
, Panel
.TextureHeight
);
3802 g_GetTexture(Panel
.TextureName
, Panel
.TextureID
);
3804 else // Спец.текстура:
3806 Panel
.TextureHeight
:= 1;
3807 Panel
.TextureWidth
:= 1;
3808 Panel
.TextureID
:= SpecialTextureID(SelectedTexture());
3813 Panel
.Blending
:= False;
3815 Undo_Add(OBJECT_PANEL
, AddPanel(Panel
));
3819 // Рисовали триггер:
3820 MOUSEACTION_DRAWTRIGGER
:
3822 trigger
.X
:= Min(MousePos
.X
-MapOffset
.X
, MouseLDownPos
.X
-MapOffset
.X
);
3823 trigger
.Y
:= Min(MousePos
.Y
-MapOffset
.Y
, MouseLDownPos
.Y
-MapOffset
.Y
);
3824 if ssCtrl
in Shift
then
3828 trigger
.Width
:= wWidth
;
3829 trigger
.Height
:= wHeight
;
3833 trigger
.Width
:= Abs(MousePos
.X
-MouseLDownPos
.X
);
3834 trigger
.Height
:= Abs(MousePos
.Y
-MouseLDownPos
.Y
);
3837 trigger
.Enabled
:= True;
3838 trigger
.TriggerType
:= lbTriggersList
.ItemIndex
+1;
3839 trigger
.TexturePanel
:= -1;
3842 trigger
.ActivateType
:= 0;
3844 if clbActivationType
.Checked
[0] then
3845 trigger
.ActivateType
:= Trigger
.ActivateType
or ACTIVATE_PLAYERCOLLIDE
;
3846 if clbActivationType
.Checked
[1] then
3847 trigger
.ActivateType
:= Trigger
.ActivateType
or ACTIVATE_MONSTERCOLLIDE
;
3848 if clbActivationType
.Checked
[2] then
3849 trigger
.ActivateType
:= Trigger
.ActivateType
or ACTIVATE_PLAYERPRESS
;
3850 if clbActivationType
.Checked
[3] then
3851 trigger
.ActivateType
:= Trigger
.ActivateType
or ACTIVATE_MONSTERPRESS
;
3852 if clbActivationType
.Checked
[4] then
3853 trigger
.ActivateType
:= Trigger
.ActivateType
or ACTIVATE_SHOT
;
3854 if clbActivationType
.Checked
[5] then
3855 trigger
.ActivateType
:= Trigger
.ActivateType
or ACTIVATE_NOMONSTER
;
3857 // Необходимые для активации ключи:
3860 if clbKeys
.Checked
[0] then
3861 trigger
.Key
:= Trigger
.Key
or KEY_RED
;
3862 if clbKeys
.Checked
[1] then
3863 trigger
.Key
:= Trigger
.Key
or KEY_GREEN
;
3864 if clbKeys
.Checked
[2] then
3865 trigger
.Key
:= Trigger
.Key
or KEY_BLUE
;
3866 if clbKeys
.Checked
[3] then
3867 trigger
.Key
:= Trigger
.Key
or KEY_REDTEAM
;
3868 if clbKeys
.Checked
[4] then
3869 trigger
.Key
:= Trigger
.Key
or KEY_BLUETEAM
;
3871 // Параметры триггера:
3872 FillByte(trigger
.Data
.Default
[0], 128, 0);
3874 case trigger
.TriggerType
of
3875 // Переключаемая панель:
3876 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
,
3877 TRIGGER_DOOR5
, TRIGGER_CLOSETRAP
, TRIGGER_TRAP
,
3878 TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
:
3880 Trigger
.Data
.PanelID
:= -1;
3886 trigger
.Data
.TargetPoint
.X
:= trigger
.X
-64;
3887 trigger
.Data
.TargetPoint
.Y
:= trigger
.Y
-64;
3888 trigger
.Data
.d2d_teleport
:= True;
3889 trigger
.Data
.TlpDir
:= 0;
3892 // Изменение других триггеров:
3893 TRIGGER_PRESS
, TRIGGER_ON
, TRIGGER_OFF
,
3896 trigger
.Data
.Count
:= 1;
3902 trigger
.Data
.Volume
:= 255;
3903 trigger
.Data
.Pan
:= 127;
3904 trigger
.Data
.PlayCount
:= 1;
3905 trigger
.Data
.Local
:= True;
3906 trigger
.Data
.SoundSwitch
:= False;
3912 trigger
.Data
.MusicAction
:= 1;
3915 // Создание монстра:
3916 TRIGGER_SPAWNMONSTER
:
3918 trigger
.Data
.MonType
:= MONSTER_ZOMBY
;
3919 trigger
.Data
.MonPos
.X
:= trigger
.X
-64;
3920 trigger
.Data
.MonPos
.Y
:= trigger
.Y
-64;
3921 trigger
.Data
.MonHealth
:= 0;
3922 trigger
.Data
.MonActive
:= False;
3923 trigger
.Data
.MonCount
:= 1;
3926 // Создание предмета:
3929 trigger
.Data
.ItemType
:= ITEM_AMMO_BULLETS
;
3930 trigger
.Data
.ItemPos
.X
:= trigger
.X
-64;
3931 trigger
.Data
.ItemPos
.Y
:= trigger
.Y
-64;
3932 trigger
.Data
.ItemOnlyDM
:= False;
3933 trigger
.Data
.ItemFalls
:= False;
3934 trigger
.Data
.ItemCount
:= 1;
3935 trigger
.Data
.ItemMax
:= 0;
3936 trigger
.Data
.ItemDelay
:= 0;
3942 trigger
.Data
.PushAngle
:= 90;
3943 trigger
.Data
.PushForce
:= 10;
3944 trigger
.Data
.ResetVel
:= True;
3949 trigger
.Data
.ScoreCount
:= 1;
3950 trigger
.Data
.ScoreCon
:= True;
3951 trigger
.Data
.ScoreMsg
:= True;
3956 trigger
.Data
.MessageKind
:= 0;
3957 trigger
.Data
.MessageSendTo
:= 0;
3958 trigger
.Data
.MessageText
:= '';
3959 trigger
.Data
.MessageTime
:= 144;
3964 trigger
.Data
.DamageValue
:= 5;
3965 trigger
.Data
.DamageInterval
:= 12;
3970 trigger
.Data
.HealValue
:= 5;
3971 trigger
.Data
.HealInterval
:= 36;
3976 trigger
.Data
.ShotType
:= TRIGGER_SHOT_BULLET
;
3977 trigger
.Data
.ShotSound
:= True;
3978 trigger
.Data
.ShotPanelID
:= -1;
3979 trigger
.Data
.ShotTarget
:= 0;
3980 trigger
.Data
.ShotIntSight
:= 0;
3981 trigger
.Data
.ShotAim
:= TRIGGER_SHOT_AIM_DEFAULT
;
3982 trigger
.Data
.ShotPos
.X
:= trigger
.X
-64;
3983 trigger
.Data
.ShotPos
.Y
:= trigger
.Y
-64;
3984 trigger
.Data
.ShotAngle
:= 0;
3985 trigger
.Data
.ShotWait
:= 18;
3986 trigger
.Data
.ShotAccuracy
:= 0;
3987 trigger
.Data
.ShotAmmo
:= 0;
3988 trigger
.Data
.ShotIntReload
:= 0;
3993 trigger
.Data
.FXCount
:= 1;
3994 trigger
.Data
.FXType
:= TRIGGER_EFFECT_PARTICLE
;
3995 trigger
.Data
.FXSubType
:= TRIGGER_EFFECT_SLIQUID
;
3996 trigger
.Data
.FXColorR
:= 0;
3997 trigger
.Data
.FXColorG
:= 0;
3998 trigger
.Data
.FXColorB
:= 255;
3999 trigger
.Data
.FXPos
:= TRIGGER_EFFECT_POS_CENTER
;
4000 trigger
.Data
.FXWait
:= 1;
4001 trigger
.Data
.FXVelX
:= 0;
4002 trigger
.Data
.FXVelY
:= -20;
4003 trigger
.Data
.FXSpreadL
:= 5;
4004 trigger
.Data
.FXSpreadR
:= 5;
4005 trigger
.Data
.FXSpreadU
:= 4;
4006 trigger
.Data
.FXSpreadD
:= 0;
4010 Undo_Add(OBJECT_TRIGGER
, AddTrigger(trigger
));
4013 // Рисовали область триггера "Расширитель":
4014 MOUSEACTION_DRAWPRESS
:
4015 with gTriggers
[SelectedObjects
[GetFirstSelected
].ID
] do
4017 Data
.tX
:= Min(MousePos
.X
-MapOffset
.X
, MouseLDownPos
.X
-MapOffset
.X
);
4018 Data
.tY
:= Min(MousePos
.Y
-MapOffset
.Y
, MouseLDownPos
.Y
-MapOffset
.Y
);
4019 Data
.tWidth
:= Abs(MousePos
.X
-MouseLDownPos
.X
);
4020 Data
.tHeight
:= Abs(MousePos
.Y
-MouseLDownPos
.Y
);
4022 DrawPressRect
:= False;
4026 MouseAction
:= MOUSEACTION_NONE
;
4028 end // if Button = mbLeft...
4029 else if Button
= mbRight
then // Right Mouse Button:
4031 if MouseAction
= MOUSEACTION_NOACTION
then
4033 MouseAction
:= MOUSEACTION_NONE
;
4037 // Объект передвинут или изменен в размере:
4038 if MouseAction
in [MOUSEACTION_MOVEOBJ
, MOUSEACTION_RESIZE
] then
4040 RenderPanel
.Cursor
:= crDefault
;
4041 MouseAction
:= MOUSEACTION_NONE
;
4046 // Еще не все выбрали:
4047 if SelectFlag
<> SELECTFLAG_NONE
then
4049 if SelectFlag
= SELECTFLAG_SELECTED
then
4050 SelectFlag
:= SELECTFLAG_NONE
;
4055 // Мышь сдвинулась во время удержания клавиши:
4056 if (MousePos
.X
<> MouseRDownPos
.X
) and
4057 (MousePos
.Y
<> MouseRDownPos
.Y
) then
4059 rSelectRect
:= True;
4061 rRect
.X
:= Min(MousePos
.X
, MouseRDownPos
.X
)-MapOffset
.X
;
4062 rRect
.Y
:= Min(MousePos
.Y
, MouseRDownPos
.Y
)-MapOffset
.Y
;
4063 rRect
.Width
:= Abs(MousePos
.X
-MouseRDownPos
.X
);
4064 rRect
.Height
:= Abs(MousePos
.Y
-MouseRDownPos
.Y
);
4066 else // Мышь не сдвинулась - нет прямоугольника:
4068 rSelectRect
:= False;
4070 rRect
.X
:= X
-MapOffset
.X
-1;
4071 rRect
.Y
:= Y
-MapOffset
.Y
-1;
4076 // Если зажат Ctrl - выделять еще, иначе только один выделенный объект:
4077 if not (ssCtrl
in Shift
) then
4078 RemoveSelectFromObjects();
4080 // Выделяем всё в выбранном прямоугольнике:
4081 if (ssCtrl
in Shift
) and (ssAlt
in Shift
) then
4083 SelectObjects(OBJECT_PANEL
);
4084 SelectObjects(OBJECT_ITEM
);
4085 SelectObjects(OBJECT_MONSTER
);
4086 SelectObjects(OBJECT_AREA
);
4087 SelectObjects(OBJECT_TRIGGER
);
4090 SelectObjects(pcObjects
.ActivePageIndex
+1);
4095 else // Middle Mouse Button
4097 RenderPanel
.Cursor
:= crDefault
;
4102 procedure TMainForm
.RenderPanelPaint(Sender
: TObject
);
4107 function TMainForm
.RenderMousePos(): Types
.TPoint
;
4109 Result
:= RenderPanel
.ScreenToClient(Mouse
.CursorPos
);
4112 procedure TMainForm
.RecountSelectedObjects();
4114 if SelectedObjectCount() = 0 then
4115 StatusBar
.Panels
[0].Text := ''
4117 StatusBar
.Panels
[0].Text := Format(MsgCapStatSelected
, [SelectedObjectCount()]);
4120 procedure TMainForm
.RenderPanelMouseMove(Sender
: TObject
;
4121 Shift
: TShiftState
; X
, Y
: Integer);
4124 dWidth
, dHeight
: Integer;
4127 wWidth
, wHeight
: Word;
4129 _id
:= GetFirstSelected();
4132 // Рисуем панель с текстурой, сетка - размеры текстуры:
4133 if (MouseAction
= MOUSEACTION_DRAWPANEL
) and
4134 (lbPanelType
.ItemIndex
in [0..8]) and
4135 (lbTextureList
.ItemIndex
<> -1) and
4136 (not IsSpecialTextureSel()) then
4138 sX
:= StrToIntDef(lTextureWidth
.Caption
, DotStep
);
4139 sY
:= StrToIntDef(lTextureHeight
.Caption
, DotStep
);
4142 // Меняем размер панели с текстурой, сетка - размеры текстуры:
4143 if (MouseAction
= MOUSEACTION_RESIZE
) and
4144 ( (SelectedObjects
[_id
].ObjectType
= OBJECT_PANEL
) and
4145 IsTexturedPanel(gPanels
[SelectedObjects
[_id
].ID
].PanelType
) and
4146 (gPanels
[SelectedObjects
[_id
].ID
].TextureName
<> '') and
4147 (not IsSpecialTexture(gPanels
[SelectedObjects
[_id
].ID
].TextureName
)) ) then
4149 sX
:= gPanels
[SelectedObjects
[_id
].ID
].TextureWidth
;
4150 sY
:= gPanels
[SelectedObjects
[_id
].ID
].TextureHeight
;
4153 // Выравнивание по сетке:
4159 else // Нет выравнивания по сетке:
4165 // Новая позиция мыши:
4167 begin // Зажата левая кнопка мыши
4168 MousePos
.X
:= (Round((X
-MouseLDownPos
.X
)/sX
)*sX
)+MouseLDownPos
.X
;
4169 MousePos
.Y
:= (Round((Y
-MouseLDownPos
.Y
)/sY
)*sY
)+MouseLDownPos
.Y
;
4173 begin // Зажата правая кнопка мыши
4174 MousePos
.X
:= (Round((X
-MouseRDownPos
.X
)/sX
)*sX
)+MouseRDownPos
.X
;
4175 MousePos
.Y
:= (Round((Y
-MouseRDownPos
.Y
)/sY
)*sY
)+MouseRDownPos
.Y
;
4178 begin // Кнопки мыши не зажаты
4179 MousePos
.X
:= Round((-MapOffset
.X
+ X
) / sX
) * sX
+ MapOffset
.X
;
4180 MousePos
.Y
:= Round((-MapOffset
.Y
+ Y
) / sY
) * sY
+ MapOffset
.Y
;
4183 // Зажата только правая кнопка мыши:
4184 if (not MouseLDown
) and (MouseRDown
) and (not MouseMDown
) then
4186 // Рисуем прямоугольник выделения:
4187 if MouseAction
= MOUSEACTION_NONE
then
4189 if DrawRect
= nil then
4191 DrawRect
.Top
:= MouseRDownPos
.y
;
4192 DrawRect
.Left
:= MouseRDownPos
.x
;
4193 DrawRect
.Bottom
:= MousePos
.y
;
4194 DrawRect
.Right
:= MousePos
.x
;
4197 // Двигаем выделенные объекты:
4198 if MouseAction
= MOUSEACTION_MOVEOBJ
then
4200 MoveSelectedObjects(ssShift
in Shift
, ssCtrl
in Shift
,
4201 MousePos
.X
-LastMovePoint
.X
,
4202 MousePos
.Y
-LastMovePoint
.Y
);
4205 // Меняем размер выделенного объекта:
4206 if MouseAction
= MOUSEACTION_RESIZE
then
4208 if (SelectedObjectCount
= 1) and
4209 (SelectedObjects
[GetFirstSelected
].Live
) then
4211 dWidth
:= MousePos
.X
-LastMovePoint
.X
;
4212 dHeight
:= MousePos
.Y
-LastMovePoint
.Y
;
4215 RESIZETYPE_VERTICAL
: dWidth
:= 0;
4216 RESIZETYPE_HORIZONTAL
: dHeight
:= 0;
4219 case ResizeDirection
of
4220 RESIZEDIR_UP
: dHeight
:= -dHeight
;
4221 RESIZEDIR_LEFT
: dWidth
:= -dWidth
;
4224 if ResizeObject(SelectedObjects
[GetFirstSelected
].ObjectType
,
4225 SelectedObjects
[GetFirstSelected
].ID
,
4226 dWidth
, dHeight
, ResizeDirection
) then
4227 LastMovePoint
:= MousePos
;
4232 // Зажата только левая кнопка мыши:
4233 if (not MouseRDown
) and (MouseLDown
) and (not MouseMDown
) then
4235 // Рисуем прямоугольник планирования панели:
4236 if MouseAction
in [MOUSEACTION_DRAWPANEL
,
4237 MOUSEACTION_DRAWTRIGGER
,
4238 MOUSEACTION_DRAWPRESS
] then
4240 if DrawRect
= nil then
4242 if ssCtrl
in Shift
then
4246 if (lbTextureList
.ItemIndex
<> -1) and (not IsSpecialTextureSel()) and
4247 (MouseAction
= MOUSEACTION_DRAWPANEL
) then
4249 if not g_GetTexture(SelectedTexture(), TextureID
) then
4250 g_GetTexture('NOTEXTURE', TextureID
);
4251 g_GetTextureSizeByID(TextureID
, wWidth
, wHeight
);
4253 DrawRect
.Top
:= MouseLDownPos
.y
;
4254 DrawRect
.Left
:= MouseLDownPos
.x
;
4255 DrawRect
.Bottom
:= DrawRect
.Top
+ wHeight
;
4256 DrawRect
.Right
:= DrawRect
.Left
+ wWidth
;
4260 DrawRect
.Top
:= MouseLDownPos
.y
;
4261 DrawRect
.Left
:= MouseLDownPos
.x
;
4262 DrawRect
.Bottom
:= MousePos
.y
;
4263 DrawRect
.Right
:= MousePos
.x
;
4266 else // Двигаем карту:
4267 if MouseAction
= MOUSEACTION_MOVEMAP
then
4273 // Only Middle Mouse Button is pressed
4274 if (not MouseLDown
) and (not MouseRDown
) and (MouseMDown
) then
4276 MapOffset
.X
:= -EnsureRange(-MapOffset
.X
+ MouseMDownPos
.X
- Mouse
.CursorPos
.X
,
4277 sbHorizontal
.Min
, sbHorizontal
.Max
);
4278 sbHorizontal
.Position
:= -MapOffset
.X
;
4279 MapOffset
.Y
:= -EnsureRange(-MapOffset
.Y
+ MouseMDownPos
.Y
- Mouse
.CursorPos
.Y
,
4280 sbVertical
.Min
, sbVertical
.Max
);
4281 sbVertical
.Position
:= -MapOffset
.Y
;
4282 MouseMDownPos
:= Mouse
.CursorPos
;
4285 // Клавиши мыши не зажаты:
4286 if (not MouseRDown
) and (not MouseLDown
) and (DrawRect
<> nil) then
4292 // Строка состояния - координаты мыши:
4293 StatusBar
.Panels
[1].Text := Format('(%d:%d)',
4294 [MousePos
.X
-MapOffset
.X
, MousePos
.Y
-MapOffset
.Y
]);
4296 RenderPanel
.Invalidate
;
4299 procedure TMainForm
.FormCloseQuery(Sender
: TObject
; var CanClose
: Boolean);
4301 CanClose
:= Application
.MessageBox(PChar(MsgMsgExitPrompt
),
4303 MB_ICONQUESTION
or MB_YESNO
or
4304 MB_DEFBUTTON1
) = idYes
;
4307 procedure TMainForm
.aExitExecute(Sender
: TObject
);
4312 procedure TMainForm
.FormDestroy(Sender
: TObject
);
4318 config
:= TConfig
.CreateFile(CfgFileName
);
4320 config
.WriteInt('WADEditor', 'LogLevel', gWADEditorLogLevel
);
4322 if WindowState
<> wsMaximized
then
4324 config
.WriteInt('Editor', 'XPos', Left
);
4325 config
.WriteInt('Editor', 'YPos', Top
);
4326 config
.WriteInt('Editor', 'Width', Width
);
4327 config
.WriteInt('Editor', 'Height', Height
);
4331 config
.WriteInt('Editor', 'XPos', RestoredLeft
);
4332 config
.WriteInt('Editor', 'YPos', RestoredTop
);
4333 config
.WriteInt('Editor', 'Width', RestoredWidth
);
4334 config
.WriteInt('Editor', 'Height', RestoredHeight
);
4336 config
.WriteBool('Editor', 'Maximize', WindowState
= wsMaximized
);
4337 config
.WriteBool('Editor', 'Minimap', ShowMap
);
4338 config
.WriteInt('Editor', 'PanelProps', PanelProps
.ClientWidth
);
4339 config
.WriteInt('Editor', 'PanelObjs', PanelObjs
.ClientHeight
);
4340 config
.WriteBool('Editor', 'DotEnable', DotEnable
);
4341 config
.WriteInt('Editor', 'DotStep', DotStep
);
4342 config
.WriteStr('Editor', 'LastOpenDir', OpenDialog
.InitialDir
);
4343 config
.WriteStr('Editor', 'LastSaveDir', SaveDialog
.InitialDir
);
4344 config
.WriteStr('Editor', 'Language', gLanguage
);
4345 config
.WriteBool('Editor', 'EdgeShow', drEdge
[3] < 255);
4346 config
.WriteInt('Editor', 'EdgeColor', gColorEdge
);
4347 config
.WriteInt('Editor', 'EdgeAlpha', gAlphaEdge
);
4348 config
.WriteInt('Editor', 'LineAlpha', gAlphaTriggerLine
);
4349 config
.WriteInt('Editor', 'TriggerAlpha', gAlphaTriggerArea
);
4350 config
.WriteInt('Editor', 'MonsterRectAlpha', gAlphaMonsterRect
);
4351 config
.WriteInt('Editor', 'AreaRectAlpha', gAlphaAreaRect
);
4353 for i
:= 0 to RecentCount
- 1 do
4355 if i
< RecentFiles
.Count
then s
:= RecentFiles
[i
] else s
:= '';
4357 config
.WriteStr('RecentFilesWin', IntToStr(i
), s
);
4359 config
.WriteStr('RecentFilesUnix', IntToStr(i
), s
);
4364 config
.SaveFile(CfgFileName
);
4367 slInvalidTextures
.Free();
4368 DiscardUndoBuffer();
4371 procedure TMainForm
.FormDropFiles(Sender
: TObject
;
4372 const FileNames
: array of String);
4374 if Length(FileNames
) <> 1 then
4377 OpenMapFile(FileNames
[0]);
4380 procedure TMainForm
.RenderPanelResize(Sender
: TObject
);
4386 procedure TMainForm
.Splitter1Moved(Sender
: TObject
);
4391 procedure TMainForm
.MapTestCheck(Sender
: TObject
);
4393 if MapTestProcess
<> nil then
4395 if MapTestProcess
.Running
= false then
4397 if MapTestProcess
.ExitCode
<> 0 then
4398 Application
.MessageBox(PChar(MsgMsgExecError
), 'FIXME', MB_OK
or MB_ICONERROR
);
4399 SysUtils
.DeleteFile(MapTestFile
);
4401 FreeAndNil(MapTestProcess
);
4402 tbTestMap
.Enabled
:= True;
4407 procedure TMainForm
.aMapOptionsExecute(Sender
: TObject
);
4411 MapOptionsForm
.ShowModal();
4413 ResName
:= OpenedMap
;
4414 while (Pos(':\', ResName
) > 0) do
4415 Delete(ResName
, 1, Pos(':\', ResName
) + 1);
4417 UpdateCaption(gMapInfo
.Name
, ExtractFileName(OpenedWAD
), ResName
);
4420 procedure TMainForm
.aAboutExecute(Sender
: TObject
);
4422 AboutForm
.ShowModal();
4425 procedure TMainForm
.FormKeyDown(Sender
: TObject
; var Key
: Word; Shift
: TShiftState
);
4428 ContourItem
: TMenuItem
;
4430 ShowContours
: QWordBool
;
4432 if (not EditingProperties
) then
4434 if ssCtrl
in Shift
then
4437 VK_F1
..VK_F12
: begin
4438 ContourItem
:= MainMenu
.FindItem(PtrInt(Key
), fkShortCut
); // must always succeed!
4439 ContourItem
.Tag
:= not ContourItem
.Tag
;
4443 ShowContours
:= True;
4444 for ContourItem
in miLayers
do
4445 if ContourItem
.IsCheckItem() and QWordBool(ContourItem
.Tag
) then
4447 ShowContours
:= False;
4450 for ContourItem
in miLayers
do
4451 ContourItem
.Tag
:= PtrInt(ShowContours
);
4455 else if Key
= VK_LCL_TILDE
then
4456 tbShowClick(Sender
);
4458 if Key
= Ord('I') then
4459 begin // Поворот монстров и областей:
4460 if (SelectedObjects
<> nil) then
4462 for i
:= 0 to High(SelectedObjects
) do
4463 if (SelectedObjects
[i
].Live
) then
4465 if (SelectedObjects
[i
].ObjectType
= OBJECT_MONSTER
) then
4467 g_ChangeDir(gMonsters
[SelectedObjects
[i
].ID
].Direction
);
4470 if (SelectedObjects
[i
].ObjectType
= OBJECT_AREA
) then
4472 g_ChangeDir(gAreas
[SelectedObjects
[i
].ID
].Direction
);
4478 if pcObjects
.ActivePage
= tsMonsters
then
4480 if rbMonsterLeft
.Checked
then
4481 rbMonsterRight
.Checked
:= True
4483 rbMonsterLeft
.Checked
:= True;
4485 if pcObjects
.ActivePage
= tsAreas
then
4487 if rbAreaLeft
.Checked
then
4488 rbAreaRight
.Checked
:= True
4490 rbAreaLeft
.Checked
:= True;
4495 if not (ssCtrl
in Shift
) then
4497 // Быстрое превью карты:
4498 if Key
= Ord('E') then
4500 if PreviewMode
= 0 then
4504 // Вертикальный скролл карты:
4507 if Key
= Ord('W') then
4510 if ssShift
in Shift
then Position
:= EnsureRange(Position
- DotStep
* 4, Min
, Max
)
4511 else Position
:= EnsureRange(Position
- DotStep
, Min
, Max
);
4512 MapOffset
.Y
:= -Position
;
4515 if (MouseLDown
or MouseRDown
) then
4517 if DrawRect
<> nil then
4519 Inc(MouseLDownPos
.y
, dy
);
4520 Inc(MouseRDownPos
.y
, dy
);
4522 Inc(LastMovePoint
.Y
, dy
);
4523 RenderPanelMouseMove(Sender
, Shift
, RenderMousePos().X
, RenderMousePos().Y
);
4527 if Key
= Ord('S') then
4530 if ssShift
in Shift
then Position
:= EnsureRange(Position
+ DotStep
* 4, Min
, Max
)
4531 else Position
:= EnsureRange(Position
+ DotStep
, Min
, Max
);
4532 MapOffset
.Y
:= -Position
;
4535 if (MouseLDown
or MouseRDown
) then
4537 if DrawRect
<> nil then
4539 Inc(MouseLDownPos
.y
, dy
);
4540 Inc(MouseRDownPos
.y
, dy
);
4542 Inc(LastMovePoint
.Y
, dy
);
4543 RenderPanelMouseMove(Sender
, Shift
, RenderMousePos().X
, RenderMousePos().Y
);
4548 // Горизонтальный скролл карты:
4549 with sbHorizontal
do
4551 if Key
= Ord('A') then
4554 if ssShift
in Shift
then Position
:= EnsureRange(Position
- DotStep
* 4, Min
, Max
)
4555 else Position
:= EnsureRange(Position
- DotStep
, Min
, Max
);
4556 MapOffset
.X
:= -Position
;
4559 if (MouseLDown
or MouseRDown
) then
4561 if DrawRect
<> nil then
4563 Inc(MouseLDownPos
.x
, dx
);
4564 Inc(MouseRDownPos
.x
, dx
);
4566 Inc(LastMovePoint
.X
, dx
);
4567 RenderPanelMouseMove(Sender
, Shift
, RenderMousePos().X
, RenderMousePos().Y
);
4571 if Key
= Ord('D') then
4574 if ssShift
in Shift
then Position
:= EnsureRange(Position
+ DotStep
* 4, Min
, Max
)
4575 else Position
:= EnsureRange(Position
+ DotStep
, Min
, Max
);
4576 MapOffset
.X
:= -Position
;
4579 if (MouseLDown
or MouseRDown
) then
4581 if DrawRect
<> nil then
4583 Inc(MouseLDownPos
.x
, dx
);
4584 Inc(MouseRDownPos
.x
, dx
);
4586 Inc(LastMovePoint
.X
, dx
);
4587 RenderPanelMouseMove(Sender
, Shift
, RenderMousePos().X
, RenderMousePos().Y
);
4592 else // ssCtrl in Shift
4594 if ssShift
in Shift
then
4596 // Вставка по абсолютному смещению:
4597 if Key
= Ord('V') then
4598 aPasteObjectExecute(Sender
);
4600 RenderPanelMouseMove(Sender
, Shift
, RenderMousePos().X
, RenderMousePos().Y
);
4604 // Удалить выделенные объекты:
4605 if (Key
= VK_DELETE
) and (SelectedObjects
<> nil) and RenderPanel
.Focused() then
4606 DeleteSelectedObjects();
4609 if (Key
= VK_ESCAPE
) and (SelectedObjects
<> nil) then
4610 RemoveSelectFromObjects();
4612 // Передвинуть объекты:
4613 if ActiveControl
= RenderPanel
then
4618 if Key
= VK_NUMPAD4
then
4619 dx
:= IfThen(ssAlt
in Shift
, -1, -DotStep
);
4620 if Key
= VK_NUMPAD6
then
4621 dx
:= IfThen(ssAlt
in Shift
, 1, DotStep
);
4622 if Key
= VK_NUMPAD8
then
4623 dy
:= IfThen(ssAlt
in Shift
, -1, -DotStep
);
4624 if Key
= VK_NUMPAD5
then
4625 dy
:= IfThen(ssAlt
in Shift
, 1, DotStep
);
4627 if (dx
<> 0) or (dy
<> 0) then
4629 MoveSelectedObjects(ssShift
in Shift
, ssCtrl
in Shift
, dx
, dy
);
4634 if ssCtrl
in Shift
then
4636 // Выбор панели с текстурой для триггера
4637 if Key
= Ord('T') then
4639 DrawPressRect
:= False;
4640 if SelectFlag
= SELECTFLAG_TEXTURE
then
4642 SelectFlag
:= SELECTFLAG_NONE
;
4645 vleObjectProperty
.FindRow(MsgPropTrTexturePanel
, i
);
4647 SelectFlag
:= SELECTFLAG_TEXTURE
;
4650 if Key
= Ord('D') then
4652 SelectFlag
:= SELECTFLAG_NONE
;
4653 if DrawPressRect
then
4655 DrawPressRect
:= False;
4660 // Выбор области воздействия, в зависимости от типа триггера
4661 vleObjectProperty
.FindRow(MsgPropTrExArea
, i
);
4664 DrawPressRect
:= True;
4667 vleObjectProperty
.FindRow(MsgPropTrDoorPanel
, i
);
4669 vleObjectProperty
.FindRow(MsgPropTrTrapPanel
, i
);
4672 SelectFlag
:= SELECTFLAG_DOOR
;
4675 vleObjectProperty
.FindRow(MsgPropTrLiftPanel
, i
);
4678 SelectFlag
:= SELECTFLAG_LIFT
;
4681 vleObjectProperty
.FindRow(MsgPropTrTeleportTo
, i
);
4684 SelectFlag
:= SELECTFLAG_TELEPORT
;
4687 vleObjectProperty
.FindRow(MsgPropTrSpawnTo
, i
);
4690 SelectFlag
:= SELECTFLAG_SPAWNPOINT
;
4694 // Выбор основного параметра, в зависимости от типа триггера
4695 vleObjectProperty
.FindRow(MsgPropTrNextMap
, i
);
4698 g_ProcessResourceStr(OpenedMap
, @FileName
, nil, nil);
4699 SelectMapForm
.Caption
:= MsgCapSelect
;
4700 SelectMapForm
.GetMaps(FileName
);
4702 if SelectMapForm
.ShowModal() = mrOK
then
4704 vleObjectProperty
.Cells
[1, i
] := SelectMapForm
.lbMapList
.Items
[SelectMapForm
.lbMapList
.ItemIndex
];
4705 bApplyProperty
.Click();
4709 vleObjectProperty
.FindRow(MsgPropTrSoundName
, i
);
4711 vleObjectProperty
.FindRow(MsgPropTrMusicName
, i
);
4714 AddSoundForm
.OKFunction
:= nil;
4715 AddSoundForm
.lbResourcesList
.MultiSelect
:= False;
4716 AddSoundForm
.SetResource
:= vleObjectProperty
.Cells
[1, i
];
4718 if (AddSoundForm
.ShowModal() = mrOk
) then
4720 vleObjectProperty
.Cells
[1, i
] := AddSoundForm
.ResourceName
;
4721 bApplyProperty
.Click();
4725 vleObjectProperty
.FindRow(MsgPropTrPushAngle
, i
);
4727 vleObjectProperty
.FindRow(MsgPropTrMessageText
, i
);
4730 vleObjectProperty
.Row
:= i
;
4731 vleObjectProperty
.SetFocus();
4738 procedure TMainForm
.aOptimizeExecute(Sender
: TObject
);
4740 RemoveSelectFromObjects();
4741 MapOptimizationForm
.ShowModal();
4744 procedure TMainForm
.aCheckMapExecute(Sender
: TObject
);
4746 MapCheckForm
.ShowModal();
4749 procedure TMainForm
.bbAddTextureClick(Sender
: TObject
);
4751 AddTextureForm
.lbResourcesList
.MultiSelect
:= True;
4752 AddTextureForm
.ShowModal();
4755 procedure TMainForm
.lbTextureListClick(Sender
: TObject
);
4758 TextureWidth
, TextureHeight
: Word;
4763 if (lbTextureList
.ItemIndex
<> -1) and
4764 (not IsSpecialTextureSel()) then
4766 if g_GetTexture(SelectedTexture(), TextureID
) then
4768 g_GetTextureSizeByID(TextureID
, TextureWidth
, TextureHeight
);
4770 lTextureWidth
.Caption
:= IntToStr(TextureWidth
);
4771 lTextureHeight
.Caption
:= IntToStr(TextureHeight
);
4774 lTextureWidth
.Caption
:= MsgNotAccessible
;
4775 lTextureHeight
.Caption
:= MsgNotAccessible
;
4780 lTextureWidth
.Caption
:= '';
4781 lTextureHeight
.Caption
:= '';
4785 procedure TMainForm
.lbTextureListDrawItem(Control
: TWinControl
; Index
: Integer;
4786 ARect
: TRect
; State
: TOwnerDrawState
);
4788 with Control
as TListBox
do
4790 if LCLType
.odSelected
in State
then
4792 Canvas
.Brush
.Color
:= clHighlight
;
4793 Canvas
.Font
.Color
:= clHighlightText
;
4795 if (Items
<> nil) and (Index
>= 0) then
4796 if slInvalidTextures
.IndexOf(Items
[Index
]) > -1 then
4798 Canvas
.Brush
.Color
:= clRed
;
4799 Canvas
.Font
.Color
:= clWhite
;
4801 Canvas
.FillRect(ARect
);
4802 Canvas
.TextRect(ARect
, ARect
.Left
, ARect
.Top
, Items
[Index
]);
4806 procedure TMainForm
.miMacMinimizeClick(Sender
: TObject
);
4808 self
.WindowState
:= wsMinimized
;
4809 self
.FormWindowStateChange(Sender
);
4812 procedure TMainForm
.miMacZoomClick(Sender
: TObject
);
4814 if self
.WindowState
= wsMaximized
then
4815 self
.WindowState
:= wsNormal
4817 self
.WindowState
:= wsMaximized
;
4818 self
.FormWindowStateChange(Sender
);
4821 procedure TMainForm
.miReopenMapClick(Sender
: TObject
);
4823 FileName
, Resource
: String;
4825 if OpenedMap
= '' then
4828 if Application
.MessageBox(PChar(MsgMsgReopenMapPrompt
),
4829 PChar(MsgMenuFileReopen
), MB_ICONQUESTION
or MB_YESNO
) <> idYes
then
4832 g_ProcessResourceStr(OpenedMap
, @FileName
, nil, @Resource
);
4833 OpenMap(FileName
, Resource
);
4836 procedure TMainForm
.vleObjectPropertyGetPickList(Sender
: TObject
;
4837 const KeyName
: String; Values
: TStrings
);
4839 if vleObjectProperty
.ItemProps
[KeyName
].EditStyle
= esPickList
then
4841 if KeyName
= MsgPropDirection
then
4843 Values
.Add(DirNames
[D_LEFT
]);
4844 Values
.Add(DirNames
[D_RIGHT
]);
4846 else if KeyName
= MsgPropTrTeleportDir
then
4848 Values
.Add(DirNamesAdv
[0]);
4849 Values
.Add(DirNamesAdv
[1]);
4850 Values
.Add(DirNamesAdv
[2]);
4851 Values
.Add(DirNamesAdv
[3]);
4853 else if KeyName
= MsgPropTrMusicAct
then
4855 Values
.Add(MsgPropTrMusicOn
);
4856 Values
.Add(MsgPropTrMusicOff
);
4858 else if KeyName
= MsgPropTrMonsterBehaviour
then
4860 Values
.Add(MsgPropTrMonsterBehaviour0
);
4861 Values
.Add(MsgPropTrMonsterBehaviour1
);
4862 Values
.Add(MsgPropTrMonsterBehaviour2
);
4863 Values
.Add(MsgPropTrMonsterBehaviour3
);
4864 Values
.Add(MsgPropTrMonsterBehaviour4
);
4865 Values
.Add(MsgPropTrMonsterBehaviour5
);
4867 else if KeyName
= MsgPropTrScoreAct
then
4869 Values
.Add(MsgPropTrScoreAct0
);
4870 Values
.Add(MsgPropTrScoreAct1
);
4871 Values
.Add(MsgPropTrScoreAct2
);
4872 Values
.Add(MsgPropTrScoreAct3
);
4874 else if KeyName
= MsgPropTrScoreTeam
then
4876 Values
.Add(MsgPropTrScoreTeam0
);
4877 Values
.Add(MsgPropTrScoreTeam1
);
4878 Values
.Add(MsgPropTrScoreTeam2
);
4879 Values
.Add(MsgPropTrScoreTeam3
);
4881 else if KeyName
= MsgPropTrMessageKind
then
4883 Values
.Add(MsgPropTrMessageKind0
);
4884 Values
.Add(MsgPropTrMessageKind1
);
4886 else if KeyName
= MsgPropTrMessageTo
then
4888 Values
.Add(MsgPropTrMessageTo0
);
4889 Values
.Add(MsgPropTrMessageTo1
);
4890 Values
.Add(MsgPropTrMessageTo2
);
4891 Values
.Add(MsgPropTrMessageTo3
);
4892 Values
.Add(MsgPropTrMessageTo4
);
4893 Values
.Add(MsgPropTrMessageTo5
);
4895 else if KeyName
= MsgPropTrShotTo
then
4897 Values
.Add(MsgPropTrShotTo0
);
4898 Values
.Add(MsgPropTrShotTo1
);
4899 Values
.Add(MsgPropTrShotTo2
);
4900 Values
.Add(MsgPropTrShotTo3
);
4901 Values
.Add(MsgPropTrShotTo4
);
4902 Values
.Add(MsgPropTrShotTo5
);
4903 Values
.Add(MsgPropTrShotTo6
);
4905 else if KeyName
= MsgPropTrShotAim
then
4907 Values
.Add(MsgPropTrShotAim0
);
4908 Values
.Add(MsgPropTrShotAim1
);
4909 Values
.Add(MsgPropTrShotAim2
);
4910 Values
.Add(MsgPropTrShotAim3
);
4912 else if KeyName
= MsgPropTrDamageKind
then
4914 Values
.Add(MsgPropTrDamageKind0
);
4915 Values
.Add(MsgPropTrDamageKind3
);
4916 Values
.Add(MsgPropTrDamageKind4
);
4917 Values
.Add(MsgPropTrDamageKind5
);
4918 Values
.Add(MsgPropTrDamageKind6
);
4919 Values
.Add(MsgPropTrDamageKind7
);
4920 Values
.Add(MsgPropTrDamageKind8
);
4922 else if (KeyName
= MsgPropPanelBlend
) or
4923 (KeyName
= MsgPropDmOnly
) or
4924 (KeyName
= MsgPropItemFalls
) or
4925 (KeyName
= MsgPropTrEnabled
) or
4926 (KeyName
= MsgPropTrD2d
) or
4927 (KeyName
= MsgPropTrSilent
) or
4928 (KeyName
= MsgPropTrTeleportSilent
) or
4929 (KeyName
= MsgPropTrExRandom
) or
4930 (KeyName
= MsgPropTrTextureOnce
) or
4931 (KeyName
= MsgPropTrTextureAnimOnce
) or
4932 (KeyName
= MsgPropTrSoundLocal
) or
4933 (KeyName
= MsgPropTrSoundSwitch
) or
4934 (KeyName
= MsgPropTrMonsterActive
) or
4935 (KeyName
= MsgPropTrPushReset
) or
4936 (KeyName
= MsgPropTrScoreCon
) or
4937 (KeyName
= MsgPropTrScoreMsg
) or
4938 (KeyName
= MsgPropTrHealthMax
) or
4939 (KeyName
= MsgPropTrShotSound
) or
4940 (KeyName
= MsgPropTrEffectCenter
) then
4942 Values
.Add(BoolNames
[True]);
4943 Values
.Add(BoolNames
[False]);
4948 procedure TMainForm
.bApplyPropertyClick(Sender
: TObject
);
4950 _id
, a
, r
, c
: Integer;
4960 if SelectedObjectCount() <> 1 then
4962 if not SelectedObjects
[GetFirstSelected()].Live
then
4966 if not CheckProperty() then
4972 _id
:= GetFirstSelected();
4974 r
:= vleObjectProperty
.Row
;
4975 c
:= vleObjectProperty
.Col
;
4977 case SelectedObjects
[_id
].ObjectType
of
4980 with gPanels
[SelectedObjects
[_id
].ID
] do
4982 X
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropX
]));
4983 Y
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropY
]));
4984 Width
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropWidth
]));
4985 Height
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropHeight
]));
4987 PanelType
:= GetPanelType(vleObjectProperty
.Values
[MsgPropPanelType
]);
4989 // Сброс ссылки на триггеры смены текстуры:
4990 if not WordBool(PanelType
and (PANEL_WALL
or PANEL_FORE
or PANEL_BACK
)) then
4991 if gTriggers
<> nil then
4992 for a
:= 0 to High(gTriggers
) do
4994 if (gTriggers
[a
].TriggerType
<> 0) and
4995 (gTriggers
[a
].TexturePanel
= Integer(SelectedObjects
[_id
].ID
)) then
4996 gTriggers
[a
].TexturePanel
:= -1;
4997 if (gTriggers
[a
].TriggerType
= TRIGGER_SHOT
) and
4998 (gTriggers
[a
].Data
.ShotPanelID
= Integer(SelectedObjects
[_id
].ID
)) then
4999 gTriggers
[a
].Data
.ShotPanelID
:= -1;
5002 // Сброс ссылки на триггеры лифта:
5003 if not WordBool(PanelType
and (PANEL_LIFTUP
or PANEL_LIFTDOWN
or PANEL_LIFTLEFT
or PANEL_LIFTRIGHT
)) then
5004 if gTriggers
<> nil then
5005 for a
:= 0 to High(gTriggers
) do
5006 if (gTriggers
[a
].TriggerType
in [TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
]) and
5007 (gTriggers
[a
].Data
.PanelID
= Integer(SelectedObjects
[_id
].ID
)) then
5008 gTriggers
[a
].Data
.PanelID
:= -1;
5010 // Сброс ссылки на триггеры двери:
5011 if not WordBool(PanelType
and (PANEL_OPENDOOR
or PANEL_CLOSEDOOR
)) then
5012 if gTriggers
<> nil then
5013 for a
:= 0 to High(gTriggers
) do
5014 if (gTriggers
[a
].TriggerType
in [TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
,
5015 TRIGGER_DOOR5
, TRIGGER_CLOSETRAP
, TRIGGER_TRAP
]) and
5016 (gTriggers
[a
].Data
.PanelID
= Integer(SelectedObjects
[_id
].ID
)) then
5017 gTriggers
[a
].Data
.PanelID
:= -1;
5019 if IsTexturedPanel(PanelType
) then
5020 begin // Может быть текстура
5021 if TextureName
<> '' then
5022 begin // Была текстура
5023 Alpha
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropPanelAlpha
]));
5024 Blending
:= NameToBool(vleObjectProperty
.Values
[MsgPropPanelBlend
]);
5033 TextureName
:= vleObjectProperty
.Values
[MsgPropPanelTex
];
5035 if TextureName
<> '' then
5036 begin // Есть текстура
5037 // Обычная текстура:
5038 if not IsSpecialTexture(TextureName
) then
5040 g_GetTextureSizeByName(TextureName
,
5041 TextureWidth
, TextureHeight
);
5043 // Проверка кратности размеров панели:
5045 if TextureWidth
<> 0 then
5046 if gPanels
[SelectedObjects
[_id
].ID
].Width
mod TextureWidth
<> 0 then
5048 ErrorMessageBox(Format(MsgMsgWrongTexwidth
,
5052 if Res
and (TextureHeight
<> 0) then
5053 if gPanels
[SelectedObjects
[_id
].ID
].Height
mod TextureHeight
<> 0 then
5055 ErrorMessageBox(Format(MsgMsgWrongTexheight
,
5062 if not g_GetTexture(TextureName
, TextureID
) then
5063 // Не удалось загрузить текстуру, рисуем NOTEXTURE
5064 if g_GetTexture('NOTEXTURE', NoTextureID
) then
5066 TextureID
:= TEXTURE_SPECIAL_NOTEXTURE
;
5067 g_GetTextureSizeByID(NoTextureID
, NW
, NH
);
5069 TextureHeight
:= NH
;
5072 TextureID
:= TEXTURE_SPECIAL_NONE
;
5082 TextureID
:= TEXTURE_SPECIAL_NONE
;
5085 else // Спец.текстура
5089 TextureID
:= SpecialTextureID(TextureName
);
5092 else // Нет текстуры
5096 TextureID
:= TEXTURE_SPECIAL_NONE
;
5099 else // Не может быть текстуры
5106 TextureID
:= TEXTURE_SPECIAL_NONE
;
5113 with gItems
[SelectedObjects
[_id
].ID
] do
5115 X
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropX
]));
5116 Y
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropY
]));
5117 OnlyDM
:= NameToBool(vleObjectProperty
.Values
[MsgPropDmOnly
]);
5118 Fall
:= NameToBool(vleObjectProperty
.Values
[MsgPropItemFalls
]);
5124 with gMonsters
[SelectedObjects
[_id
].ID
] do
5126 X
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropX
]));
5127 Y
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropY
]));
5128 Direction
:= NameToDir(vleObjectProperty
.Values
[MsgPropDirection
]);
5134 with gAreas
[SelectedObjects
[_id
].ID
] do
5136 X
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropX
]));
5137 Y
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropY
]));
5138 Direction
:= NameToDir(vleObjectProperty
.Values
[MsgPropDirection
]);
5144 with gTriggers
[SelectedObjects
[_id
].ID
] do
5146 X
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropX
]));
5147 Y
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropY
]));
5148 Width
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropWidth
]));
5149 Height
:= StrToInt(Trim(vleObjectProperty
.Values
[MsgPropHeight
]));
5150 Enabled
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrEnabled
]);
5151 ActivateType
:= StrToActivate(vleObjectProperty
.Values
[MsgPropTrActivation
]);
5152 Key
:= StrToKey(vleObjectProperty
.Values
[MsgPropTrKeys
]);
5157 s
:= utf2win(vleObjectProperty
.Values
[MsgPropTrNextMap
]);
5158 FillByte(Data
.MapName
[0], 16, 0);
5160 Move(s
[1], Data
.MapName
[0], Min(Length(s
), 16));
5165 Data
.ActivateOnce
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrTextureOnce
]);
5166 Data
.AnimOnce
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrTextureAnimOnce
]);
5169 TRIGGER_PRESS
, TRIGGER_ON
, TRIGGER_OFF
, TRIGGER_ONOFF
:
5171 Data
.Wait
:= Min(StrToIntDef(vleObjectProperty
.Values
[MsgPropTrExDelay
], 0), 65535);
5172 Data
.Count
:= Min(StrToIntDef(vleObjectProperty
.Values
[MsgPropTrExCount
], 0), 65535);
5173 if Data
.Count
< 1 then
5175 if TriggerType
= TRIGGER_PRESS
then
5176 Data
.ExtRandom
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrExRandom
]);
5179 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
, TRIGGER_DOOR5
,
5180 TRIGGER_CLOSETRAP
, TRIGGER_TRAP
, TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
,
5183 Data
.NoSound
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrSilent
]);
5184 Data
.d2d_doors
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrD2d
]);
5189 Data
.d2d_teleport
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrD2d
]);
5190 Data
.silent_teleport
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrTeleportSilent
]);
5191 Data
.TlpDir
:= NameToDirAdv(vleObjectProperty
.Values
[MsgPropTrTeleportDir
]);
5196 s
:= utf2win(vleObjectProperty
.Values
[MsgPropTrSoundName
]);
5197 FillByte(Data
.SoundName
[0], 64, 0);
5199 Move(s
[1], Data
.SoundName
[0], Min(Length(s
), 64));
5201 Data
.Volume
:= Min(StrToIntDef(vleObjectProperty
.Values
[MsgPropTrSoundVolume
], 0), 255);
5202 Data
.Pan
:= Min(StrToIntDef(vleObjectProperty
.Values
[MsgPropTrSoundPan
], 0), 255);
5203 Data
.PlayCount
:= Min(StrToIntDef(vleObjectProperty
.Values
[MsgPropTrSoundCount
], 0), 255);
5204 Data
.Local
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrSoundLocal
]);
5205 Data
.SoundSwitch
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrSoundSwitch
]);
5208 TRIGGER_SPAWNMONSTER
:
5210 Data
.MonType
:= StrToMonster(vleObjectProperty
.Values
[MsgPropTrMonsterType
]);
5211 Data
.MonDir
:= Byte(NameToDir(vleObjectProperty
.Values
[MsgPropDirection
]));
5212 Data
.MonHealth
:= Min(StrToIntDef(vleObjectProperty
.Values
[MsgPropTrHealth
], 0), 1000000);
5213 if Data
.MonHealth
< 0 then
5214 Data
.MonHealth
:= 0;
5215 Data
.MonActive
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrMonsterActive
]);
5216 Data
.MonCount
:= Min(StrToIntDef(vleObjectProperty
.Values
[MsgPropTrCount
], 0), 64);
5217 if Data
.MonCount
< 1 then
5219 Data
.MonEffect
:= StrToEffect(vleObjectProperty
.Values
[MsgPropTrFxType
]);
5220 Data
.MonMax
:= Min(StrToIntDef(vleObjectProperty
.Values
[MsgPropTrSpawnMax
], 0), 65535);
5221 Data
.MonDelay
:= Min(StrToIntDef(vleObjectProperty
.Values
[MsgPropTrSpawnDelay
], 0), 65535);
5223 if vleObjectProperty
.Values
[MsgPropTrMonsterBehaviour
] = MsgPropTrMonsterBehaviour1
then
5225 if vleObjectProperty
.Values
[MsgPropTrMonsterBehaviour
] = MsgPropTrMonsterBehaviour2
then
5227 if vleObjectProperty
.Values
[MsgPropTrMonsterBehaviour
] = MsgPropTrMonsterBehaviour3
then
5229 if vleObjectProperty
.Values
[MsgPropTrMonsterBehaviour
] = MsgPropTrMonsterBehaviour4
then
5231 if vleObjectProperty
.Values
[MsgPropTrMonsterBehaviour
] = MsgPropTrMonsterBehaviour5
then
5237 Data
.ItemType
:= StrToItem(vleObjectProperty
.Values
[MsgPropTrItemType
]);
5238 Data
.ItemOnlyDM
:= NameToBool(vleObjectProperty
.Values
[MsgPropDmOnly
]);
5239 Data
.ItemFalls
:= NameToBool(vleObjectProperty
.Values
[MsgPropItemFalls
]);
5240 Data
.ItemCount
:= Min(StrToIntDef(vleObjectProperty
.Values
[MsgPropTrCount
], 0), 64);
5241 if Data
.ItemCount
< 1 then
5242 Data
.ItemCount
:= 1;
5243 Data
.ItemEffect
:= StrToEffect(vleObjectProperty
.Values
[MsgPropTrFxType
]);
5244 Data
.ItemMax
:= Min(StrToIntDef(vleObjectProperty
.Values
[MsgPropTrSpawnMax
], 0), 65535);
5245 Data
.ItemDelay
:= Min(StrToIntDef(vleObjectProperty
.Values
[MsgPropTrSpawnDelay
], 0), 65535);
5250 s
:= utf2win(vleObjectProperty
.Values
[MsgPropTrMusicName
]);
5251 FillByte(Data
.MusicName
[0], 64, 0);
5253 Move(s
[1], Data
.MusicName
[0], Min(Length(s
), 64));
5255 if vleObjectProperty
.Values
[MsgPropTrMusicAct
] = MsgPropTrMusicOn
then
5256 Data
.MusicAction
:= 1
5258 Data
.MusicAction
:= 0;
5263 Data
.PushAngle
:= Min(
5264 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrPushAngle
], 0), 360);
5265 Data
.PushForce
:= Min(
5266 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrPushForce
], 0), 255);
5267 Data
.ResetVel
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrPushReset
]);
5272 Data
.ScoreAction
:= 0;
5273 if vleObjectProperty
.Values
[MsgPropTrScoreAct
] = MsgPropTrScoreAct1
then
5274 Data
.ScoreAction
:= 1
5275 else if vleObjectProperty
.Values
[MsgPropTrScoreAct
] = MsgPropTrScoreAct2
then
5276 Data
.ScoreAction
:= 2
5277 else if vleObjectProperty
.Values
[MsgPropTrScoreAct
] = MsgPropTrScoreAct3
then
5278 Data
.ScoreAction
:= 3;
5279 Data
.ScoreCount
:= Min(Max(
5280 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrCount
], 0), 0), 255);
5281 Data
.ScoreTeam
:= 0;
5282 if vleObjectProperty
.Values
[MsgPropTrScoreTeam
] = MsgPropTrScoreTeam1
then
5284 else if vleObjectProperty
.Values
[MsgPropTrScoreTeam
] = MsgPropTrScoreTeam2
then
5286 else if vleObjectProperty
.Values
[MsgPropTrScoreTeam
] = MsgPropTrScoreTeam3
then
5287 Data
.ScoreTeam
:= 3;
5288 Data
.ScoreCon
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrScoreCon
]);
5289 Data
.ScoreMsg
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrScoreMsg
]);
5294 Data
.MessageKind
:= 0;
5295 if vleObjectProperty
.Values
[MsgPropTrMessageKind
] = MsgPropTrMessageKind1
then
5296 Data
.MessageKind
:= 1;
5298 Data
.MessageSendTo
:= 0;
5299 if vleObjectProperty
.Values
[MsgPropTrMessageTo
] = MsgPropTrMessageTo1
then
5300 Data
.MessageSendTo
:= 1
5301 else if vleObjectProperty
.Values
[MsgPropTrMessageTo
] = MsgPropTrMessageTo2
then
5302 Data
.MessageSendTo
:= 2
5303 else if vleObjectProperty
.Values
[MsgPropTrMessageTo
] = MsgPropTrMessageTo3
then
5304 Data
.MessageSendTo
:= 3
5305 else if vleObjectProperty
.Values
[MsgPropTrMessageTo
] = MsgPropTrMessageTo4
then
5306 Data
.MessageSendTo
:= 4
5307 else if vleObjectProperty
.Values
[MsgPropTrMessageTo
] = MsgPropTrMessageTo5
then
5308 Data
.MessageSendTo
:= 5;
5310 s
:= utf2win(vleObjectProperty
.Values
[MsgPropTrMessageText
]);
5311 FillByte(Data
.MessageText
[0], 100, 0);
5313 Move(s
[1], Data
.MessageText
[0], Min(Length(s
), 100));
5315 Data
.MessageTime
:= Min(Max(
5316 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrMessageTime
], 0), 0), 65535);
5321 Data
.DamageValue
:= Min(Max(
5322 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrDamageValue
], 0), 0), 65535);
5323 Data
.DamageInterval
:= Min(Max(
5324 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrInterval
], 0), 0), 65535);
5325 s
:= vleObjectProperty
.Values
[MsgPropTrDamageKind
];
5326 if s
= MsgPropTrDamageKind3
then
5327 Data
.DamageKind
:= 3
5328 else if s
= MsgPropTrDamageKind4
then
5329 Data
.DamageKind
:= 4
5330 else if s
= MsgPropTrDamageKind5
then
5331 Data
.DamageKind
:= 5
5332 else if s
= MsgPropTrDamageKind6
then
5333 Data
.DamageKind
:= 6
5334 else if s
= MsgPropTrDamageKind7
then
5335 Data
.DamageKind
:= 7
5336 else if s
= MsgPropTrDamageKind8
then
5337 Data
.DamageKind
:= 8
5339 Data
.DamageKind
:= 0;
5344 Data
.HealValue
:= Min(Max(
5345 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrHealth
], 0), 0), 65535);
5346 Data
.HealInterval
:= Min(Max(
5347 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrInterval
], 0), 0), 65535);
5348 Data
.HealMax
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrHealthMax
]);
5349 Data
.HealSilent
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrSilent
]);
5354 Data
.ShotType
:= StrToShot(vleObjectProperty
.Values
[MsgPropTrShotType
]);
5355 Data
.ShotSound
:= NameToBool(vleObjectProperty
.Values
[MsgPropTrShotSound
]);
5356 Data
.ShotTarget
:= 0;
5357 if vleObjectProperty
.Values
[MsgPropTrShotTo
] = MsgPropTrShotTo1
then
5358 Data
.ShotTarget
:= 1
5359 else if vleObjectProperty
.Values
[MsgPropTrShotTo
] = MsgPropTrShotTo2
then
5360 Data
.ShotTarget
:= 2
5361 else if vleObjectProperty
.Values
[MsgPropTrShotTo
] = MsgPropTrShotTo3
then
5362 Data
.ShotTarget
:= 3
5363 else if vleObjectProperty
.Values
[MsgPropTrShotTo
] = MsgPropTrShotTo4
then
5364 Data
.ShotTarget
:= 4
5365 else if vleObjectProperty
.Values
[MsgPropTrShotTo
] = MsgPropTrShotTo5
then
5366 Data
.ShotTarget
:= 5
5367 else if vleObjectProperty
.Values
[MsgPropTrShotTo
] = MsgPropTrShotTo6
then
5368 Data
.ShotTarget
:= 6;
5369 Data
.ShotIntSight
:= Min(Max(
5370 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrShotSight
], 0), 0), 65535);
5372 if vleObjectProperty
.Values
[MsgPropTrShotAim
] = MsgPropTrShotAim1
then
5374 else if vleObjectProperty
.Values
[MsgPropTrShotAim
] = MsgPropTrShotAim2
then
5376 else if vleObjectProperty
.Values
[MsgPropTrShotAim
] = MsgPropTrShotAim3
then
5378 Data
.ShotAngle
:= Min(
5379 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrShotAngle
], 0), 360);
5380 Data
.ShotWait
:= Min(Max(
5381 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrExDelay
], 0), 0), 65535);
5382 Data
.ShotAccuracy
:= Min(Max(
5383 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrShotAcc
], 0), 0), 65535);
5384 Data
.ShotAmmo
:= Min(Max(
5385 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrShotAmmo
], 0), 0), 65535);
5386 Data
.ShotIntReload
:= Min(Max(
5387 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrShotReload
], 0), 0), 65535);
5392 Data
.FXCount
:= Min(Max(
5393 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrCount
], 0), 0), 255);
5394 if vleObjectProperty
.Values
[MsgPropTrEffectType
] = MsgPropTrEffectParticle
then
5396 Data
.FXType
:= TRIGGER_EFFECT_PARTICLE
;
5397 Data
.FXSubType
:= TRIGGER_EFFECT_SLIQUID
;
5398 if vleObjectProperty
.Values
[MsgPropTrEffectSubtype
] = MsgPropTrEffectSliquid
then
5399 Data
.FXSubType
:= TRIGGER_EFFECT_SLIQUID
5400 else if vleObjectProperty
.Values
[MsgPropTrEffectSubtype
] = MsgPropTrEffectLliquid
then
5401 Data
.FXSubType
:= TRIGGER_EFFECT_LLIQUID
5402 else if vleObjectProperty
.Values
[MsgPropTrEffectSubtype
] = MsgPropTrEffectDliquid
then
5403 Data
.FXSubType
:= TRIGGER_EFFECT_DLIQUID
5404 else if vleObjectProperty
.Values
[MsgPropTrEffectSubtype
] = MsgPropTrEffectBlood
then
5405 Data
.FXSubType
:= TRIGGER_EFFECT_BLOOD
5406 else if vleObjectProperty
.Values
[MsgPropTrEffectSubtype
] = MsgPropTrEffectSpark
then
5407 Data
.FXSubType
:= TRIGGER_EFFECT_SPARK
5408 else if vleObjectProperty
.Values
[MsgPropTrEffectSubtype
] = MsgPropTrEffectBubble
then
5409 Data
.FXSubType
:= TRIGGER_EFFECT_BUBBLE
;
5412 Data
.FXType
:= TRIGGER_EFFECT_ANIMATION
;
5413 Data
.FXSubType
:= StrToEffect(vleObjectProperty
.Values
[MsgPropTrEffectSubtype
]);
5416 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrEffectColor
], 0), 0), $FFFFFF);
5417 Data
.FXColorR
:= a
and $FF;
5418 Data
.FXColorG
:= (a
shr 8) and $FF;
5419 Data
.FXColorB
:= (a
shr 16) and $FF;
5420 if NameToBool(vleObjectProperty
.Values
[MsgPropTrEffectCenter
]) then
5424 Data
.FXWait
:= Min(Max(
5425 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrExDelay
], 0), 0), 65535);
5426 Data
.FXVelX
:= Min(Max(
5427 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrEffectVelx
], 0), -128), 127);
5428 Data
.FXVelY
:= Min(Max(
5429 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrEffectVely
], 0), -128), 127);
5430 Data
.FXSpreadL
:= Min(Max(
5431 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrEffectSpl
], 0), 0), 255);
5432 Data
.FXSpreadR
:= Min(Max(
5433 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrEffectSpr
], 0), 0), 255);
5434 Data
.FXSpreadU
:= Min(Max(
5435 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrEffectSpu
], 0), 0), 255);
5436 Data
.FXSpreadD
:= Min(Max(
5437 StrToIntDef(vleObjectProperty
.Values
[MsgPropTrEffectSpd
], 0), 0), 255);
5446 vleObjectProperty
.Row
:= r
;
5447 vleObjectProperty
.Col
:= c
;
5450 procedure TMainForm
.bbRemoveTextureClick(Sender
: TObject
);
5454 i
:= lbTextureList
.ItemIndex
;
5458 if Application
.MessageBox(PChar(Format(MsgMsgDelTexturePrompt
,
5459 [SelectedTexture()])),
5460 PChar(MsgMsgDelTexture
),
5461 MB_ICONQUESTION
or MB_YESNO
or
5462 MB_DEFBUTTON1
) <> idYes
then
5465 if gPanels
<> nil then
5466 for a
:= 0 to High(gPanels
) do
5467 if (gPanels
[a
].PanelType
<> 0) and
5468 (gPanels
[a
].TextureName
= SelectedTexture()) then
5470 ErrorMessageBox(MsgMsgDelTextureCant
);
5474 g_DeleteTexture(SelectedTexture());
5475 i
:= slInvalidTextures
.IndexOf(lbTextureList
.Items
[i
]);
5477 slInvalidTextures
.Delete(i
);
5478 if lbTextureList
.ItemIndex
> -1 then
5479 lbTextureList
.Items
.Delete(lbTextureList
.ItemIndex
)
5482 procedure TMainForm
.aNewMapExecute(Sender
: TObject
);
5484 if Application
.MessageBox(PChar(MsgMsgClearMapPrompt
), PChar(MsgMsgClearMap
), MB_ICONQUESTION
or MB_YESNO
or MB_DEFBUTTON1
) = mrYes
then
5488 procedure TMainForm
.aUndoExecute(Sender
: TObject
);
5492 if UndoBuffer
= nil then
5494 if UndoBuffer
[High(UndoBuffer
)] = nil then
5497 for a
:= 0 to High(UndoBuffer
[High(UndoBuffer
)]) do
5498 with UndoBuffer
[High(UndoBuffer
)][a
] do
5506 UNDO_DELETE_ITEM
: AddItem(Item
);
5507 UNDO_DELETE_AREA
: AddArea(Area
);
5508 UNDO_DELETE_MONSTER
: AddMonster(Monster
);
5509 UNDO_DELETE_TRIGGER
: AddTrigger(Trigger
);
5510 UNDO_ADD_PANEL
: RemoveObject(AddID
, OBJECT_PANEL
);
5511 UNDO_ADD_ITEM
: RemoveObject(AddID
, OBJECT_ITEM
);
5512 UNDO_ADD_AREA
: RemoveObject(AddID
, OBJECT_AREA
);
5513 UNDO_ADD_MONSTER
: RemoveObject(AddID
, OBJECT_MONSTER
);
5514 UNDO_ADD_TRIGGER
: RemoveObject(AddID
, OBJECT_TRIGGER
);
5518 SetLength(UndoBuffer
, Length(UndoBuffer
)-1);
5519 RemoveSelectFromObjects();
5520 miUndo
.Enabled
:= UndoBuffer
<> nil;
5524 procedure TMainForm
.aCopyObjectExecute(Sender
: TObject
);
5527 CopyBuffer
: TCopyRecArray
;
5531 function CB_Compare(I1
, I2
: TCopyRec
): Integer;
5533 Result
:= Integer(I1
.ObjectType
) - Integer(I2
.ObjectType
);
5535 if Result
= 0 then // Одного типа
5536 Result
:= Integer(I1
.ID
) - Integer(I2
.ID
);
5539 procedure QuickSortCopyBuffer(L
, R
: Integer);
5547 P
:= CopyBuffer
[(L
+ R
) shr 1];
5550 while CB_Compare(CopyBuffer
[I
], P
) < 0 do
5552 while CB_Compare(CopyBuffer
[J
], P
) > 0 do
5558 CopyBuffer
[I
] := CopyBuffer
[J
];
5566 QuickSortCopyBuffer(L
, J
);
5573 if SelectedObjects
= nil then
5579 // Копируем объекты:
5580 for a
:= 0 to High(SelectedObjects
) do
5581 if SelectedObjects
[a
].Live
then
5582 with SelectedObjects
[a
] do
5584 SetLength(CopyBuffer
, Length(CopyBuffer
)+1);
5585 b
:= High(CopyBuffer
);
5586 CopyBuffer
[b
].ID
:= ID
;
5587 CopyBuffer
[b
].Panel
:= nil;
5592 CopyBuffer
[b
].ObjectType
:= OBJECT_PANEL
;
5593 New(CopyBuffer
[b
].Panel
);
5594 CopyBuffer
[b
].Panel
^ := gPanels
[ID
];
5599 CopyBuffer
[b
].ObjectType
:= OBJECT_ITEM
;
5600 CopyBuffer
[b
].Item
:= gItems
[ID
];
5605 CopyBuffer
[b
].ObjectType
:= OBJECT_MONSTER
;
5606 CopyBuffer
[b
].Monster
:= gMonsters
[ID
];
5611 CopyBuffer
[b
].ObjectType
:= OBJECT_AREA
;
5612 CopyBuffer
[b
].Area
:= gAreas
[ID
];
5617 CopyBuffer
[b
].ObjectType
:= OBJECT_TRIGGER
;
5618 CopyBuffer
[b
].Trigger
:= gTriggers
[ID
];
5623 // Сортировка по ID:
5624 if CopyBuffer
<> nil then
5626 QuickSortCopyBuffer(0, b
);
5629 // Постановка ссылок триггеров:
5630 for a
:= 0 to Length(CopyBuffer
)-1 do
5631 if CopyBuffer
[a
].ObjectType
= OBJECT_TRIGGER
then
5633 case CopyBuffer
[a
].Trigger
.TriggerType
of
5634 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
,
5635 TRIGGER_DOOR5
, TRIGGER_CLOSETRAP
, TRIGGER_TRAP
,
5636 TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
:
5637 if CopyBuffer
[a
].Trigger
.Data
.PanelID
<> -1 then
5641 for b
:= 0 to Length(CopyBuffer
)-1 do
5642 if (CopyBuffer
[b
].ObjectType
= OBJECT_PANEL
) and
5643 (Integer(CopyBuffer
[b
].ID
) = CopyBuffer
[a
].Trigger
.Data
.PanelID
) then
5645 CopyBuffer
[a
].Trigger
.Data
.PanelID
:= b
;
5650 // Этих панелей нет среди копируемых:
5652 CopyBuffer
[a
].Trigger
.Data
.PanelID
:= -1;
5655 TRIGGER_PRESS
, TRIGGER_ON
,
5656 TRIGGER_OFF
, TRIGGER_ONOFF
:
5657 if CopyBuffer
[a
].Trigger
.Data
.MonsterID
<> 0 then
5661 for b
:= 0 to Length(CopyBuffer
)-1 do
5662 if (CopyBuffer
[b
].ObjectType
= OBJECT_MONSTER
) and
5663 (Integer(CopyBuffer
[b
].ID
) = CopyBuffer
[a
].Trigger
.Data
.MonsterID
-1) then
5665 CopyBuffer
[a
].Trigger
.Data
.MonsterID
:= b
+1;
5670 // Этих монстров нет среди копируемых:
5672 CopyBuffer
[a
].Trigger
.Data
.MonsterID
:= 0;
5676 if CopyBuffer
[a
].Trigger
.Data
.ShotPanelID
<> -1 then
5680 for b
:= 0 to Length(CopyBuffer
)-1 do
5681 if (CopyBuffer
[b
].ObjectType
= OBJECT_PANEL
) and
5682 (Integer(CopyBuffer
[b
].ID
) = CopyBuffer
[a
].Trigger
.Data
.ShotPanelID
) then
5684 CopyBuffer
[a
].Trigger
.Data
.ShotPanelID
:= b
;
5689 // Этих панелей нет среди копируемых:
5691 CopyBuffer
[a
].Trigger
.Data
.ShotPanelID
:= -1;
5695 if CopyBuffer
[a
].Trigger
.TexturePanel
<> -1 then
5699 for b
:= 0 to Length(CopyBuffer
)-1 do
5700 if (CopyBuffer
[b
].ObjectType
= OBJECT_PANEL
) and
5701 (Integer(CopyBuffer
[b
].ID
) = CopyBuffer
[a
].Trigger
.TexturePanel
) then
5703 CopyBuffer
[a
].Trigger
.TexturePanel
:= b
;
5708 // Этих панелей нет среди копируемых:
5710 CopyBuffer
[a
].Trigger
.TexturePanel
:= -1;
5715 str
:= CopyBufferToString(CopyBuffer
);
5716 ClipBoard
.AsText
:= str
;
5718 for a
:= 0 to Length(CopyBuffer
)-1 do
5719 if (CopyBuffer
[a
].ObjectType
= OBJECT_PANEL
) and
5720 (CopyBuffer
[a
].Panel
<> nil) then
5721 Dispose(CopyBuffer
[a
].Panel
);
5726 procedure TMainForm
.aPasteObjectExecute(Sender
: TObject
);
5729 CopyBuffer
: TCopyRecArray
;
5731 swad
, ssec
, sres
: String;
5734 xadj
, yadj
: LongInt;
5739 pmin
.X
:= High(pmin
.X
);
5740 pmin
.Y
:= High(pmin
.Y
);
5742 StringToCopyBuffer(ClipBoard
.AsText
, CopyBuffer
, pmin
);
5743 if CopyBuffer
= nil then
5746 rel
:= not(ssShift
in GetKeyShiftState());
5747 h
:= High(CopyBuffer
);
5748 RemoveSelectFromObjects();
5751 pmin
.X
, pmin
.Y
, -MapOffset
.X
-32, -MapOffset
.Y
-32, RenderPanel
.Width
, RenderPanel
.Height
) then
5758 xadj
:= Floor((-pmin
.X
- MapOffset
.X
+ 32) / DotStep
) * DotStep
;
5759 yadj
:= Floor((-pmin
.Y
- MapOffset
.Y
+ 32) / DotStep
) * DotStep
;
5763 with CopyBuffer
[a
] do
5767 if Panel
<> nil then
5775 Panel
^.TextureID
:= TEXTURE_SPECIAL_NONE
;
5776 Panel
^.TextureWidth
:= 1;
5777 Panel
^.TextureHeight
:= 1;
5779 if (Panel
^.PanelType
= PANEL_LIFTUP
) or
5780 (Panel
^.PanelType
= PANEL_LIFTDOWN
) or
5781 (Panel
^.PanelType
= PANEL_LIFTLEFT
) or
5782 (Panel
^.PanelType
= PANEL_LIFTRIGHT
) or
5783 (Panel
^.PanelType
= PANEL_BLOCKMON
) or
5784 (Panel
^.TextureName
= '') then
5785 begin // Нет или не может быть текстуры:
5787 else // Есть текстура:
5789 // Обычная текстура:
5790 if not IsSpecialTexture(Panel
^.TextureName
) then
5792 res
:= g_GetTexture(Panel
^.TextureName
, Panel
^.TextureID
);
5796 g_ProcessResourceStr(Panel
^.TextureName
, swad
, ssec
, sres
);
5797 AddTexture(swad
, ssec
, sres
, True);
5798 res
:= g_GetTexture(Panel
^.TextureName
, Panel
^.TextureID
);
5802 g_GetTextureSizeByName(Panel
^.TextureName
,
5803 Panel
^.TextureWidth
, Panel
^.TextureHeight
)
5805 if g_GetTexture('NOTEXTURE', NoTextureID
) then
5807 Panel
^.TextureID
:= TEXTURE_SPECIAL_NOTEXTURE
;
5808 g_GetTextureSizeByID(NoTextureID
, Panel
^.TextureWidth
, Panel
^.TextureHeight
);
5811 else // Спец.текстура:
5813 Panel
^.TextureID
:= SpecialTextureID(Panel
^.TextureName
);
5814 with lbTextureList
.Items
do
5815 if IndexOf(Panel
^.TextureName
) = -1 then
5816 Add(Panel
^.TextureName
);
5820 ID
:= AddPanel(Panel
^);
5822 Undo_Add(OBJECT_PANEL
, ID
, a
> 0);
5823 SelectObject(OBJECT_PANEL
, ID
, True);
5834 ID
:= AddItem(Item
);
5835 Undo_Add(OBJECT_ITEM
, ID
, a
> 0);
5836 SelectObject(OBJECT_ITEM
, ID
, True);
5847 ID
:= AddMonster(Monster
);
5848 Undo_Add(OBJECT_MONSTER
, ID
, a
> 0);
5849 SelectObject(OBJECT_MONSTER
, ID
, True);
5860 ID
:= AddArea(Area
);
5861 Undo_Add(OBJECT_AREA
, ID
, a
> 0);
5862 SelectObject(OBJECT_AREA
, ID
, True);
5876 Data
.TargetPoint
.X
+= xadj
;
5877 Data
.TargetPoint
.Y
+= yadj
;
5879 TRIGGER_PRESS
, TRIGGER_ON
, TRIGGER_OFF
, TRIGGER_ONOFF
:
5884 TRIGGER_SPAWNMONSTER
:
5886 Data
.MonPos
.X
+= xadj
;
5887 Data
.MonPos
.Y
+= yadj
;
5891 Data
.ItemPos
.X
+= xadj
;
5892 Data
.ItemPos
.Y
+= yadj
;
5896 Data
.ShotPos
.X
+= xadj
;
5897 Data
.ShotPos
.Y
+= yadj
;
5902 ID
:= AddTrigger(Trigger
);
5903 Undo_Add(OBJECT_TRIGGER
, ID
, a
> 0);
5904 SelectObject(OBJECT_TRIGGER
, ID
, True);
5909 // Переставляем ссылки триггеров:
5910 for a
:= 0 to High(CopyBuffer
) do
5911 if CopyBuffer
[a
].ObjectType
= OBJECT_TRIGGER
then
5913 case CopyBuffer
[a
].Trigger
.TriggerType
of
5914 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
,
5915 TRIGGER_DOOR5
, TRIGGER_CLOSETRAP
, TRIGGER_TRAP
,
5916 TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
:
5917 if CopyBuffer
[a
].Trigger
.Data
.PanelID
<> -1 then
5918 gTriggers
[CopyBuffer
[a
].ID
].Data
.PanelID
:=
5919 CopyBuffer
[CopyBuffer
[a
].Trigger
.Data
.PanelID
].ID
;
5921 TRIGGER_PRESS
, TRIGGER_ON
,
5922 TRIGGER_OFF
, TRIGGER_ONOFF
:
5923 if CopyBuffer
[a
].Trigger
.Data
.MonsterID
<> 0 then
5924 gTriggers
[CopyBuffer
[a
].ID
].Data
.MonsterID
:=
5925 CopyBuffer
[CopyBuffer
[a
].Trigger
.Data
.MonsterID
-1].ID
+1;
5928 if CopyBuffer
[a
].Trigger
.Data
.ShotPanelID
<> -1 then
5929 gTriggers
[CopyBuffer
[a
].ID
].Data
.ShotPanelID
:=
5930 CopyBuffer
[CopyBuffer
[a
].Trigger
.Data
.ShotPanelID
].ID
;
5933 if CopyBuffer
[a
].Trigger
.TexturePanel
<> -1 then
5934 gTriggers
[CopyBuffer
[a
].ID
].TexturePanel
:=
5935 CopyBuffer
[CopyBuffer
[a
].Trigger
.TexturePanel
].ID
;
5944 procedure TMainForm
.aCutObjectExecute(Sender
: TObject
);
5947 DeleteSelectedObjects();
5950 procedure TMainForm
.vleObjectPropertyEditButtonClick(Sender
: TObject
);
5952 Key
, FileName
: String;
5955 Key
:= vleObjectProperty
.Keys
[vleObjectProperty
.Row
];
5957 if Key
= MsgPropPanelType
then
5959 with ChooseTypeForm
, vleObjectProperty
do
5960 begin // Выбор типа панели:
5961 Caption
:= MsgPropPanelType
;
5962 lbTypeSelect
.Items
.Clear();
5964 for b
:= 0 to High(PANELNAMES
) do
5966 lbTypeSelect
.Items
.Add(PANELNAMES
[b
]);
5967 if Values
[Key
] = PANELNAMES
[b
] then
5968 lbTypeSelect
.ItemIndex
:= b
;
5971 if ShowModal() = mrOK
then
5973 b
:= lbTypeSelect
.ItemIndex
;
5974 Values
[Key
] := PANELNAMES
[b
];
5975 vleObjectPropertyApply(Sender
);
5979 else if Key
= MsgPropTrTeleportTo
then
5980 SelectFlag
:= SELECTFLAG_TELEPORT
5981 else if Key
= MsgPropTrSpawnTo
then
5982 SelectFlag
:= SELECTFLAG_SPAWNPOINT
5983 else if (Key
= MsgPropTrDoorPanel
) or
5984 (Key
= MsgPropTrTrapPanel
) then
5985 SelectFlag
:= SELECTFLAG_DOOR
5986 else if Key
= MsgPropTrTexturePanel
then
5988 DrawPressRect
:= False;
5989 SelectFlag
:= SELECTFLAG_TEXTURE
;
5991 else if Key
= MsgPropTrShotPanel
then
5992 SelectFlag
:= SELECTFLAG_SHOTPANEL
5993 else if Key
= MsgPropTrLiftPanel
then
5994 SelectFlag
:= SELECTFLAG_LIFT
5995 else if key
= MsgPropTrExMonster
then
5996 SelectFlag
:= SELECTFLAG_MONSTER
5997 else if Key
= MsgPropTrExArea
then
5999 SelectFlag
:= SELECTFLAG_NONE
;
6000 DrawPressRect
:= True;
6002 else if Key
= MsgPropTrNextMap
then
6003 begin // Выбор следующей карты:
6004 g_ProcessResourceStr(OpenedMap
, @FileName
, nil, nil);
6005 SelectMapForm
.Caption
:= MsgCapSelect
;
6006 SelectMapForm
.GetMaps(FileName
);
6008 if SelectMapForm
.ShowModal() = mrOK
then
6010 vleObjectProperty
.Values
[Key
] := SelectMapForm
.lbMapList
.Items
[SelectMapForm
.lbMapList
.ItemIndex
];
6011 vleObjectPropertyApply(Sender
);
6014 else if (Key
= MsgPropTrSoundName
) or
6015 (Key
= MsgPropTrMusicName
) then
6016 begin // Выбор файла звука/музыки:
6017 AddSoundForm
.OKFunction
:= nil;
6018 AddSoundForm
.lbResourcesList
.MultiSelect
:= False;
6019 AddSoundForm
.SetResource
:= vleObjectProperty
.Values
[Key
];
6021 if (AddSoundForm
.ShowModal() = mrOk
) then
6023 vleObjectProperty
.Values
[Key
] := AddSoundForm
.ResourceName
;
6024 vleObjectPropertyApply(Sender
);
6027 else if Key
= MsgPropTrActivation
then
6028 with ActivationTypeForm
, vleObjectProperty
do
6029 begin // Выбор типов активации:
6030 cbPlayerCollide
.Checked
:= Pos('PC', Values
[Key
]) > 0;
6031 cbMonsterCollide
.Checked
:= Pos('MC', Values
[Key
]) > 0;
6032 cbPlayerPress
.Checked
:= Pos('PP', Values
[Key
]) > 0;
6033 cbMonsterPress
.Checked
:= Pos('MP', Values
[Key
]) > 0;
6034 cbShot
.Checked
:= Pos('SH', Values
[Key
]) > 0;
6035 cbNoMonster
.Checked
:= Pos('NM', Values
[Key
]) > 0;
6037 if ShowModal() = mrOK
then
6040 if cbPlayerCollide
.Checked
then
6041 b
:= ACTIVATE_PLAYERCOLLIDE
;
6042 if cbMonsterCollide
.Checked
then
6043 b
:= b
or ACTIVATE_MONSTERCOLLIDE
;
6044 if cbPlayerPress
.Checked
then
6045 b
:= b
or ACTIVATE_PLAYERPRESS
;
6046 if cbMonsterPress
.Checked
then
6047 b
:= b
or ACTIVATE_MONSTERPRESS
;
6048 if cbShot
.Checked
then
6049 b
:= b
or ACTIVATE_SHOT
;
6050 if cbNoMonster
.Checked
then
6051 b
:= b
or ACTIVATE_NOMONSTER
;
6053 Values
[Key
] := ActivateToStr(b
);
6054 vleObjectPropertyApply(Sender
);
6057 else if Key
= MsgPropTrKeys
then
6058 with KeysForm
, vleObjectProperty
do
6059 begin // Выбор необходимых ключей:
6060 cbRedKey
.Checked
:= Pos('RK', Values
[Key
]) > 0;
6061 cbGreenKey
.Checked
:= Pos('GK', Values
[Key
]) > 0;
6062 cbBlueKey
.Checked
:= Pos('BK', Values
[Key
]) > 0;
6063 cbRedTeam
.Checked
:= Pos('RT', Values
[Key
]) > 0;
6064 cbBlueTeam
.Checked
:= Pos('BT', Values
[Key
]) > 0;
6066 if ShowModal() = mrOK
then
6069 if cbRedKey
.Checked
then
6071 if cbGreenKey
.Checked
then
6072 b
:= b
or KEY_GREEN
;
6073 if cbBlueKey
.Checked
then
6075 if cbRedTeam
.Checked
then
6076 b
:= b
or KEY_REDTEAM
;
6077 if cbBlueTeam
.Checked
then
6078 b
:= b
or KEY_BLUETEAM
;
6080 Values
[Key
] := KeyToStr(b
);
6081 vleObjectPropertyApply(Sender
);
6084 else if Key
= MsgPropTrFxType
then
6085 with ChooseTypeForm
, vleObjectProperty
do
6086 begin // Выбор типа эффекта:
6087 Caption
:= MsgCapFxType
;
6088 lbTypeSelect
.Items
.Clear();
6090 for b
:= EFFECT_NONE
to EFFECT_FIRE
do
6091 lbTypeSelect
.Items
.Add(EffectToStr(b
));
6093 lbTypeSelect
.ItemIndex
:= StrToEffect(Values
[Key
]);
6095 if ShowModal() = mrOK
then
6097 b
:= lbTypeSelect
.ItemIndex
;
6098 Values
[Key
] := EffectToStr(b
);
6099 vleObjectPropertyApply(Sender
);
6102 else if Key
= MsgPropTrMonsterType
then
6103 with ChooseTypeForm
, vleObjectProperty
do
6104 begin // Выбор типа монстра:
6105 Caption
:= MsgCapMonsterType
;
6106 lbTypeSelect
.Items
.Clear();
6108 for b
:= MONSTER_DEMON
to MONSTER_MAN
do
6109 lbTypeSelect
.Items
.Add(MonsterToStr(b
));
6111 lbTypeSelect
.ItemIndex
:= StrToMonster(Values
[Key
]) - MONSTER_DEMON
;
6113 if ShowModal() = mrOK
then
6115 b
:= lbTypeSelect
.ItemIndex
+ MONSTER_DEMON
;
6116 Values
[Key
] := MonsterToStr(b
);
6117 vleObjectPropertyApply(Sender
);
6120 else if Key
= MsgPropTrItemType
then
6121 with ChooseTypeForm
, vleObjectProperty
do
6122 begin // Выбор типа предмета:
6123 Caption
:= MsgCapItemType
;
6124 lbTypeSelect
.Items
.Clear();
6126 for b
:= ITEM_MEDKIT_SMALL
to ITEM_KEY_BLUE
do
6127 lbTypeSelect
.Items
.Add(ItemToStr(b
));
6128 lbTypeSelect
.Items
.Add(ItemToStr(ITEM_BOTTLE
));
6129 lbTypeSelect
.Items
.Add(ItemToStr(ITEM_HELMET
));
6130 lbTypeSelect
.Items
.Add(ItemToStr(ITEM_JETPACK
));
6131 lbTypeSelect
.Items
.Add(ItemToStr(ITEM_INVIS
));
6132 lbTypeSelect
.Items
.Add(ItemToStr(ITEM_WEAPON_FLAMETHROWER
));
6133 lbTypeSelect
.Items
.Add(ItemToStr(ITEM_AMMO_FUELCAN
));
6135 b
:= StrToItem(Values
[Key
]);
6136 if b
>= ITEM_BOTTLE
then
6138 lbTypeSelect
.ItemIndex
:= b
- ITEM_MEDKIT_SMALL
;
6140 if ShowModal() = mrOK
then
6142 b
:= lbTypeSelect
.ItemIndex
+ ITEM_MEDKIT_SMALL
;
6143 if b
>= ITEM_WEAPON_IRONFIST
then
6145 Values
[Key
] := ItemToStr(b
);
6146 vleObjectPropertyApply(Sender
);
6149 else if Key
= MsgPropTrShotType
then
6150 with ChooseTypeForm
, vleObjectProperty
do
6151 begin // Выбор типа предмета:
6152 Caption
:= MsgPropTrShotType
;
6153 lbTypeSelect
.Items
.Clear();
6155 for b
:= TRIGGER_SHOT_PISTOL
to TRIGGER_SHOT_MAX
do
6156 lbTypeSelect
.Items
.Add(ShotToStr(b
));
6158 lbTypeSelect
.ItemIndex
:= StrToShot(Values
[Key
]);
6160 if ShowModal() = mrOK
then
6162 b
:= lbTypeSelect
.ItemIndex
;
6163 Values
[Key
] := ShotToStr(b
);
6164 vleObjectPropertyApply(Sender
);
6167 else if Key
= MsgPropTrEffectType
then
6168 with ChooseTypeForm
, vleObjectProperty
do
6169 begin // Выбор типа эффекта:
6170 Caption
:= MsgCapFxType
;
6171 lbTypeSelect
.Items
.Clear();
6173 lbTypeSelect
.Items
.Add(MsgPropTrEffectParticle
);
6174 lbTypeSelect
.Items
.Add(MsgPropTrEffectAnimation
);
6175 if Values
[Key
] = MsgPropTrEffectAnimation
then
6176 lbTypeSelect
.ItemIndex
:= 1
6178 lbTypeSelect
.ItemIndex
:= 0;
6180 if ShowModal() = mrOK
then
6182 b
:= lbTypeSelect
.ItemIndex
;
6184 Values
[Key
] := MsgPropTrEffectParticle
6186 Values
[Key
] := MsgPropTrEffectAnimation
;
6187 vleObjectPropertyApply(Sender
);
6190 else if Key
= MsgPropTrEffectSubtype
then
6191 with ChooseTypeForm
, vleObjectProperty
do
6192 begin // Выбор подтипа эффекта:
6193 Caption
:= MsgCapFxType
;
6194 lbTypeSelect
.Items
.Clear();
6196 if Values
[MsgPropTrEffectType
] = MsgPropTrEffectAnimation
then
6198 for b
:= EFFECT_TELEPORT
to EFFECT_FIRE
do
6199 lbTypeSelect
.Items
.Add(EffectToStr(b
));
6201 lbTypeSelect
.ItemIndex
:= StrToEffect(Values
[Key
]) - 1;
6204 lbTypeSelect
.Items
.Add(MsgPropTrEffectSliquid
);
6205 lbTypeSelect
.Items
.Add(MsgPropTrEffectLliquid
);
6206 lbTypeSelect
.Items
.Add(MsgPropTrEffectDliquid
);
6207 lbTypeSelect
.Items
.Add(MsgPropTrEffectBlood
);
6208 lbTypeSelect
.Items
.Add(MsgPropTrEffectSpark
);
6209 lbTypeSelect
.Items
.Add(MsgPropTrEffectBubble
);
6210 lbTypeSelect
.ItemIndex
:= TRIGGER_EFFECT_SLIQUID
;
6211 if Values
[Key
] = MsgPropTrEffectLliquid
then
6212 lbTypeSelect
.ItemIndex
:= TRIGGER_EFFECT_LLIQUID
;
6213 if Values
[Key
] = MsgPropTrEffectDliquid
then
6214 lbTypeSelect
.ItemIndex
:= TRIGGER_EFFECT_DLIQUID
;
6215 if Values
[Key
] = MsgPropTrEffectBlood
then
6216 lbTypeSelect
.ItemIndex
:= TRIGGER_EFFECT_BLOOD
;
6217 if Values
[Key
] = MsgPropTrEffectSpark
then
6218 lbTypeSelect
.ItemIndex
:= TRIGGER_EFFECT_SPARK
;
6219 if Values
[Key
] = MsgPropTrEffectBubble
then
6220 lbTypeSelect
.ItemIndex
:= TRIGGER_EFFECT_BUBBLE
;
6223 if ShowModal() = mrOK
then
6225 b
:= lbTypeSelect
.ItemIndex
;
6227 if Values
[MsgPropTrEffectType
] = MsgPropTrEffectAnimation
then
6228 Values
[Key
] := EffectToStr(b
+ 1)
6230 Values
[Key
] := MsgPropTrEffectSliquid
;
6231 if b
= TRIGGER_EFFECT_LLIQUID
then
6232 Values
[Key
] := MsgPropTrEffectLliquid
;
6233 if b
= TRIGGER_EFFECT_DLIQUID
then
6234 Values
[Key
] := MsgPropTrEffectDliquid
;
6235 if b
= TRIGGER_EFFECT_BLOOD
then
6236 Values
[Key
] := MsgPropTrEffectBlood
;
6237 if b
= TRIGGER_EFFECT_SPARK
then
6238 Values
[Key
] := MsgPropTrEffectSpark
;
6239 if b
= TRIGGER_EFFECT_BUBBLE
then
6240 Values
[Key
] := MsgPropTrEffectBubble
;
6243 vleObjectPropertyApply(Sender
);
6246 else if Key
= MsgPropTrEffectColor
then
6247 with vleObjectProperty
do
6248 begin // Выбор цвета эффекта:
6249 ColorDialog
.Color
:= StrToIntDef(Values
[Key
], 0);
6250 if ColorDialog
.Execute
then
6252 Values
[Key
] := IntToStr(ColorDialog
.Color
);
6253 vleObjectPropertyApply(Sender
);
6256 else if Key
= MsgPropPanelTex
then
6257 begin // Смена текстуры:
6258 vleObjectProperty
.Values
[Key
] := SelectedTexture();
6259 vleObjectPropertyApply(Sender
);
6263 procedure TMainForm
.vleObjectPropertyApply(Sender
: TObject
);
6265 // hack to prevent empty ID in list
6266 RenderPanel
.SetFocus();
6267 bApplyProperty
.Click();
6268 vleObjectProperty
.SetFocus();
6271 procedure TMainForm
.aSaveMapExecute(Sender
: TObject
);
6273 FileName
, Section
, Res
: String;
6275 if OpenedMap
= '' then
6277 aSaveMapAsExecute(nil);
6281 g_ProcessResourceStr(OpenedMap
, FileName
, Section
, Res
);
6283 SaveMap(FileName
+':\'+Res
, '');
6286 procedure TMainForm
.aOpenMapExecute(Sender
: TObject
);
6288 OpenDialog
.Filter
:= MsgFileFilterAll
;
6290 if OpenDialog
.Execute() then
6292 OpenMapFile(OpenDialog
.FileName
);
6293 OpenDialog
.InitialDir
:= ExtractFileDir(OpenDialog
.FileName
);
6297 procedure TMainForm
.OpenMapFile(FileName
: String);
6299 if (Pos('.ini', LowerCase(ExtractFileName(FileName
))) > 0) then
6303 pLoadProgress
.Left
:= (RenderPanel
.Width
div 2)-(pLoadProgress
.Width
div 2);
6304 pLoadProgress
.Top
:= (RenderPanel
.Height
div 2)-(pLoadProgress
.Height
div 2);
6305 pLoadProgress
.Show();
6310 LoadMapOld(FileName
);
6312 Caption
:= Format('%s - %s', [FormCaption
, ExtractFileName(FileName
)]);
6314 pLoadProgress
.Hide();
6317 else // Карты из WAD:
6319 OpenMap(FileName
, '');
6323 procedure TMainForm
.FormActivate(Sender
: TObject
);
6325 ActiveControl
:= RenderPanel
;
6328 procedure TMainForm
.aDeleteMap(Sender
: TObject
);
6336 OpenDialog
.Filter
:= MsgFileFilterWad
;
6338 if not OpenDialog
.Execute() then
6341 WAD
:= TWADEditor_1
.Create();
6343 if not WAD
.ReadFile(OpenDialog
.FileName
) then
6351 MapList
:= WAD
.GetResourcesList('');
6353 SelectMapForm
.Caption
:= MsgCapRemove
;
6354 SelectMapForm
.lbMapList
.Items
.Clear();
6356 if MapList
<> nil then
6357 for a
:= 0 to High(MapList
) do
6358 SelectMapForm
.lbMapList
.Items
.Add(win2utf(MapList
[a
]));
6360 if (SelectMapForm
.ShowModal() = mrOK
) then
6362 str
:= SelectMapForm
.lbMapList
.Items
[SelectMapForm
.lbMapList
.ItemIndex
];
6364 Move(str
[1], MapName
[0], Min(16, Length(str
)));
6366 if Application
.MessageBox(PChar(Format(MsgMsgDeleteMapPrompt
, [MapName
, OpenDialog
.FileName
])), PChar(MsgMsgDeleteMap
), MB_ICONQUESTION
or MB_YESNO
or MB_DEFBUTTON2
) <> mrYes
then
6369 WAD
.RemoveResource('', utf2win(MapName
));
6371 Application
.MessageBox(
6372 PChar(Format(MsgMsgMapDeletedPrompt
, [MapName
])),
6373 PChar(MsgMsgMapDeleted
),
6374 MB_ICONINFORMATION
or MB_OK
or MB_DEFBUTTON1
6377 WAD
.SaveTo(OpenDialog
.FileName
);
6379 // Удалили текущую карту - сохранять по старому ее нельзя:
6380 if OpenedMap
= (OpenDialog
.FileName
+':\'+MapName
) then
6384 Caption
:= FormCaption
;
6391 procedure TMainForm
.vleObjectPropertyKeyDown(Sender
: TObject
;
6392 var Key
: Word; Shift
: TShiftState
);
6394 if Key
= VK_RETURN
then
6395 vleObjectPropertyApply(Sender
);
6398 procedure MovePanel(var ID
: DWORD
; MoveType
: Byte);
6403 if (ID
= 0) and (MoveType
= 0) then
6405 if (ID
= DWORD(High(gPanels
))) and (MoveType
<> 0) then
6407 if (ID
> DWORD(High(gPanels
))) then
6412 if MoveType
= 0 then // to Back
6414 if gTriggers
<> nil then
6415 for a
:= 0 to High(gTriggers
) do
6416 with gTriggers
[a
] do
6418 if TriggerType
= TRIGGER_NONE
then
6421 if TexturePanel
= _id
then
6424 if (TexturePanel
>= 0) and (TexturePanel
< _id
) then
6428 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
,
6429 TRIGGER_DOOR5
, TRIGGER_CLOSETRAP
, TRIGGER_TRAP
,
6430 TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
:
6431 if Data
.PanelID
= _id
then
6434 if (Data
.PanelID
>= 0) and (Data
.PanelID
< _id
) then
6438 if Data
.ShotPanelID
= _id
then
6439 Data
.ShotPanelID
:= 0
6441 if (Data
.ShotPanelID
>= 0) and (Data
.ShotPanelID
< _id
) then
6442 Inc(Data
.ShotPanelID
);
6446 tmp
:= gPanels
[_id
];
6448 for a
:= _id
downto 1 do
6449 gPanels
[a
] := gPanels
[a
-1];
6457 if gTriggers
<> nil then
6458 for a
:= 0 to High(gTriggers
) do
6459 with gTriggers
[a
] do
6461 if TriggerType
= TRIGGER_NONE
then
6464 if TexturePanel
= _id
then
6465 TexturePanel
:= High(gPanels
)
6467 if TexturePanel
> _id
then
6471 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
,
6472 TRIGGER_DOOR5
, TRIGGER_CLOSETRAP
, TRIGGER_TRAP
,
6473 TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
:
6474 if Data
.PanelID
= _id
then
6475 Data
.PanelID
:= High(gPanels
)
6477 if Data
.PanelID
> _id
then
6481 if Data
.ShotPanelID
= _id
then
6482 Data
.ShotPanelID
:= High(gPanels
)
6484 if Data
.ShotPanelID
> _id
then
6485 Dec(Data
.ShotPanelID
);
6489 tmp
:= gPanels
[_id
];
6491 for a
:= _id
to High(gPanels
)-1 do
6492 gPanels
[a
] := gPanels
[a
+1];
6494 gPanels
[High(gPanels
)] := tmp
;
6496 ID
:= High(gPanels
);
6500 procedure TMainForm
.aMoveToBack(Sender
: TObject
);
6504 if SelectedObjects
= nil then
6507 for a
:= 0 to High(SelectedObjects
) do
6508 with SelectedObjects
[a
] do
6509 if Live
and (ObjectType
= OBJECT_PANEL
) then
6511 SelectedObjects
[0] := SelectedObjects
[a
];
6512 SetLength(SelectedObjects
, 1);
6519 procedure TMainForm
.aMoveToFore(Sender
: TObject
);
6523 if SelectedObjects
= nil then
6526 for a
:= 0 to High(SelectedObjects
) do
6527 with SelectedObjects
[a
] do
6528 if Live
and (ObjectType
= OBJECT_PANEL
) then
6530 SelectedObjects
[0] := SelectedObjects
[a
];
6531 SetLength(SelectedObjects
, 1);
6538 procedure TMainForm
.aSaveMapAsExecute(Sender
: TObject
);
6539 var i
, idx
: Integer; list
: TStringList
; fmt
: String;
6541 list
:= TStringList
.Create();
6543 // TODO: get loclized strings automatically from language files
6544 SaveDialog
.DefaultExt
:= '.dfz';
6545 SaveDialog
.FilterIndex
:= 1;
6546 SaveDialog
.Filter
:= '';
6547 gWADEditorFactory
.GetRegistredEditors(list
);
6548 for i
:= 0 to list
.Count
- 1 do
6550 if list
[i
] = 'DFZIP' then
6551 SaveDialog
.FilterIndex
:= i
+ 1;
6554 SaveDialog
.Filter
:= SaveDialog
.Filter
+ '|';
6556 if list
[i
] = 'DFWAD' then
6557 SaveDialog
.Filter
:= SaveDialog
.Filter
+ MsgFileFilterSaveDFWAD
6558 else if list
[i
] = 'DFZIP' then
6559 SaveDialog
.Filter
:= SaveDialog
.Filter
+ MsgFileFilterSaveDFZIP
6561 SaveDialog
.Filter
:= SaveDialog
.Filter
+ list
[i
] + '|*.*';
6564 if SaveDialog
.Execute() then
6566 i
:= SaveDialog
.FilterIndex
- 1;
6567 if (i
>= 0) and (i
< list
.Count
) then fmt
:= list
[i
] else fmt
:= '';
6569 SaveMapForm
.GetMaps(SaveDialog
.FileName
, True, fmt
);
6570 if SaveMapForm
.ShowModal() = mrOK
then
6572 SaveDialog
.InitialDir
:= ExtractFileDir(SaveDialog
.FileName
);
6573 OpenedMap
:= SaveDialog
.FileName
+':\'+SaveMapForm
.eMapName
.Text;
6574 OpenedWAD
:= SaveDialog
.FileName
;
6576 idx
:= RecentFiles
.IndexOf(OpenedMap
);
6577 // Такая карта уже недавно открывалась:
6579 RecentFiles
.Delete(idx
);
6580 RecentFiles
.Insert(0, OpenedMap
);
6583 SaveMap(OpenedMap
, fmt
);
6585 gMapInfo
.FileName
:= SaveDialog
.FileName
;
6586 gMapInfo
.MapName
:= SaveMapForm
.eMapName
.Text;
6587 UpdateCaption(gMapInfo
.Name
, ExtractFileName(gMapInfo
.FileName
), gMapInfo
.MapName
);
6594 procedure TMainForm
.aSelectAllExecute(Sender
: TObject
);
6598 RemoveSelectFromObjects();
6600 case pcObjects
.ActivePageIndex
+1 of
6602 if gPanels
<> nil then
6603 for a
:= 0 to High(gPanels
) do
6604 if gPanels
[a
].PanelType
<> PANEL_NONE
then
6605 SelectObject(OBJECT_PANEL
, a
, True);
6607 if gItems
<> nil then
6608 for a
:= 0 to High(gItems
) do
6609 if gItems
[a
].ItemType
<> ITEM_NONE
then
6610 SelectObject(OBJECT_ITEM
, a
, True);
6612 if gMonsters
<> nil then
6613 for a
:= 0 to High(gMonsters
) do
6614 if gMonsters
[a
].MonsterType
<> MONSTER_NONE
then
6615 SelectObject(OBJECT_MONSTER
, a
, True);
6617 if gAreas
<> nil then
6618 for a
:= 0 to High(gAreas
) do
6619 if gAreas
[a
].AreaType
<> AREA_NONE
then
6620 SelectObject(OBJECT_AREA
, a
, True);
6622 if gTriggers
<> nil then
6623 for a
:= 0 to High(gTriggers
) do
6624 if gTriggers
[a
].TriggerType
<> TRIGGER_NONE
then
6625 SelectObject(OBJECT_TRIGGER
, a
, True);
6628 RecountSelectedObjects();
6631 procedure TMainForm
.tbGridOnClick(Sender
: TObject
);
6633 DotEnable
:= not DotEnable
;
6634 (Sender
as TToolButton
).Down
:= DotEnable
;
6637 procedure TMainForm
.OnIdle(Sender
: TObject
; var Done
: Boolean);
6641 // TODO: move refresh to user actions (ask to repaint only when something changed)
6642 if GetTickCount64() - LastDrawTime
>= 1000 div MaxFPS
then
6647 if StartMap
<> '' then
6655 procedure TMainForm
.miMapPreviewClick(Sender
: TObject
);
6657 if PreviewMode
= 2 then
6660 if PreviewMode
= 0 then
6662 Splitter2
.Visible
:= False;
6663 Splitter1
.Visible
:= False;
6664 StatusBar
.Visible
:= False;
6665 PanelObjs
.Visible
:= False;
6666 PanelProps
.Visible
:= False;
6667 MainToolBar
.Visible
:= False;
6668 sbHorizontal
.Visible
:= False;
6669 sbVertical
.Visible
:= False;
6673 StatusBar
.Visible
:= True;
6674 PanelObjs
.Visible
:= True;
6675 PanelProps
.Visible
:= True;
6676 Splitter2
.Visible
:= True;
6677 Splitter1
.Visible
:= True;
6678 MainToolBar
.Visible
:= True;
6679 sbHorizontal
.Visible
:= True;
6680 sbVertical
.Visible
:= True;
6683 PreviewMode
:= PreviewMode
xor 1;
6684 (Sender
as TMenuItem
).Checked
:= PreviewMode
> 0;
6689 procedure TMainForm
.miLayerClick(Sender
: TObject
);
6691 // TODO: Deselect only the objects of the layer that was hidden.
6692 if not (Sender
as TMenuItem
).Checked
then
6693 RemoveSelectFromObjects();
6696 procedure TMainForm
.tbShowClick(Sender
: TObject
);
6698 LayerItem
: TMenuItem
;
6699 ShowLayers
: Boolean;
6701 ShowLayers
:= False;
6702 for LayerItem
in miLayers
do
6703 if LayerItem
.IsCheckItem() and not LayerItem
.Checked
then
6709 if not ShowLayers
then
6710 RemoveSelectFromObjects();
6712 for LayerItem
in miLayers
do
6713 LayerItem
.Checked
:= ShowLayers
;
6716 procedure TMainForm
.miMiniMapClick(Sender
: TObject
);
6721 procedure TMainForm
.miSwitchGridClick(Sender
: TObject
);
6723 if DotStep
= DotStepOne
6724 then DotStep
:= DotStepTwo
6725 else DotStep
:= DotStepOne
;
6727 MousePos
.X
:= (MousePos
.X
div DotStep
) * DotStep
;
6728 MousePos
.Y
:= (MousePos
.Y
div DotStep
) * DotStep
;
6731 procedure TMainForm
.miShowEdgesClick(Sender
: TObject
);
6736 procedure TMainForm
.miSnapToGridClick(Sender
: TObject
);
6738 SnapToGrid
:= not SnapToGrid
;
6740 MousePos
.X
:= (MousePos
.X
div DotStep
) * DotStep
;
6741 MousePos
.Y
:= (MousePos
.Y
div DotStep
) * DotStep
;
6743 miSnapToGrid
.Checked
:= SnapToGrid
;
6746 procedure TMainForm
.minexttabClick(Sender
: TObject
);
6748 if pcObjects
.ActivePageIndex
< pcObjects
.PageCount
-1 then
6749 pcObjects
.ActivePageIndex
:= pcObjects
.ActivePageIndex
+1
6751 pcObjects
.ActivePageIndex
:= 0;
6754 procedure TMainForm
.miSaveMiniMapClick(Sender
: TObject
);
6756 SaveMiniMapForm
.ShowModal();
6759 procedure TMainForm
.bClearTextureClick(Sender
: TObject
);
6761 lbTextureList
.ItemIndex
:= -1;
6762 lTextureWidth
.Caption
:= '';
6763 lTextureHeight
.Caption
:= '';
6766 procedure TMainForm
.miPackMapClick(Sender
: TObject
);
6768 PackMapForm
.ShowModal();
6771 type SSArray
= array of String;
6773 function ParseString (Str
: AnsiString
): SSArray
;
6774 function GetStr (var Str
: AnsiString
): AnsiString
;
6778 if Str
[1] = '"' then
6779 for b
:= 1 to Length(Str
) do
6780 if (b
= Length(Str
)) or (Str
[b
+ 1] = '"') then
6782 Result
:= Copy(Str
, 2, b
- 1);
6783 Delete(Str
, 1, b
+ 1);
6787 for a
:= 1 to Length(Str
) do
6788 if (a
= Length(Str
)) or (Str
[a
+ 1] = ' ') then
6790 Result
:= Copy(Str
, 1, a
);
6791 Delete(Str
, 1, a
+ 1);
6801 SetLength(Result
, Length(Result
)+1);
6802 Result
[High(Result
)] := GetStr(Str
);
6806 procedure TMainForm
.miTestMapClick(Sender
: TObject
);
6808 newWAD
, oldWAD
, tempMap
: String;
6815 // Ignore while map testing in progress
6816 if MapTestProcess
<> nil then
6819 // Сохраняем временную карту:
6822 newWAD
:= Format('%s/temp%.4d', [MapsDir
, time
]);
6824 until not FileExists(newWAD
);
6825 if OpenedMap
<> '' then
6827 oldWad
:= g_ExtractWadName(OpenedMap
);
6828 newWad
+= ExtractFileExt(oldWad
);
6829 if not CopyFile(oldWad
, newWad
) then
6830 e_WriteLog('MapTest: unable to copy [' + oldWad
+ '] to [' + newWad
+ ']', MSG_WARNING
)
6836 tempMap
:= newWAD
+ ':\' + TEST_MAP_NAME
;
6837 SaveMap(tempMap
, '');
6841 if TestOptionsTwoPlayers
then
6843 if TestOptionsTeamDamage
then
6845 if TestOptionsAllowExit
then
6847 if TestOptionsWeaponStay
then
6849 if TestOptionsMonstersDM
then
6853 proc
:= TProcessUTF8
.Create(nil);
6854 proc
.Executable
:= TestD2dExe
;
6856 // TODO: get real executable name from Info.plist
6857 if LowerCase(ExtractFileExt(TestD2dExe
)) = '.app' then
6858 proc
.Executable
:= TestD2dExe
+ DirectorySeparator
+ 'Contents' + DirectorySeparator
+
6859 'MacOS' + DirectorySeparator
+ 'Doom2DF';
6861 proc
.Parameters
.Add('-map');
6862 proc
.Parameters
.Add(tempMap
);
6863 proc
.Parameters
.Add('-gm');
6864 proc
.Parameters
.Add(TestGameMode
);
6865 proc
.Parameters
.Add('-limt');
6866 proc
.Parameters
.Add(TestLimTime
);
6867 proc
.Parameters
.Add('-lims');
6868 proc
.Parameters
.Add(TestLimScore
);
6869 proc
.Parameters
.Add('-opt');
6870 proc
.Parameters
.Add(IntToStr(opt
));
6871 proc
.Parameters
.Add('--debug');
6873 proc
.Parameters
.Add('--close');
6875 args
:= ParseString(TestD2dArgs
);
6876 for i
:= 0 to High(args
) do
6877 proc
.Parameters
.Add(args
[i
]);
6887 tbTestMap
.Enabled
:= False;
6888 MapTestFile
:= newWAD
;
6889 MapTestProcess
:= proc
;
6893 Application
.MessageBox(PChar(MsgMsgExecError
), 'FIXME', MB_OK
or MB_ICONERROR
);
6894 SysUtils
.DeleteFile(newWAD
);
6899 procedure TMainForm
.sbVerticalScroll(Sender
: TObject
;
6900 ScrollCode
: TScrollCode
; var ScrollPos
: Integer);
6902 MapOffset
.Y
:= -sbVertical
.Position
;
6903 RenderPanel
.Invalidate
;
6906 procedure TMainForm
.sbHorizontalScroll(Sender
: TObject
;
6907 ScrollCode
: TScrollCode
; var ScrollPos
: Integer);
6909 MapOffset
.X
:= -sbHorizontal
.Position
;
6910 RenderPanel
.Invalidate
;
6913 procedure TMainForm
.miOpenWadMapClick(Sender
: TObject
);
6915 if OpenedWAD
<> '' then
6917 OpenMap(OpenedWAD
, '');
6921 procedure TMainForm
.selectall1Click(Sender
: TObject
);
6925 RemoveSelectFromObjects();
6927 if gPanels
<> nil then
6928 for a
:= 0 to High(gPanels
) do
6929 if gPanels
[a
].PanelType
<> PANEL_NONE
then
6930 SelectObject(OBJECT_PANEL
, a
, True);
6932 if gItems
<> nil then
6933 for a
:= 0 to High(gItems
) do
6934 if gItems
[a
].ItemType
<> ITEM_NONE
then
6935 SelectObject(OBJECT_ITEM
, a
, True);
6937 if gMonsters
<> nil then
6938 for a
:= 0 to High(gMonsters
) do
6939 if gMonsters
[a
].MonsterType
<> MONSTER_NONE
then
6940 SelectObject(OBJECT_MONSTER
, a
, True);
6942 if gAreas
<> nil then
6943 for a
:= 0 to High(gAreas
) do
6944 if gAreas
[a
].AreaType
<> AREA_NONE
then
6945 SelectObject(OBJECT_AREA
, a
, True);
6947 if gTriggers
<> nil then
6948 for a
:= 0 to High(gTriggers
) do
6949 if gTriggers
[a
].TriggerType
<> TRIGGER_NONE
then
6950 SelectObject(OBJECT_TRIGGER
, a
, True);
6952 RecountSelectedObjects();
6955 procedure TMainForm
.Splitter1CanResize(Sender
: TObject
;
6956 var NewSize
: Integer; var Accept
: Boolean);
6958 Accept
:= (NewSize
> 140);
6961 procedure TMainForm
.Splitter2CanResize(Sender
: TObject
;
6962 var NewSize
: Integer; var Accept
: Boolean);
6964 Accept
:= (NewSize
> 110);
6967 procedure TMainForm
.vleObjectPropertyEnter(Sender
: TObject
);
6969 EditingProperties
:= True;
6972 procedure TMainForm
.vleObjectPropertyExit(Sender
: TObject
);
6974 EditingProperties
:= False;
6977 procedure TMainForm
.FormKeyUp(Sender
: TObject
; var Key
: Word; Shift
: TShiftState
);
6979 // Объекты передвигались:
6980 if ActiveControl
= RenderPanel
then
6982 if (Key
= VK_NUMPAD4
) or
6983 (Key
= VK_NUMPAD6
) or
6984 (Key
= VK_NUMPAD8
) or
6985 (Key
= VK_NUMPAD5
) or
6986 (Key
= Ord('V')) then
6989 // Быстрое превью карты:
6990 if Key
= Ord('E') then
6992 if PreviewMode
= 2 then
6995 RenderPanelMouseMove(Sender
, Shift
, RenderMousePos().X
, RenderMousePos().Y
);