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 miMenuFile
: TMenuItem
;
26 miSaveMapAs
: TMenuItem
;
27 miOpenWadMap
: TMenuItem
;
29 miSaveMiniMap
: TMenuItem
;
30 miDeleteMap
: TMenuItem
;
35 miMenuEdit
: TMenuItem
;
42 miSelectAll
: TMenuItem
;
47 miMenuTools
: TMenuItem
;
48 miSnapToGrid
: TMenuItem
;
50 miSwitchGrid
: TMenuItem
;
51 miShowEdges
: TMenuItem
;
63 miMenuService
: TMenuItem
;
64 miCheckMap
: TMenuItem
;
65 miOptimmization
: TMenuItem
;
66 miMapPreview
: TMenuItem
;
69 miMenuSettings
: TMenuItem
;
70 miMapOptions
: TMenuItem
;
74 miMapTestSettings
: TMenuItem
;
76 miMenuHelp
: TMenuItem
;
78 // Скрытый пункт меню для Ctrl+Tab:
82 // Панель инструментов:
83 MainToolBar
: TToolBar
;
85 pLoadProgress
: TPanel
;
86 RenderPanel
: TOpenGLControl
;
87 tbNewMap
: TToolButton
;
88 tbOpenMap
: TToolButton
;
89 tbSaveMap
: TToolButton
;
90 tbOpenWadMap
: TToolButton
;
92 tbShowMap
: TToolButton
;
96 tbGridOn
: TToolButton
;
99 tbTestMap
: TToolButton
;
100 // Всплывающее меню для кнопки слоев:
102 miLayerP1
: TMenuItem
;
103 miLayerP2
: TMenuItem
;
104 miLayerP3
: TMenuItem
;
105 miLayerP4
: TMenuItem
;
106 miLayerP5
: TMenuItem
;
107 miLayerP6
: TMenuItem
;
108 miLayerP7
: TMenuItem
;
109 miLayerP8
: TMenuItem
;
110 miLayerP9
: TMenuItem
;
111 // Всплывающее меню для кнопки теста карты:
112 pmMapTest
: TPopupMenu
;
113 miMapTestPMSet
: TMenuItem
;
118 sbHorizontal
: TScrollBar
;
119 sbVertical
: TScrollBar
;
123 // Панель применения свойств:
124 PanelPropApply
: TPanel
;
125 bApplyProperty
: TButton
;
126 // Редактор свойств объектов:
127 vleObjectProperty
: TValueListEditor
;
129 // Панель объектов - вкладки:
131 pcObjects
: TPageControl
;
134 lbTextureList
: TListBox
;
135 // Панель настройки текстур:
136 PanelTextures
: TPanel
;
138 lTextureWidth
: TLabel
;
140 lTextureHeight
: TLabel
;
141 cbPreview
: TCheckBox
;
142 bbAddTexture
: TBitBtn
;
143 bbRemoveTexture
: TBitBtn
;
144 bClearTexture
: TButton
;
145 // Панель типов панелей:
146 PanelPanelType
: TPanel
;
147 lbPanelType
: TListBox
;
148 // Вкладка "Предметы":
150 lbItemList
: TListBox
;
153 // Вкладка "Монстры":
154 tsMonsters
: TTabSheet
;
155 lbMonsterList
: TListBox
;
156 rbMonsterLeft
: TRadioButton
;
157 rbMonsterRight
: TRadioButton
;
158 // Вкладка "Области":
160 lbAreasList
: TListBox
;
161 rbAreaLeft
: TRadioButton
;
162 rbAreaRight
: TRadioButton
;
163 // Вкладка "Триггеры":
164 tsTriggers
: TTabSheet
;
165 lbTriggersList
: TListBox
;
166 clbActivationType
: TCheckListBox
;
167 clbKeys
: TCheckListBox
;
170 Splitter1
: TSplitter
;
171 Splitter2
: TSplitter
;
172 StatusBar
: TStatusBar
;
174 // Специальные объекты:
175 ImageList
: TImageList
;
176 ilToolbar
: TImageList
;
177 OpenDialog
: TOpenDialog
;
178 SaveDialog
: TSaveDialog
;
179 selectall1
: TMenuItem
;
180 ColorDialog
: TColorDialog
;
182 procedure aAboutExecute(Sender
: TObject
);
183 procedure aCheckMapExecute(Sender
: TObject
);
184 procedure aMoveToFore(Sender
: TObject
);
185 procedure aMoveToBack(Sender
: TObject
);
186 procedure aCopyObjectExecute(Sender
: TObject
);
187 procedure aCutObjectExecute(Sender
: TObject
);
188 procedure aEditorOptionsExecute(Sender
: TObject
);
189 procedure aExitExecute(Sender
: TObject
);
190 procedure aMapOptionsExecute(Sender
: TObject
);
191 procedure aNewMapExecute(Sender
: TObject
);
192 procedure aOpenMapExecute(Sender
: TObject
);
193 procedure aOptimizeExecute(Sender
: TObject
);
194 procedure aPasteObjectExecute(Sender
: TObject
);
195 procedure aSelectAllExecute(Sender
: TObject
);
196 procedure aSaveMapExecute(Sender
: TObject
);
197 procedure aSaveMapAsExecute(Sender
: TObject
);
198 procedure aUndoExecute(Sender
: TObject
);
199 procedure aDeleteMap(Sender
: TObject
);
200 procedure bApplyPropertyClick(Sender
: TObject
);
201 procedure bbAddTextureClick(Sender
: TObject
);
202 procedure bbRemoveTextureClick(Sender
: TObject
);
203 procedure FormActivate(Sender
: TObject
);
204 procedure FormCloseQuery(Sender
: TObject
; var CanClose
: Boolean);
205 procedure FormCreate(Sender
: TObject
);
206 procedure FormDestroy(Sender
: TObject
);
207 procedure FormKeyDown(Sender
: TObject
; var Key
: Word; Shift
: TShiftState
);
208 procedure FormResize(Sender
: TObject
);
209 procedure lbTextureListClick(Sender
: TObject
);
210 procedure lbTextureListDrawItem(Control
: TWinControl
; Index
: Integer;
211 ARect
: TRect
; State
: TOwnerDrawState
);
212 procedure RenderPanelMouseDown(Sender
: TObject
; Button
: TMouseButton
; Shift
: TShiftState
; X
, Y
: Integer);
213 procedure RenderPanelMouseMove(Sender
: TObject
; Shift
: TShiftState
; X
, Y
: Integer);
214 procedure RenderPanelMouseUp(Sender
: TObject
; Button
: TMouseButton
; Shift
: TShiftState
; X
, Y
: Integer);
215 procedure RenderPanelPaint(Sender
: TObject
);
216 procedure RenderPanelResize(Sender
: TObject
);
217 procedure Splitter1Moved(Sender
: TObject
);
218 procedure vleObjectPropertyEditButtonClick(Sender
: TObject
);
219 procedure vleObjectPropertyApply(Sender
: TObject
);
220 procedure vleObjectPropertyGetPickList(Sender
: TObject
; const KeyName
: String; Values
: TStrings
);
221 procedure vleObjectPropertyKeyDown(Sender
: TObject
; var Key
: Word;
223 procedure tbGridOnClick(Sender
: TObject
);
224 procedure miMapPreviewClick(Sender
: TObject
);
225 procedure miLayer1Click(Sender
: TObject
);
226 procedure miLayer2Click(Sender
: TObject
);
227 procedure miLayer3Click(Sender
: TObject
);
228 procedure miLayer4Click(Sender
: TObject
);
229 procedure miLayer5Click(Sender
: TObject
);
230 procedure miLayer6Click(Sender
: TObject
);
231 procedure miLayer7Click(Sender
: TObject
);
232 procedure miLayer8Click(Sender
: TObject
);
233 procedure miLayer9Click(Sender
: TObject
);
234 procedure tbShowClick(Sender
: TObject
);
235 procedure miSnapToGridClick(Sender
: TObject
);
236 procedure miMiniMapClick(Sender
: TObject
);
237 procedure miSwitchGridClick(Sender
: TObject
);
238 procedure miShowEdgesClick(Sender
: TObject
);
239 procedure minexttabClick(Sender
: TObject
);
240 procedure miSaveMiniMapClick(Sender
: TObject
);
241 procedure bClearTextureClick(Sender
: TObject
);
242 procedure miPackMapClick(Sender
: TObject
);
243 procedure aRecentFileExecute(Sender
: TObject
);
244 procedure miMapTestSettingsClick(Sender
: TObject
);
245 procedure miTestMapClick(Sender
: TObject
);
246 procedure sbVerticalScroll(Sender
: TObject
; ScrollCode
: TScrollCode
;
247 var ScrollPos
: Integer);
248 procedure sbHorizontalScroll(Sender
: TObject
; ScrollCode
: TScrollCode
;
249 var ScrollPos
: Integer);
250 procedure miOpenWadMapClick(Sender
: TObject
);
251 procedure selectall1Click(Sender
: TObject
);
252 procedure Splitter1CanResize(Sender
: TObject
; var NewSize
: Integer;
253 var Accept
: Boolean);
254 procedure Splitter2CanResize(Sender
: TObject
; var NewSize
: Integer;
255 var Accept
: Boolean);
256 procedure vleObjectPropertyEnter(Sender
: TObject
);
257 procedure vleObjectPropertyExit(Sender
: TObject
);
258 procedure FormKeyUp(Sender
: TObject
; var Key
: Word;
262 procedure OnIdle(Sender
: TObject
; var Done
: Boolean);
264 procedure RefreshRecentMenu();
270 LAYER_FOREGROUND
= 2;
278 TEST_MAP_NAME
= '$$$_TEST_$$$';
279 LANGUAGE_FILE_NAME
= '_Editor.txt';
290 DotStepOne
, DotStepTwo
: Byte;
292 DrawTexturePanel
: Boolean;
293 DrawPanelSize
: Boolean;
295 PreviewColor
: TColor
;
297 RecentCount
: Integer;
298 RecentFiles
: TStringList
;
299 slInvalidTextures
: TStringList
;
301 TestGameMode
: String;
303 TestLimScore
: String;
304 TestOptionsTwoPlayers
: Boolean;
305 TestOptionsTeamDamage
: Boolean;
306 TestOptionsAllowExit
: Boolean;
307 TestOptionsWeaponStay
: Boolean;
308 TestOptionsMonstersDM
: Boolean;
310 TestMapOnce
: Boolean;
312 LayerEnabled
: Array [LAYER_BACK
..LAYER_TRIGGERS
] of Boolean =
313 (True, True, True, True, True, True, True, True, True);
314 PreviewMode
: Byte = 0;
320 procedure OpenMap(FileName
: String; mapN
: String);
321 function AddTexture(aWAD
, aSection
, aTex
: String; silent
: Boolean): Boolean;
322 procedure RemoveSelectFromObjects();
323 procedure ChangeShownProperty(Name
: String; NewValue
: String);
328 f_options
, e_graphics
, e_log
, GL
, Math
,
329 f_mapoptions
, g_basic
, f_about
, f_mapoptimization
,
330 f_mapcheck
, f_addresource_texture
, g_textures
,
331 f_activationtype
, f_keys
,
332 MAPREADER
, f_selectmap
, f_savemap
, WADEDITOR
, WADSTRUCT
, MAPDEF
,
333 g_map
, f_saveminimap
, f_addresource
, CONFIG
, f_packmap
,
334 f_addresource_sound
, f_maptest
, f_choosetype
,
335 g_language
, f_selectlang
, ClipBrd
;
338 UNDO_DELETE_PANEL
= 1;
339 UNDO_DELETE_ITEM
= 2;
340 UNDO_DELETE_AREA
= 3;
341 UNDO_DELETE_MONSTER
= 4;
342 UNDO_DELETE_TRIGGER
= 5;
346 UNDO_ADD_MONSTER
= 9;
347 UNDO_ADD_TRIGGER
= 10;
348 UNDO_MOVE_PANEL
= 11;
351 UNDO_MOVE_MONSTER
= 14;
352 UNDO_MOVE_TRIGGER
= 15;
353 UNDO_RESIZE_PANEL
= 16;
354 UNDO_RESIZE_TRIGGER
= 17;
356 MOUSEACTION_NONE
= 0;
357 MOUSEACTION_DRAWPANEL
= 1;
358 MOUSEACTION_DRAWTRIGGER
= 2;
359 MOUSEACTION_MOVEOBJ
= 3;
360 MOUSEACTION_RESIZE
= 4;
361 MOUSEACTION_MOVEMAP
= 5;
362 MOUSEACTION_DRAWPRESS
= 6;
363 MOUSEACTION_NOACTION
= 7;
366 RESIZETYPE_VERTICAL
= 1;
367 RESIZETYPE_HORIZONTAL
= 2;
376 SELECTFLAG_TELEPORT
= 1;
378 SELECTFLAG_TEXTURE
= 3;
380 SELECTFLAG_MONSTER
= 5;
381 SELECTFLAG_SPAWNPOINT
= 6;
382 SELECTFLAG_SHOTPANEL
= 7;
383 SELECTFLAG_SELECTED
= 8;
385 RECENT_FILES_MENU_START
= 11;
387 CLIPBOARD_SIG
= 'DF:ED';
393 UNDO_DELETE_PANEL
: (Panel
: ^TPanel
);
394 UNDO_DELETE_ITEM
: (Item
: TItem
);
395 UNDO_DELETE_AREA
: (Area
: TArea
);
396 UNDO_DELETE_MONSTER
: (Monster
: TMonster
);
397 UNDO_DELETE_TRIGGER
: (Trigger
: TTrigger
);
402 UNDO_ADD_TRIGGER
: (AddID
: DWORD
);
407 UNDO_MOVE_TRIGGER
: (MoveID
: DWORD
; dX
, dY
: Integer);
409 UNDO_RESIZE_TRIGGER
: (ResizeID
: DWORD
; dW
, dH
: Integer);
416 OBJECT_PANEL
: (Panel
: ^TPanel
);
417 OBJECT_ITEM
: (Item
: TItem
);
418 OBJECT_AREA
: (Area
: TArea
);
419 OBJECT_MONSTER
: (Monster
: TMonster
);
420 OBJECT_TRIGGER
: (Trigger
: TTrigger
);
423 TCopyRecArray
= Array of TCopyRec
;
427 gDataLoaded
: Boolean = False;
428 ShowMap
: Boolean = False;
429 DrawRect
: PRect
= nil;
430 SnapToGrid
: Boolean = True;
432 MousePos
: Types
.TPoint
;
433 LastMovePoint
: Types
.TPoint
;
436 MouseLDownPos
: Types
.TPoint
;
437 MouseRDownPos
: Types
.TPoint
;
440 SelectFlag
: Byte = SELECTFLAG_NONE
;
441 MouseAction
: Byte = MOUSEACTION_NONE
;
442 ResizeType
: Byte = RESIZETYPE_NONE
;
443 ResizeDirection
: Byte = RESIZEDIR_NONE
;
445 DrawPressRect
: Boolean = False;
446 EditingProperties
: Boolean = False;
448 UndoBuffer
: Array of Array of TUndoRec
= nil;
453 //----------------------------------------
454 //Далее идут вспомогательные процедуры
455 //----------------------------------------
457 function NameToBool(Name
: String): Boolean;
459 if Name
= BoolNames
[True] then
465 function NameToDir(Name
: String): TDirection
;
467 if Name
= DirNames
[D_LEFT
] then
473 function NameToDirAdv(Name
: String): Byte;
475 if Name
= DirNamesAdv
[1] then
478 if Name
= DirNamesAdv
[2] then
481 if Name
= DirNamesAdv
[3] then
487 function ActivateToStr(ActivateType
: Byte): String;
491 if ByteBool(ACTIVATE_PLAYERCOLLIDE
and ActivateType
) then
492 Result
:= Result
+ '+PC';
493 if ByteBool(ACTIVATE_MONSTERCOLLIDE
and ActivateType
) then
494 Result
:= Result
+ '+MC';
495 if ByteBool(ACTIVATE_PLAYERPRESS
and ActivateType
) then
496 Result
:= Result
+ '+PP';
497 if ByteBool(ACTIVATE_MONSTERPRESS
and ActivateType
) then
498 Result
:= Result
+ '+MP';
499 if ByteBool(ACTIVATE_SHOT
and ActivateType
) then
500 Result
:= Result
+ '+SH';
501 if ByteBool(ACTIVATE_NOMONSTER
and ActivateType
) then
502 Result
:= Result
+ '+NM';
504 if (Result
<> '') and (Result
[1] = '+') then
505 Delete(Result
, 1, 1);
508 function StrToActivate(Str
: String): Byte;
512 if Pos('PC', Str
) > 0 then
513 Result
:= ACTIVATE_PLAYERCOLLIDE
;
514 if Pos('MC', Str
) > 0 then
515 Result
:= Result
or ACTIVATE_MONSTERCOLLIDE
;
516 if Pos('PP', Str
) > 0 then
517 Result
:= Result
or ACTIVATE_PLAYERPRESS
;
518 if Pos('MP', Str
) > 0 then
519 Result
:= Result
or ACTIVATE_MONSTERPRESS
;
520 if Pos('SH', Str
) > 0 then
521 Result
:= Result
or ACTIVATE_SHOT
;
522 if Pos('NM', Str
) > 0 then
523 Result
:= Result
or ACTIVATE_NOMONSTER
;
526 function KeyToStr(Key
: Byte): String;
530 if ByteBool(KEY_RED
and Key
) then
531 Result
:= Result
+ '+RK';
532 if ByteBool(KEY_GREEN
and Key
) then
533 Result
:= Result
+ '+GK';
534 if ByteBool(KEY_BLUE
and Key
) then
535 Result
:= Result
+ '+BK';
536 if ByteBool(KEY_REDTEAM
and Key
) then
537 Result
:= Result
+ '+RT';
538 if ByteBool(KEY_BLUETEAM
and Key
) then
539 Result
:= Result
+ '+BT';
541 if (Result
<> '') and (Result
[1] = '+') then
542 Delete(Result
, 1, 1);
545 function StrToKey(Str
: String): Byte;
549 if Pos('RK', Str
) > 0 then
551 if Pos('GK', Str
) > 0 then
552 Result
:= Result
or KEY_GREEN
;
553 if Pos('BK', Str
) > 0 then
554 Result
:= Result
or KEY_BLUE
;
555 if Pos('RT', Str
) > 0 then
556 Result
:= Result
or KEY_REDTEAM
;
557 if Pos('BT', Str
) > 0 then
558 Result
:= Result
or KEY_BLUETEAM
;
561 function EffectToStr(Effect
: Byte): String;
563 if Effect
in [EFFECT_TELEPORT
..EFFECT_FIRE
] then
564 Result
:= EffectNames
[Effect
]
566 Result
:= EffectNames
[EFFECT_NONE
];
569 function StrToEffect(Str
: String): Byte;
573 Result
:= EFFECT_NONE
;
574 for i
:= EFFECT_TELEPORT
to EFFECT_FIRE
do
575 if EffectNames
[i
] = Str
then
582 function MonsterToStr(MonType
: Byte): String;
584 if MonType
in [MONSTER_DEMON
..MONSTER_MAN
] then
585 Result
:= MonsterNames
[MonType
]
587 Result
:= MonsterNames
[MONSTER_ZOMBY
];
590 function StrToMonster(Str
: String): Byte;
594 Result
:= MONSTER_ZOMBY
;
595 for i
:= MONSTER_DEMON
to MONSTER_MAN
do
596 if MonsterNames
[i
] = Str
then
603 function ItemToStr(ItemType
: Byte): String;
605 if ItemType
in [ITEM_MEDKIT_SMALL
..ITEM_MAX
] then
606 Result
:= ItemNames
[ItemType
]
608 Result
:= ItemNames
[ITEM_AMMO_BULLETS
];
611 function StrToItem(Str
: String): Byte;
615 Result
:= ITEM_AMMO_BULLETS
;
616 for i
:= ITEM_MEDKIT_SMALL
to ITEM_MAX
do
617 if ItemNames
[i
] = Str
then
624 function ShotToStr(ShotType
: Byte): String;
626 if ShotType
in [TRIGGER_SHOT_PISTOL
..TRIGGER_SHOT_MAX
] then
627 Result
:= ShotNames
[ShotType
]
629 Result
:= ShotNames
[TRIGGER_SHOT_PISTOL
];
632 function StrToShot(Str
: String): Byte;
636 Result
:= TRIGGER_SHOT_PISTOL
;
637 for i
:= TRIGGER_SHOT_PISTOL
to TRIGGER_SHOT_MAX
do
638 if ShotNames
[i
] = Str
then
645 function SelectedObjectCount(): Word;
651 if SelectedObjects
= nil then
654 for a
:= 0 to High(SelectedObjects
) do
655 if SelectedObjects
[a
].Live
then
656 Result
:= Result
+ 1;
659 function GetFirstSelected(): Integer;
665 if SelectedObjects
= nil then
668 for a
:= 0 to High(SelectedObjects
) do
669 if SelectedObjects
[a
].Live
then
676 function Normalize16(x
: Integer): Integer;
678 Result
:= (x
div 16) * 16;
681 procedure MoveMap(X
, Y
: Integer);
683 rx
, ry
, ScaleSz
: Integer;
685 with MainForm
.RenderPanel
do
687 ScaleSz
:= 16 div Scale
;
688 // Размер видимой части карты:
689 rx
:= min(Normalize16(Width
), Normalize16(gMapInfo
.Width
)) div 2;
690 ry
:= min(Normalize16(Height
), Normalize16(gMapInfo
.Height
)) div 2;
691 // Место клика на мини-карте:
692 MapOffset
.X
:= X
- (Width
-max(gMapInfo
.Width
div ScaleSz
, 1)-1);
693 MapOffset
.Y
:= Y
- 1;
694 // Это же место на "большой" карте:
695 MapOffset
.X
:= MapOffset
.X
* ScaleSz
;
696 MapOffset
.Y
:= MapOffset
.Y
* ScaleSz
;
697 // Левый верхний угол новой видимой части карты:
698 MapOffset
.X
:= MapOffset
.X
- rx
;
699 MapOffset
.Y
:= MapOffset
.Y
- ry
;
701 if MapOffset
.X
< 0 then
703 if MapOffset
.Y
< 0 then
705 if MapOffset
.X
> MainForm
.sbHorizontal
.Max
then
706 MapOffset
.X
:= MainForm
.sbHorizontal
.Max
;
707 if MapOffset
.Y
> MainForm
.sbVertical
.Max
then
708 MapOffset
.Y
:= MainForm
.sbVertical
.Max
;
710 MapOffset
.X
:= Normalize16(MapOffset
.X
);
711 MapOffset
.Y
:= Normalize16(MapOffset
.Y
);
714 MainForm
.sbHorizontal
.Position
:= MapOffset
.X
;
715 MainForm
.sbVertical
.Position
:= MapOffset
.Y
;
717 MapOffset
.X
:= -MapOffset
.X
;
718 MapOffset
.Y
:= -MapOffset
.Y
;
723 function IsTexturedPanel(PanelType
: Word): Boolean;
725 Result
:= WordBool(PanelType
and (PANEL_WALL
or PANEL_BACK
or PANEL_FORE
or
726 PANEL_STEP
or PANEL_OPENDOOR
or PANEL_CLOSEDOOR
or
727 PANEL_WATER
or PANEL_ACID1
or PANEL_ACID2
));
730 procedure FillProperty();
735 MainForm
.vleObjectProperty
.Strings
.Clear();
737 // Отображаем свойства если выделен только один объект:
738 if SelectedObjectCount() <> 1 then
741 _id
:= GetFirstSelected();
742 if not SelectedObjects
[_id
].Live
then
745 with MainForm
.vleObjectProperty
do
746 with ItemProps
[InsertRow(_lc
[I_PROP_ID
], IntToStr(SelectedObjects
[_id
].ID
), True)] do
748 EditStyle
:= esSimple
;
752 case SelectedObjects
[0].ObjectType
of
755 with MainForm
.vleObjectProperty
,
756 gPanels
[SelectedObjects
[_id
].ID
] do
758 with ItemProps
[InsertRow(_lc
[I_PROP_X
], IntToStr(X
), True)] do
760 EditStyle
:= esSimple
;
764 with ItemProps
[InsertRow(_lc
[I_PROP_Y
], IntToStr(Y
), True)] do
766 EditStyle
:= esSimple
;
770 with ItemProps
[InsertRow(_lc
[I_PROP_WIDTH
], IntToStr(Width
), True)] do
772 EditStyle
:= esSimple
;
776 with ItemProps
[InsertRow(_lc
[I_PROP_HEIGHT
], IntToStr(Height
), True)] do
778 EditStyle
:= esSimple
;
782 with ItemProps
[InsertRow(_lc
[I_PROP_PANEL_TYPE
], GetPanelName(PanelType
), True)] do
784 EditStyle
:= esEllipsis
;
788 if IsTexturedPanel(PanelType
) then
789 begin // Может быть текстура
790 with ItemProps
[InsertRow(_lc
[I_PROP_PANEL_TEX
], TextureName
, True)] do
792 EditStyle
:= esEllipsis
;
796 if TextureName
<> '' then
797 begin // Есть текстура
798 with ItemProps
[InsertRow(_lc
[I_PROP_PANEL_ALPHA
], IntToStr(Alpha
), True)] do
800 EditStyle
:= esSimple
;
804 with ItemProps
[InsertRow(_lc
[I_PROP_PANEL_BLEND
], BoolNames
[Blending
], True)] do
806 EditStyle
:= esPickList
;
816 with MainForm
.vleObjectProperty
,
817 gItems
[SelectedObjects
[_id
].ID
] do
819 with ItemProps
[InsertRow(_lc
[I_PROP_X
], IntToStr(X
), True)] do
821 EditStyle
:= esSimple
;
825 with ItemProps
[InsertRow(_lc
[I_PROP_Y
], IntToStr(Y
), True)] do
827 EditStyle
:= esSimple
;
831 with ItemProps
[InsertRow(_lc
[I_PROP_DM_ONLY
], BoolNames
[OnlyDM
], True)] do
833 EditStyle
:= esPickList
;
837 with ItemProps
[InsertRow(_lc
[I_PROP_ITEM_FALLS
], BoolNames
[Fall
], True)] do
839 EditStyle
:= esPickList
;
847 with MainForm
.vleObjectProperty
,
848 gMonsters
[SelectedObjects
[_id
].ID
] do
850 with ItemProps
[InsertRow(_lc
[I_PROP_X
], IntToStr(X
), True)] do
852 EditStyle
:= esSimple
;
856 with ItemProps
[InsertRow(_lc
[I_PROP_Y
], IntToStr(Y
), True)] do
858 EditStyle
:= esSimple
;
862 with ItemProps
[InsertRow(_lc
[I_PROP_DIRECTION
], DirNames
[Direction
], True)] do
864 EditStyle
:= esPickList
;
872 with MainForm
.vleObjectProperty
,
873 gAreas
[SelectedObjects
[_id
].ID
] do
875 with ItemProps
[InsertRow(_lc
[I_PROP_X
], IntToStr(X
), True)] do
877 EditStyle
:= esSimple
;
881 with ItemProps
[InsertRow(_lc
[I_PROP_Y
], IntToStr(Y
), True)] do
883 EditStyle
:= esSimple
;
887 with ItemProps
[InsertRow(_lc
[I_PROP_DIRECTION
], DirNames
[Direction
], True)] do
889 EditStyle
:= esPickList
;
897 with MainForm
.vleObjectProperty
,
898 gTriggers
[SelectedObjects
[_id
].ID
] do
900 with ItemProps
[InsertRow(_lc
[I_PROP_TR_TYPE
], GetTriggerName(TriggerType
), True)] do
902 EditStyle
:= esSimple
;
906 with ItemProps
[InsertRow(_lc
[I_PROP_X
], IntToStr(X
), True)] do
908 EditStyle
:= esSimple
;
912 with ItemProps
[InsertRow(_lc
[I_PROP_Y
], IntToStr(Y
), True)] do
914 EditStyle
:= esSimple
;
918 with ItemProps
[InsertRow(_lc
[I_PROP_WIDTH
], IntToStr(Width
), True)] do
920 EditStyle
:= esSimple
;
924 with ItemProps
[InsertRow(_lc
[I_PROP_HEIGHT
], IntToStr(Height
), True)] do
926 EditStyle
:= esSimple
;
930 with ItemProps
[InsertRow(_lc
[I_PROP_TR_ENABLED
], BoolNames
[Enabled
], True)] do
932 EditStyle
:= esPickList
;
936 with ItemProps
[InsertRow(_lc
[I_PROP_TR_TEXTURE_PANEL
], IntToStr(TexturePanel
), True)] do
938 EditStyle
:= esEllipsis
;
942 with ItemProps
[InsertRow(_lc
[I_PROP_TR_ACTIVATION
], ActivateToStr(ActivateType
), True)] do
944 EditStyle
:= esEllipsis
;
948 with ItemProps
[InsertRow(_lc
[I_PROP_TR_KEYS
], KeyToStr(Key
), True)] do
950 EditStyle
:= esEllipsis
;
957 str
:= win2utf(Data
.MapName
);
958 with ItemProps
[InsertRow(_lc
[I_PROP_TR_NEXT_MAP
], str
, True)] do
960 EditStyle
:= esEllipsis
;
967 with ItemProps
[InsertRow(_lc
[I_PROP_TR_TELEPORT_TO
], Format('(%d:%d)', [Data
.TargetPoint
.X
, Data
.TargetPoint
.Y
]), True)] do
969 EditStyle
:= esEllipsis
;
973 with ItemProps
[InsertRow(_lc
[I_PROP_TR_D2D
], BoolNames
[Data
.d2d_teleport
], True)] do
975 EditStyle
:= esPickList
;
979 with ItemProps
[InsertRow(_lc
[I_PROP_TR_TELEPORT_SILENT
], BoolNames
[Data
.silent_teleport
], True)] do
981 EditStyle
:= esPickList
;
985 with ItemProps
[InsertRow(_lc
[I_PROP_TR_TELEPORT_DIR
], DirNamesAdv
[Data
.TlpDir
], True)] do
987 EditStyle
:= esPickList
;
992 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
,
993 TRIGGER_DOOR
, TRIGGER_DOOR5
:
995 with ItemProps
[InsertRow(_lc
[I_PROP_TR_DOOR_PANEL
], IntToStr(Data
.PanelID
), True)] do
997 EditStyle
:= esEllipsis
;
1001 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SILENT
], BoolNames
[Data
.NoSound
], True)] do
1003 EditStyle
:= esPickList
;
1007 with ItemProps
[InsertRow(_lc
[I_PROP_TR_D2D
], BoolNames
[Data
.d2d_doors
], True)] do
1009 EditStyle
:= esPickList
;
1014 TRIGGER_CLOSETRAP
, TRIGGER_TRAP
:
1016 with ItemProps
[InsertRow(_lc
[I_PROP_TR_TRAP_PANEL
], IntToStr(Data
.PanelID
), True)] do
1018 EditStyle
:= esEllipsis
;
1022 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SILENT
], BoolNames
[Data
.NoSound
], True)] do
1024 EditStyle
:= esPickList
;
1028 with ItemProps
[InsertRow(_lc
[I_PROP_TR_D2D
], BoolNames
[Data
.d2d_doors
], True)] do
1030 EditStyle
:= esPickList
;
1035 TRIGGER_PRESS
, TRIGGER_ON
, TRIGGER_OFF
,
1038 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EX_AREA
],
1039 Format('(%d:%d %d:%d)', [Data
.tX
, Data
.tY
, Data
.tWidth
, Data
.tHeight
]), True)] do
1041 EditStyle
:= esEllipsis
;
1045 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EX_DELAY
], IntToStr(Data
.Wait
), True)] do
1047 EditStyle
:= esSimple
;
1051 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EX_COUNT
], IntToStr(Data
.Count
), True)] do
1053 EditStyle
:= esSimple
;
1057 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EX_MONSTER
], IntToStr(Data
.MonsterID
-1), True)] do
1059 EditStyle
:= esEllipsis
;
1063 if TriggerType
= TRIGGER_PRESS
then
1064 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EX_RANDOM
], BoolNames
[Data
.ExtRandom
], True)] do
1066 EditStyle
:= esPickList
;
1074 TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
:
1076 with ItemProps
[InsertRow(_lc
[I_PROP_TR_LIFT_PANEL
], IntToStr(Data
.PanelID
), True)] do
1078 EditStyle
:= esEllipsis
;
1082 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SILENT
], BoolNames
[Data
.NoSound
], True)] do
1084 EditStyle
:= esPickList
;
1088 with ItemProps
[InsertRow(_lc
[I_PROP_TR_D2D
], BoolNames
[Data
.d2d_doors
], True)] do
1090 EditStyle
:= esPickList
;
1097 with ItemProps
[InsertRow(_lc
[I_PROP_TR_TEXTURE_ONCE
], BoolNames
[Data
.ActivateOnce
], True)] do
1099 EditStyle
:= esPickList
;
1103 with ItemProps
[InsertRow(_lc
[I_PROP_TR_TEXTURE_ANIM_ONCE
], BoolNames
[Data
.AnimOnce
], True)] do
1105 EditStyle
:= esPickList
;
1112 str
:= win2utf(Data
.SoundName
);
1113 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SOUND_NAME
], str
, True)] do
1115 EditStyle
:= esEllipsis
;
1119 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SOUND_VOLUME
], IntToStr(Data
.Volume
), True)] do
1121 EditStyle
:= esSimple
;
1125 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SOUND_PAN
], IntToStr(Data
.Pan
), True)] do
1127 EditStyle
:= esSimple
;
1131 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SOUND_COUNT
], IntToStr(Data
.PlayCount
), True)] do
1133 EditStyle
:= esSimple
;
1137 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SOUND_LOCAL
], BoolNames
[Data
.Local
], True)] do
1139 EditStyle
:= esPickList
;
1143 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SOUND_SWITCH
], BoolNames
[Data
.SoundSwitch
], True)] do
1145 EditStyle
:= esPickList
;
1150 TRIGGER_SPAWNMONSTER
:
1152 with ItemProps
[InsertRow(_lc
[I_PROP_TR_MONSTER_TYPE
], MonsterToStr(Data
.MonType
), True)] do
1154 EditStyle
:= esEllipsis
;
1158 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SPAWN_TO
],
1159 Format('(%d:%d)', [Data
.MonPos
.X
, Data
.MonPos
.Y
]), True)] do
1161 EditStyle
:= esEllipsis
;
1165 with ItemProps
[InsertRow(_lc
[I_PROP_DIRECTION
], DirNames
[TDirection(Data
.MonDir
)], True)] do
1167 EditStyle
:= esPickList
;
1171 with ItemProps
[InsertRow(_lc
[I_PROP_TR_HEALTH
], IntToStr(Data
.MonHealth
), True)] do
1173 EditStyle
:= esSimple
;
1177 with ItemProps
[InsertRow(_lc
[I_PROP_TR_MONSTER_ACTIVE
], BoolNames
[Data
.MonActive
], True)] do
1179 EditStyle
:= esPickList
;
1183 with ItemProps
[InsertRow(_lc
[I_PROP_TR_COUNT
], IntToStr(Data
.MonCount
), True)] do
1185 EditStyle
:= esSimple
;
1189 with ItemProps
[InsertRow(_lc
[I_PROP_TR_FX_TYPE
], EffectToStr(Data
.MonEffect
), True)] do
1191 EditStyle
:= esEllipsis
;
1195 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SPAWN_MAX
], IntToStr(Data
.MonMax
), True)] do
1197 EditStyle
:= esSimple
;
1201 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SPAWN_DELAY
], IntToStr(Data
.MonDelay
), True)] do
1203 EditStyle
:= esSimple
;
1207 case Data
.MonBehav
of
1208 1: str
:= _lc
[I_PROP_TR_MONSTER_BEHAVIOUR_1
];
1209 2: str
:= _lc
[I_PROP_TR_MONSTER_BEHAVIOUR_2
];
1210 3: str
:= _lc
[I_PROP_TR_MONSTER_BEHAVIOUR_3
];
1211 4: str
:= _lc
[I_PROP_TR_MONSTER_BEHAVIOUR_4
];
1212 5: str
:= _lc
[I_PROP_TR_MONSTER_BEHAVIOUR_5
];
1213 else str
:= _lc
[I_PROP_TR_MONSTER_BEHAVIOUR_0
];
1215 with ItemProps
[InsertRow(_lc
[I_PROP_TR_MONSTER_BEHAVIOUR
], str
, True)] do
1217 EditStyle
:= esPickList
;
1224 with ItemProps
[InsertRow(_lc
[I_PROP_TR_ITEM_TYPE
], ItemToStr(Data
.ItemType
), True)] do
1226 EditStyle
:= esEllipsis
;
1230 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SPAWN_TO
],
1231 Format('(%d:%d)', [Data
.ItemPos
.X
, Data
.ItemPos
.Y
]), True)] do
1233 EditStyle
:= esEllipsis
;
1237 with ItemProps
[InsertRow(_lc
[I_PROP_DM_ONLY
], BoolNames
[Data
.ItemOnlyDM
], True)] do
1239 EditStyle
:= esPickList
;
1243 with ItemProps
[InsertRow(_lc
[I_PROP_ITEM_FALLS
], BoolNames
[Data
.ItemFalls
], True)] do
1245 EditStyle
:= esPickList
;
1249 with ItemProps
[InsertRow(_lc
[I_PROP_TR_COUNT
], IntToStr(Data
.ItemCount
), True)] do
1251 EditStyle
:= esSimple
;
1255 with ItemProps
[InsertRow(_lc
[I_PROP_TR_FX_TYPE
], EffectToStr(Data
.ItemEffect
), True)] do
1257 EditStyle
:= esEllipsis
;
1261 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SPAWN_MAX
], IntToStr(Data
.ItemMax
), True)] do
1263 EditStyle
:= esSimple
;
1267 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SPAWN_DELAY
], IntToStr(Data
.ItemDelay
), True)] do
1269 EditStyle
:= esSimple
;
1276 str
:= win2utf(Data
.MusicName
);
1277 with ItemProps
[InsertRow(_lc
[I_PROP_TR_MUSIC_NAME
], str
, True)] do
1279 EditStyle
:= esEllipsis
;
1283 if Data
.MusicAction
= 1 then
1284 str
:= _lc
[I_PROP_TR_MUSIC_ON
]
1286 str
:= _lc
[I_PROP_TR_MUSIC_OFF
];
1288 with ItemProps
[InsertRow(_lc
[I_PROP_TR_MUSIC_ACT
], str
, True)] do
1290 EditStyle
:= esPickList
;
1297 with ItemProps
[InsertRow(_lc
[I_PROP_TR_PUSH_ANGLE
], IntToStr(Data
.PushAngle
), True)] do
1299 EditStyle
:= esSimple
;
1302 with ItemProps
[InsertRow(_lc
[I_PROP_TR_PUSH_FORCE
], IntToStr(Data
.PushForce
), True)] do
1304 EditStyle
:= esSimple
;
1307 with ItemProps
[InsertRow(_lc
[I_PROP_TR_PUSH_RESET
], BoolNames
[Data
.ResetVel
], True)] do
1309 EditStyle
:= esPickList
;
1316 case Data
.ScoreAction
of
1317 1: str
:= _lc
[I_PROP_TR_SCORE_ACT_1
];
1318 2: str
:= _lc
[I_PROP_TR_SCORE_ACT_2
];
1319 3: str
:= _lc
[I_PROP_TR_SCORE_ACT_3
];
1320 else str
:= _lc
[I_PROP_TR_SCORE_ACT_0
];
1322 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SCORE_ACT
], str
, True)] do
1324 EditStyle
:= esPickList
;
1327 with ItemProps
[InsertRow(_lc
[I_PROP_TR_COUNT
], IntToStr(Data
.ScoreCount
), True)] do
1329 EditStyle
:= esSimple
;
1332 case Data
.ScoreTeam
of
1333 1: str
:= _lc
[I_PROP_TR_SCORE_TEAM_1
];
1334 2: str
:= _lc
[I_PROP_TR_SCORE_TEAM_2
];
1335 3: str
:= _lc
[I_PROP_TR_SCORE_TEAM_3
];
1336 else str
:= _lc
[I_PROP_TR_SCORE_TEAM_0
];
1338 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SCORE_TEAM
], str
, True)] do
1340 EditStyle
:= esPickList
;
1343 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SCORE_CON
], BoolNames
[Data
.ScoreCon
], True)] do
1345 EditStyle
:= esPickList
;
1348 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SCORE_MSG
], BoolNames
[Data
.ScoreMsg
], True)] do
1350 EditStyle
:= esPickList
;
1357 case Data
.MessageKind
of
1358 1: str
:= _lc
[I_PROP_TR_MESSAGE_KIND_1
];
1359 else str
:= _lc
[I_PROP_TR_MESSAGE_KIND_0
];
1361 with ItemProps
[InsertRow(_lc
[I_PROP_TR_MESSAGE_KIND
], str
, True)] do
1363 EditStyle
:= esPickList
;
1366 case Data
.MessageSendTo
of
1367 1: str
:= _lc
[I_PROP_TR_MESSAGE_TO_1
];
1368 2: str
:= _lc
[I_PROP_TR_MESSAGE_TO_2
];
1369 3: str
:= _lc
[I_PROP_TR_MESSAGE_TO_3
];
1370 4: str
:= _lc
[I_PROP_TR_MESSAGE_TO_4
];
1371 5: str
:= _lc
[I_PROP_TR_MESSAGE_TO_5
];
1372 else str
:= _lc
[I_PROP_TR_MESSAGE_TO_0
];
1374 with ItemProps
[InsertRow(_lc
[I_PROP_TR_MESSAGE_TO
], str
, True)] do
1376 EditStyle
:= esPickList
;
1379 str
:= win2utf(Data
.MessageText
);
1380 with ItemProps
[InsertRow(_lc
[I_PROP_TR_MESSAGE_TEXT
], str
, True)] do
1382 EditStyle
:= esSimple
;
1385 with ItemProps
[InsertRow(_lc
[I_PROP_TR_MESSAGE_TIME
], IntToStr(Data
.MessageTime
), True)] do
1387 EditStyle
:= esSimple
;
1394 with ItemProps
[InsertRow(_lc
[I_PROP_TR_DAMAGE_VALUE
], IntToStr(Data
.DamageValue
), True)] do
1396 EditStyle
:= esSimple
;
1399 with ItemProps
[InsertRow(_lc
[I_PROP_TR_INTERVAL
], IntToStr(Data
.DamageInterval
), True)] do
1401 EditStyle
:= esSimple
;
1408 with ItemProps
[InsertRow(_lc
[I_PROP_TR_HEALTH
], IntToStr(Data
.HealValue
), True)] do
1410 EditStyle
:= esSimple
;
1413 with ItemProps
[InsertRow(_lc
[I_PROP_TR_INTERVAL
], IntToStr(Data
.HealInterval
), True)] do
1415 EditStyle
:= esSimple
;
1418 with ItemProps
[InsertRow(_lc
[I_PROP_TR_HEALTH_MAX
], BoolNames
[Data
.HealMax
], True)] do
1420 EditStyle
:= esPickList
;
1423 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SILENT
], BoolNames
[Data
.HealSilent
], True)] do
1425 EditStyle
:= esPickList
;
1432 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SHOT_TYPE
], ShotToStr(Data
.ShotType
), True)] do
1434 EditStyle
:= esEllipsis
;
1438 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SHOT_SOUND
], BoolNames
[Data
.ShotSound
], True)] do
1440 EditStyle
:= esPickList
;
1444 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SHOT_PANEL
], IntToStr(Data
.ShotPanelID
), True)] do
1446 EditStyle
:= esEllipsis
;
1450 case Data
.ShotTarget
of
1451 1: str
:= _lc
[I_PROP_TR_SHOT_TO_1
];
1452 2: str
:= _lc
[I_PROP_TR_SHOT_TO_2
];
1453 3: str
:= _lc
[I_PROP_TR_SHOT_TO_3
];
1454 4: str
:= _lc
[I_PROP_TR_SHOT_TO_4
];
1455 5: str
:= _lc
[I_PROP_TR_SHOT_TO_5
];
1456 6: str
:= _lc
[I_PROP_TR_SHOT_TO_6
];
1457 else str
:= _lc
[I_PROP_TR_SHOT_TO_0
];
1459 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SHOT_TO
], str
, True)] do
1461 EditStyle
:= esPickList
;
1465 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SHOT_SIGHT
], IntToStr(Data
.ShotIntSight
), True)] do
1467 EditStyle
:= esSimple
;
1471 case Data
.ShotAim
of
1472 1: str
:= _lc
[I_PROP_TR_SHOT_AIM_1
];
1473 2: str
:= _lc
[I_PROP_TR_SHOT_AIM_2
];
1474 3: str
:= _lc
[I_PROP_TR_SHOT_AIM_3
];
1475 else str
:= _lc
[I_PROP_TR_SHOT_AIM_0
];
1477 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SHOT_AIM
], str
, True)-1] do
1479 EditStyle
:= esPickList
;
1483 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SPAWN_TO
],
1484 Format('(%d:%d)', [Data
.ShotPos
.X
, Data
.ShotPos
.Y
]), True)] do
1486 EditStyle
:= esEllipsis
;
1490 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SHOT_ANGLE
], IntToStr(Data
.ShotAngle
), True)] do
1492 EditStyle
:= esSimple
;
1496 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EX_DELAY
], IntToStr(Data
.ShotWait
), True)] do
1498 EditStyle
:= esSimple
;
1502 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SHOT_ACC
], IntToStr(Data
.ShotAccuracy
), True)] do
1504 EditStyle
:= esSimple
;
1508 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SHOT_AMMO
], IntToStr(Data
.ShotAmmo
), True)] do
1510 EditStyle
:= esSimple
;
1514 with ItemProps
[InsertRow(_lc
[I_PROP_TR_SHOT_RELOAD
], IntToStr(Data
.ShotIntReload
), True)] do
1516 EditStyle
:= esSimple
;
1523 with ItemProps
[InsertRow(_lc
[I_PROP_TR_COUNT
], IntToStr(Data
.FXCount
), True)] do
1525 EditStyle
:= esSimple
;
1529 if Data
.FXType
= 0 then
1530 str
:= _lc
[I_PROP_TR_EFFECT_PARTICLE
]
1532 str
:= _lc
[I_PROP_TR_EFFECT_ANIMATION
];
1533 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EFFECT_TYPE
], str
, True)] do
1535 EditStyle
:= esEllipsis
;
1540 if Data
.FXType
= 0 then
1541 case Data
.FXSubType
of
1542 TRIGGER_EFFECT_SLIQUID
:
1543 str
:= _lc
[I_PROP_TR_EFFECT_SLIQUID
];
1544 TRIGGER_EFFECT_LLIQUID
:
1545 str
:= _lc
[I_PROP_TR_EFFECT_LLIQUID
];
1546 TRIGGER_EFFECT_DLIQUID
:
1547 str
:= _lc
[I_PROP_TR_EFFECT_DLIQUID
];
1548 TRIGGER_EFFECT_BLOOD
:
1549 str
:= _lc
[I_PROP_TR_EFFECT_BLOOD
];
1550 TRIGGER_EFFECT_SPARK
:
1551 str
:= _lc
[I_PROP_TR_EFFECT_SPARK
];
1552 TRIGGER_EFFECT_BUBBLE
:
1553 str
:= _lc
[I_PROP_TR_EFFECT_BUBBLE
];
1555 if Data
.FXType
= 1 then
1557 if (Data
.FXSubType
= 0) or (Data
.FXSubType
> EFFECT_FIRE
) then
1558 Data
.FXSubType
:= EFFECT_TELEPORT
;
1559 str
:= EffectToStr(Data
.FXSubType
);
1561 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EFFECT_SUBTYPE
], str
, True)] do
1563 EditStyle
:= esEllipsis
;
1567 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EFFECT_COLOR
], IntToStr(Data
.FXColorR
or (Data
.FXColorG
shl 8) or (Data
.FXColorB
shl 16)), True)] do
1569 EditStyle
:= esEllipsis
;
1573 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EFFECT_CENTER
], BoolNames
[Data
.FXPos
= 0], True)] do
1575 EditStyle
:= esPickList
;
1579 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EX_DELAY
], IntToStr(Data
.FXWait
), True)] do
1581 EditStyle
:= esSimple
;
1585 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EFFECT_VELX
], IntToStr(Data
.FXVelX
), True)] do
1587 EditStyle
:= esSimple
;
1591 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EFFECT_VELY
], IntToStr(Data
.FXVelY
), True)] do
1593 EditStyle
:= esSimple
;
1597 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EFFECT_SPL
], IntToStr(Data
.FXSpreadL
), True)] do
1599 EditStyle
:= esSimple
;
1603 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EFFECT_SPR
], IntToStr(Data
.FXSpreadR
), True)] do
1605 EditStyle
:= esSimple
;
1609 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EFFECT_SPU
], IntToStr(Data
.FXSpreadU
), True)] do
1611 EditStyle
:= esSimple
;
1615 with ItemProps
[InsertRow(_lc
[I_PROP_TR_EFFECT_SPD
], IntToStr(Data
.FXSpreadD
), True)] do
1617 EditStyle
:= esSimple
;
1621 end; //case TriggerType
1623 end; // OBJECT_TRIGGER:
1627 procedure ChangeShownProperty(Name
: String; NewValue
: String);
1631 if SelectedObjectCount() <> 1 then
1633 if not SelectedObjects
[GetFirstSelected()].Live
then
1636 // Есть ли такой ключ:
1637 if MainForm
.vleObjectProperty
.FindRow(Name
, row
) then
1639 MainForm
.vleObjectProperty
.Values
[Name
] := NewValue
;
1643 procedure SelectObject(fObjectType
: Byte; fID
: DWORD
; Multi
: Boolean);
1652 // Уже выделен - убираем:
1653 if SelectedObjects
<> nil then
1654 for a
:= 0 to High(SelectedObjects
) do
1655 with SelectedObjects
[a
] do
1656 if Live
and (ID
= fID
) and
1657 (ObjectType
= fObjectType
) then
1666 SetLength(SelectedObjects
, Length(SelectedObjects
)+1);
1668 with SelectedObjects
[High(SelectedObjects
)] do
1670 ObjectType
:= fObjectType
;
1677 SetLength(SelectedObjects
, 1);
1679 with SelectedObjects
[0] do
1681 ObjectType
:= fObjectType
;
1687 MainForm
.miCopy
.Enabled
:= True;
1688 MainForm
.miCut
.Enabled
:= True;
1690 if fObjectType
= OBJECT_PANEL
then
1692 MainForm
.miToFore
.Enabled
:= True;
1693 MainForm
.miToBack
.Enabled
:= True;
1697 procedure RemoveSelectFromObjects();
1699 SelectedObjects
:= nil;
1700 DrawPressRect
:= False;
1701 MouseLDown
:= False;
1702 MouseRDown
:= False;
1703 MouseAction
:= MOUSEACTION_NONE
;
1704 SelectFlag
:= SELECTFLAG_NONE
;
1705 ResizeType
:= RESIZETYPE_NONE
;
1706 ResizeDirection
:= RESIZEDIR_NONE
;
1708 MainForm
.vleObjectProperty
.Strings
.Clear();
1710 MainForm
.miCopy
.Enabled
:= False;
1711 MainForm
.miCut
.Enabled
:= False;
1712 MainForm
.miToFore
.Enabled
:= False;
1713 MainForm
.miToBack
.Enabled
:= False;
1716 procedure DeleteSelectedObjects();
1721 if SelectedObjects
= nil then
1727 for a
:= 0 to High(SelectedObjects
) do
1728 with SelectedObjects
[a
] do
1733 SetLength(UndoBuffer
, Length(UndoBuffer
)+1);
1734 i
:= High(UndoBuffer
);
1738 SetLength(UndoBuffer
[i
], Length(UndoBuffer
[i
])+1);
1739 ii
:= High(UndoBuffer
[i
]);
1744 UndoBuffer
[i
, ii
].UndoType
:= UNDO_DELETE_PANEL
;
1745 New(UndoBuffer
[i
, ii
].Panel
);
1746 UndoBuffer
[i
, ii
].Panel
^ := gPanels
[ID
];
1750 UndoBuffer
[i
, ii
].UndoType
:= UNDO_DELETE_ITEM
;
1751 UndoBuffer
[i
, ii
].Item
:= gItems
[ID
];
1755 UndoBuffer
[i
, ii
].UndoType
:= UNDO_DELETE_AREA
;
1756 UndoBuffer
[i
, ii
].Area
:= gAreas
[ID
];
1760 UndoBuffer
[i
, ii
].UndoType
:= UNDO_DELETE_TRIGGER
;
1761 UndoBuffer
[i
, ii
].Trigger
:= gTriggers
[ID
];
1765 RemoveObject(ID
, ObjectType
);
1768 RemoveSelectFromObjects();
1770 MainForm
.miUndo
.Enabled
:= UndoBuffer
<> nil;
1773 procedure Undo_Add(ObjectType
: Byte; ID
: DWORD
; Group
: Boolean = False);
1777 if (not Group
) or (Length(UndoBuffer
) = 0) then
1778 SetLength(UndoBuffer
, Length(UndoBuffer
)+1);
1779 SetLength(UndoBuffer
[High(UndoBuffer
)], Length(UndoBuffer
[High(UndoBuffer
)])+1);
1780 i
:= High(UndoBuffer
);
1781 ii
:= High(UndoBuffer
[i
]);
1785 UndoBuffer
[i
, ii
].UndoType
:= UNDO_ADD_PANEL
;
1787 UndoBuffer
[i
, ii
].UndoType
:= UNDO_ADD_ITEM
;
1789 UndoBuffer
[i
, ii
].UndoType
:= UNDO_ADD_MONSTER
;
1791 UndoBuffer
[i
, ii
].UndoType
:= UNDO_ADD_AREA
;
1793 UndoBuffer
[i
, ii
].UndoType
:= UNDO_ADD_TRIGGER
;
1796 UndoBuffer
[i
, ii
].AddID
:= ID
;
1798 MainForm
.miUndo
.Enabled
:= UndoBuffer
<> nil;
1801 procedure FullClear();
1803 RemoveSelectFromObjects();
1805 LoadSky(gMapInfo
.SkyName
);
1807 slInvalidTextures
.Clear();
1808 MapCheckForm
.lbErrorList
.Clear();
1809 MapCheckForm
.mErrorDescription
.Clear();
1811 MainForm
.miUndo
.Enabled
:= False;
1812 MainForm
.sbHorizontal
.Position
:= 0;
1813 MainForm
.sbVertical
.Position
:= 0;
1814 MainForm
.FormResize(nil);
1815 MainForm
.Caption
:= FormCaption
;
1820 procedure ErrorMessageBox(str
: String);
1822 MessageBox(0, PChar(str
), PChar(_lc
[I_MSG_ERROR
]),
1823 MB_ICONINFORMATION
or MB_OK
or MB_DEFBUTTON1
);
1826 function CheckProperty(): Boolean;
1832 _id
:= GetFirstSelected();
1834 if SelectedObjects
[_id
].ObjectType
= OBJECT_PANEL
then
1835 with gPanels
[SelectedObjects
[_id
].ID
] do
1837 if TextureWidth
<> 0 then
1838 if StrToIntDef(MainForm
.vleObjectProperty
.Values
[_lc
[I_PROP_WIDTH
]], 1) mod TextureWidth
<> 0 then
1840 ErrorMessageBox(Format(_lc
[I_MSG_WRONG_TEXWIDTH
],
1845 if TextureHeight
<> 0 then
1846 if StrToIntDef(Trim(MainForm
.vleObjectProperty
.Values
[_lc
[I_PROP_HEIGHT
]]), 1) mod TextureHeight
<> 0 then
1848 ErrorMessageBox(Format(_lc
[I_MSG_WRONG_TEXHEIGHT
],
1853 if IsTexturedPanel(PanelType
) and (TextureName
<> '') then
1854 if not (StrToIntDef(MainForm
.vleObjectProperty
.Values
[_lc
[I_PROP_PANEL_ALPHA
]], -1) in [0..255]) then
1856 ErrorMessageBox(_lc
[I_MSG_WRONG_ALPHA
]);
1861 if SelectedObjects
[_id
].ObjectType
in [OBJECT_PANEL
, OBJECT_TRIGGER
] then
1862 if (StrToIntDef(MainForm
.vleObjectProperty
.Values
[_lc
[I_PROP_WIDTH
]], 0) <= 0) or
1863 (StrToIntDef(MainForm
.vleObjectProperty
.Values
[_lc
[I_PROP_HEIGHT
]], 0) <= 0) then
1865 ErrorMessageBox(_lc
[I_MSG_WRONG_SIZE
]);
1869 if (Trim(MainForm
.vleObjectProperty
.Values
[_lc
[I_PROP_X
]]) = '') or
1870 (Trim(MainForm
.vleObjectProperty
.Values
[_lc
[I_PROP_Y
]]) = '') then
1872 ErrorMessageBox(_lc
[I_MSG_WRONG_XY
]);
1879 procedure SelectTexture(ID
: Integer);
1881 MainForm
.lbTextureList
.ItemIndex
:= ID
;
1882 MainForm
.lbTextureListClick(nil);
1885 function AddTexture(aWAD
, aSection
, aTex
: String; silent
: Boolean): Boolean;
1887 a
, FrameLen
: Integer;
1890 ResourceName
: String;
1891 FullResourceName
: String;
1892 SectionName
: String;
1894 Width
, Height
: Word;
1902 if aSection
= '..' then
1905 SectionName
:= aSection
;
1907 if aWAD
= _lc
[I_WAD_SPECIAL_MAP
] then
1909 g_ProcessResourceStr(OpenedMap
, @fn
, nil, nil);
1910 //FileName := EditorDir+'maps\'+ExtractFileName(fn);
1912 ResourceName
:= ':'+SectionName
+'\'+aTex
;
1915 if aWAD
= _lc
[I_WAD_SPECIAL_TEXS
] then
1916 begin // Спец. текстуры
1918 ResourceName
:= aTex
;
1921 begin // Внешний WAD
1922 FileName
:= EditorDir
+'wads/'+aWAD
;
1923 ResourceName
:= aWAD
+':'+SectionName
+'\'+aTex
;
1928 // Есть ли уже такая текстура:
1929 for a
:= 0 to MainForm
.lbTextureList
.Items
.Count
-1 do
1930 if ResourceName
= MainForm
.lbTextureList
.Items
[a
] then
1933 ErrorMessageBox(Format(_lc
[I_MSG_TEXTURE_ALREADY
],
1938 // Название ресурса <= 64 символов:
1939 if Length(ResourceName
) > 64 then
1942 ErrorMessageBox(Format(_lc
[I_MSG_RES_NAME_64
],
1950 if aWAD
= _lc
[I_WAD_SPECIAL_TEXS
] then
1952 a
:= MainForm
.lbTextureList
.Items
.Add(ResourceName
);
1959 FullResourceName
:= FileName
+':'+SectionName
+'\'+aTex
;
1961 if IsAnim(FullResourceName
) then
1962 begin // Аним. текстура
1963 GetFrame(FullResourceName
, Data
, FrameLen
, Width
, Height
);
1965 if g_CreateTextureMemorySize(Data
, FrameLen
, ResourceName
, 0, 0, Width
, Height
, 1) then
1966 a
:= MainForm
.lbTextureList
.Items
.Add(ResourceName
);
1968 else // Обычная текстура
1970 if g_CreateTextureWAD(ResourceName
, FullResourceName
) then
1971 a
:= MainForm
.lbTextureList
.Items
.Add(ResourceName
);
1973 if (a
> -1) and (not silent
) then
1980 procedure UpdateCaption(sMap
, sFile
, sRes
: String);
1983 if (sFile
= '') and (sRes
= '') and (sMap
= '') then
1984 Caption
:= FormCaption
1987 Caption
:= Format('%s - %s:%s', [FormCaption
, sFile
, sRes
])
1989 if (sFile
<> '') and (sRes
<> '') then
1990 Caption
:= Format('%s - %s (%s:%s)', [FormCaption
, sMap
, sFile
, sRes
])
1992 Caption
:= Format('%s - %s', [FormCaption
, sMap
]);
1995 procedure OpenMap(FileName
: String; mapN
: String);
2000 SelectMapForm
.Caption
:= _lc
[I_CAP_OPEN
];
2001 SelectMapForm
.GetMaps(FileName
);
2003 if (FileName
= OpenedWAD
) and
2004 (OpenedMap
<> '') then
2006 MapName
:= OpenedMap
;
2007 while (Pos(':\', MapName
) > 0) do
2008 Delete(MapName
, 1, Pos(':\', MapName
) + 1);
2010 idx
:= SelectMapForm
.lbMapList
.Items
.IndexOf(MapName
);
2011 SelectMapForm
.lbMapList
.ItemIndex
:= idx
;
2014 if SelectMapForm
.lbMapList
.Count
> 0 then
2015 SelectMapForm
.lbMapList
.ItemIndex
:= 0
2017 SelectMapForm
.lbMapList
.ItemIndex
:= -1;
2022 idx
:= SelectMapForm
.lbMapList
.Items
.IndexOf(mapN
);
2026 if (SelectMapForm
.ShowModal() = mrOK
) and
2027 (SelectMapForm
.lbMapList
.ItemIndex
<> -1) then
2028 idx
:= SelectMapForm
.lbMapList
.ItemIndex
2033 MapName
:= SelectMapForm
.lbMapList
.Items
[idx
];
2039 pLoadProgress
.Left
:= (RenderPanel
.Width
div 2)-(pLoadProgress
.Width
div 2);
2040 pLoadProgress
.Top
:= (RenderPanel
.Height
div 2)-(pLoadProgress
.Height
div 2);
2041 pLoadProgress
.Show();
2043 OpenedMap
:= FileName
+':\'+MapName
;
2044 OpenedWAD
:= FileName
;
2046 idx
:= RecentFiles
.IndexOf(OpenedMap
);
2047 // Такая карта уже недавно открывалась:
2049 RecentFiles
.Delete(idx
);
2050 RecentFiles
.Insert(0, OpenedMap
);
2051 RefreshRecentMenu();
2055 pLoadProgress
.Hide();
2058 lbTextureList
.Sorted
:= True;
2059 lbTextureList
.Sorted
:= False;
2061 UpdateCaption(gMapInfo
.Name
, ExtractFileName(FileName
), MapName
);
2065 procedure MoveSelectedObjects(Wall
, alt
: Boolean; dx
, dy
: Integer);
2070 if SelectedObjects
= nil then
2077 for a
:= 0 to High(SelectedObjects
) do
2078 if SelectedObjects
[a
].Live
then
2080 if ObjectCollideLevel(SelectedObjects
[a
].ID
, SelectedObjects
[a
].ObjectType
, dx
, 0) then
2083 if ObjectCollideLevel(SelectedObjects
[a
].ID
, SelectedObjects
[a
].ObjectType
, 0, dy
) then
2086 if (not okX
) or (not okY
) then
2092 for a
:= 0 to High(SelectedObjects
) do
2093 if SelectedObjects
[a
].Live
then
2096 MoveObject(SelectedObjects
[a
].ObjectType
, SelectedObjects
[a
].ID
, dx
, 0);
2099 MoveObject(SelectedObjects
[a
].ObjectType
, SelectedObjects
[a
].ID
, 0, dy
);
2101 if alt
and (SelectedObjects
[a
].ObjectType
= OBJECT_TRIGGER
) then
2103 if gTriggers
[SelectedObjects
[a
].ID
].TriggerType
in [TRIGGER_PRESS
,
2104 TRIGGER_ON
, TRIGGER_OFF
, TRIGGER_ONOFF
] then
2105 begin // Двигаем зону Расширителя
2107 gTriggers
[SelectedObjects
[a
].ID
].Data
.tX
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.tX
+dx
;
2109 gTriggers
[SelectedObjects
[a
].ID
].Data
.tY
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.tY
+dy
;
2112 if gTriggers
[SelectedObjects
[a
].ID
].TriggerType
in [TRIGGER_TELEPORT
] then
2113 begin // Двигаем точку назначения Телепорта
2115 gTriggers
[SelectedObjects
[a
].ID
].Data
.TargetPoint
.X
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.TargetPoint
.X
+dx
;
2117 gTriggers
[SelectedObjects
[a
].ID
].Data
.TargetPoint
.Y
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.TargetPoint
.Y
+dy
;
2120 if gTriggers
[SelectedObjects
[a
].ID
].TriggerType
in [TRIGGER_SPAWNMONSTER
] then
2121 begin // Двигаем точку создания монстра
2123 gTriggers
[SelectedObjects
[a
].ID
].Data
.MonPos
.X
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.MonPos
.X
+dx
;
2125 gTriggers
[SelectedObjects
[a
].ID
].Data
.MonPos
.Y
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.MonPos
.Y
+dy
;
2128 if gTriggers
[SelectedObjects
[a
].ID
].TriggerType
in [TRIGGER_SPAWNITEM
] then
2129 begin // Двигаем точку создания предмета
2131 gTriggers
[SelectedObjects
[a
].ID
].Data
.ItemPos
.X
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.ItemPos
.X
+dx
;
2133 gTriggers
[SelectedObjects
[a
].ID
].Data
.ItemPos
.Y
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.ItemPos
.Y
+dy
;
2136 if gTriggers
[SelectedObjects
[a
].ID
].TriggerType
in [TRIGGER_SHOT
] then
2137 begin // Двигаем точку создания выстрела
2139 gTriggers
[SelectedObjects
[a
].ID
].Data
.ShotPos
.X
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.ShotPos
.X
+dx
;
2141 gTriggers
[SelectedObjects
[a
].ID
].Data
.ShotPos
.Y
:= gTriggers
[SelectedObjects
[a
].ID
].Data
.ShotPos
.Y
+dy
;
2146 LastMovePoint
:= MousePos
;
2150 procedure ShowLayer(Layer
: Byte; show
: Boolean);
2152 LayerEnabled
[Layer
] := show
;
2157 MainForm
.miLayer1
.Checked
:= show
;
2158 MainForm
.miLayerP1
.Checked
:= show
;
2162 MainForm
.miLayer2
.Checked
:= show
;
2163 MainForm
.miLayerP2
.Checked
:= show
;
2167 MainForm
.miLayer3
.Checked
:= show
;
2168 MainForm
.miLayerP3
.Checked
:= show
;
2172 MainForm
.miLayer4
.Checked
:= show
;
2173 MainForm
.miLayerP4
.Checked
:= show
;
2177 MainForm
.miLayer5
.Checked
:= show
;
2178 MainForm
.miLayerP5
.Checked
:= show
;
2182 MainForm
.miLayer6
.Checked
:= show
;
2183 MainForm
.miLayerP6
.Checked
:= show
;
2187 MainForm
.miLayer7
.Checked
:= show
;
2188 MainForm
.miLayerP7
.Checked
:= show
;
2192 MainForm
.miLayer8
.Checked
:= show
;
2193 MainForm
.miLayerP8
.Checked
:= show
;
2197 MainForm
.miLayer9
.Checked
:= show
;
2198 MainForm
.miLayerP9
.Checked
:= show
;
2202 RemoveSelectFromObjects();
2205 procedure SwitchLayer(Layer
: Byte);
2207 ShowLayer(Layer
, not LayerEnabled
[Layer
]);
2210 procedure SwitchMap();
2212 ShowMap
:= not ShowMap
;
2213 MainForm
.tbShowMap
.Down
:= ShowMap
;
2216 procedure ShowEdges();
2218 if drEdge
[3] < 255 then
2221 drEdge
[3] := gAlphaEdge
;
2224 function SelectedTexture(): String;
2226 if MainForm
.lbTextureList
.ItemIndex
<> -1 then
2227 Result
:= MainForm
.lbTextureList
.Items
[MainForm
.lbTextureList
.ItemIndex
]
2232 function IsSpecialTextureSel(): Boolean;
2234 Result
:= (MainForm
.lbTextureList
.ItemIndex
<> -1) and
2235 IsSpecialTexture(MainForm
.lbTextureList
.Items
[MainForm
.lbTextureList
.ItemIndex
]);
2238 function CopyBufferToString(var CopyBuf
: TCopyRecArray
): String;
2243 procedure AddInt(x
: Integer);
2245 Res
:= Res
+ IntToStr(x
) + ' ';
2251 if Length(CopyBuf
) = 0 then
2254 Res
:= CLIPBOARD_SIG
+ ' ';
2256 for i
:= 0 to High(CopyBuf
) do
2258 if (CopyBuf
[i
].ObjectType
= OBJECT_PANEL
) and
2259 (CopyBuf
[i
].Panel
= nil) then
2263 AddInt(CopyBuf
[i
].ObjectType
);
2266 // Свойства объекта:
2267 case CopyBuf
[i
].ObjectType
of
2269 with CopyBuf
[i
].Panel
^ do
2276 Res
:= Res
+ '"' + TextureName
+ '" ';
2278 AddInt(IfThen(Blending
, 1, 0));
2282 with CopyBuf
[i
].Item
do
2287 AddInt(IfThen(OnlyDM
, 1, 0));
2288 AddInt(IfThen(Fall
, 1, 0));
2292 with CopyBuf
[i
].Monster
do
2294 AddInt(MonsterType
);
2297 AddInt(IfThen(Direction
= D_LEFT
, 1, 0));
2301 with CopyBuf
[i
].Area
do
2306 AddInt(IfThen(Direction
= D_LEFT
, 1, 0));
2310 with CopyBuf
[i
].Trigger
do
2312 AddInt(TriggerType
);
2317 AddInt(ActivateType
);
2319 AddInt(IfThen(Enabled
, 1, 0));
2320 AddInt(TexturePanel
);
2322 for j
:= 0 to 127 do
2323 AddInt(Data
.Default
[j
]);
2331 procedure StringToCopyBuffer(Str
: String; var CopyBuf
: TCopyRecArray
);
2335 function GetNext(): String;
2340 if Str
[1] = '"' then
2352 Result
:= Copy(Str
, 1, p
-1);
2368 Result
:= Copy(Str
, 1, p
-1);
2378 if GetNext() <> CLIPBOARD_SIG
then
2384 t
:= StrToIntDef(GetNext(), 0);
2386 if (t
< OBJECT_PANEL
) or (t
> OBJECT_TRIGGER
) or
2387 (GetNext() <> ';') then
2388 begin // Что-то не то => пропускаем:
2396 i
:= Length(CopyBuf
);
2397 SetLength(CopyBuf
, i
+ 1);
2399 CopyBuf
[i
].ObjectType
:= t
;
2400 CopyBuf
[i
].Panel
:= nil;
2402 // Свойства объекта:
2406 New(CopyBuf
[i
].Panel
);
2408 with CopyBuf
[i
].Panel
^ do
2410 PanelType
:= StrToIntDef(GetNext(), PANEL_WALL
);
2411 X
:= StrToIntDef(GetNext(), 0);
2412 Y
:= StrToIntDef(GetNext(), 0);
2413 Width
:= StrToIntDef(GetNext(), 16);
2414 Height
:= StrToIntDef(GetNext(), 16);
2415 TextureName
:= GetNext();
2416 Alpha
:= StrToIntDef(GetNext(), 0);
2417 Blending
:= (GetNext() = '1');
2422 with CopyBuf
[i
].Item
do
2424 ItemType
:= StrToIntDef(GetNext(), ITEM_MEDKIT_SMALL
);
2425 X
:= StrToIntDef(GetNext(), 0);
2426 Y
:= StrToIntDef(GetNext(), 0);
2427 OnlyDM
:= (GetNext() = '1');
2428 Fall
:= (GetNext() = '1');
2432 with CopyBuf
[i
].Monster
do
2434 MonsterType
:= StrToIntDef(GetNext(), MONSTER_DEMON
);
2435 X
:= StrToIntDef(GetNext(), 0);
2436 Y
:= StrToIntDef(GetNext(), 0);
2438 if GetNext() = '1' then
2441 Direction
:= D_RIGHT
;
2445 with CopyBuf
[i
].Area
do
2447 AreaType
:= StrToIntDef(GetNext(), AREA_PLAYERPOINT1
);
2448 X
:= StrToIntDef(GetNext(), 0);
2449 Y
:= StrToIntDef(GetNext(), 0);
2450 if GetNext() = '1' then
2453 Direction
:= D_RIGHT
;
2457 with CopyBuf
[i
].Trigger
do
2459 TriggerType
:= StrToIntDef(GetNext(), TRIGGER_EXIT
);
2460 X
:= StrToIntDef(GetNext(), 0);
2461 Y
:= StrToIntDef(GetNext(), 0);
2462 Width
:= StrToIntDef(GetNext(), 16);
2463 Height
:= StrToIntDef(GetNext(), 16);
2464 ActivateType
:= StrToIntDef(GetNext(), 0);
2465 Key
:= StrToIntDef(GetNext(), 0);
2466 Enabled
:= (GetNext() = '1');
2467 TexturePanel
:= StrToIntDef(GetNext(), 0);
2469 for j
:= 0 to 127 do
2470 Data
.Default
[j
] := StrToIntDef(GetNext(), 0);
2476 //----------------------------------------
2477 //Закончились вспомогательные процедуры
2478 //----------------------------------------
2480 procedure TMainForm
.RefreshRecentMenu();
2485 // Лишние запомненные карты:
2486 while RecentFiles
.Count
> RecentCount
do
2487 RecentFiles
.Delete(RecentFiles
.Count
-1);
2489 // Лишние строки меню:
2490 while MainMenu
.Items
[0].Count
> RECENT_FILES_MENU_START
do
2491 MainMenu
.Items
[0].Delete(MainMenu
.Items
[0].Count
-1);
2493 // Отделение списка карт от строки "Выход":
2494 if RecentFiles
.Count
> 0 then
2496 MI
:= TMenuItem
.Create(MainMenu
.Items
[0]);
2498 MainMenu
.Items
[0].Add(MI
);
2501 // Добавление в меню списка запомненных карт:
2502 for i
:= 0 to RecentFiles
.Count
-1 do
2504 MI
:= TMenuItem
.Create(MainMenu
.Items
[0]);
2505 MI
.Caption
:= IntToStr(i
+1) + ' ' + RecentFiles
[i
];
2506 MI
.OnClick
:= aRecentFileExecute
;
2507 MainMenu
.Items
[0].Add(MI
);
2511 procedure TMainForm
.aRecentFileExecute(Sender
: TObject
);
2517 s
:= LowerCase((Sender
as TMenuItem
).Caption
);
2518 Delete(s
, Pos('&', s
), 1);
2519 s
:= Trim(Copy(s
, 1, 2));
2520 n
:= StrToIntDef(s
, 0) - 1;
2522 if (n
< 0) or (n
>= RecentFiles
.Count
) then
2525 s
:= RecentFiles
[n
];
2526 pw
:= Pos('.wad:\', LowerCase(s
));
2530 begin // Map name included
2531 fn
:= Copy(s
, 1, pw
+ 3);
2532 Delete(s
, 1, pw
+ 5);
2533 if (FileExists(fn
)) then
2539 else // Only wad name
2540 if (FileExists(s
)) then
2546 if (not b
) and (MessageBox(0, PChar(_lc
[I_MSG_DEL_RECENT_PROMT
]),
2547 PChar(_lc
[I_MSG_DEL_RECENT
]), MB_ICONQUESTION
or MB_YESNO
) = idYes
) then
2549 RecentFiles
.Delete(n
);
2550 RefreshRecentMenu();
2554 procedure TMainForm
.aEditorOptionsExecute(Sender
: TObject
);
2556 OptionsForm
.ShowModal();
2559 procedure LoadStdFont(cfgres
, texture
: string; var FontID
: DWORD
);
2573 wad
:= TWADEditor_1
.Create
;
2574 if wad
.ReadFile(EditorDir
+'data/Game.wad') then
2575 wad
.GetResource('FONTS', cfgres
, cfgdata
, cfglen
);
2580 if not g_CreateTextureWAD('FONT_STD', EditorDir
+'data/Game.wad:FONTS\'+texture
) then
2581 e_WriteLog('ERROR ERROR ERROR', MSG_WARNING
);
2583 config
:= TConfig
.CreateMem(cfgdata
, cfglen
);
2584 cwdt
:= Min(Max(config
.ReadInt('FontMap', 'CharWidth', 0), 0), 255);
2585 chgt
:= Min(Max(config
.ReadInt('FontMap', 'CharHeight', 0), 0), 255);
2586 spc
:= Min(Max(config
.ReadInt('FontMap', 'Kerning', 0), -128), 127);
2588 if g_GetTexture('FONT_STD', ID
) then
2589 e_TextureFontBuild(ID
, FontID
, cwdt
, chgt
, spc
-2);
2594 e_WriteLog('Could not load FONT_STD', MSG_WARNING
);
2596 if cfglen
<> 0 then FreeMem(cfgdata
);
2599 procedure TMainForm
.FormCreate(Sender
: TObject
);
2607 EditorDir
:= ExtractFilePath(Application
.ExeName
);
2609 e_InitLog(EditorDir
+'Editor.log', WM_NEWFILE
);
2611 slInvalidTextures
:= TStringList
.Create
;
2613 ShowLayer(LAYER_BACK
, True);
2614 ShowLayer(LAYER_WALLS
, True);
2615 ShowLayer(LAYER_FOREGROUND
, True);
2616 ShowLayer(LAYER_STEPS
, True);
2617 ShowLayer(LAYER_WATER
, True);
2618 ShowLayer(LAYER_ITEMS
, True);
2619 ShowLayer(LAYER_MONSTERS
, True);
2620 ShowLayer(LAYER_AREAS
, True);
2621 ShowLayer(LAYER_TRIGGERS
, True);
2625 FormCaption
:= MainForm
.Caption
;
2629 config
:= TConfig
.CreateFile(EditorDir
+'Editor.cfg');
2631 if config
.ReadInt('Editor', 'XPos', -1) = -1 then
2632 Position
:= poDesktopCenter
2634 Left
:= config
.ReadInt('Editor', 'XPos', Left
);
2635 Top
:= config
.ReadInt('Editor', 'YPos', Top
);
2636 Width
:= config
.ReadInt('Editor', 'Width', Width
);
2637 Height
:= config
.ReadInt('Editor', 'Height', Height
);
2639 if config
.ReadBool('Editor', 'Maximize', False) then
2640 WindowState
:= wsMaximized
;
2641 ShowMap
:= config
.ReadBool('Editor', 'Minimap', False);
2642 PanelProps
.Width
:= config
.ReadInt('Editor', 'PanelProps', PanelProps
.ClientWidth
);
2643 Splitter1
.Left
:= PanelProps
.Left
;
2644 PanelObjs
.Height
:= config
.ReadInt('Editor', 'PanelObjs', PanelObjs
.ClientHeight
);
2645 Splitter2
.Top
:= PanelObjs
.Top
;
2646 StatusBar
.Top
:= PanelObjs
.BoundsRect
.Bottom
;
2647 DotEnable
:= config
.ReadBool('Editor', 'DotEnable', True);
2648 DotColor
:= config
.ReadInt('Editor', 'DotColor', $FFFFFF);
2649 DotStepOne
:= config
.ReadInt('Editor', 'DotStepOne', 16);
2650 DotStepTwo
:= config
.ReadInt('Editor', 'DotStepTwo', 8);
2651 DotStep
:= config
.ReadInt('Editor', 'DotStep', DotStepOne
);
2652 DrawTexturePanel
:= config
.ReadBool('Editor', 'DrawTexturePanel', True);
2653 DrawPanelSize
:= config
.ReadBool('Editor', 'DrawPanelSize', True);
2654 BackColor
:= config
.ReadInt('Editor', 'BackColor', $7F6040);
2655 PreviewColor
:= config
.ReadInt('Editor', 'PreviewColor', $00FF00);
2656 gColorEdge
:= config
.ReadInt('Editor', 'EdgeColor', COLOR_EDGE
);
2657 gAlphaEdge
:= config
.ReadInt('Editor', 'EdgeAlpha', ALPHA_EDGE
);
2658 if gAlphaEdge
= 255 then
2659 gAlphaEdge
:= ALPHA_EDGE
;
2660 drEdge
[0] := GetRValue(gColorEdge
);
2661 drEdge
[1] := GetGValue(gColorEdge
);
2662 drEdge
[2] := GetBValue(gColorEdge
);
2663 if not config
.ReadBool('Editor', 'EdgeShow', True) then
2666 drEdge
[3] := gAlphaEdge
;
2667 gAlphaTriggerLine
:= config
.ReadInt('Editor', 'LineAlpha', ALPHA_LINE
);
2668 if gAlphaTriggerLine
= 255 then
2669 gAlphaTriggerLine
:= ALPHA_LINE
;
2670 gAlphaTriggerArea
:= config
.ReadInt('Editor', 'TriggerAlpha', ALPHA_AREA
);
2671 if gAlphaTriggerArea
= 255 then
2672 gAlphaTriggerArea
:= ALPHA_AREA
;
2673 if config
.ReadInt('Editor', 'Scale', 0) = 1 then
2677 if config
.ReadInt('Editor', 'DotSize', 0) = 1 then
2681 OpenDialog
.InitialDir
:= config
.ReadStr('Editor', 'LastOpenDir', EditorDir
);
2682 SaveDialog
.InitialDir
:= config
.ReadStr('Editor', 'LastSaveDir', EditorDir
);
2684 s
:= config
.ReadStr('Editor', 'Language', '');
2687 RecentCount
:= config
.ReadInt('Editor', 'RecentCount', 5);
2688 if RecentCount
> 10 then
2690 if RecentCount
< 2 then
2693 RecentFiles
:= TStringList
.Create();
2694 for i
:= 0 to RecentCount
-1 do
2696 s
:= config
.ReadStr('RecentFiles', IntToStr(i
+1), '');
2700 RefreshRecentMenu();
2704 tbShowMap
.Down
:= ShowMap
;
2705 tbGridOn
.Down
:= DotEnable
;
2706 pcObjects
.ActivePageIndex
:= 0;
2707 Application
.Title
:= _lc
[I_EDITOR_TITLE
];
2709 Application
.OnIdle
:= OnIdle
;
2712 procedure PrintBlack(X
, Y
: Integer; Text: string; FontID
: DWORD
);
2714 // NOTE: all the font printing routines assume CP1251
2715 e_TextureFontPrintEx(X
, Y
, Text, FontID
, 0, 0, 0, 1.0);
2718 procedure TMainForm
.Draw();
2723 Width
, Height
: Word;
2726 aX
, aY
, aX2
, aY2
, XX
, ScaleSz
: Integer;
2735 e_Clear(GL_COLOR_BUFFER_BIT
,
2736 GetRValue(BackColor
)/255,
2737 GetGValue(BackColor
)/255,
2738 GetBValue(BackColor
)/255);
2742 ObjCount
:= SelectedObjectCount();
2744 // Обводим выделенные объекты красной рамкой:
2745 if ObjCount
> 0 then
2747 for a
:= 0 to High(SelectedObjects
) do
2748 if SelectedObjects
[a
].Live
then
2750 Rect
:= ObjectGetRect(SelectedObjects
[a
].ObjectType
, SelectedObjects
[a
].ID
);
2754 e_DrawQuad(X
+MapOffset
.X
, Y
+MapOffset
.Y
,
2755 X
+MapOffset
.X
+Width
-1, Y
+MapOffset
.Y
+Height
-1,
2758 // Рисуем точки изменения размеров:
2759 if (ObjCount
= 1) and
2760 (SelectedObjects
[GetFirstSelected
].ObjectType
in [OBJECT_PANEL
, OBJECT_TRIGGER
]) then
2762 e_DrawPoint(5, X
+MapOffset
.X
, Y
+MapOffset
.Y
+(Height
div 2), 255, 255, 255);
2763 e_DrawPoint(5, X
+MapOffset
.X
+Width
-1, Y
+MapOffset
.Y
+(Height
div 2), 255, 255, 255);
2764 e_DrawPoint(5, X
+MapOffset
.X
+(Width
div 2), Y
+MapOffset
.Y
, 255, 255, 255);
2765 e_DrawPoint(5, X
+MapOffset
.X
+(Width
div 2), Y
+MapOffset
.Y
+Height
-1, 255, 255, 255);
2767 e_DrawPoint(3, X
+MapOffset
.X
, Y
+MapOffset
.Y
+(Height
div 2), 255, 0, 0);
2768 e_DrawPoint(3, X
+MapOffset
.X
+Width
-1, Y
+MapOffset
.Y
+(Height
div 2), 255, 0, 0);
2769 e_DrawPoint(3, X
+MapOffset
.X
+(Width
div 2), Y
+MapOffset
.Y
, 255, 0, 0);
2770 e_DrawPoint(3, X
+MapOffset
.X
+(Width
div 2), Y
+MapOffset
.Y
+Height
-1, 255, 0, 0);
2777 if DotEnable
and (PreviewMode
= 0) then
2784 for x
:= 0 to (RenderPanel
.Width
div DotStep
) do
2785 for y
:= 0 to (RenderPanel
.Height
div DotStep
) do
2786 e_DrawPoint(DotSize
, x
*DotStep
+ a
, y
*DotStep
+ a
,
2787 GetRValue(DotColor
),
2788 GetGValue(DotColor
),
2789 GetBValue(DotColor
));
2793 if (lbTextureList
.ItemIndex
<> -1) and (cbPreview
.Checked
) and
2794 (not IsSpecialTextureSel()) and (PreviewMode
= 0) then
2796 if not g_GetTexture(SelectedTexture(), ID
) then
2797 g_GetTexture('NOTEXTURE', ID
);
2798 g_GetTextureSizeByID(ID
, Width
, Height
);
2799 if g_GetTexture('PREVIEW', PID
) then
2800 e_DrawFill(PID
, RenderPanel
.Width
-Width
, RenderPanel
.Height
-Height
, Width
div 16 + 1, Height
div 16 + 1, 0, True, False);
2801 e_Draw(ID
, RenderPanel
.Width
-Width
, RenderPanel
.Height
-Height
, 0, True, False);
2804 // Подсказка при выборе точки Телепорта:
2805 if SelectFlag
= SELECTFLAG_TELEPORT
then
2807 with gTriggers
[SelectedObjects
[GetFirstSelected()].ID
] do
2808 if Data
.d2d_teleport
then
2809 e_DrawLine(2, MousePos
.X
-16, MousePos
.Y
-1,
2810 MousePos
.X
+16, MousePos
.Y
-1,
2813 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+AreaSize
[AREA_DMPOINT
].Width
-1,
2814 MousePos
.Y
+AreaSize
[AREA_DMPOINT
].Height
-1, 255, 255, 255);
2816 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 192, 192, 192, 127);
2817 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 255, 255, 255);
2818 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, _glc
[I_HINT_TELEPORT
], gEditorFont
);
2821 // Подсказка при выборе точки появления:
2822 if SelectFlag
= SELECTFLAG_SPAWNPOINT
then
2824 e_DrawLine(2, MousePos
.X
-16, MousePos
.Y
-1,
2825 MousePos
.X
+16, MousePos
.Y
-1,
2827 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 192, 192, 192, 127);
2828 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 255, 255, 255);
2829 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, _glc
[I_HINT_SPAWN
], gEditorFont
);
2832 // Подсказка при выборе панели двери:
2833 if SelectFlag
= SELECTFLAG_DOOR
then
2835 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 192, 192, 192, 127);
2836 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 255, 255, 255);
2837 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, _glc
[I_HINT_PANEL_DOOR
], gEditorFont
);
2840 // Подсказка при выборе панели с текстурой:
2841 if SelectFlag
= SELECTFLAG_TEXTURE
then
2843 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+196, MousePos
.Y
+18, 192, 192, 192, 127);
2844 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+196, MousePos
.Y
+18, 255, 255, 255);
2845 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, _glc
[I_HINT_PANEL_TEXTURE
], gEditorFont
);
2848 // Подсказка при выборе панели индикации выстрела:
2849 if SelectFlag
= SELECTFLAG_SHOTPANEL
then
2851 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+316, MousePos
.Y
+18, 192, 192, 192, 127);
2852 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+316, MousePos
.Y
+18, 255, 255, 255);
2853 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, _glc
[I_HINT_PANEL_SHOT
], gEditorFont
);
2856 // Подсказка при выборе панели лифта:
2857 if SelectFlag
= SELECTFLAG_LIFT
then
2859 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 192, 192, 192, 127);
2860 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+180, MousePos
.Y
+18, 255, 255, 255);
2861 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, _glc
[I_HINT_PANEL_LIFT
], gEditorFont
);
2864 // Подсказка при выборе монстра:
2865 if SelectFlag
= SELECTFLAG_MONSTER
then
2867 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+120, MousePos
.Y
+18, 192, 192, 192, 127);
2868 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+120, MousePos
.Y
+18, 255, 255, 255);
2869 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, _glc
[I_HINT_MONSTER
], gEditorFont
);
2872 // Подсказка при выборе области воздействия:
2873 if DrawPressRect
then
2875 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+204, MousePos
.Y
+18, 192, 192, 192, 127);
2876 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+204, MousePos
.Y
+18, 255, 255, 255);
2877 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, _glc
[I_HINT_EXT_AREA
], gEditorFont
);
2880 // Рисуем текстуры, если чертим панель:
2881 if (MouseAction
= MOUSEACTION_DRAWPANEL
) and (DrawTexturePanel
) and
2882 (lbTextureList
.ItemIndex
<> -1) and (DrawRect
<> nil) and
2883 (lbPanelType
.ItemIndex
in [0..8]) and not IsSpecialTextureSel() then
2885 if not g_GetTexture(SelectedTexture(), ID
) then
2886 g_GetTexture('NOTEXTURE', ID
);
2887 g_GetTextureSizeByID(ID
, Width
, Height
);
2889 e_DrawFill(ID
, Min(Left
, Right
), Min(Top
, Bottom
), Abs(Right
-Left
) div Width
,
2890 Abs(Bottom
-Top
) div Height
, 0, True, False);
2893 // Прямоугольник выделения:
2894 if DrawRect
<> nil then
2896 e_DrawQuad(Left
, Top
, Right
-1, Bottom
-1, 255, 255, 255);
2898 // Чертим мышью панель/триггер или меняем мышью их размер:
2899 if (MouseAction
in [MOUSEACTION_DRAWPANEL
, MOUSEACTION_DRAWTRIGGER
, MOUSEACTION_RESIZE
]) and
2900 (DrawPanelSize
) then
2902 e_DrawFillQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+88, MousePos
.Y
+33, 192, 192, 192, 127);
2903 e_DrawQuad(MousePos
.X
, MousePos
.Y
, MousePos
.X
+88, MousePos
.Y
+33, 255, 255, 255);
2905 if MouseAction
in [MOUSEACTION_DRAWPANEL
, MOUSEACTION_DRAWTRIGGER
] then
2906 begin // Чертим новый
2907 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, Format(_glc
[I_HINT_WIDTH
],
2908 [Abs(MousePos
.X
-MouseLDownPos
.X
)]), gEditorFont
);
2909 PrintBlack(MousePos
.X
+2, MousePos
.Y
+14, Format(_glc
[I_HINT_HEIGHT
],
2910 [Abs(MousePos
.Y
-MouseLDownPos
.Y
)]), gEditorFont
);
2912 else // Растягиваем существующий
2913 if SelectedObjects
[GetFirstSelected
].ObjectType
in [OBJECT_PANEL
, OBJECT_TRIGGER
] then
2915 if SelectedObjects
[GetFirstSelected
].ObjectType
= OBJECT_PANEL
then
2917 Width
:= gPanels
[SelectedObjects
[GetFirstSelected
].ID
].Width
;
2918 Height
:= gPanels
[SelectedObjects
[GetFirstSelected
].ID
].Height
;
2922 Width
:= gTriggers
[SelectedObjects
[GetFirstSelected
].ID
].Width
;
2923 Height
:= gTriggers
[SelectedObjects
[GetFirstSelected
].ID
].Height
;
2926 PrintBlack(MousePos
.X
+2, MousePos
.Y
+2, Format(_glc
[I_HINT_WIDTH
], [Width
]),
2928 PrintBlack(MousePos
.X
+2, MousePos
.Y
+14, Format(_glc
[I_HINT_HEIGHT
], [Height
]),
2933 // Ближайшая к курсору мыши точка на сетке:
2934 e_DrawPoint(3, MousePos
.X
, MousePos
.Y
, 0, 0, 255);
2939 // Сколько пикселов карты в 1 пикселе мини-карты:
2940 ScaleSz
:= 16 div Scale
;
2941 // Размеры мини-карты:
2942 aX
:= max(gMapInfo
.Width
div ScaleSz
, 1);
2943 aY
:= max(gMapInfo
.Height
div ScaleSz
, 1);
2944 // X-координата на RenderPanel нулевой x-координаты карты:
2945 XX
:= RenderPanel
.Width
- aX
- 1;
2947 e_DrawFillQuad(XX
-1, 0, RenderPanel
.Width
-1, aY
+1, 0, 0, 0, 0);
2948 e_DrawQuad(XX
-1, 0, RenderPanel
.Width
-1, aY
+1, 197, 197, 197);
2950 if gPanels
<> nil then
2953 for a
:= 0 to High(gPanels
) do
2955 if PanelType
<> 0 then
2957 // Левый верхний угол:
2958 aX
:= XX
+ (X
div ScaleSz
);
2959 aY
:= 1 + (Y
div ScaleSz
);
2961 aX2
:= max(Width
div ScaleSz
, 1);
2962 aY2
:= max(Height
div ScaleSz
, 1);
2963 // Правый нижний угол:
2964 aX2
:= aX
+ aX2
- 1;
2965 aY2
:= aY
+ aY2
- 1;
2968 PANEL_WALL
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 208, 208, 208, 0);
2969 PANEL_WATER
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 0, 0, 192, 0);
2970 PANEL_ACID1
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 0, 176, 0, 0);
2971 PANEL_ACID2
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 176, 0, 0, 0);
2972 PANEL_STEP
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 128, 128, 128, 0);
2973 PANEL_LIFTUP
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 116, 72, 36, 0);
2974 PANEL_LIFTDOWN
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 116, 124, 96, 0);
2975 PANEL_LIFTLEFT
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 200, 80, 4, 0);
2976 PANEL_LIFTRIGHT
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 252, 140, 56, 0);
2977 PANEL_OPENDOOR
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 100, 220, 92, 0);
2978 PANEL_CLOSEDOOR
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 212, 184, 64, 0);
2979 PANEL_BLOCKMON
: e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 192, 0, 192, 0);
2983 // Рисуем красным выделенные панели:
2984 if SelectedObjects
<> nil then
2985 for b
:= 0 to High(SelectedObjects
) do
2986 with SelectedObjects
[b
] do
2987 if Live
and (ObjectType
= OBJECT_PANEL
) then
2988 with gPanels
[SelectedObjects
[b
].ID
] do
2989 if PanelType
and not(PANEL_BACK
or PANEL_FORE
) <> 0 then
2991 // Левый верхний угол:
2992 aX
:= XX
+ (X
div ScaleSz
);
2993 aY
:= 1 + (Y
div ScaleSz
);
2995 aX2
:= max(Width
div ScaleSz
, 1);
2996 aY2
:= max(Height
div ScaleSz
, 1);
2997 // Правый нижний угол:
2998 aX2
:= aX
+ aX2
- 1;
2999 aY2
:= aY
+ aY2
- 1;
3001 e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 255, 0, 0, 0)
3005 if (gMapInfo
.Width
> RenderPanel
.Width
) or
3006 (gMapInfo
.Height
> RenderPanel
.Height
) then
3008 // Окно, показывающее текущее положение экрана на карте:
3010 x
:= max(min(RenderPanel
.Width
, gMapInfo
.Width
) div ScaleSz
, 1);
3011 y
:= max(min(RenderPanel
.Height
, gMapInfo
.Height
) div ScaleSz
, 1);
3012 // Левый верхний угол:
3013 aX
:= XX
+ ((-MapOffset
.X
) div ScaleSz
);
3014 aY
:= 1 + ((-MapOffset
.Y
) div ScaleSz
);
3015 // Правый нижний угол:
3019 e_DrawFillQuad(aX
, aY
, aX2
, aY2
, 127, 192, 127, 127, B_BLEND
);
3020 e_DrawQuad(aX
, aY
, aX2
, aY2
, 255, 0, 0);
3025 RenderPanel
.SwapBuffers();
3028 procedure TMainForm
.FormResize(Sender
: TObject
);
3030 e_SetViewPort(0, 0, RenderPanel
.Width
, RenderPanel
.Height
);
3032 if gMapInfo
.Width
>= RenderPanel
.Width
then
3033 sbHorizontal
.Max
:= Normalize16(gMapInfo
.Width
-RenderPanel
.Width
+16)
3035 sbHorizontal
.Max
:= 0;
3037 if gMapInfo
.Height
>= RenderPanel
.Height
then
3038 sbVertical
.Max
:= Normalize16(gMapInfo
.Height
-RenderPanel
.Height
+16)
3040 sbVertical
.Max
:= 0;
3042 MapOffset
.X
:= -Normalize16(sbHorizontal
.Position
);
3043 MapOffset
.Y
:= -Normalize16(sbVertical
.Position
);
3046 procedure SelectNextObject(X
, Y
: Integer; ObjectType
: Byte; ID
: DWORD
);
3051 j_max
:= 0; // shut up compiler
3055 res
:= (gPanels
<> nil) and
3056 PanelInShownLayer(gPanels
[ID
].PanelType
) and
3057 g_CollidePoint(X
, Y
, gPanels
[ID
].X
, gPanels
[ID
].Y
,
3059 gPanels
[ID
].Height
);
3060 j_max
:= Length(gPanels
) - 1;
3065 res
:= (gItems
<> nil) and
3066 LayerEnabled
[LAYER_ITEMS
] and
3067 g_CollidePoint(X
, Y
, gItems
[ID
].X
, gItems
[ID
].Y
,
3068 ItemSize
[gItems
[ID
].ItemType
][0],
3069 ItemSize
[gItems
[ID
].ItemType
][1]);
3070 j_max
:= Length(gItems
) - 1;
3075 res
:= (gMonsters
<> nil) and
3076 LayerEnabled
[LAYER_MONSTERS
] and
3077 g_CollidePoint(X
, Y
, gMonsters
[ID
].X
, gMonsters
[ID
].Y
,
3078 MonsterSize
[gMonsters
[ID
].MonsterType
].Width
,
3079 MonsterSize
[gMonsters
[ID
].MonsterType
].Height
);
3080 j_max
:= Length(gMonsters
) - 1;
3085 res
:= (gAreas
<> nil) and
3086 LayerEnabled
[LAYER_AREAS
] and
3087 g_CollidePoint(X
, Y
, gAreas
[ID
].X
, gAreas
[ID
].Y
,
3088 AreaSize
[gAreas
[ID
].AreaType
].Width
,
3089 AreaSize
[gAreas
[ID
].AreaType
].Height
);
3090 j_max
:= Length(gAreas
) - 1;
3095 res
:= (gTriggers
<> nil) and
3096 LayerEnabled
[LAYER_TRIGGERS
] and
3097 g_CollidePoint(X
, Y
, gTriggers
[ID
].X
, gTriggers
[ID
].Y
,
3098 gTriggers
[ID
].Width
,
3099 gTriggers
[ID
].Height
);
3100 j_max
:= Length(gTriggers
) - 1;
3110 // Перебор ID: от ID-1 до 0; потом от High до ID+1:
3119 if j
= Integer(ID
) then
3124 res
:= PanelInShownLayer(gPanels
[j
].PanelType
) and
3125 g_CollidePoint(X
, Y
, gPanels
[j
].X
, gPanels
[j
].Y
,
3129 res
:= (gItems
[j
].ItemType
<> ITEM_NONE
) and
3130 g_CollidePoint(X
, Y
, gItems
[j
].X
, gItems
[j
].Y
,
3131 ItemSize
[gItems
[j
].ItemType
][0],
3132 ItemSize
[gItems
[j
].ItemType
][1]);
3134 res
:= (gMonsters
[j
].MonsterType
<> MONSTER_NONE
) and
3135 g_CollidePoint(X
, Y
, gMonsters
[j
].X
, gMonsters
[j
].Y
,
3136 MonsterSize
[gMonsters
[j
].MonsterType
].Width
,
3137 MonsterSize
[gMonsters
[j
].MonsterType
].Height
);
3139 res
:= (gAreas
[j
].AreaType
<> AREA_NONE
) and
3140 g_CollidePoint(X
, Y
, gAreas
[j
].X
, gAreas
[j
].Y
,
3141 AreaSize
[gAreas
[j
].AreaType
].Width
,
3142 AreaSize
[gAreas
[j
].AreaType
].Height
);
3144 res
:= (gTriggers
[j
].TriggerType
<> TRIGGER_NONE
) and
3145 g_CollidePoint(X
, Y
, gTriggers
[j
].X
, gTriggers
[j
].Y
,
3147 gTriggers
[j
].Height
);
3154 SetLength(SelectedObjects
, 1);
3156 SelectedObjects
[0].ObjectType
:= ObjectType
;
3157 SelectedObjects
[0].ID
:= j
;
3158 SelectedObjects
[0].Live
:= True;
3166 procedure TMainForm
.RenderPanelMouseDown(Sender
: TObject
;
3167 Button
: TMouseButton
; Shift
: TShiftState
; X
, Y
: Integer);
3171 c1
, c2
, c3
, c4
: Boolean;
3177 MainForm
.ActiveControl
:= RenderPanel
;
3178 RenderPanel
.SetFocus();
3180 RenderPanelMouseMove(RenderPanel
, Shift
, X
, Y
);
3182 if Button
= mbLeft
then // Left Mouse Button
3184 // Двигаем карту с помощью мыши и мини-карты:
3186 g_CollidePoint(X
, Y
,
3187 RenderPanel
.Width
-max(gMapInfo
.Width
div (16 div Scale
), 1)-1,
3189 max(gMapInfo
.Width
div (16 div Scale
), 1),
3190 max(gMapInfo
.Height
div (16 div Scale
), 1) ) then
3193 MouseAction
:= MOUSEACTION_MOVEMAP
;
3195 else // Ставим предмет/монстра/область:
3196 if (pcObjects
.ActivePageIndex
in [1, 2, 3]) and
3197 (not (ssShift
in Shift
)) then
3199 case pcObjects
.ActivePageIndex
of
3201 if lbItemList
.ItemIndex
= -1 then
3202 ErrorMessageBox(_lc
[I_MSG_CHOOSE_ITEM
])
3205 item
.ItemType
:= lbItemList
.ItemIndex
+ ITEM_MEDKIT_SMALL
;
3206 if item
.ItemType
>= ITEM_WEAPON_KASTET
then
3207 item
.ItemType
:= item
.ItemType
+ 2;
3208 item
.X
:= MousePos
.X
-MapOffset
.X
;
3209 item
.Y
:= MousePos
.Y
-MapOffset
.Y
;
3211 if not (ssCtrl
in Shift
) then
3213 item
.X
:= item
.X
- (ItemSize
[item
.ItemType
][0] div 2);
3214 item
.Y
:= item
.Y
- ItemSize
[item
.ItemType
][1];
3217 item
.OnlyDM
:= cbOnlyDM
.Checked
;
3218 item
.Fall
:= cbFall
.Checked
;
3219 Undo_Add(OBJECT_ITEM
, AddItem(item
));
3222 if lbMonsterList
.ItemIndex
= -1 then
3223 ErrorMessageBox(_lc
[I_MSG_CHOOSE_MONSTER
])
3226 monster
.MonsterType
:= lbMonsterList
.ItemIndex
+ MONSTER_DEMON
;
3227 monster
.X
:= MousePos
.X
-MapOffset
.X
;
3228 monster
.Y
:= MousePos
.Y
-MapOffset
.Y
;
3230 if not (ssCtrl
in Shift
) then
3232 monster
.X
:= monster
.X
- (MonsterSize
[monster
.MonsterType
].Width
div 2);
3233 monster
.Y
:= monster
.Y
- MonsterSize
[monster
.MonsterType
].Height
;
3236 if rbMonsterLeft
.Checked
then
3237 monster
.Direction
:= D_LEFT
3239 monster
.Direction
:= D_RIGHT
;
3240 Undo_Add(OBJECT_MONSTER
, AddMonster(monster
));
3243 if lbAreasList
.ItemIndex
= -1 then
3244 ErrorMessageBox(_lc
[I_MSG_CHOOSE_AREA
])
3246 if (lbAreasList
.ItemIndex
+ 1) <> AREA_DOMFLAG
then
3248 area
.AreaType
:= lbAreasList
.ItemIndex
+ AREA_PLAYERPOINT1
;
3249 area
.X
:= MousePos
.X
-MapOffset
.X
;
3250 area
.Y
:= MousePos
.Y
-MapOffset
.Y
;
3252 if not (ssCtrl
in Shift
) then
3254 area
.X
:= area
.X
- (AreaSize
[area
.AreaType
].Width
div 2);
3255 area
.Y
:= area
.Y
- AreaSize
[area
.AreaType
].Height
;
3258 if rbAreaLeft
.Checked
then
3259 area
.Direction
:= D_LEFT
3261 area
.Direction
:= D_RIGHT
;
3262 Undo_Add(OBJECT_AREA
, AddArea(area
));
3268 i
:= GetFirstSelected();
3270 // Выбираем объект под текущим:
3271 if (SelectedObjects
<> nil) and
3272 (ssShift
in Shift
) and (i
>= 0) and
3273 (SelectedObjects
[i
].Live
) then
3275 if SelectedObjectCount() = 1 then
3276 SelectNextObject(X
-MapOffset
.X
, Y
-MapOffset
.Y
,
3277 SelectedObjects
[i
].ObjectType
,
3278 SelectedObjects
[i
].ID
);
3282 // Рисуем область триггера "Расширитель":
3283 if DrawPressRect
and (i
>= 0) and
3284 (SelectedObjects
[i
].ObjectType
= OBJECT_TRIGGER
) and
3285 (gTriggers
[SelectedObjects
[i
].ID
].TriggerType
in
3286 [TRIGGER_PRESS
, TRIGGER_ON
, TRIGGER_OFF
, TRIGGER_ONOFF
]) then
3287 MouseAction
:= MOUSEACTION_DRAWPRESS
3288 else // Рисуем панель:
3289 if pcObjects
.ActivePageIndex
= 0 then
3291 if (lbPanelType
.ItemIndex
>= 0) then
3292 MouseAction
:= MOUSEACTION_DRAWPANEL
3294 else // Рисуем триггер:
3295 if (lbTriggersList
.ItemIndex
>= 0) then
3297 MouseAction
:= MOUSEACTION_DRAWTRIGGER
;
3301 end; // if Button = mbLeft
3303 if Button
= mbRight
then // Right Mouse Button
3305 // Клик по мини-карте:
3307 g_CollidePoint(X
, Y
,
3308 RenderPanel
.Width
-max(gMapInfo
.Width
div (16 div Scale
), 1)-1,
3310 max(gMapInfo
.Width
div (16 div Scale
), 1),
3311 max(gMapInfo
.Height
div (16 div Scale
), 1) ) then
3313 MouseAction
:= MOUSEACTION_NOACTION
;
3315 else // Нужно что-то выбрать мышью:
3316 if SelectFlag
<> SELECTFLAG_NONE
then
3319 SELECTFLAG_TELEPORT
:
3320 // Точку назначения телепортации:
3321 with gTriggers
[SelectedObjects
[
3322 GetFirstSelected() ].ID
].Data
.TargetPoint
do
3324 X
:= MousePos
.X
-MapOffset
.X
;
3325 Y
:= MousePos
.Y
-MapOffset
.Y
;
3328 SELECTFLAG_SPAWNPOINT
:
3329 // Точку создания монстра:
3330 with gTriggers
[SelectedObjects
[GetFirstSelected()].ID
] do
3331 if TriggerType
= TRIGGER_SPAWNMONSTER
then
3333 Data
.MonPos
.X
:= MousePos
.X
-MapOffset
.X
;
3334 Data
.MonPos
.Y
:= MousePos
.Y
-MapOffset
.Y
;
3336 else if TriggerType
= TRIGGER_SPAWNITEM
then
3337 begin // Точка создания предмета:
3338 Data
.ItemPos
.X
:= MousePos
.X
-MapOffset
.X
;
3339 Data
.ItemPos
.Y
:= MousePos
.Y
-MapOffset
.Y
;
3341 else if TriggerType
= TRIGGER_SHOT
then
3342 begin // Точка создания выстрела:
3343 Data
.ShotPos
.X
:= MousePos
.X
-MapOffset
.X
;
3344 Data
.ShotPos
.Y
:= MousePos
.Y
-MapOffset
.Y
;
3350 IDArray
:= ObjectInRect(X
-MapOffset
.X
,
3352 2, 2, OBJECT_PANEL
, True);
3353 if IDArray
<> nil then
3355 for i
:= 0 to High(IDArray
) do
3356 if (gPanels
[IDArray
[i
]].PanelType
= PANEL_OPENDOOR
) or
3357 (gPanels
[IDArray
[i
]].PanelType
= PANEL_CLOSEDOOR
) then
3359 gTriggers
[SelectedObjects
[
3360 GetFirstSelected() ].ID
].Data
.PanelID
:= IDArray
[i
];
3365 gTriggers
[SelectedObjects
[
3366 GetFirstSelected() ].ID
].Data
.PanelID
:= -1;
3370 // Панель с текстурой:
3372 IDArray
:= ObjectInRect(X
-MapOffset
.X
,
3374 2, 2, OBJECT_PANEL
, True);
3375 if IDArray
<> nil then
3377 for i
:= 0 to High(IDArray
) do
3378 if ((gPanels
[IDArray
[i
]].PanelType
in
3379 [PANEL_WALL
, PANEL_BACK
, PANEL_FORE
,
3380 PANEL_WATER
, PANEL_ACID1
, PANEL_ACID2
,
3382 (gPanels
[IDArray
[i
]].PanelType
= PANEL_OPENDOOR
) or
3383 (gPanels
[IDArray
[i
]].PanelType
= PANEL_CLOSEDOOR
)) and
3384 (gPanels
[IDArray
[i
]].TextureName
<> '') then
3386 gTriggers
[SelectedObjects
[
3387 GetFirstSelected() ].ID
].TexturePanel
:= IDArray
[i
];
3392 gTriggers
[SelectedObjects
[
3393 GetFirstSelected() ].ID
].TexturePanel
:= -1;
3399 IDArray
:= ObjectInRect(X
-MapOffset
.X
,
3401 2, 2, OBJECT_PANEL
, True);
3402 if IDArray
<> nil then
3404 for i
:= 0 to High(IDArray
) do
3405 if (gPanels
[IDArray
[i
]].PanelType
= PANEL_LIFTUP
) or
3406 (gPanels
[IDArray
[i
]].PanelType
= PANEL_LIFTDOWN
) or
3407 (gPanels
[IDArray
[i
]].PanelType
= PANEL_LIFTLEFT
) or
3408 (gPanels
[IDArray
[i
]].PanelType
= PANEL_LIFTRIGHT
) then
3410 gTriggers
[SelectedObjects
[
3411 GetFirstSelected() ].ID
].Data
.PanelID
:= IDArray
[i
];
3416 gTriggers
[SelectedObjects
[
3417 GetFirstSelected() ].ID
].Data
.PanelID
:= -1;
3423 IDArray
:= ObjectInRect(X
-MapOffset
.X
,
3425 2, 2, OBJECT_MONSTER
, False);
3426 if IDArray
<> nil then
3427 gTriggers
[SelectedObjects
[
3428 GetFirstSelected() ].ID
].Data
.MonsterID
:= IDArray
[0]+1
3430 gTriggers
[SelectedObjects
[
3431 GetFirstSelected() ].ID
].Data
.MonsterID
:= 0;
3434 SELECTFLAG_SHOTPANEL
:
3435 // Панель индикации выстрела:
3437 if gTriggers
[SelectedObjects
[
3438 GetFirstSelected() ].ID
].TriggerType
= TRIGGER_SHOT
then
3440 IDArray
:= ObjectInRect(X
-MapOffset
.X
,
3442 2, 2, OBJECT_PANEL
, True);
3443 if IDArray
<> nil then
3445 for i
:= 0 to High(IDArray
) do
3446 if ((gPanels
[IDArray
[i
]].PanelType
in
3447 [PANEL_WALL
, PANEL_BACK
, PANEL_FORE
,
3448 PANEL_WATER
, PANEL_ACID1
, PANEL_ACID2
,
3450 (gPanels
[IDArray
[i
]].PanelType
= PANEL_OPENDOOR
) or
3451 (gPanels
[IDArray
[i
]].PanelType
= PANEL_CLOSEDOOR
)) and
3452 (gPanels
[IDArray
[i
]].TextureName
<> '') then
3454 gTriggers
[SelectedObjects
[
3455 GetFirstSelected() ].ID
].Data
.ShotPanelID
:= IDArray
[i
];
3460 gTriggers
[SelectedObjects
[
3461 GetFirstSelected() ].ID
].Data
.ShotPanelID
:= -1;
3466 SelectFlag
:= SELECTFLAG_SELECTED
;
3468 else // if SelectFlag <> SELECTFLAG_NONE...
3470 // Что уже выбрано и не нажат Ctrl:
3471 if (SelectedObjects
<> nil) and
3472 (not (ssCtrl
in Shift
)) then
3473 for i
:= 0 to High(SelectedObjects
) do
3474 with SelectedObjects
[i
] do
3477 if (ObjectType
in [OBJECT_PANEL
, OBJECT_TRIGGER
]) and
3478 (SelectedObjectCount() = 1) then
3480 Rect
:= ObjectGetRect(ObjectType
, ID
);
3482 c1
:= g_Collide(X
-MapOffset
.X
-1, Y
-MapOffset
.Y
-1, 2, 2,
3483 Rect
.X
-2, Rect
.Y
+(Rect
.Height
div 2)-2, 4, 4);
3484 c2
:= g_Collide(X
-MapOffset
.X
-1, Y
-MapOffset
.Y
-1, 2, 2,
3485 Rect
.X
+Rect
.Width
-3, Rect
.Y
+(Rect
.Height
div 2)-2, 4, 4);
3486 c3
:= g_Collide(X
-MapOffset
.X
-1, Y
-MapOffset
.Y
-1, 2, 2,
3487 Rect
.X
+(Rect
.Width
div 2)-2, Rect
.Y
-2, 4, 4);
3488 c4
:= g_Collide(X
-MapOffset
.X
-1, Y
-MapOffset
.Y
-1, 2, 2,
3489 Rect
.X
+(Rect
.Width
div 2)-2, Rect
.Y
+Rect
.Height
-3, 4, 4);
3491 // Меняем размер панели или триггера:
3492 if c1
or c2
or c3
or c4
then
3494 MouseAction
:= MOUSEACTION_RESIZE
;
3495 LastMovePoint
:= MousePos
;
3499 ResizeType
:= RESIZETYPE_HORIZONTAL
;
3501 ResizeDirection
:= RESIZEDIR_LEFT
3503 ResizeDirection
:= RESIZEDIR_RIGHT
;
3504 RenderPanel
.Cursor
:= crSizeWE
;
3508 ResizeType
:= RESIZETYPE_VERTICAL
;
3510 ResizeDirection
:= RESIZEDIR_UP
3512 ResizeDirection
:= RESIZEDIR_DOWN
;
3513 RenderPanel
.Cursor
:= crSizeNS
;
3520 // Перемещаем панель или триггер:
3521 if ObjectCollide(ObjectType
, ID
,
3523 Y
-MapOffset
.Y
-1, 2, 2) then
3525 MouseAction
:= MOUSEACTION_MOVEOBJ
;
3526 LastMovePoint
:= MousePos
;
3532 end; // if Button = mbRight
3534 MouseRDown
:= Button
= mbRight
;
3536 MouseRDownPos
:= MousePos
;
3538 MouseLDown
:= Button
= mbLeft
;
3540 MouseLDownPos
:= MousePos
;
3543 procedure TMainForm
.RenderPanelMouseUp(Sender
: TObject
;
3544 Button
: TMouseButton
; Shift
: TShiftState
; X
, Y
: Integer);
3551 rSelectRect
: Boolean;
3553 if Button
= mbLeft
then
3554 MouseLDown
:= False;
3555 if Button
= mbRight
then
3556 MouseRDown
:= False;
3559 ResizeType
:= RESIZETYPE_NONE
;
3561 if Button
= mbLeft
then // Left Mouse Button
3563 if MouseAction
<> MOUSEACTION_NONE
then
3564 begin // Было действие мышью
3565 // Мышь сдвинулась во время удержания клавиши:
3566 if (MousePos
.X
<> MouseLDownPos
.X
) and
3567 (MousePos
.Y
<> MouseLDownPos
.Y
) then
3570 MOUSEACTION_DRAWPANEL
:
3572 // Фон или передний план без текстуры - ошибка:
3573 if (lbPanelType
.ItemIndex
in [1, 2]) and
3574 (lbTextureList
.ItemIndex
= -1) then
3575 ErrorMessageBox(_lc
[I_MSG_CHOOSE_TEXTURE
])
3576 else // Назначаем параметры панели:
3578 case lbPanelType
.ItemIndex
of
3579 0: Panel
.PanelType
:= PANEL_WALL
;
3580 1: Panel
.PanelType
:= PANEL_BACK
;
3581 2: Panel
.PanelType
:= PANEL_FORE
;
3582 3: Panel
.PanelType
:= PANEL_OPENDOOR
;
3583 4: Panel
.PanelType
:= PANEL_CLOSEDOOR
;
3584 5: Panel
.PanelType
:= PANEL_STEP
;
3585 6: Panel
.PanelType
:= PANEL_WATER
;
3586 7: Panel
.PanelType
:= PANEL_ACID1
;
3587 8: Panel
.PanelType
:= PANEL_ACID2
;
3588 9: Panel
.PanelType
:= PANEL_LIFTUP
;
3589 10: Panel
.PanelType
:= PANEL_LIFTDOWN
;
3590 11: Panel
.PanelType
:= PANEL_LIFTLEFT
;
3591 12: Panel
.PanelType
:= PANEL_LIFTRIGHT
;
3592 13: Panel
.PanelType
:= PANEL_BLOCKMON
;
3595 Panel
.X
:= Min(MousePos
.X
-MapOffset
.X
, MouseLDownPos
.X
-MapOffset
.X
);
3596 Panel
.Y
:= Min(MousePos
.Y
-MapOffset
.Y
, MouseLDownPos
.Y
-MapOffset
.Y
);
3597 Panel
.Width
:= Abs(MousePos
.X
-MouseLDownPos
.X
);
3598 Panel
.Height
:= Abs(MousePos
.Y
-MouseLDownPos
.Y
);
3600 // Лифты, блокМон или отсутствие текстуры - пустая текстура:
3601 if (lbPanelType
.ItemIndex
in [9, 10, 11, 12, 13]) or
3602 (lbTextureList
.ItemIndex
= -1) then
3604 Panel
.TextureHeight
:= 1;
3605 Panel
.TextureWidth
:= 1;
3606 Panel
.TextureName
:= '';
3607 Panel
.TextureID
:= TEXTURE_SPECIAL_NONE
;
3609 else // Есть текстура:
3611 Panel
.TextureName
:= SelectedTexture();
3613 // Обычная текстура:
3614 if not IsSpecialTextureSel() then
3616 g_GetTextureSizeByName(Panel
.TextureName
,
3617 Panel
.TextureWidth
, Panel
.TextureHeight
);
3618 g_GetTexture(Panel
.TextureName
, Panel
.TextureID
);
3620 else // Спец.текстура:
3622 Panel
.TextureHeight
:= 1;
3623 Panel
.TextureWidth
:= 1;
3624 Panel
.TextureID
:= SpecialTextureID(SelectedTexture());
3629 Panel
.Blending
:= False;
3631 Undo_Add(OBJECT_PANEL
, AddPanel(Panel
));
3635 // Рисовали триггер:
3636 MOUSEACTION_DRAWTRIGGER
:
3638 trigger
.X
:= Min(MousePos
.X
-MapOffset
.X
, MouseLDownPos
.X
-MapOffset
.X
);
3639 trigger
.Y
:= Min(MousePos
.Y
-MapOffset
.Y
, MouseLDownPos
.Y
-MapOffset
.Y
);
3640 trigger
.Width
:= Abs(MousePos
.X
-MouseLDownPos
.X
);
3641 trigger
.Height
:= Abs(MousePos
.Y
-MouseLDownPos
.Y
);
3643 trigger
.Enabled
:= True;
3644 trigger
.TriggerType
:= lbTriggersList
.ItemIndex
+1;
3645 trigger
.TexturePanel
:= -1;
3648 trigger
.ActivateType
:= 0;
3650 if clbActivationType
.Checked
[0] then
3651 trigger
.ActivateType
:= Trigger
.ActivateType
or ACTIVATE_PLAYERCOLLIDE
;
3652 if clbActivationType
.Checked
[1] then
3653 trigger
.ActivateType
:= Trigger
.ActivateType
or ACTIVATE_MONSTERCOLLIDE
;
3654 if clbActivationType
.Checked
[2] then
3655 trigger
.ActivateType
:= Trigger
.ActivateType
or ACTIVATE_PLAYERPRESS
;
3656 if clbActivationType
.Checked
[3] then
3657 trigger
.ActivateType
:= Trigger
.ActivateType
or ACTIVATE_MONSTERPRESS
;
3658 if clbActivationType
.Checked
[4] then
3659 trigger
.ActivateType
:= Trigger
.ActivateType
or ACTIVATE_SHOT
;
3660 if clbActivationType
.Checked
[5] then
3661 trigger
.ActivateType
:= Trigger
.ActivateType
or ACTIVATE_NOMONSTER
;
3663 // Необходимые для активации ключи:
3666 if clbKeys
.Checked
[0] then
3667 trigger
.Key
:= Trigger
.Key
or KEY_RED
;
3668 if clbKeys
.Checked
[1] then
3669 trigger
.Key
:= Trigger
.Key
or KEY_GREEN
;
3670 if clbKeys
.Checked
[2] then
3671 trigger
.Key
:= Trigger
.Key
or KEY_BLUE
;
3672 if clbKeys
.Checked
[3] then
3673 trigger
.Key
:= Trigger
.Key
or KEY_REDTEAM
;
3674 if clbKeys
.Checked
[4] then
3675 trigger
.Key
:= Trigger
.Key
or KEY_BLUETEAM
;
3677 // Параметры триггера:
3678 FillByte(trigger
.Data
.Default
[0], 128, 0);
3680 case trigger
.TriggerType
of
3681 // Переключаемая панель:
3682 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
,
3683 TRIGGER_DOOR5
, TRIGGER_CLOSETRAP
, TRIGGER_TRAP
,
3684 TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
:
3686 Trigger
.Data
.PanelID
:= -1;
3692 trigger
.Data
.TargetPoint
.X
:= trigger
.X
-64;
3693 trigger
.Data
.TargetPoint
.Y
:= trigger
.Y
-64;
3694 trigger
.Data
.d2d_teleport
:= True;
3695 trigger
.Data
.TlpDir
:= 0;
3698 // Изменение других триггеров:
3699 TRIGGER_PRESS
, TRIGGER_ON
, TRIGGER_OFF
,
3702 trigger
.Data
.Count
:= 1;
3708 trigger
.Data
.Volume
:= 255;
3709 trigger
.Data
.Pan
:= 127;
3710 trigger
.Data
.PlayCount
:= 1;
3711 trigger
.Data
.Local
:= True;
3712 trigger
.Data
.SoundSwitch
:= False;
3718 trigger
.Data
.MusicAction
:= 1;
3721 // Создание монстра:
3722 TRIGGER_SPAWNMONSTER
:
3724 trigger
.Data
.MonType
:= MONSTER_ZOMBY
;
3725 trigger
.Data
.MonPos
.X
:= trigger
.X
-64;
3726 trigger
.Data
.MonPos
.Y
:= trigger
.Y
-64;
3727 trigger
.Data
.MonHealth
:= 0;
3728 trigger
.Data
.MonActive
:= False;
3729 trigger
.Data
.MonCount
:= 1;
3732 // Создание предмета:
3735 trigger
.Data
.ItemType
:= ITEM_AMMO_BULLETS
;
3736 trigger
.Data
.ItemPos
.X
:= trigger
.X
-64;
3737 trigger
.Data
.ItemPos
.Y
:= trigger
.Y
-64;
3738 trigger
.Data
.ItemOnlyDM
:= False;
3739 trigger
.Data
.ItemFalls
:= False;
3740 trigger
.Data
.ItemCount
:= 1;
3741 trigger
.Data
.ItemMax
:= 0;
3742 trigger
.Data
.ItemDelay
:= 0;
3748 trigger
.Data
.PushAngle
:= 90;
3749 trigger
.Data
.PushForce
:= 10;
3750 trigger
.Data
.ResetVel
:= True;
3755 trigger
.Data
.ScoreCount
:= 1;
3756 trigger
.Data
.ScoreCon
:= True;
3757 trigger
.Data
.ScoreMsg
:= True;
3762 trigger
.Data
.MessageKind
:= 0;
3763 trigger
.Data
.MessageSendTo
:= 0;
3764 trigger
.Data
.MessageText
:= '';
3765 trigger
.Data
.MessageTime
:= 144;
3770 trigger
.Data
.DamageValue
:= 5;
3771 trigger
.Data
.DamageInterval
:= 12;
3776 trigger
.Data
.HealValue
:= 5;
3777 trigger
.Data
.HealInterval
:= 36;
3782 trigger
.Data
.ShotType
:= TRIGGER_SHOT_BULLET
;
3783 trigger
.Data
.ShotSound
:= True;
3784 trigger
.Data
.ShotPanelID
:= -1;
3785 trigger
.Data
.ShotTarget
:= 0;
3786 trigger
.Data
.ShotIntSight
:= 0;
3787 trigger
.Data
.ShotAim
:= TRIGGER_SHOT_AIM_DEFAULT
;
3788 trigger
.Data
.ShotPos
.X
:= trigger
.X
-64;
3789 trigger
.Data
.ShotPos
.Y
:= trigger
.Y
-64;
3790 trigger
.Data
.ShotAngle
:= 0;
3791 trigger
.Data
.ShotWait
:= 18;
3792 trigger
.Data
.ShotAccuracy
:= 0;
3793 trigger
.Data
.ShotAmmo
:= 0;
3794 trigger
.Data
.ShotIntReload
:= 0;
3799 trigger
.Data
.FXCount
:= 1;
3800 trigger
.Data
.FXType
:= TRIGGER_EFFECT_PARTICLE
;
3801 trigger
.Data
.FXSubType
:= TRIGGER_EFFECT_SLIQUID
;
3802 trigger
.Data
.FXColorR
:= 0;
3803 trigger
.Data
.FXColorG
:= 0;
3804 trigger
.Data
.FXColorB
:= 255;
3805 trigger
.Data
.FXPos
:= TRIGGER_EFFECT_POS_CENTER
;
3806 trigger
.Data
.FXWait
:= 1;
3807 trigger
.Data
.FXVelX
:= 0;
3808 trigger
.Data
.FXVelY
:= -20;
3809 trigger
.Data
.FXSpreadL
:= 5;
3810 trigger
.Data
.FXSpreadR
:= 5;
3811 trigger
.Data
.FXSpreadU
:= 4;
3812 trigger
.Data
.FXSpreadD
:= 0;
3816 Undo_Add(OBJECT_TRIGGER
, AddTrigger(trigger
));
3819 // Рисовали область триггера "Расширитель":
3820 MOUSEACTION_DRAWPRESS
:
3821 with gTriggers
[SelectedObjects
[GetFirstSelected
].ID
] do
3823 Data
.tX
:= Min(MousePos
.X
-MapOffset
.X
, MouseLDownPos
.X
-MapOffset
.X
);
3824 Data
.tY
:= Min(MousePos
.Y
-MapOffset
.Y
, MouseLDownPos
.Y
-MapOffset
.Y
);
3825 Data
.tWidth
:= Abs(MousePos
.X
-MouseLDownPos
.X
);
3826 Data
.tHeight
:= Abs(MousePos
.Y
-MouseLDownPos
.Y
);
3828 DrawPressRect
:= False;
3832 MouseAction
:= MOUSEACTION_NONE
;
3834 end // if Button = mbLeft...
3835 else // Right Mouse Button:
3837 if MouseAction
= MOUSEACTION_NOACTION
then
3839 MouseAction
:= MOUSEACTION_NONE
;
3843 // Объект передвинут или изменен в размере:
3844 if MouseAction
in [MOUSEACTION_MOVEOBJ
, MOUSEACTION_RESIZE
] then
3846 MouseAction
:= MOUSEACTION_NONE
;
3851 // Еще не все выбрали:
3852 if SelectFlag
<> SELECTFLAG_NONE
then
3854 if SelectFlag
= SELECTFLAG_SELECTED
then
3855 SelectFlag
:= SELECTFLAG_NONE
;
3860 // Мышь сдвинулась во время удержания клавиши:
3861 if (MousePos
.X
<> MouseRDownPos
.X
) and
3862 (MousePos
.Y
<> MouseRDownPos
.Y
) then
3864 rSelectRect
:= True;
3866 rRect
.X
:= Min(MousePos
.X
, MouseRDownPos
.X
)-MapOffset
.X
;
3867 rRect
.Y
:= Min(MousePos
.Y
, MouseRDownPos
.Y
)-MapOffset
.Y
;
3868 rRect
.Width
:= Abs(MousePos
.X
-MouseRDownPos
.X
);
3869 rRect
.Height
:= Abs(MousePos
.Y
-MouseRDownPos
.Y
);
3871 else // Мышь не сдвинулась - нет прямоугольника:
3873 rSelectRect
:= False;
3875 rRect
.X
:= X
-MapOffset
.X
-1;
3876 rRect
.Y
:= Y
-MapOffset
.Y
-1;
3881 // Если зажат Ctrl - выделять еще, иначе только один выделенный объект:
3882 if not (ssCtrl
in Shift
) then
3883 RemoveSelectFromObjects();
3885 // Выделяем всё в выбранном прямоугольнике:
3886 IDArray
:= ObjectInRect(rRect
.X
, rRect
.Y
,
3887 rRect
.Width
, rRect
.Height
,
3888 pcObjects
.ActivePageIndex
+1, rSelectRect
);
3890 if IDArray
<> nil then
3891 for i
:= 0 to High(IDArray
) do
3892 SelectObject(pcObjects
.ActivePageIndex
+1, IDArray
[i
],
3893 (ssCtrl
in Shift
) or rSelectRect
);
3899 procedure TMainForm
.RenderPanelPaint(Sender
: TObject
);
3904 procedure TMainForm
.RenderPanelMouseMove(Sender
: TObject
;
3905 Shift
: TShiftState
; X
, Y
: Integer);
3908 dWidth
, dHeight
: Integer;
3911 _id
:= GetFirstSelected();
3913 // Рисуем панель с текстурой, сетка - размеры текстуры:
3914 if (MouseAction
= MOUSEACTION_DRAWPANEL
) and
3915 (lbPanelType
.ItemIndex
in [0..8]) and
3916 (lbTextureList
.ItemIndex
<> -1) and
3917 (not IsSpecialTextureSel()) then
3919 sX
:= StrToIntDef(lTextureWidth
.Caption
, DotStep
);
3920 sY
:= StrToIntDef(lTextureHeight
.Caption
, DotStep
);
3923 // Меняем размер панели с текстурой, сетка - размеры текстуры:
3924 if (MouseAction
= MOUSEACTION_RESIZE
) and
3925 ( (SelectedObjects
[_id
].ObjectType
= OBJECT_PANEL
) and
3926 IsTexturedPanel(gPanels
[SelectedObjects
[_id
].ID
].PanelType
) and
3927 (gPanels
[SelectedObjects
[_id
].ID
].TextureName
<> '') and
3928 (not IsSpecialTexture(gPanels
[SelectedObjects
[_id
].ID
].TextureName
)) ) then
3930 sX
:= gPanels
[SelectedObjects
[_id
].ID
].TextureWidth
;
3931 sY
:= gPanels
[SelectedObjects
[_id
].ID
].TextureHeight
;
3934 // Выравнивание по сетке:
3940 else // Нет выравнивания по сетке:
3946 // Новая позиция мыши:
3948 begin // Зажата левая кнопка мыши
3949 MousePos
.X
:= (Round((X
-MouseLDownPos
.X
)/sX
)*sX
)+MouseLDownPos
.X
;
3950 MousePos
.Y
:= (Round((Y
-MouseLDownPos
.Y
)/sY
)*sY
)+MouseLDownPos
.Y
;
3954 begin // Зажата правая кнопка мыши
3955 MousePos
.X
:= (Round((X
-MouseRDownPos
.X
)/sX
)*sX
)+MouseRDownPos
.X
;
3956 MousePos
.Y
:= (Round((Y
-MouseRDownPos
.Y
)/sY
)*sY
)+MouseRDownPos
.Y
;
3959 begin // Кнопки мыши не зажаты
3960 MousePos
.X
:= (Round(X
/sX
)*sX
);
3961 MousePos
.Y
:= (Round(Y
/sY
)*sY
);
3964 // Изменение размера закончилось - ставим обычный курсор:
3965 if ResizeType
= RESIZETYPE_NONE
then
3966 RenderPanel
.Cursor
:= crDefault
;
3968 // Зажата только правая кнопка мыши:
3969 if (not MouseLDown
) and (MouseRDown
) then
3971 // Рисуем прямоугольник выделения:
3972 if MouseAction
= MOUSEACTION_NONE
then
3974 if DrawRect
= nil then
3976 DrawRect
.Top
:= MouseRDownPos
.y
;
3977 DrawRect
.Left
:= MouseRDownPos
.x
;
3978 DrawRect
.Bottom
:= MousePos
.y
;
3979 DrawRect
.Right
:= MousePos
.x
;
3982 // Двигаем выделенные объекты:
3983 if MouseAction
= MOUSEACTION_MOVEOBJ
then
3985 MoveSelectedObjects(ssShift
in Shift
, ssCtrl
in Shift
,
3986 MousePos
.X
-LastMovePoint
.X
+WASDOffset
.X
,
3987 MousePos
.Y
-LastMovePoint
.Y
+WASDOffset
.Y
);
3992 // Меняем размер выделенного объекта:
3993 if MouseAction
= MOUSEACTION_RESIZE
then
3995 if (SelectedObjectCount
= 1) and
3996 (SelectedObjects
[GetFirstSelected
].Live
) then
3998 dWidth
:= MousePos
.X
-LastMovePoint
.X
+WASDOffset
.X
;
3999 dHeight
:= MousePos
.Y
-LastMovePoint
.Y
+WASDOffset
.Y
;
4004 RESIZETYPE_VERTICAL
: dWidth
:= 0;
4005 RESIZETYPE_HORIZONTAL
: dHeight
:= 0;
4008 case ResizeDirection
of
4009 RESIZEDIR_UP
: dHeight
:= -dHeight
;
4010 RESIZEDIR_LEFT
: dWidth
:= -dWidth
;
4013 ResizeObject(SelectedObjects
[GetFirstSelected
].ObjectType
,
4014 SelectedObjects
[GetFirstSelected
].ID
,
4015 dWidth
, dHeight
, ResizeDirection
);
4017 LastMovePoint
:= MousePos
;
4022 // Зажата только левая кнопка мыши:
4023 if (not MouseRDown
) and (MouseLDown
) then
4025 // Рисуем прямоугольник планирования панели:
4026 if MouseAction
in [MOUSEACTION_DRAWPANEL
,
4027 MOUSEACTION_DRAWTRIGGER
,
4028 MOUSEACTION_DRAWPRESS
] then
4030 if DrawRect
= nil then
4032 DrawRect
.Top
:= MouseLDownPos
.y
;
4033 DrawRect
.Left
:= MouseLDownPos
.x
;
4034 DrawRect
.Bottom
:= MousePos
.y
;
4035 DrawRect
.Right
:= MousePos
.x
;
4037 else // Двигаем карту:
4038 if MouseAction
= MOUSEACTION_MOVEMAP
then
4044 // Клавиши мыши не зажаты:
4045 if (not MouseRDown
) and (not MouseLDown
) then
4048 // Строка состояния - координаты мыши:
4049 StatusBar
.Panels
[1].Text := Format('(%d:%d)',
4050 [MousePos
.X
-MapOffset
.X
, MousePos
.Y
-MapOffset
.Y
]);
4053 procedure TMainForm
.FormCloseQuery(Sender
: TObject
; var CanClose
: Boolean);
4055 CanClose
:= MessageBox(0, PChar(_lc
[I_MSG_EXIT_PROMT
]),
4056 PChar(_lc
[I_MSG_EXIT
]),
4057 MB_ICONQUESTION
or MB_YESNO
or
4058 MB_DEFBUTTON1
) = idYes
;
4061 procedure TMainForm
.aExitExecute(Sender
: TObject
);
4066 procedure TMainForm
.FormDestroy(Sender
: TObject
);
4071 config
:= TConfig
.CreateFile(EditorDir
+'Editor.cfg');
4073 if WindowState
<> wsMaximized
then
4075 config
.WriteInt('Editor', 'XPos', Left
);
4076 config
.WriteInt('Editor', 'YPos', Top
);
4077 config
.WriteInt('Editor', 'Width', Width
);
4078 config
.WriteInt('Editor', 'Height', Height
);
4082 config
.WriteInt('Editor', 'XPos', RestoredLeft
);
4083 config
.WriteInt('Editor', 'YPos', RestoredTop
);
4084 config
.WriteInt('Editor', 'Width', RestoredWidth
);
4085 config
.WriteInt('Editor', 'Height', RestoredHeight
);
4087 config
.WriteBool('Editor', 'Maximize', WindowState
= wsMaximized
);
4088 config
.WriteBool('Editor', 'Minimap', ShowMap
);
4089 config
.WriteInt('Editor', 'PanelProps', PanelProps
.ClientWidth
);
4090 config
.WriteInt('Editor', 'PanelObjs', PanelObjs
.ClientHeight
);
4091 config
.WriteBool('Editor', 'DotEnable', DotEnable
);
4092 config
.WriteInt('Editor', 'DotStep', DotStep
);
4093 config
.WriteStr('Editor', 'LastOpenDir', OpenDialog
.InitialDir
);
4094 config
.WriteStr('Editor', 'LastSaveDir', SaveDialog
.InitialDir
);
4095 config
.WriteBool('Editor', 'EdgeShow', drEdge
[3] < 255);
4096 config
.WriteInt('Editor', 'EdgeColor', gColorEdge
);
4097 config
.WriteInt('Editor', 'EdgeAlpha', gAlphaEdge
);
4098 config
.WriteInt('Editor', 'LineAlpha', gAlphaTriggerLine
);
4099 config
.WriteInt('Editor', 'TriggerAlpha', gAlphaTriggerArea
);
4101 for i
:= 0 to RecentCount
-1 do
4102 if i
< RecentFiles
.Count
then
4103 config
.WriteStr('RecentFiles', IntToStr(i
+1), RecentFiles
[i
])
4105 config
.WriteStr('RecentFiles', IntToStr(i
+1), '');
4108 config
.SaveFile(EditorDir
+'Editor.cfg');
4111 slInvalidTextures
.Free
;
4114 procedure TMainForm
.RenderPanelResize(Sender
: TObject
);
4116 if MainForm
.Visible
then
4120 procedure TMainForm
.Splitter1Moved(Sender
: TObject
);
4125 procedure TMainForm
.aMapOptionsExecute(Sender
: TObject
);
4129 MapOptionsForm
.ShowModal();
4131 ResName
:= OpenedMap
;
4132 while (Pos(':\', ResName
) > 0) do
4133 Delete(ResName
, 1, Pos(':\', ResName
) + 1);
4135 UpdateCaption(gMapInfo
.Name
, ExtractFileName(OpenedWAD
), ResName
);
4138 procedure TMainForm
.aAboutExecute(Sender
: TObject
);
4140 AboutForm
.ShowModal();
4143 procedure TMainForm
.FormKeyDown(Sender
: TObject
; var Key
: Word;
4144 Shift
: TShiftState
);
4149 if (not EditingProperties
) then
4151 if Key
= Ord('1') then
4152 SwitchLayer(LAYER_BACK
);
4153 if Key
= Ord('2') then
4154 SwitchLayer(LAYER_WALLS
);
4155 if Key
= Ord('3') then
4156 SwitchLayer(LAYER_FOREGROUND
);
4157 if Key
= Ord('4') then
4158 SwitchLayer(LAYER_STEPS
);
4159 if Key
= Ord('5') then
4160 SwitchLayer(LAYER_WATER
);
4161 if Key
= Ord('6') then
4162 SwitchLayer(LAYER_ITEMS
);
4163 if Key
= Ord('7') then
4164 SwitchLayer(LAYER_MONSTERS
);
4165 if Key
= Ord('8') then
4166 SwitchLayer(LAYER_AREAS
);
4167 if Key
= Ord('9') then
4168 SwitchLayer(LAYER_TRIGGERS
);
4169 if Key
= Ord('0') then
4170 tbShowClick(tbShow
);
4172 if Key
= Ord('V') then
4173 begin // Поворот монстров и областей:
4174 if (SelectedObjects
<> nil) then
4176 for i
:= 0 to High(SelectedObjects
) do
4177 if (SelectedObjects
[i
].Live
) then
4179 if (SelectedObjects
[i
].ObjectType
= OBJECT_MONSTER
) then
4181 g_ChangeDir(gMonsters
[SelectedObjects
[i
].ID
].Direction
);
4184 if (SelectedObjects
[i
].ObjectType
= OBJECT_AREA
) then
4186 g_ChangeDir(gAreas
[SelectedObjects
[i
].ID
].Direction
);
4192 if pcObjects
.ActivePage
= tsMonsters
then
4194 if rbMonsterLeft
.Checked
then
4195 rbMonsterRight
.Checked
:= True
4197 rbMonsterLeft
.Checked
:= True;
4199 if pcObjects
.ActivePage
= tsAreas
then
4201 if rbAreaLeft
.Checked
then
4202 rbAreaRight
.Checked
:= True
4204 rbAreaLeft
.Checked
:= True;
4209 if not (ssCtrl
in Shift
) then
4211 // Быстрое превью карты:
4212 if Key
= Ord('E') then
4214 if PreviewMode
= 0 then
4218 // Вертикальный скролл карты:
4221 if Key
= Ord('W') then
4223 if (MouseLDown
or MouseRDown
) and (Position
>= DotStep
) then
4225 Dec(WASDOffset
.Y
, DotStep
);
4226 RenderPanelMouseMove(Sender
, Shift
, LastMovePoint
.X
, LastMovePoint
.Y
);
4228 Position
:= IfThen(Position
> DotStep
, Position
-DotStep
, 0);
4229 MapOffset
.Y
:= -Round(Position
/16) * 16;
4232 if Key
= Ord('S') then
4234 if (MouseLDown
or MouseRDown
) and (Position
+DotStep
<= Max
) then
4236 Inc(WASDOffset
.Y
, DotStep
);
4237 RenderPanelMouseMove(Sender
, Shift
, LastMovePoint
.X
, LastMovePoint
.Y
);
4239 Position
:= IfThen(Position
+DotStep
< Max
, Position
+DotStep
, Max
);
4240 MapOffset
.Y
:= -Round(Position
/16) * 16;
4244 // Горизонтальный скролл карты:
4245 with sbHorizontal
do
4247 if Key
= Ord('A') then
4249 if (MouseLDown
or MouseRDown
) and (Position
>= DotStep
) then
4251 Dec(WASDOffset
.X
, DotStep
);
4252 RenderPanelMouseMove(Sender
, Shift
, LastMovePoint
.X
, LastMovePoint
.Y
);
4254 Position
:= IfThen(Position
> DotStep
, Position
-DotStep
, 0);
4255 MapOffset
.X
:= -Round(Position
/16) * 16;
4258 if Key
= Ord('D') then
4260 if (MouseLDown
or MouseRDown
) and (Position
+DotStep
<= Max
) then
4262 Inc(WASDOffset
.X
, DotStep
);
4263 RenderPanelMouseMove(Sender
, Shift
, LastMovePoint
.X
, LastMovePoint
.Y
);
4265 Position
:= IfThen(Position
+DotStep
< Max
, Position
+DotStep
, Max
);
4266 MapOffset
.X
:= -Round(Position
/16) * 16;
4272 // Удалить выделенные объекты:
4273 if (Key
= VK_DELETE
) and (SelectedObjects
<> nil) and
4274 RenderPanel
.Focused() then
4275 DeleteSelectedObjects();
4278 if (Key
= VK_ESCAPE
) and (SelectedObjects
<> nil) then
4279 RemoveSelectFromObjects();
4281 // Передвинуть объекты:
4282 if MainForm
.ActiveControl
= RenderPanel
then
4287 if Key
= VK_NUMPAD4
then
4288 dx
:= IfThen(ssAlt
in Shift
, -1, -DotStep
);
4289 if Key
= VK_NUMPAD6
then
4290 dx
:= IfThen(ssAlt
in Shift
, 1, DotStep
);
4291 if Key
= VK_NUMPAD8
then
4292 dy
:= IfThen(ssAlt
in Shift
, -1, -DotStep
);
4293 if Key
= VK_NUMPAD5
then
4294 dy
:= IfThen(ssAlt
in Shift
, 1, DotStep
);
4296 if (dx
<> 0) or (dy
<> 0) then
4298 MoveSelectedObjects(ssShift
in Shift
, ssCtrl
in Shift
, dx
, dy
);
4303 if ssCtrl
in Shift
then
4305 // Выбор панели с текстурой для триггера
4306 if Key
= Ord('T') then
4308 DrawPressRect
:= False;
4309 if SelectFlag
= SELECTFLAG_TEXTURE
then
4311 SelectFlag
:= SELECTFLAG_NONE
;
4314 vleObjectProperty
.FindRow(_lc
[I_PROP_TR_TEXTURE_PANEL
], i
);
4316 SelectFlag
:= SELECTFLAG_TEXTURE
;
4319 if Key
= Ord('D') then
4321 SelectFlag
:= SELECTFLAG_NONE
;
4322 if DrawPressRect
then
4324 DrawPressRect
:= False;
4329 // Выбор области воздействия, в зависимости от типа триггера
4330 vleObjectProperty
.FindRow(_lc
[I_PROP_TR_EX_AREA
], i
);
4333 DrawPressRect
:= True;
4336 vleObjectProperty
.FindRow(_lc
[I_PROP_TR_DOOR_PANEL
], i
);
4338 vleObjectProperty
.FindRow(_lc
[I_PROP_TR_TRAP_PANEL
], i
);
4341 SelectFlag
:= SELECTFLAG_DOOR
;
4344 vleObjectProperty
.FindRow(_lc
[I_PROP_TR_LIFT_PANEL
], i
);
4347 SelectFlag
:= SELECTFLAG_LIFT
;
4350 vleObjectProperty
.FindRow(_lc
[I_PROP_TR_TELEPORT_TO
], i
);
4353 SelectFlag
:= SELECTFLAG_TELEPORT
;
4356 vleObjectProperty
.FindRow(_lc
[I_PROP_TR_SPAWN_TO
], i
);
4359 SelectFlag
:= SELECTFLAG_SPAWNPOINT
;
4363 // Выбор основного параметра, в зависимости от типа триггера
4364 vleObjectProperty
.FindRow(_lc
[I_PROP_TR_NEXT_MAP
], i
);
4367 g_ProcessResourceStr(OpenedMap
, @FileName
, nil, nil);
4368 SelectMapForm
.Caption
:= _lc
[I_CAP_SELECT
];
4369 SelectMapForm
.GetMaps(FileName
);
4371 if SelectMapForm
.ShowModal() = mrOK
then
4373 vleObjectProperty
.Cells
[1, i
] := SelectMapForm
.lbMapList
.Items
[SelectMapForm
.lbMapList
.ItemIndex
];
4374 bApplyProperty
.Click();
4378 vleObjectProperty
.FindRow(_lc
[I_PROP_TR_SOUND_NAME
], i
);
4380 vleObjectProperty
.FindRow(_lc
[I_PROP_TR_MUSIC_NAME
], i
);
4383 AddSoundForm
.OKFunction
:= nil;
4384 AddSoundForm
.lbResourcesList
.MultiSelect
:= False;
4385 AddSoundForm
.SetResource
:= vleObjectProperty
.Cells
[1, i
];
4387 if (AddSoundForm
.ShowModal() = mrOk
) then
4389 vleObjectProperty
.Cells
[1, i
] := AddSoundForm
.ResourceName
;
4390 bApplyProperty
.Click();
4394 vleObjectProperty
.FindRow(_lc
[I_PROP_TR_PUSH_ANGLE
], i
);
4396 vleObjectProperty
.FindRow(_lc
[I_PROP_TR_MESSAGE_TEXT
], i
);
4399 vleObjectProperty
.Row
:= i
;
4400 vleObjectProperty
.SetFocus();
4407 procedure TMainForm
.aOptimizeExecute(Sender
: TObject
);
4409 RemoveSelectFromObjects();
4410 MapOptimizationForm
.ShowModal();
4413 procedure TMainForm
.aCheckMapExecute(Sender
: TObject
);
4415 MapCheckForm
.ShowModal();
4418 procedure TMainForm
.bbAddTextureClick(Sender
: TObject
);
4420 AddTextureForm
.lbResourcesList
.MultiSelect
:= True;
4421 AddTextureForm
.ShowModal();
4424 procedure TMainForm
.lbTextureListClick(Sender
: TObject
);
4427 TextureWidth
, TextureHeight
: Word;
4432 if (lbTextureList
.ItemIndex
<> -1) and
4433 (not IsSpecialTextureSel()) then
4435 if g_GetTexture(SelectedTexture(), TextureID
) then
4437 g_GetTextureSizeByID(TextureID
, TextureWidth
, TextureHeight
);
4439 lTextureWidth
.Caption
:= IntToStr(TextureWidth
);
4440 lTextureHeight
.Caption
:= IntToStr(TextureHeight
);
4443 lTextureWidth
.Caption
:= _lc
[I_NOT_ACCESSIBLE
];
4444 lTextureHeight
.Caption
:= _lc
[I_NOT_ACCESSIBLE
];
4449 lTextureWidth
.Caption
:= '';
4450 lTextureHeight
.Caption
:= '';
4454 procedure TMainForm
.lbTextureListDrawItem(Control
: TWinControl
; Index
: Integer;
4455 ARect
: TRect
; State
: TOwnerDrawState
);
4457 with Control
as TListBox
do
4459 if LCLType
.odSelected
in State
then
4461 Canvas
.Brush
.Color
:= clHighlight
;
4462 Canvas
.Font
.Color
:= clHighlightText
;
4464 if (Items
<> nil) and (Index
>= 0) then
4465 if slInvalidTextures
.IndexOf(Items
[Index
]) > -1 then
4467 Canvas
.Brush
.Color
:= clRed
;
4468 Canvas
.Font
.Color
:= clWhite
;
4470 Canvas
.FillRect(ARect
);
4471 Canvas
.TextRect(ARect
, ARect
.Left
, ARect
.Top
, Items
[Index
]);
4475 procedure TMainForm
.vleObjectPropertyGetPickList(Sender
: TObject
;
4476 const KeyName
: String; Values
: TStrings
);
4478 if vleObjectProperty
.ItemProps
[KeyName
].EditStyle
= esPickList
then
4480 if KeyName
= _lc
[I_PROP_DIRECTION
] then
4482 Values
.Add(DirNames
[D_LEFT
]);
4483 Values
.Add(DirNames
[D_RIGHT
]);
4485 else if KeyName
= _lc
[I_PROP_TR_TELEPORT_DIR
] then
4487 Values
.Add(DirNamesAdv
[0]);
4488 Values
.Add(DirNamesAdv
[1]);
4489 Values
.Add(DirNamesAdv
[2]);
4490 Values
.Add(DirNamesAdv
[3]);
4492 else if KeyName
= _lc
[I_PROP_TR_MUSIC_ACT
] then
4494 Values
.Add(_lc
[I_PROP_TR_MUSIC_ON
]);
4495 Values
.Add(_lc
[I_PROP_TR_MUSIC_OFF
]);
4497 else if KeyName
= _lc
[I_PROP_TR_MONSTER_BEHAVIOUR
] then
4499 Values
.Add(_lc
[I_PROP_TR_MONSTER_BEHAVIOUR_0
]);
4500 Values
.Add(_lc
[I_PROP_TR_MONSTER_BEHAVIOUR_1
]);
4501 Values
.Add(_lc
[I_PROP_TR_MONSTER_BEHAVIOUR_2
]);
4502 Values
.Add(_lc
[I_PROP_TR_MONSTER_BEHAVIOUR_3
]);
4503 Values
.Add(_lc
[I_PROP_TR_MONSTER_BEHAVIOUR_4
]);
4504 Values
.Add(_lc
[I_PROP_TR_MONSTER_BEHAVIOUR_5
]);
4506 else if KeyName
= _lc
[I_PROP_TR_SCORE_ACT
] then
4508 Values
.Add(_lc
[I_PROP_TR_SCORE_ACT_0
]);
4509 Values
.Add(_lc
[I_PROP_TR_SCORE_ACT_1
]);
4510 Values
.Add(_lc
[I_PROP_TR_SCORE_ACT_2
]);
4511 Values
.Add(_lc
[I_PROP_TR_SCORE_ACT_3
]);
4513 else if KeyName
= _lc
[I_PROP_TR_SCORE_TEAM
] then
4515 Values
.Add(_lc
[I_PROP_TR_SCORE_TEAM_0
]);
4516 Values
.Add(_lc
[I_PROP_TR_SCORE_TEAM_1
]);
4517 Values
.Add(_lc
[I_PROP_TR_SCORE_TEAM_2
]);
4518 Values
.Add(_lc
[I_PROP_TR_SCORE_TEAM_3
]);
4520 else if KeyName
= _lc
[I_PROP_TR_MESSAGE_KIND
] then
4522 Values
.Add(_lc
[I_PROP_TR_MESSAGE_KIND_0
]);
4523 Values
.Add(_lc
[I_PROP_TR_MESSAGE_KIND_1
]);
4525 else if KeyName
= _lc
[I_PROP_TR_MESSAGE_TO
] then
4527 Values
.Add(_lc
[I_PROP_TR_MESSAGE_TO_0
]);
4528 Values
.Add(_lc
[I_PROP_TR_MESSAGE_TO_1
]);
4529 Values
.Add(_lc
[I_PROP_TR_MESSAGE_TO_2
]);
4530 Values
.Add(_lc
[I_PROP_TR_MESSAGE_TO_3
]);
4531 Values
.Add(_lc
[I_PROP_TR_MESSAGE_TO_4
]);
4532 Values
.Add(_lc
[I_PROP_TR_MESSAGE_TO_5
]);
4534 else if KeyName
= _lc
[I_PROP_TR_SHOT_TO
] then
4536 Values
.Add(_lc
[I_PROP_TR_SHOT_TO_0
]);
4537 Values
.Add(_lc
[I_PROP_TR_SHOT_TO_1
]);
4538 Values
.Add(_lc
[I_PROP_TR_SHOT_TO_2
]);
4539 Values
.Add(_lc
[I_PROP_TR_SHOT_TO_3
]);
4540 Values
.Add(_lc
[I_PROP_TR_SHOT_TO_4
]);
4541 Values
.Add(_lc
[I_PROP_TR_SHOT_TO_5
]);
4542 Values
.Add(_lc
[I_PROP_TR_SHOT_TO_6
]);
4544 else if KeyName
= _lc
[I_PROP_TR_SHOT_AIM
] then
4546 Values
.Add(_lc
[I_PROP_TR_SHOT_AIM_0
]);
4547 Values
.Add(_lc
[I_PROP_TR_SHOT_AIM_1
]);
4548 Values
.Add(_lc
[I_PROP_TR_SHOT_AIM_2
]);
4549 Values
.Add(_lc
[I_PROP_TR_SHOT_AIM_3
]);
4551 else if (KeyName
= _lc
[I_PROP_PANEL_BLEND
]) or
4552 (KeyName
= _lc
[I_PROP_DM_ONLY
]) or
4553 (KeyName
= _lc
[I_PROP_ITEM_FALLS
]) or
4554 (KeyName
= _lc
[I_PROP_TR_ENABLED
]) or
4555 (KeyName
= _lc
[I_PROP_TR_D2D
]) or
4556 (KeyName
= _lc
[I_PROP_TR_SILENT
]) or
4557 (KeyName
= _lc
[I_PROP_TR_TELEPORT_SILENT
]) or
4558 (KeyName
= _lc
[I_PROP_TR_EX_RANDOM
]) or
4559 (KeyName
= _lc
[I_PROP_TR_TEXTURE_ONCE
]) or
4560 (KeyName
= _lc
[I_PROP_TR_TEXTURE_ANIM_ONCE
]) or
4561 (KeyName
= _lc
[I_PROP_TR_SOUND_LOCAL
]) or
4562 (KeyName
= _lc
[I_PROP_TR_SOUND_SWITCH
]) or
4563 (KeyName
= _lc
[I_PROP_TR_MONSTER_ACTIVE
]) or
4564 (KeyName
= _lc
[I_PROP_TR_PUSH_RESET
]) or
4565 (KeyName
= _lc
[I_PROP_TR_SCORE_CON
]) or
4566 (KeyName
= _lc
[I_PROP_TR_SCORE_MSG
]) or
4567 (KeyName
= _lc
[I_PROP_TR_HEALTH_MAX
]) or
4568 (KeyName
= _lc
[I_PROP_TR_SHOT_SOUND
]) or
4569 (KeyName
= _lc
[I_PROP_TR_EFFECT_CENTER
]) then
4571 Values
.Add(BoolNames
[True]);
4572 Values
.Add(BoolNames
[False]);
4577 procedure TMainForm
.bApplyPropertyClick(Sender
: TObject
);
4579 _id
, a
, r
, c
: Integer;
4589 if SelectedObjectCount() <> 1 then
4591 if not SelectedObjects
[GetFirstSelected()].Live
then
4595 if not CheckProperty() then
4601 _id
:= GetFirstSelected();
4603 r
:= vleObjectProperty
.Row
;
4604 c
:= vleObjectProperty
.Col
;
4606 case SelectedObjects
[_id
].ObjectType
of
4609 with gPanels
[SelectedObjects
[_id
].ID
] do
4611 X
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_X
]]));
4612 Y
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_Y
]]));
4613 Width
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_WIDTH
]]));
4614 Height
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_HEIGHT
]]));
4616 PanelType
:= GetPanelType(vleObjectProperty
.Values
[_lc
[I_PROP_PANEL_TYPE
]]);
4618 // Сброс ссылки на триггеры смены текстуры:
4619 if not WordBool(PanelType
and (PANEL_WALL
or PANEL_FORE
or PANEL_BACK
)) then
4620 if gTriggers
<> nil then
4621 for a
:= 0 to High(gTriggers
) do
4623 if (gTriggers
[a
].TriggerType
<> 0) and
4624 (gTriggers
[a
].TexturePanel
= Integer(SelectedObjects
[_id
].ID
)) then
4625 gTriggers
[a
].TexturePanel
:= -1;
4626 if (gTriggers
[a
].TriggerType
= TRIGGER_SHOT
) and
4627 (gTriggers
[a
].Data
.ShotPanelID
= Integer(SelectedObjects
[_id
].ID
)) then
4628 gTriggers
[a
].Data
.ShotPanelID
:= -1;
4631 // Сброс ссылки на триггеры лифта:
4632 if not WordBool(PanelType
and (PANEL_LIFTUP
or PANEL_LIFTDOWN
or PANEL_LIFTLEFT
or PANEL_LIFTRIGHT
)) then
4633 if gTriggers
<> nil then
4634 for a
:= 0 to High(gTriggers
) do
4635 if (gTriggers
[a
].TriggerType
in [TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
]) and
4636 (gTriggers
[a
].Data
.PanelID
= Integer(SelectedObjects
[_id
].ID
)) then
4637 gTriggers
[a
].Data
.PanelID
:= -1;
4639 // Сброс ссылки на триггеры двери:
4640 if not WordBool(PanelType
and (PANEL_OPENDOOR
or PANEL_CLOSEDOOR
)) then
4641 if gTriggers
<> nil then
4642 for a
:= 0 to High(gTriggers
) do
4643 if (gTriggers
[a
].TriggerType
in [TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
,
4644 TRIGGER_DOOR5
, TRIGGER_CLOSETRAP
, TRIGGER_TRAP
]) and
4645 (gTriggers
[a
].Data
.PanelID
= Integer(SelectedObjects
[_id
].ID
)) then
4646 gTriggers
[a
].Data
.PanelID
:= -1;
4648 if IsTexturedPanel(PanelType
) then
4649 begin // Может быть текстура
4650 if TextureName
<> '' then
4651 begin // Была текстура
4652 Alpha
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_PANEL_ALPHA
]]));
4653 Blending
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_PANEL_BLEND
]]);
4662 TextureName
:= vleObjectProperty
.Values
[_lc
[I_PROP_PANEL_TEX
]];
4664 if TextureName
<> '' then
4665 begin // Есть текстура
4666 // Обычная текстура:
4667 if not IsSpecialTexture(TextureName
) then
4669 g_GetTextureSizeByName(TextureName
,
4670 TextureWidth
, TextureHeight
);
4672 // Проверка кратности размеров панели:
4674 if TextureWidth
<> 0 then
4675 if gPanels
[SelectedObjects
[_id
].ID
].Width
mod TextureWidth
<> 0 then
4677 ErrorMessageBox(Format(_lc
[I_MSG_WRONG_TEXWIDTH
],
4681 if Res
and (TextureHeight
<> 0) then
4682 if gPanels
[SelectedObjects
[_id
].ID
].Height
mod TextureHeight
<> 0 then
4684 ErrorMessageBox(Format(_lc
[I_MSG_WRONG_TEXHEIGHT
],
4691 if not g_GetTexture(TextureName
, TextureID
) then
4692 // Не удалось загрузить текстуру, рисуем NOTEXTURE
4693 if g_GetTexture('NOTEXTURE', NoTextureID
) then
4695 TextureID
:= TEXTURE_SPECIAL_NOTEXTURE
;
4696 g_GetTextureSizeByID(NoTextureID
, NW
, NH
);
4698 TextureHeight
:= NH
;
4701 TextureID
:= TEXTURE_SPECIAL_NONE
;
4711 TextureID
:= TEXTURE_SPECIAL_NONE
;
4714 else // Спец.текстура
4718 TextureID
:= SpecialTextureID(TextureName
);
4721 else // Нет текстуры
4725 TextureID
:= TEXTURE_SPECIAL_NONE
;
4728 else // Не может быть текстуры
4735 TextureID
:= TEXTURE_SPECIAL_NONE
;
4742 with gItems
[SelectedObjects
[_id
].ID
] do
4744 X
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_X
]]));
4745 Y
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_Y
]]));
4746 OnlyDM
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_DM_ONLY
]]);
4747 Fall
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_ITEM_FALLS
]]);
4753 with gMonsters
[SelectedObjects
[_id
].ID
] do
4755 X
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_X
]]));
4756 Y
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_Y
]]));
4757 Direction
:= NameToDir(vleObjectProperty
.Values
[_lc
[I_PROP_DIRECTION
]]);
4763 with gAreas
[SelectedObjects
[_id
].ID
] do
4765 X
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_X
]]));
4766 Y
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_Y
]]));
4767 Direction
:= NameToDir(vleObjectProperty
.Values
[_lc
[I_PROP_DIRECTION
]]);
4773 with gTriggers
[SelectedObjects
[_id
].ID
] do
4775 X
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_X
]]));
4776 Y
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_Y
]]));
4777 Width
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_WIDTH
]]));
4778 Height
:= StrToInt(Trim(vleObjectProperty
.Values
[_lc
[I_PROP_HEIGHT
]]));
4779 Enabled
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_ENABLED
]]);
4780 ActivateType
:= StrToActivate(vleObjectProperty
.Values
[_lc
[I_PROP_TR_ACTIVATION
]]);
4781 Key
:= StrToKey(vleObjectProperty
.Values
[_lc
[I_PROP_TR_KEYS
]]);
4786 s
:= utf2win(vleObjectProperty
.Values
[_lc
[I_PROP_TR_NEXT_MAP
]]);
4787 FillByte(Data
.MapName
[0], 16, 0);
4789 Move(s
[1], Data
.MapName
[0], Min(Length(s
), 16));
4794 Data
.ActivateOnce
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_TEXTURE_ONCE
]]);
4795 Data
.AnimOnce
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_TEXTURE_ANIM_ONCE
]]);
4798 TRIGGER_PRESS
, TRIGGER_ON
, TRIGGER_OFF
, TRIGGER_ONOFF
:
4800 Data
.Wait
:= Min(StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EX_DELAY
]], 0), 65535);
4801 Data
.Count
:= Min(StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EX_COUNT
]], 0), 65535);
4802 if Data
.Count
< 1 then
4804 if TriggerType
= TRIGGER_PRESS
then
4805 Data
.ExtRandom
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EX_RANDOM
]]);
4808 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
, TRIGGER_DOOR5
,
4809 TRIGGER_CLOSETRAP
, TRIGGER_TRAP
, TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
,
4812 Data
.NoSound
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SILENT
]]);
4813 Data
.d2d_doors
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_D2D
]]);
4818 Data
.d2d_teleport
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_D2D
]]);
4819 Data
.silent_teleport
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_TELEPORT_SILENT
]]);
4820 Data
.TlpDir
:= NameToDirAdv(vleObjectProperty
.Values
[_lc
[I_PROP_TR_TELEPORT_DIR
]]);
4825 s
:= utf2win(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SOUND_NAME
]]);
4826 FillByte(Data
.SoundName
[0], 64, 0);
4828 Move(s
[1], Data
.SoundName
[0], Min(Length(s
), 64));
4830 Data
.Volume
:= Min(StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SOUND_VOLUME
]], 0), 255);
4831 Data
.Pan
:= Min(StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SOUND_PAN
]], 0), 255);
4832 Data
.PlayCount
:= Min(StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SOUND_COUNT
]], 0), 255);
4833 Data
.Local
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SOUND_LOCAL
]]);
4834 Data
.SoundSwitch
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SOUND_SWITCH
]]);
4837 TRIGGER_SPAWNMONSTER
:
4839 Data
.MonType
:= StrToMonster(vleObjectProperty
.Values
[_lc
[I_PROP_TR_MONSTER_TYPE
]]);
4840 Data
.MonDir
:= Byte(NameToDir(vleObjectProperty
.Values
[_lc
[I_PROP_DIRECTION
]]));
4841 Data
.MonHealth
:= Min(StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_HEALTH
]], 0), 1000000);
4842 if Data
.MonHealth
< 0 then
4843 Data
.MonHealth
:= 0;
4844 Data
.MonActive
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_MONSTER_ACTIVE
]]);
4845 Data
.MonCount
:= Min(StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_COUNT
]], 0), 64);
4846 if Data
.MonCount
< 1 then
4848 Data
.MonEffect
:= StrToEffect(vleObjectProperty
.Values
[_lc
[I_PROP_TR_FX_TYPE
]]);
4849 Data
.MonMax
:= Min(StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SPAWN_MAX
]], 0), 65535);
4850 Data
.MonDelay
:= Min(StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SPAWN_DELAY
]], 0), 65535);
4852 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_MONSTER_BEHAVIOUR
]] = _lc
[I_PROP_TR_MONSTER_BEHAVIOUR_1
] then
4854 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_MONSTER_BEHAVIOUR
]] = _lc
[I_PROP_TR_MONSTER_BEHAVIOUR_2
] then
4856 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_MONSTER_BEHAVIOUR
]] = _lc
[I_PROP_TR_MONSTER_BEHAVIOUR_3
] then
4858 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_MONSTER_BEHAVIOUR
]] = _lc
[I_PROP_TR_MONSTER_BEHAVIOUR_4
] then
4860 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_MONSTER_BEHAVIOUR
]] = _lc
[I_PROP_TR_MONSTER_BEHAVIOUR_5
] then
4866 Data
.ItemType
:= StrToItem(vleObjectProperty
.Values
[_lc
[I_PROP_TR_ITEM_TYPE
]]);
4867 Data
.ItemOnlyDM
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_DM_ONLY
]]);
4868 Data
.ItemFalls
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_ITEM_FALLS
]]);
4869 Data
.ItemCount
:= Min(StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_COUNT
]], 0), 64);
4870 if Data
.ItemCount
< 1 then
4871 Data
.ItemCount
:= 1;
4872 Data
.ItemEffect
:= StrToEffect(vleObjectProperty
.Values
[_lc
[I_PROP_TR_FX_TYPE
]]);
4873 Data
.ItemMax
:= Min(StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SPAWN_MAX
]], 0), 65535);
4874 Data
.ItemDelay
:= Min(StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SPAWN_DELAY
]], 0), 65535);
4879 s
:= utf2win(vleObjectProperty
.Values
[_lc
[I_PROP_TR_MUSIC_NAME
]]);
4880 FillByte(Data
.MusicName
[0], 64, 0);
4882 Move(s
[1], Data
.MusicName
[0], Min(Length(s
), 64));
4884 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_MUSIC_ACT
]] = _lc
[I_PROP_TR_MUSIC_ON
] then
4885 Data
.MusicAction
:= 1
4887 Data
.MusicAction
:= 2;
4892 Data
.PushAngle
:= Min(
4893 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_PUSH_ANGLE
]], 0), 360);
4894 Data
.PushForce
:= Min(
4895 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_PUSH_FORCE
]], 0), 255);
4896 Data
.ResetVel
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_PUSH_RESET
]]);
4901 Data
.ScoreAction
:= 0;
4902 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SCORE_ACT
]] = _lc
[I_PROP_TR_SCORE_ACT_1
] then
4903 Data
.ScoreAction
:= 1
4904 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SCORE_ACT
]] = _lc
[I_PROP_TR_SCORE_ACT_2
] then
4905 Data
.ScoreAction
:= 2
4906 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SCORE_ACT
]] = _lc
[I_PROP_TR_SCORE_ACT_3
] then
4907 Data
.ScoreAction
:= 3;
4908 Data
.ScoreCount
:= Min(Max(
4909 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_COUNT
]], 0), 0), 255);
4910 Data
.ScoreTeam
:= 0;
4911 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SCORE_TEAM
]] = _lc
[I_PROP_TR_SCORE_TEAM_1
] then
4913 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SCORE_TEAM
]] = _lc
[I_PROP_TR_SCORE_TEAM_2
] then
4915 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SCORE_TEAM
]] = _lc
[I_PROP_TR_SCORE_TEAM_3
] then
4916 Data
.ScoreTeam
:= 3;
4917 Data
.ScoreCon
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SCORE_CON
]]);
4918 Data
.ScoreMsg
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SCORE_MSG
]]);
4923 Data
.MessageKind
:= 0;
4924 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_MESSAGE_KIND
]] = _lc
[I_PROP_TR_MESSAGE_KIND_1
] then
4925 Data
.MessageKind
:= 1;
4927 Data
.MessageSendTo
:= 0;
4928 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_MESSAGE_TO
]] = _lc
[I_PROP_TR_MESSAGE_TO_1
] then
4929 Data
.MessageSendTo
:= 1
4930 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_MESSAGE_TO
]] = _lc
[I_PROP_TR_MESSAGE_TO_2
] then
4931 Data
.MessageSendTo
:= 2
4932 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_MESSAGE_TO
]] = _lc
[I_PROP_TR_MESSAGE_TO_3
] then
4933 Data
.MessageSendTo
:= 3
4934 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_MESSAGE_TO
]] = _lc
[I_PROP_TR_MESSAGE_TO_4
] then
4935 Data
.MessageSendTo
:= 4
4936 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_MESSAGE_TO
]] = _lc
[I_PROP_TR_MESSAGE_TO_5
] then
4937 Data
.MessageSendTo
:= 5;
4939 s
:= utf2win(vleObjectProperty
.Values
[_lc
[I_PROP_TR_MESSAGE_TEXT
]]);
4940 FillByte(Data
.MessageText
[0], 100, 0);
4942 Move(s
[1], Data
.MessageText
[0], Min(Length(s
), 100));
4944 Data
.MessageTime
:= Min(Max(
4945 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_MESSAGE_TIME
]], 0), 0), 65535);
4950 Data
.DamageValue
:= Min(Max(
4951 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_DAMAGE_VALUE
]], 0), 0), 65535);
4952 Data
.DamageInterval
:= Min(Max(
4953 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_INTERVAL
]], 0), 0), 65535);
4958 Data
.HealValue
:= Min(Max(
4959 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_HEALTH
]], 0), 0), 65535);
4960 Data
.HealInterval
:= Min(Max(
4961 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_INTERVAL
]], 0), 0), 65535);
4962 Data
.HealMax
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_HEALTH_MAX
]]);
4963 Data
.HealSilent
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SILENT
]]);
4968 Data
.ShotType
:= StrToShot(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_TYPE
]]);
4969 Data
.ShotSound
:= NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_SOUND
]]);
4970 Data
.ShotTarget
:= 0;
4971 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_TO
]] = _lc
[I_PROP_TR_SHOT_TO_1
] then
4972 Data
.ShotTarget
:= 1
4973 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_TO
]] = _lc
[I_PROP_TR_SHOT_TO_2
] then
4974 Data
.ShotTarget
:= 2
4975 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_TO
]] = _lc
[I_PROP_TR_SHOT_TO_3
] then
4976 Data
.ShotTarget
:= 3
4977 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_TO
]] = _lc
[I_PROP_TR_SHOT_TO_4
] then
4978 Data
.ShotTarget
:= 4
4979 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_TO
]] = _lc
[I_PROP_TR_SHOT_TO_5
] then
4980 Data
.ShotTarget
:= 5
4981 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_TO
]] = _lc
[I_PROP_TR_SHOT_TO_6
] then
4982 Data
.ShotTarget
:= 6;
4983 Data
.ShotIntSight
:= Min(Max(
4984 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_SIGHT
]], 0), 0), 65535);
4986 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_AIM
]] = _lc
[I_PROP_TR_SHOT_AIM_1
] then
4988 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_AIM
]] = _lc
[I_PROP_TR_SHOT_AIM_2
] then
4990 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_AIM
]] = _lc
[I_PROP_TR_SHOT_AIM_3
] then
4992 Data
.ShotAngle
:= Min(
4993 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_ANGLE
]], 0), 360);
4994 Data
.ShotWait
:= Min(Max(
4995 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EX_DELAY
]], 0), 0), 65535);
4996 Data
.ShotAccuracy
:= Min(Max(
4997 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_ACC
]], 0), 0), 65535);
4998 Data
.ShotAmmo
:= Min(Max(
4999 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_AMMO
]], 0), 0), 65535);
5000 Data
.ShotIntReload
:= Min(Max(
5001 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_SHOT_RELOAD
]], 0), 0), 65535);
5006 Data
.FXCount
:= Min(Max(
5007 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_COUNT
]], 0), 0), 255);
5008 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_TYPE
]] = _lc
[I_PROP_TR_EFFECT_PARTICLE
] then
5010 Data
.FXType
:= TRIGGER_EFFECT_PARTICLE
;
5011 Data
.FXSubType
:= TRIGGER_EFFECT_SLIQUID
;
5012 if vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_SUBTYPE
]] = _lc
[I_PROP_TR_EFFECT_SLIQUID
] then
5013 Data
.FXSubType
:= TRIGGER_EFFECT_SLIQUID
5014 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_SUBTYPE
]] = _lc
[I_PROP_TR_EFFECT_LLIQUID
] then
5015 Data
.FXSubType
:= TRIGGER_EFFECT_LLIQUID
5016 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_SUBTYPE
]] = _lc
[I_PROP_TR_EFFECT_DLIQUID
] then
5017 Data
.FXSubType
:= TRIGGER_EFFECT_DLIQUID
5018 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_SUBTYPE
]] = _lc
[I_PROP_TR_EFFECT_BLOOD
] then
5019 Data
.FXSubType
:= TRIGGER_EFFECT_BLOOD
5020 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_SUBTYPE
]] = _lc
[I_PROP_TR_EFFECT_SPARK
] then
5021 Data
.FXSubType
:= TRIGGER_EFFECT_SPARK
5022 else if vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_SUBTYPE
]] = _lc
[I_PROP_TR_EFFECT_BUBBLE
] then
5023 Data
.FXSubType
:= TRIGGER_EFFECT_BUBBLE
;
5026 Data
.FXType
:= TRIGGER_EFFECT_ANIMATION
;
5027 Data
.FXSubType
:= StrToEffect(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_SUBTYPE
]]);
5030 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_COLOR
]], 0), 0), $FFFFFF);
5031 Data
.FXColorR
:= a
and $FF;
5032 Data
.FXColorG
:= (a
shr 8) and $FF;
5033 Data
.FXColorB
:= (a
shr 16) and $FF;
5034 if NameToBool(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_CENTER
]]) then
5038 Data
.FXWait
:= Min(Max(
5039 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EX_DELAY
]], 0), 0), 65535);
5040 Data
.FXVelX
:= Min(Max(
5041 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_VELX
]], 0), -128), 127);
5042 Data
.FXVelY
:= Min(Max(
5043 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_VELY
]], 0), -128), 127);
5044 Data
.FXSpreadL
:= Min(Max(
5045 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_SPL
]], 0), 0), 255);
5046 Data
.FXSpreadR
:= Min(Max(
5047 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_SPR
]], 0), 0), 255);
5048 Data
.FXSpreadU
:= Min(Max(
5049 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_SPU
]], 0), 0), 255);
5050 Data
.FXSpreadD
:= Min(Max(
5051 StrToIntDef(vleObjectProperty
.Values
[_lc
[I_PROP_TR_EFFECT_SPD
]], 0), 0), 255);
5060 vleObjectProperty
.Row
:= r
;
5061 vleObjectProperty
.Col
:= c
;
5064 procedure TMainForm
.bbRemoveTextureClick(Sender
: TObject
);
5068 i
:= lbTextureList
.ItemIndex
;
5072 if MessageBox(0, PChar(Format(_lc
[I_MSG_DEL_TEXTURE_PROMT
],
5073 [SelectedTexture()])),
5074 PChar(_lc
[I_MSG_DEL_TEXTURE
]),
5075 MB_ICONQUESTION
or MB_YESNO
or
5076 MB_DEFBUTTON1
) <> idYes
then
5079 if gPanels
<> nil then
5080 for a
:= 0 to High(gPanels
) do
5081 if (gPanels
[a
].PanelType
<> 0) and
5082 (gPanels
[a
].TextureName
= SelectedTexture()) then
5084 ErrorMessageBox(_lc
[I_MSG_DEL_TEXTURE_CANT
]);
5088 g_DeleteTexture(SelectedTexture());
5089 i
:= slInvalidTextures
.IndexOf(lbTextureList
.Items
[i
]);
5091 slInvalidTextures
.Delete(i
);
5092 if lbTextureList
.ItemIndex
> -1 then
5093 lbTextureList
.Items
.Delete(lbTextureList
.ItemIndex
)
5096 procedure TMainForm
.aNewMapExecute(Sender
: TObject
);
5098 if (MessageBox(0, PChar(_lc
[I_MSG_CLEAR_MAP_PROMT
]),
5099 PChar(_lc
[I_MSG_CLEAR_MAP
]),
5100 MB_ICONQUESTION
or MB_YESNO
or
5101 MB_DEFBUTTON1
) = mrYes
) then
5105 procedure TMainForm
.aUndoExecute(Sender
: TObject
);
5109 if UndoBuffer
= nil then
5111 if UndoBuffer
[High(UndoBuffer
)] = nil then
5114 for a
:= 0 to High(UndoBuffer
[High(UndoBuffer
)]) do
5115 with UndoBuffer
[High(UndoBuffer
)][a
] do
5123 UNDO_DELETE_ITEM
: AddItem(Item
);
5124 UNDO_DELETE_AREA
: AddArea(Area
);
5125 UNDO_DELETE_MONSTER
: AddMonster(Monster
);
5126 UNDO_DELETE_TRIGGER
: AddTrigger(Trigger
);
5127 UNDO_ADD_PANEL
: RemoveObject(AddID
, OBJECT_PANEL
);
5128 UNDO_ADD_ITEM
: RemoveObject(AddID
, OBJECT_ITEM
);
5129 UNDO_ADD_AREA
: RemoveObject(AddID
, OBJECT_AREA
);
5130 UNDO_ADD_MONSTER
: RemoveObject(AddID
, OBJECT_MONSTER
);
5131 UNDO_ADD_TRIGGER
: RemoveObject(AddID
, OBJECT_TRIGGER
);
5135 SetLength(UndoBuffer
, Length(UndoBuffer
)-1);
5137 RemoveSelectFromObjects();
5139 miUndo
.Enabled
:= UndoBuffer
<> nil;
5143 procedure TMainForm
.aCopyObjectExecute(Sender
: TObject
);
5146 CopyBuffer
: TCopyRecArray
;
5150 function CB_Compare(I1
, I2
: TCopyRec
): Integer;
5152 Result
:= Integer(I1
.ObjectType
) - Integer(I2
.ObjectType
);
5154 if Result
= 0 then // Одного типа
5155 Result
:= Integer(I1
.ID
) - Integer(I2
.ID
);
5158 procedure QuickSortCopyBuffer(L
, R
: Integer);
5166 P
:= CopyBuffer
[(L
+ R
) shr 1];
5169 while CB_Compare(CopyBuffer
[I
], P
) < 0 do
5171 while CB_Compare(CopyBuffer
[J
], P
) > 0 do
5177 CopyBuffer
[I
] := CopyBuffer
[J
];
5185 QuickSortCopyBuffer(L
, J
);
5192 if SelectedObjects
= nil then
5198 // Копируем объекты:
5199 for a
:= 0 to High(SelectedObjects
) do
5200 if SelectedObjects
[a
].Live
then
5201 with SelectedObjects
[a
] do
5203 SetLength(CopyBuffer
, Length(CopyBuffer
)+1);
5204 b
:= High(CopyBuffer
);
5205 CopyBuffer
[b
].ID
:= ID
;
5206 CopyBuffer
[b
].Panel
:= nil;
5211 CopyBuffer
[b
].ObjectType
:= OBJECT_PANEL
;
5212 New(CopyBuffer
[b
].Panel
);
5213 CopyBuffer
[b
].Panel
^ := gPanels
[ID
];
5218 CopyBuffer
[b
].ObjectType
:= OBJECT_ITEM
;
5219 CopyBuffer
[b
].Item
:= gItems
[ID
];
5224 CopyBuffer
[b
].ObjectType
:= OBJECT_MONSTER
;
5225 CopyBuffer
[b
].Monster
:= gMonsters
[ID
];
5230 CopyBuffer
[b
].ObjectType
:= OBJECT_AREA
;
5231 CopyBuffer
[b
].Area
:= gAreas
[ID
];
5236 CopyBuffer
[b
].ObjectType
:= OBJECT_TRIGGER
;
5237 CopyBuffer
[b
].Trigger
:= gTriggers
[ID
];
5242 // Сортировка по ID:
5243 if CopyBuffer
<> nil then
5245 QuickSortCopyBuffer(0, b
);
5248 // Пестановка ссылок триггеров:
5249 for a
:= 0 to Length(CopyBuffer
)-1 do
5250 if CopyBuffer
[a
].ObjectType
= OBJECT_TRIGGER
then
5252 case CopyBuffer
[a
].Trigger
.TriggerType
of
5253 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
,
5254 TRIGGER_DOOR5
, TRIGGER_CLOSETRAP
, TRIGGER_TRAP
,
5255 TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
:
5256 if CopyBuffer
[a
].Trigger
.Data
.PanelID
<> -1 then
5260 for b
:= 0 to Length(CopyBuffer
)-1 do
5261 if (CopyBuffer
[b
].ObjectType
= OBJECT_PANEL
) and
5262 (Integer(CopyBuffer
[b
].ID
) = CopyBuffer
[a
].Trigger
.Data
.PanelID
) then
5264 CopyBuffer
[a
].Trigger
.Data
.PanelID
:= b
;
5269 // Этих панелей нет среди копируемых:
5271 CopyBuffer
[a
].Trigger
.Data
.PanelID
:= -1;
5274 TRIGGER_PRESS
, TRIGGER_ON
,
5275 TRIGGER_OFF
, TRIGGER_ONOFF
:
5276 if CopyBuffer
[a
].Trigger
.Data
.MonsterID
<> 0 then
5280 for b
:= 0 to Length(CopyBuffer
)-1 do
5281 if (CopyBuffer
[b
].ObjectType
= OBJECT_MONSTER
) and
5282 (Integer(CopyBuffer
[b
].ID
) = CopyBuffer
[a
].Trigger
.Data
.MonsterID
-1) then
5284 CopyBuffer
[a
].Trigger
.Data
.MonsterID
:= b
+1;
5289 // Этих монстров нет среди копируемых:
5291 CopyBuffer
[a
].Trigger
.Data
.MonsterID
:= 0;
5295 if CopyBuffer
[a
].Trigger
.Data
.ShotPanelID
<> -1 then
5299 for b
:= 0 to Length(CopyBuffer
)-1 do
5300 if (CopyBuffer
[b
].ObjectType
= OBJECT_PANEL
) and
5301 (Integer(CopyBuffer
[b
].ID
) = CopyBuffer
[a
].Trigger
.Data
.ShotPanelID
) then
5303 CopyBuffer
[a
].Trigger
.Data
.ShotPanelID
:= b
;
5308 // Этих панелей нет среди копируемых:
5310 CopyBuffer
[a
].Trigger
.Data
.ShotPanelID
:= -1;
5314 if CopyBuffer
[a
].Trigger
.TexturePanel
<> -1 then
5318 for b
:= 0 to Length(CopyBuffer
)-1 do
5319 if (CopyBuffer
[b
].ObjectType
= OBJECT_PANEL
) and
5320 (Integer(CopyBuffer
[b
].ID
) = CopyBuffer
[a
].Trigger
.TexturePanel
) then
5322 CopyBuffer
[a
].Trigger
.TexturePanel
:= b
;
5327 // Этих панелей нет среди копируемых:
5329 CopyBuffer
[a
].Trigger
.TexturePanel
:= -1;
5334 str
:= CopyBufferToString(CopyBuffer
);
5335 ClipBoard
.AsText
:= str
;
5337 for a
:= 0 to Length(CopyBuffer
)-1 do
5338 if (CopyBuffer
[a
].ObjectType
= OBJECT_PANEL
) and
5339 (CopyBuffer
[a
].Panel
<> nil) then
5340 Dispose(CopyBuffer
[a
].Panel
);
5345 procedure TMainForm
.aPasteObjectExecute(Sender
: TObject
);
5348 CopyBuffer
: TCopyRecArray
;
5350 swad
, ssec
, sres
: String;
5354 StringToCopyBuffer(ClipBoard
.AsText
, CopyBuffer
);
5356 if CopyBuffer
= nil then
5359 RemoveSelectFromObjects();
5361 h
:= High(CopyBuffer
);
5363 with CopyBuffer
[a
] do
5367 if Panel
<> nil then
5369 Panel
^.X
:= Panel
^.X
+ 16;
5370 Panel
^.Y
:= Panel
^.Y
+ 16;
5372 Panel
^.TextureID
:= TEXTURE_SPECIAL_NONE
;
5373 Panel
^.TextureWidth
:= 1;
5374 Panel
^.TextureHeight
:= 1;
5376 if (Panel
^.PanelType
= PANEL_LIFTUP
) or
5377 (Panel
^.PanelType
= PANEL_LIFTDOWN
) or
5378 (Panel
^.PanelType
= PANEL_LIFTLEFT
) or
5379 (Panel
^.PanelType
= PANEL_LIFTRIGHT
) or
5380 (Panel
^.PanelType
= PANEL_BLOCKMON
) or
5381 (Panel
^.TextureName
= '') then
5382 begin // Нет или не может быть текстуры:
5384 else // Есть текстура:
5386 // Обычная текстура:
5387 if not IsSpecialTexture(Panel
^.TextureName
) then
5389 res
:= g_GetTexture(Panel
^.TextureName
, Panel
^.TextureID
);
5393 g_ProcessResourceStr(Panel
^.TextureName
, swad
, ssec
, sres
);
5394 AddTexture(swad
, ssec
, sres
, True);
5395 res
:= g_GetTexture(Panel
^.TextureName
, Panel
^.TextureID
);
5399 g_GetTextureSizeByName(Panel
^.TextureName
,
5400 Panel
^.TextureWidth
, Panel
^.TextureHeight
)
5402 Panel
^.TextureName
:= '';
5404 else // Спец.текстура:
5406 Panel
^.TextureID
:= SpecialTextureID(Panel
^.TextureName
);
5407 with MainForm
.lbTextureList
.Items
do
5408 if IndexOf(Panel
^.TextureName
) = -1 then
5409 Add(Panel
^.TextureName
);
5413 ID
:= AddPanel(Panel
^);
5415 Undo_Add(OBJECT_PANEL
, ID
, a
> 0);
5416 SelectObject(OBJECT_PANEL
, ID
, True);
5421 Item
.X
:= Item
.X
+ 16;
5422 Item
.Y
:= Item
.Y
+ 16;
5424 ID
:= AddItem(Item
);
5425 Undo_Add(OBJECT_ITEM
, ID
, a
> 0);
5426 SelectObject(OBJECT_ITEM
, ID
, True);
5431 Monster
.X
:= Monster
.X
+ 16;
5432 Monster
.Y
:= Monster
.Y
+ 16;
5434 ID
:= AddMonster(Monster
);
5435 Undo_Add(OBJECT_MONSTER
, ID
, a
> 0);
5436 SelectObject(OBJECT_MONSTER
, ID
, True);
5441 Area
.X
:= Area
.X
+ 16;
5442 Area
.Y
:= Area
.Y
+ 16;
5444 ID
:= AddArea(Area
);
5445 Undo_Add(OBJECT_AREA
, ID
, a
> 0);
5446 SelectObject(OBJECT_AREA
, ID
, True);
5451 Trigger
.X
:= Trigger
.X
+ 16;
5452 Trigger
.Y
:= Trigger
.Y
+ 16;
5454 ID
:= AddTrigger(Trigger
);
5455 Undo_Add(OBJECT_TRIGGER
, ID
, a
> 0);
5456 SelectObject(OBJECT_TRIGGER
, ID
, True);
5461 // Переставляем ссылки триггеров:
5462 for a
:= 0 to High(CopyBuffer
) do
5463 if CopyBuffer
[a
].ObjectType
= OBJECT_TRIGGER
then
5465 case CopyBuffer
[a
].Trigger
.TriggerType
of
5466 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
,
5467 TRIGGER_DOOR5
, TRIGGER_CLOSETRAP
, TRIGGER_TRAP
,
5468 TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
:
5469 if CopyBuffer
[a
].Trigger
.Data
.PanelID
<> -1 then
5470 gTriggers
[CopyBuffer
[a
].ID
].Data
.PanelID
:=
5471 CopyBuffer
[CopyBuffer
[a
].Trigger
.Data
.PanelID
].ID
;
5473 TRIGGER_PRESS
, TRIGGER_ON
,
5474 TRIGGER_OFF
, TRIGGER_ONOFF
:
5475 if CopyBuffer
[a
].Trigger
.Data
.MonsterID
<> 0 then
5476 gTriggers
[CopyBuffer
[a
].ID
].Data
.MonsterID
:=
5477 CopyBuffer
[CopyBuffer
[a
].Trigger
.Data
.MonsterID
-1].ID
+1;
5480 if CopyBuffer
[a
].Trigger
.Data
.ShotPanelID
<> -1 then
5481 gTriggers
[CopyBuffer
[a
].ID
].Data
.ShotPanelID
:=
5482 CopyBuffer
[CopyBuffer
[a
].Trigger
.Data
.ShotPanelID
].ID
;
5485 if CopyBuffer
[a
].Trigger
.TexturePanel
<> -1 then
5486 gTriggers
[CopyBuffer
[a
].ID
].TexturePanel
:=
5487 CopyBuffer
[CopyBuffer
[a
].Trigger
.TexturePanel
].ID
;
5496 procedure TMainForm
.aCutObjectExecute(Sender
: TObject
);
5499 DeleteSelectedObjects();
5502 procedure TMainForm
.vleObjectPropertyEditButtonClick(Sender
: TObject
);
5504 Key
, FileName
: String;
5507 Key
:= vleObjectProperty
.Keys
[vleObjectProperty
.Row
];
5509 if Key
= _lc
[I_PROP_PANEL_TYPE
] then
5511 with ChooseTypeForm
, vleObjectProperty
do
5512 begin // Выбор типа панели:
5513 Caption
:= _lc
[I_PROP_PANEL_TYPE
];
5514 lbTypeSelect
.Items
.Clear();
5516 for b
:= 0 to High(PANELNAMES
) do
5518 lbTypeSelect
.Items
.Add(PANELNAMES
[b
]);
5519 if Values
[Key
] = PANELNAMES
[b
] then
5520 lbTypeSelect
.ItemIndex
:= b
;
5523 if ShowModal() = mrOK
then
5525 b
:= lbTypeSelect
.ItemIndex
;
5526 Values
[Key
] := PANELNAMES
[b
];
5527 vleObjectPropertyApply(Sender
);
5531 else if Key
= _lc
[I_PROP_TR_TELEPORT_TO
] then
5532 SelectFlag
:= SELECTFLAG_TELEPORT
5533 else if Key
= _lc
[I_PROP_TR_SPAWN_TO
] then
5534 SelectFlag
:= SELECTFLAG_SPAWNPOINT
5535 else if (Key
= _lc
[I_PROP_TR_DOOR_PANEL
]) or
5536 (Key
= _lc
[I_PROP_TR_TRAP_PANEL
]) then
5537 SelectFlag
:= SELECTFLAG_DOOR
5538 else if Key
= _lc
[I_PROP_TR_TEXTURE_PANEL
] then
5540 DrawPressRect
:= False;
5541 SelectFlag
:= SELECTFLAG_TEXTURE
;
5543 else if Key
= _lc
[I_PROP_TR_SHOT_PANEL
] then
5544 SelectFlag
:= SELECTFLAG_SHOTPANEL
5545 else if Key
= _lc
[I_PROP_TR_LIFT_PANEL
] then
5546 SelectFlag
:= SELECTFLAG_LIFT
5547 else if key
= _lc
[I_PROP_TR_EX_MONSTER
] then
5548 SelectFlag
:= SELECTFLAG_MONSTER
5549 else if Key
= _lc
[I_PROP_TR_EX_AREA
] then
5551 SelectFlag
:= SELECTFLAG_NONE
;
5552 DrawPressRect
:= True;
5554 else if Key
= _lc
[I_PROP_TR_NEXT_MAP
] then
5555 begin // Выбор следующей карты:
5556 g_ProcessResourceStr(OpenedMap
, @FileName
, nil, nil);
5557 SelectMapForm
.Caption
:= _lc
[I_CAP_SELECT
];
5558 SelectMapForm
.GetMaps(FileName
);
5560 if SelectMapForm
.ShowModal() = mrOK
then
5562 vleObjectProperty
.Values
[Key
] := SelectMapForm
.lbMapList
.Items
[SelectMapForm
.lbMapList
.ItemIndex
];
5563 vleObjectPropertyApply(Sender
);
5566 else if (Key
= _lc
[I_PROP_TR_SOUND_NAME
]) or
5567 (Key
= _lc
[I_PROP_TR_MUSIC_NAME
]) then
5568 begin // Выбор файла звука/музыки:
5569 AddSoundForm
.OKFunction
:= nil;
5570 AddSoundForm
.lbResourcesList
.MultiSelect
:= False;
5571 AddSoundForm
.SetResource
:= vleObjectProperty
.Values
[Key
];
5573 if (AddSoundForm
.ShowModal() = mrOk
) then
5575 vleObjectProperty
.Values
[Key
] := AddSoundForm
.ResourceName
;
5576 vleObjectPropertyApply(Sender
);
5579 else if Key
= _lc
[I_PROP_TR_ACTIVATION
] then
5580 with ActivationTypeForm
, vleObjectProperty
do
5581 begin // Выбор типов активации:
5582 cbPlayerCollide
.Checked
:= Pos('PC', Values
[Key
]) > 0;
5583 cbMonsterCollide
.Checked
:= Pos('MC', Values
[Key
]) > 0;
5584 cbPlayerPress
.Checked
:= Pos('PP', Values
[Key
]) > 0;
5585 cbMonsterPress
.Checked
:= Pos('MP', Values
[Key
]) > 0;
5586 cbShot
.Checked
:= Pos('SH', Values
[Key
]) > 0;
5587 cbNoMonster
.Checked
:= Pos('NM', Values
[Key
]) > 0;
5589 if ShowModal() = mrOK
then
5592 if cbPlayerCollide
.Checked
then
5593 b
:= ACTIVATE_PLAYERCOLLIDE
;
5594 if cbMonsterCollide
.Checked
then
5595 b
:= b
or ACTIVATE_MONSTERCOLLIDE
;
5596 if cbPlayerPress
.Checked
then
5597 b
:= b
or ACTIVATE_PLAYERPRESS
;
5598 if cbMonsterPress
.Checked
then
5599 b
:= b
or ACTIVATE_MONSTERPRESS
;
5600 if cbShot
.Checked
then
5601 b
:= b
or ACTIVATE_SHOT
;
5602 if cbNoMonster
.Checked
then
5603 b
:= b
or ACTIVATE_NOMONSTER
;
5605 Values
[Key
] := ActivateToStr(b
);
5606 vleObjectPropertyApply(Sender
);
5609 else if Key
= _lc
[I_PROP_TR_KEYS
] then
5610 with KeysForm
, vleObjectProperty
do
5611 begin // Выбор необходимых ключей:
5612 cbRedKey
.Checked
:= Pos('RK', Values
[Key
]) > 0;
5613 cbGreenKey
.Checked
:= Pos('GK', Values
[Key
]) > 0;
5614 cbBlueKey
.Checked
:= Pos('BK', Values
[Key
]) > 0;
5615 cbRedTeam
.Checked
:= Pos('RT', Values
[Key
]) > 0;
5616 cbBlueTeam
.Checked
:= Pos('BT', Values
[Key
]) > 0;
5618 if ShowModal() = mrOK
then
5621 if cbRedKey
.Checked
then
5623 if cbGreenKey
.Checked
then
5624 b
:= b
or KEY_GREEN
;
5625 if cbBlueKey
.Checked
then
5627 if cbRedTeam
.Checked
then
5628 b
:= b
or KEY_REDTEAM
;
5629 if cbBlueTeam
.Checked
then
5630 b
:= b
or KEY_BLUETEAM
;
5632 Values
[Key
] := KeyToStr(b
);
5633 vleObjectPropertyApply(Sender
);
5636 else if Key
= _lc
[I_PROP_TR_FX_TYPE
] then
5637 with ChooseTypeForm
, vleObjectProperty
do
5638 begin // Выбор типа эффекта:
5639 Caption
:= _lc
[I_CAP_FX_TYPE
];
5640 lbTypeSelect
.Items
.Clear();
5642 for b
:= EFFECT_NONE
to EFFECT_FIRE
do
5643 lbTypeSelect
.Items
.Add(EffectToStr(b
));
5645 lbTypeSelect
.ItemIndex
:= StrToEffect(Values
[Key
]);
5647 if ShowModal() = mrOK
then
5649 b
:= lbTypeSelect
.ItemIndex
;
5650 Values
[Key
] := EffectToStr(b
);
5651 vleObjectPropertyApply(Sender
);
5654 else if Key
= _lc
[I_PROP_TR_MONSTER_TYPE
] then
5655 with ChooseTypeForm
, vleObjectProperty
do
5656 begin // Выбор типа монстра:
5657 Caption
:= _lc
[I_CAP_MONSTER_TYPE
];
5658 lbTypeSelect
.Items
.Clear();
5660 for b
:= MONSTER_DEMON
to MONSTER_MAN
do
5661 lbTypeSelect
.Items
.Add(MonsterToStr(b
));
5663 lbTypeSelect
.ItemIndex
:= StrToMonster(Values
[Key
]) - MONSTER_DEMON
;
5665 if ShowModal() = mrOK
then
5667 b
:= lbTypeSelect
.ItemIndex
+ MONSTER_DEMON
;
5668 Values
[Key
] := MonsterToStr(b
);
5669 vleObjectPropertyApply(Sender
);
5672 else if Key
= _lc
[I_PROP_TR_ITEM_TYPE
] then
5673 with ChooseTypeForm
, vleObjectProperty
do
5674 begin // Выбор типа предмета:
5675 Caption
:= _lc
[I_CAP_ITEM_TYPE
];
5676 lbTypeSelect
.Items
.Clear();
5678 for b
:= ITEM_MEDKIT_SMALL
to ITEM_KEY_BLUE
do
5679 lbTypeSelect
.Items
.Add(ItemToStr(b
));
5680 lbTypeSelect
.Items
.Add(ItemToStr(ITEM_BOTTLE
));
5681 lbTypeSelect
.Items
.Add(ItemToStr(ITEM_HELMET
));
5682 lbTypeSelect
.Items
.Add(ItemToStr(ITEM_JETPACK
));
5683 lbTypeSelect
.Items
.Add(ItemToStr(ITEM_INVIS
));
5684 lbTypeSelect
.Items
.Add(ItemToStr(ITEM_WEAPON_FLAMETHROWER
));
5685 lbTypeSelect
.Items
.Add(ItemToStr(ITEM_AMMO_FUELCAN
));
5687 b
:= StrToItem(Values
[Key
]);
5688 if b
>= ITEM_BOTTLE
then
5690 lbTypeSelect
.ItemIndex
:= b
- ITEM_MEDKIT_SMALL
;
5692 if ShowModal() = mrOK
then
5694 b
:= lbTypeSelect
.ItemIndex
+ ITEM_MEDKIT_SMALL
;
5695 if b
>= ITEM_WEAPON_KASTET
then
5697 Values
[Key
] := ItemToStr(b
);
5698 vleObjectPropertyApply(Sender
);
5701 else if Key
= _lc
[I_PROP_TR_SHOT_TYPE
] then
5702 with ChooseTypeForm
, vleObjectProperty
do
5703 begin // Выбор типа предмета:
5704 Caption
:= _lc
[I_PROP_TR_SHOT_TYPE
];
5705 lbTypeSelect
.Items
.Clear();
5707 for b
:= TRIGGER_SHOT_PISTOL
to TRIGGER_SHOT_MAX
do
5708 lbTypeSelect
.Items
.Add(ShotToStr(b
));
5710 lbTypeSelect
.ItemIndex
:= StrToShot(Values
[Key
]);
5712 if ShowModal() = mrOK
then
5714 b
:= lbTypeSelect
.ItemIndex
;
5715 Values
[Key
] := ShotToStr(b
);
5716 vleObjectPropertyApply(Sender
);
5719 else if Key
= _lc
[I_PROP_TR_EFFECT_TYPE
] then
5720 with ChooseTypeForm
, vleObjectProperty
do
5721 begin // Выбор типа эффекта:
5722 Caption
:= _lc
[I_CAP_FX_TYPE
];
5723 lbTypeSelect
.Items
.Clear();
5725 lbTypeSelect
.Items
.Add(_lc
[I_PROP_TR_EFFECT_PARTICLE
]);
5726 lbTypeSelect
.Items
.Add(_lc
[I_PROP_TR_EFFECT_ANIMATION
]);
5727 if Values
[Key
] = _lc
[I_PROP_TR_EFFECT_ANIMATION
] then
5728 lbTypeSelect
.ItemIndex
:= 1
5730 lbTypeSelect
.ItemIndex
:= 0;
5732 if ShowModal() = mrOK
then
5734 b
:= lbTypeSelect
.ItemIndex
;
5736 Values
[Key
] := _lc
[I_PROP_TR_EFFECT_PARTICLE
]
5738 Values
[Key
] := _lc
[I_PROP_TR_EFFECT_ANIMATION
];
5739 vleObjectPropertyApply(Sender
);
5742 else if Key
= _lc
[I_PROP_TR_EFFECT_SUBTYPE
] then
5743 with ChooseTypeForm
, vleObjectProperty
do
5744 begin // Выбор подтипа эффекта:
5745 Caption
:= _lc
[I_CAP_FX_TYPE
];
5746 lbTypeSelect
.Items
.Clear();
5748 if Values
[_lc
[I_PROP_TR_EFFECT_TYPE
]] = _lc
[I_PROP_TR_EFFECT_ANIMATION
] then
5750 for b
:= EFFECT_TELEPORT
to EFFECT_FIRE
do
5751 lbTypeSelect
.Items
.Add(EffectToStr(b
));
5753 lbTypeSelect
.ItemIndex
:= StrToEffect(Values
[Key
]) - 1;
5756 lbTypeSelect
.Items
.Add(_lc
[I_PROP_TR_EFFECT_SLIQUID
]);
5757 lbTypeSelect
.Items
.Add(_lc
[I_PROP_TR_EFFECT_LLIQUID
]);
5758 lbTypeSelect
.Items
.Add(_lc
[I_PROP_TR_EFFECT_DLIQUID
]);
5759 lbTypeSelect
.Items
.Add(_lc
[I_PROP_TR_EFFECT_BLOOD
]);
5760 lbTypeSelect
.Items
.Add(_lc
[I_PROP_TR_EFFECT_SPARK
]);
5761 lbTypeSelect
.Items
.Add(_lc
[I_PROP_TR_EFFECT_BUBBLE
]);
5762 lbTypeSelect
.ItemIndex
:= TRIGGER_EFFECT_SLIQUID
;
5763 if Values
[Key
] = _lc
[I_PROP_TR_EFFECT_LLIQUID
] then
5764 lbTypeSelect
.ItemIndex
:= TRIGGER_EFFECT_LLIQUID
;
5765 if Values
[Key
] = _lc
[I_PROP_TR_EFFECT_DLIQUID
] then
5766 lbTypeSelect
.ItemIndex
:= TRIGGER_EFFECT_DLIQUID
;
5767 if Values
[Key
] = _lc
[I_PROP_TR_EFFECT_BLOOD
] then
5768 lbTypeSelect
.ItemIndex
:= TRIGGER_EFFECT_BLOOD
;
5769 if Values
[Key
] = _lc
[I_PROP_TR_EFFECT_SPARK
] then
5770 lbTypeSelect
.ItemIndex
:= TRIGGER_EFFECT_SPARK
;
5771 if Values
[Key
] = _lc
[I_PROP_TR_EFFECT_BUBBLE
] then
5772 lbTypeSelect
.ItemIndex
:= TRIGGER_EFFECT_BUBBLE
;
5775 if ShowModal() = mrOK
then
5777 b
:= lbTypeSelect
.ItemIndex
;
5779 if Values
[_lc
[I_PROP_TR_EFFECT_TYPE
]] = _lc
[I_PROP_TR_EFFECT_ANIMATION
] then
5780 Values
[Key
] := EffectToStr(b
+ 1)
5782 Values
[Key
] := _lc
[I_PROP_TR_EFFECT_SLIQUID
];
5783 if b
= TRIGGER_EFFECT_LLIQUID
then
5784 Values
[Key
] := _lc
[I_PROP_TR_EFFECT_LLIQUID
];
5785 if b
= TRIGGER_EFFECT_DLIQUID
then
5786 Values
[Key
] := _lc
[I_PROP_TR_EFFECT_DLIQUID
];
5787 if b
= TRIGGER_EFFECT_BLOOD
then
5788 Values
[Key
] := _lc
[I_PROP_TR_EFFECT_BLOOD
];
5789 if b
= TRIGGER_EFFECT_SPARK
then
5790 Values
[Key
] := _lc
[I_PROP_TR_EFFECT_SPARK
];
5791 if b
= TRIGGER_EFFECT_BUBBLE
then
5792 Values
[Key
] := _lc
[I_PROP_TR_EFFECT_BUBBLE
];
5795 vleObjectPropertyApply(Sender
);
5798 else if Key
= _lc
[I_PROP_TR_EFFECT_COLOR
] then
5799 with vleObjectProperty
do
5800 begin // Выбор цвета эффекта:
5801 ColorDialog
.Color
:= StrToIntDef(Values
[Key
], 0);
5802 if ColorDialog
.Execute
then
5804 Values
[Key
] := IntToStr(ColorDialog
.Color
);
5805 vleObjectPropertyApply(Sender
);
5808 else if Key
= _lc
[I_PROP_PANEL_TEX
] then
5809 begin // Смена текстуры:
5810 vleObjectProperty
.Values
[Key
] := SelectedTexture();
5811 vleObjectPropertyApply(Sender
);
5815 procedure TMainForm
.vleObjectPropertyApply(Sender
: TObject
);
5817 // hack to prevent empty ID in list
5818 RenderPanel
.SetFocus();
5819 bApplyProperty
.Click();
5820 vleObjectProperty
.SetFocus();
5823 procedure TMainForm
.aSaveMapExecute(Sender
: TObject
);
5825 FileName
, Section
, Res
: String;
5827 if OpenedMap
= '' then
5829 aSaveMapAsExecute(nil);
5833 g_ProcessResourceStr(OpenedMap
, FileName
, Section
, Res
);
5835 SaveMap(FileName
+':\'+Res
);
5838 procedure TMainForm
.aOpenMapExecute(Sender
: TObject
);
5840 OpenDialog
.Filter
:= _lc
[I_FILE_FILTER_ALL
];
5842 if OpenDialog
.Execute() then
5844 if (Pos('.ini', LowerCase(ExtractFileName(OpenDialog
.FileName
))) > 0) then
5848 pLoadProgress
.Left
:= (RenderPanel
.Width
div 2)-(pLoadProgress
.Width
div 2);
5849 pLoadProgress
.Top
:= (RenderPanel
.Height
div 2)-(pLoadProgress
.Height
div 2);
5850 pLoadProgress
.Show();
5855 LoadMapOld(OpenDialog
.FileName
);
5857 MainForm
.Caption
:= Format('%s - %s', [FormCaption
, ExtractFileName(OpenDialog
.FileName
)]);
5859 pLoadProgress
.Hide();
5860 MainForm
.FormResize(Self
);
5862 else // Карты из WAD:
5864 OpenMap(OpenDialog
.FileName
, '');
5867 OpenDialog
.InitialDir
:= ExtractFileDir(OpenDialog
.FileName
);
5871 procedure TMainForm
.FormActivate(Sender
: TObject
);
5876 MainForm
.ActiveControl
:= RenderPanel
;
5879 if gLanguage
= '' then
5881 lang
:= SelectLanguageForm
.ShowModal();
5883 1: gLanguage
:= LANGUAGE_ENGLISH
;
5884 else gLanguage
:= LANGUAGE_RUSSIAN
;
5887 config
:= TConfig
.CreateFile(EditorDir
+'Editor.cfg');
5888 config
.WriteStr('Editor', 'Language', gLanguage
);
5889 config
.SaveFile(EditorDir
+'Editor.cfg');
5893 //e_WriteLog('Read language file', MSG_NOTIFY);
5894 //g_Language_Load(EditorDir+'\data\'+gLanguage+LANGUAGE_FILE_NAME);
5895 g_Language_Set(gLanguage
);
5898 procedure TMainForm
.aDeleteMap(Sender
: TObject
);
5906 OpenDialog
.Filter
:= _lc
[I_FILE_FILTER_WAD
];
5908 if not OpenDialog
.Execute() then
5911 WAD
:= TWADEditor_1
.Create();
5913 if not WAD
.ReadFile(OpenDialog
.FileName
) then
5921 MapList
:= WAD
.GetResourcesList('');
5923 SelectMapForm
.Caption
:= _lc
[I_CAP_REMOVE
];
5924 SelectMapForm
.lbMapList
.Items
.Clear();
5926 if MapList
<> nil then
5927 for a
:= 0 to High(MapList
) do
5928 SelectMapForm
.lbMapList
.Items
.Add(win2utf(MapList
[a
]));
5930 if (SelectMapForm
.ShowModal() = mrOK
) then
5932 str
:= SelectMapForm
.lbMapList
.Items
[SelectMapForm
.lbMapList
.ItemIndex
];
5934 Move(str
[1], MapName
[0], Min(16, Length(str
)));
5936 if MessageBox(0, PChar(Format(_lc
[I_MSG_DELETE_MAP_PROMT
],
5937 [MapName
, OpenDialog
.FileName
])),
5938 PChar(_lc
[I_MSG_DELETE_MAP
]),
5939 MB_ICONQUESTION
or MB_YESNO
or
5940 MB_DEFBUTTON2
) <> mrYes
then
5943 WAD
.RemoveResource('', utf2win(MapName
));
5945 MessageBox(0, PChar(Format(_lc
[I_MSG_MAP_DELETED_PROMT
],
5947 PChar(_lc
[I_MSG_MAP_DELETED
]),
5948 MB_ICONINFORMATION
or MB_OK
or
5951 WAD
.SaveTo(OpenDialog
.FileName
);
5953 // Удалили текущую карту - сохранять по старому ее нельзя:
5954 if OpenedMap
= (OpenDialog
.FileName
+':\'+MapName
) then
5958 MainForm
.Caption
:= FormCaption
;
5965 procedure TMainForm
.vleObjectPropertyKeyDown(Sender
: TObject
;
5966 var Key
: Word; Shift
: TShiftState
);
5968 if Key
= VK_RETURN
then
5969 vleObjectPropertyApply(Sender
);
5972 procedure MovePanel(var ID
: DWORD
; MoveType
: Byte);
5977 if (ID
= 0) and (MoveType
= 0) then
5979 if (ID
= DWORD(High(gPanels
))) and (MoveType
<> 0) then
5981 if (ID
> DWORD(High(gPanels
))) then
5986 if MoveType
= 0 then // to Back
5988 if gTriggers
<> nil then
5989 for a
:= 0 to High(gTriggers
) do
5990 with gTriggers
[a
] do
5992 if TriggerType
= TRIGGER_NONE
then
5995 if TexturePanel
= _id
then
5998 if (TexturePanel
>= 0) and (TexturePanel
< _id
) then
6002 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
,
6003 TRIGGER_DOOR5
, TRIGGER_CLOSETRAP
, TRIGGER_TRAP
,
6004 TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
:
6005 if Data
.PanelID
= _id
then
6008 if (Data
.PanelID
>= 0) and (Data
.PanelID
< _id
) then
6012 if Data
.ShotPanelID
= _id
then
6013 Data
.ShotPanelID
:= 0
6015 if (Data
.ShotPanelID
>= 0) and (Data
.ShotPanelID
< _id
) then
6016 Inc(Data
.ShotPanelID
);
6020 tmp
:= gPanels
[_id
];
6022 for a
:= _id
downto 1 do
6023 gPanels
[a
] := gPanels
[a
-1];
6031 if gTriggers
<> nil then
6032 for a
:= 0 to High(gTriggers
) do
6033 with gTriggers
[a
] do
6035 if TriggerType
= TRIGGER_NONE
then
6038 if TexturePanel
= _id
then
6039 TexturePanel
:= High(gPanels
)
6041 if TexturePanel
> _id
then
6045 TRIGGER_OPENDOOR
, TRIGGER_CLOSEDOOR
, TRIGGER_DOOR
,
6046 TRIGGER_DOOR5
, TRIGGER_CLOSETRAP
, TRIGGER_TRAP
,
6047 TRIGGER_LIFTUP
, TRIGGER_LIFTDOWN
, TRIGGER_LIFT
:
6048 if Data
.PanelID
= _id
then
6049 Data
.PanelID
:= High(gPanels
)
6051 if Data
.PanelID
> _id
then
6055 if Data
.ShotPanelID
= _id
then
6056 Data
.ShotPanelID
:= High(gPanels
)
6058 if Data
.ShotPanelID
> _id
then
6059 Dec(Data
.ShotPanelID
);
6063 tmp
:= gPanels
[_id
];
6065 for a
:= _id
to High(gPanels
)-1 do
6066 gPanels
[a
] := gPanels
[a
+1];
6068 gPanels
[High(gPanels
)] := tmp
;
6070 ID
:= High(gPanels
);
6074 procedure TMainForm
.aMoveToBack(Sender
: TObject
);
6078 if SelectedObjects
= nil then
6081 for a
:= 0 to High(SelectedObjects
) do
6082 with SelectedObjects
[a
] do
6083 if Live
and (ObjectType
= OBJECT_PANEL
) then
6085 SelectedObjects
[0] := SelectedObjects
[a
];
6086 SetLength(SelectedObjects
, 1);
6093 procedure TMainForm
.aMoveToFore(Sender
: TObject
);
6097 if SelectedObjects
= nil then
6100 for a
:= 0 to High(SelectedObjects
) do
6101 with SelectedObjects
[a
] do
6102 if Live
and (ObjectType
= OBJECT_PANEL
) then
6104 SelectedObjects
[0] := SelectedObjects
[a
];
6105 SetLength(SelectedObjects
, 1);
6112 procedure TMainForm
.aSaveMapAsExecute(Sender
: TObject
);
6116 SaveDialog
.Filter
:= _lc
[I_FILE_FILTER_WAD
];
6118 if not SaveDialog
.Execute() then
6121 SaveMapForm
.GetMaps(SaveDialog
.FileName
, True);
6123 if SaveMapForm
.ShowModal() <> mrOK
then
6126 SaveDialog
.InitialDir
:= ExtractFileDir(SaveDialog
.FileName
);
6127 OpenedMap
:= SaveDialog
.FileName
+':\'+SaveMapForm
.eMapName
.Text;
6128 OpenedWAD
:= SaveDialog
.FileName
;
6130 idx
:= RecentFiles
.IndexOf(OpenedMap
);
6131 // Такая карта уже недавно открывалась:
6133 RecentFiles
.Delete(idx
);
6134 RecentFiles
.Insert(0, OpenedMap
);
6139 gMapInfo
.FileName
:= SaveDialog
.FileName
;
6140 gMapInfo
.MapName
:= SaveMapForm
.eMapName
.Text;
6141 UpdateCaption(gMapInfo
.Name
, ExtractFileName(gMapInfo
.FileName
), gMapInfo
.MapName
);
6144 procedure TMainForm
.aSelectAllExecute(Sender
: TObject
);
6148 RemoveSelectFromObjects();
6150 case pcObjects
.ActivePageIndex
+1 of
6152 if gPanels
<> nil then
6153 for a
:= 0 to High(gPanels
) do
6154 if gPanels
[a
].PanelType
<> PANEL_NONE
then
6155 SelectObject(OBJECT_PANEL
, a
, True);
6157 if gItems
<> nil then
6158 for a
:= 0 to High(gItems
) do
6159 if gItems
[a
].ItemType
<> ITEM_NONE
then
6160 SelectObject(OBJECT_ITEM
, a
, True);
6162 if gMonsters
<> nil then
6163 for a
:= 0 to High(gMonsters
) do
6164 if gMonsters
[a
].MonsterType
<> MONSTER_NONE
then
6165 SelectObject(OBJECT_MONSTER
, a
, True);
6167 if gAreas
<> nil then
6168 for a
:= 0 to High(gAreas
) do
6169 if gAreas
[a
].AreaType
<> AREA_NONE
then
6170 SelectObject(OBJECT_AREA
, a
, True);
6172 if gTriggers
<> nil then
6173 for a
:= 0 to High(gTriggers
) do
6174 if gTriggers
[a
].TriggerType
<> TRIGGER_NONE
then
6175 SelectObject(OBJECT_TRIGGER
, a
, True);
6179 procedure TMainForm
.tbGridOnClick(Sender
: TObject
);
6181 DotEnable
:= not DotEnable
;
6182 (Sender
as TToolButton
).Down
:= DotEnable
;
6185 procedure TMainForm
.OnIdle(Sender
: TObject
; var Done
: Boolean);
6187 // FIXME: this is a shitty hack
6188 if not gDataLoaded
then
6190 e_WriteLog('Init OpenGL', MSG_NOTIFY
);
6192 e_WriteLog('Loading data', MSG_NOTIFY
);
6193 LoadStdFont('STDTXT', 'STDFONT', gEditorFont
);
6194 e_WriteLog('Loading more data', MSG_NOTIFY
);
6196 e_WriteLog('Loading even more data', MSG_NOTIFY
);
6197 gDataLoaded
:= True;
6198 MainForm
.FormResize(nil);
6203 procedure TMainForm
.miMapPreviewClick(Sender
: TObject
);
6205 if PreviewMode
= 2 then
6208 if PreviewMode
= 0 then
6210 Splitter2
.Visible
:= False;
6211 Splitter1
.Visible
:= False;
6212 StatusBar
.Visible
:= False;
6213 PanelObjs
.Visible
:= False;
6214 PanelProps
.Visible
:= False;
6215 MainToolBar
.Visible
:= False;
6216 sbHorizontal
.Visible
:= False;
6217 sbVertical
.Visible
:= False;
6221 StatusBar
.Visible
:= True;
6222 PanelObjs
.Visible
:= True;
6223 PanelProps
.Visible
:= True;
6224 Splitter2
.Visible
:= True;
6225 Splitter1
.Visible
:= True;
6226 MainToolBar
.Visible
:= True;
6227 sbHorizontal
.Visible
:= True;
6228 sbVertical
.Visible
:= True;
6231 PreviewMode
:= PreviewMode
xor 1;
6232 (Sender
as TMenuItem
).Checked
:= PreviewMode
> 0;
6237 procedure TMainForm
.miLayer1Click(Sender
: TObject
);
6239 SwitchLayer(LAYER_BACK
);
6242 procedure TMainForm
.miLayer2Click(Sender
: TObject
);
6244 SwitchLayer(LAYER_WALLS
);
6247 procedure TMainForm
.miLayer3Click(Sender
: TObject
);
6249 SwitchLayer(LAYER_FOREGROUND
);
6252 procedure TMainForm
.miLayer4Click(Sender
: TObject
);
6254 SwitchLayer(LAYER_STEPS
);
6257 procedure TMainForm
.miLayer5Click(Sender
: TObject
);
6259 SwitchLayer(LAYER_WATER
);
6262 procedure TMainForm
.miLayer6Click(Sender
: TObject
);
6264 SwitchLayer(LAYER_ITEMS
);
6267 procedure TMainForm
.miLayer7Click(Sender
: TObject
);
6269 SwitchLayer(LAYER_MONSTERS
);
6272 procedure TMainForm
.miLayer8Click(Sender
: TObject
);
6274 SwitchLayer(LAYER_AREAS
);
6277 procedure TMainForm
.miLayer9Click(Sender
: TObject
);
6279 SwitchLayer(LAYER_TRIGGERS
);
6282 procedure TMainForm
.tbShowClick(Sender
: TObject
);
6288 for a
:= 0 to High(LayerEnabled
) do
6289 b
:= b
and LayerEnabled
[a
];
6293 ShowLayer(LAYER_BACK
, b
);
6294 ShowLayer(LAYER_WALLS
, b
);
6295 ShowLayer(LAYER_FOREGROUND
, b
);
6296 ShowLayer(LAYER_STEPS
, b
);
6297 ShowLayer(LAYER_WATER
, b
);
6298 ShowLayer(LAYER_ITEMS
, b
);
6299 ShowLayer(LAYER_MONSTERS
, b
);
6300 ShowLayer(LAYER_AREAS
, b
);
6301 ShowLayer(LAYER_TRIGGERS
, b
);
6304 procedure TMainForm
.miMiniMapClick(Sender
: TObject
);
6309 procedure TMainForm
.miSwitchGridClick(Sender
: TObject
);
6311 if DotStep
= DotStepOne
then
6312 DotStep
:= DotStepTwo
6314 DotStep
:= DotStepOne
;
6316 MousePos
.X
:= (MousePos
.X
div DotStep
) * DotStep
;
6317 MousePos
.Y
:= (MousePos
.Y
div DotStep
) * DotStep
;
6320 procedure TMainForm
.miShowEdgesClick(Sender
: TObject
);
6325 procedure TMainForm
.miSnapToGridClick(Sender
: TObject
);
6327 SnapToGrid
:= not SnapToGrid
;
6329 MousePos
.X
:= (MousePos
.X
div DotStep
) * DotStep
;
6330 MousePos
.Y
:= (MousePos
.Y
div DotStep
) * DotStep
;
6332 miSnapToGrid
.Checked
:= SnapToGrid
;
6335 procedure TMainForm
.minexttabClick(Sender
: TObject
);
6337 if pcObjects
.ActivePageIndex
< pcObjects
.PageCount
-1 then
6338 pcObjects
.ActivePageIndex
:= pcObjects
.ActivePageIndex
+1
6340 pcObjects
.ActivePageIndex
:= 0;
6343 procedure TMainForm
.miSaveMiniMapClick(Sender
: TObject
);
6345 SaveMiniMapForm
.ShowModal();
6348 procedure TMainForm
.bClearTextureClick(Sender
: TObject
);
6350 lbTextureList
.ItemIndex
:= -1;
6351 lTextureWidth
.Caption
:= '';
6352 lTextureHeight
.Caption
:= '';
6355 procedure TMainForm
.miPackMapClick(Sender
: TObject
);
6357 PackMapForm
.ShowModal();
6360 procedure TMainForm
.miMapTestSettingsClick(Sender
: TObject
);
6362 MapTestForm
.ShowModal();
6365 procedure TMainForm
.miTestMapClick(Sender
: TObject
);
6367 cmd
, mapWAD
, mapToRun
, tempWAD
: String;
6374 if OpenedMap
<> '' then
6376 // Указываем текущую карту для теста:
6377 g_ProcessResourceStr(OpenedMap
, @mapWAD
, nil, @mapToRun
);
6378 mapToRun
:= mapWAD
+ ':\' + mapToRun
;
6379 mapToRun
:= ExtractRelativePath(ExtractFilePath(TestD2dExe
) + 'maps/', mapToRun
);
6381 // Сохраняем временную карту:
6384 mapWAD
:= ExtractFilePath(TestD2dExe
) + Format('maps/temp%.4d.wad', [time
]);
6386 until not FileExists(mapWAD
);
6387 tempWAD
:= mapWAD
+ ':\' + TEST_MAP_NAME
;
6390 tempWAD
:= ExtractRelativePath(ExtractFilePath(TestD2dExe
) + 'maps/', tempWAD
);
6391 // Если карта не была открыта, указываем временную в качестве текущей:
6392 if mapToRun
= '' then
6393 mapToRun
:= tempWAD
;
6397 if TestOptionsTwoPlayers
then
6399 if TestOptionsTeamDamage
then
6401 if TestOptionsAllowExit
then
6403 if TestOptionsWeaponStay
then
6405 if TestOptionsMonstersDM
then
6408 // Составляем командную строку:
6409 cmd
:= '-map "' + mapToRun
+ '"';
6410 cmd
:= cmd
+ ' -testmap "' + tempWAD
+ '"';
6411 cmd
:= cmd
+ ' -gm ' + TestGameMode
;
6412 cmd
:= cmd
+ ' -limt ' + TestLimTime
;
6413 cmd
:= cmd
+ ' -lims ' + TestLimScore
;
6414 cmd
:= cmd
+ ' -opt ' + IntToStr(opt
);
6417 cmd
:= cmd
+ ' --close';
6419 cmd
:= cmd
+ ' --debug';
6422 proc
:= TProcessUTF8
.Create(nil);
6423 proc
.Executable
:= TestD2dExe
;
6424 proc
.Parameters
.Add(cmd
);
6433 Application
.Minimize();
6436 if (not res
) or (proc
.ExitCode
< 0) then
6438 MessageBox(0, 'FIXME',
6439 PChar(_lc
[I_MSG_EXEC_ERROR
]),
6440 MB_OK
or MB_ICONERROR
);
6444 SysUtils
.DeleteFile(mapWAD
);
6445 Application
.Restore();
6448 procedure TMainForm
.sbVerticalScroll(Sender
: TObject
;
6449 ScrollCode
: TScrollCode
; var ScrollPos
: Integer);
6451 MapOffset
.Y
:= -Normalize16(sbVertical
.Position
);
6454 procedure TMainForm
.sbHorizontalScroll(Sender
: TObject
;
6455 ScrollCode
: TScrollCode
; var ScrollPos
: Integer);
6457 MapOffset
.X
:= -Normalize16(sbHorizontal
.Position
);
6460 procedure TMainForm
.miOpenWadMapClick(Sender
: TObject
);
6462 if OpenedWAD
<> '' then
6464 OpenMap(OpenedWAD
, '');
6468 procedure TMainForm
.selectall1Click(Sender
: TObject
);
6472 RemoveSelectFromObjects();
6474 if gPanels
<> nil then
6475 for a
:= 0 to High(gPanels
) do
6476 if gPanels
[a
].PanelType
<> PANEL_NONE
then
6477 SelectObject(OBJECT_PANEL
, a
, True);
6479 if gItems
<> nil then
6480 for a
:= 0 to High(gItems
) do
6481 if gItems
[a
].ItemType
<> ITEM_NONE
then
6482 SelectObject(OBJECT_ITEM
, a
, True);
6484 if gMonsters
<> nil then
6485 for a
:= 0 to High(gMonsters
) do
6486 if gMonsters
[a
].MonsterType
<> MONSTER_NONE
then
6487 SelectObject(OBJECT_MONSTER
, a
, True);
6489 if gAreas
<> nil then
6490 for a
:= 0 to High(gAreas
) do
6491 if gAreas
[a
].AreaType
<> AREA_NONE
then
6492 SelectObject(OBJECT_AREA
, a
, True);
6494 if gTriggers
<> nil then
6495 for a
:= 0 to High(gTriggers
) do
6496 if gTriggers
[a
].TriggerType
<> TRIGGER_NONE
then
6497 SelectObject(OBJECT_TRIGGER
, a
, True);
6500 procedure TMainForm
.Splitter1CanResize(Sender
: TObject
;
6501 var NewSize
: Integer; var Accept
: Boolean);
6503 Accept
:= (NewSize
> 140);
6506 procedure TMainForm
.Splitter2CanResize(Sender
: TObject
;
6507 var NewSize
: Integer; var Accept
: Boolean);
6509 Accept
:= (NewSize
> 110);
6512 procedure TMainForm
.vleObjectPropertyEnter(Sender
: TObject
);
6514 EditingProperties
:= True;
6517 procedure TMainForm
.vleObjectPropertyExit(Sender
: TObject
);
6519 EditingProperties
:= False;
6522 procedure TMainForm
.FormKeyUp(Sender
: TObject
; var Key
: Word;
6523 Shift
: TShiftState
);
6525 // Объекты передвигались:
6526 if MainForm
.ActiveControl
= RenderPanel
then
6528 if (Key
= VK_NUMPAD4
) or
6529 (Key
= VK_NUMPAD6
) or
6530 (Key
= VK_NUMPAD8
) or
6531 (Key
= VK_NUMPAD5
) or
6532 (Key
= Ord('V')) then
6535 // Быстрое превью карты:
6536 if Key
= Ord('E') then
6538 if PreviewMode
= 2 then