7490 lines
269 KiB
Plaintext
7490 lines
269 KiB
Plaintext
(*
|
||
* CDDL HEADER START
|
||
*
|
||
* The contents of this file are subject to the terms of the
|
||
* Common Development and Distribution License, Version 1.0 only
|
||
* (the "License"). You may not use this file except in compliance
|
||
* with the License.
|
||
*
|
||
* You can obtain a copy of the license at
|
||
* http://www.opensource.org/licenses/cddl1.php.
|
||
* See the License for the specific language governing permissions
|
||
* and limitations under the License.
|
||
*
|
||
* When distributing Covered Code, include this CDDL HEADER in each
|
||
* file and include the License file at
|
||
* http://www.opensource.org/licenses/cddl1.php. If applicable,
|
||
* add the following below this CDDL HEADER, with the fields enclosed
|
||
* by brackets "[]" replaced with your own identifying * information:
|
||
* Portions Copyright [yyyy] [name of copyright owner]
|
||
*
|
||
* CDDL HEADER END
|
||
*
|
||
*
|
||
* Portions Copyright 2009 Andreas Schneider
|
||
*)
|
||
unit UfrmMain;
|
||
|
||
{$mode objfpc}{$H+}
|
||
|
||
interface
|
||
|
||
uses
|
||
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, Menus,
|
||
ComCtrls, OpenGLContext, GL, GLu, UGameResources, ULandscape, ExtCtrls,
|
||
StdCtrls, Spin, UEnums, laz.VirtualTrees, VirtualList, Buttons, math, UMulBlock,
|
||
UWorldItem, LCLIntf, UOverlayUI, UStatics, UEnhancedMemoryStream, ActnList,
|
||
XMLPropStorage, LazHelpHTML, fgl, ImagingClasses, dateutils, UPlatformTypes,
|
||
UMap, UPacket, UGLFont, DOM, XMLRead, XMLWrite, strutils, ULightManager,
|
||
UndoRedoCmd, ImagingTypes, ImagingCanvases, types, Registry,
|
||
IniFiles, LMessages;
|
||
|
||
const
|
||
FVLightSrcImageCount = 15; // Количество иконок виртуальных источников
|
||
FUndoListLength = 64; // Количество элементов в списке отмены
|
||
|
||
type
|
||
TAccessChangedListener = procedure(AAccessLevel: TAccessLevel) of object;
|
||
TSelectionListener = procedure(AWorldItem: TWorldItem) of object;
|
||
TScreenBufferState = (sbsValid, sbsIndexed, sbsFiltered);
|
||
TScreenBufferStates = set of TScreenBufferState;
|
||
|
||
TBlockInfoList = specialize TFPGList<PBlockInfo>;
|
||
|
||
TGhostTile = class(TStaticItem)
|
||
public
|
||
CenterX, CenterY: Word; // Точки привязки к курсору (центральный тайл для объектов размером больше 1 тайла)
|
||
end;
|
||
TPacketList = specialize TFPGObjectList<TPacket>;
|
||
PPacketList = ^TPacketList;
|
||
TAccessChangedListeners = specialize TFPGList<TAccessChangedListener>;
|
||
TSelectionListeners = specialize TFPGList<TSelectionListener>;
|
||
|
||
TTileHintInfo = record
|
||
Column: Byte;
|
||
Obj: String;
|
||
Name: String;
|
||
Flags: String;
|
||
ObjRect: TRect;
|
||
NameRect: TRect;
|
||
FlagsRect: TRect;
|
||
end;
|
||
|
||
TGroupTile = record
|
||
ID: LongWord;
|
||
end;
|
||
|
||
TEntryTile = record
|
||
ID: LongWord;
|
||
Hue: Word;
|
||
X,Y: Smallint;
|
||
Z: ShortInt;
|
||
end;
|
||
|
||
TBrushTile = record
|
||
ID: Word;
|
||
Chance: Float;
|
||
Mask: Byte;
|
||
Brush1: ^TGroupBrush;
|
||
Brush2: ^TGroupBrush;
|
||
end;
|
||
PBrushTile = ^TBrushTile;
|
||
|
||
TGroupEntry = record
|
||
ID: Word;
|
||
Name: string;
|
||
Image: TSingleImage;
|
||
Count: Word; // Число тайлов в объекте
|
||
ETile: ^TEntryTile;
|
||
end;
|
||
PGroupEntry = ^TGroupEntry;
|
||
|
||
TGroupBrushEdge = record
|
||
ID: Word;
|
||
CountDR: Word;
|
||
BTileDR: ^PBrushTile;
|
||
CountDL: Word;
|
||
BTileDL: ^PBrushTile;
|
||
CountUR: Word;
|
||
BTileUR: ^PBrushTile;
|
||
CountUL: Word;
|
||
BTileUL: ^PBrushTile;
|
||
CountLL: Word;
|
||
BTileLL: ^PBrushTile;
|
||
CountUU: Word;
|
||
BTileUU: ^PBrushTile;
|
||
end;
|
||
PGroupBrushEdge = ^TGroupBrushEdge;
|
||
|
||
TGroupBrush = record
|
||
ID: Word;
|
||
Name: string;
|
||
Image: TSingleImage;
|
||
Count: Word; // Число тайлов в объекте
|
||
BTile: ^PBrushTile;
|
||
|
||
ECount: Word; // Число тайлов перехода (в <Edge />)
|
||
EdgeId: ^PWord; // <20>ндификаторы кистей переходов (ссылка на кисть в <Edge />)
|
||
BEdges: ^PGroupBrushEdge; // Тайлы переходов
|
||
end;
|
||
PGroupBrush = ^TGroupBrush;
|
||
|
||
TEntryList = record
|
||
Entry: ^PGroupEntry;
|
||
Count: Word;
|
||
end;
|
||
|
||
TBrushList = record
|
||
Brush: ^PGroupBrush;
|
||
Count: Word;
|
||
Tiles: array[0..$3FFF] of TBrushTile;
|
||
end;
|
||
|
||
TGroupNode = record
|
||
Name : string;
|
||
Color: TColor;
|
||
Bold : Boolean;
|
||
Ital : Boolean;
|
||
Items: LongWord; // число элементов (тайлы, объекты, кисти и тд) в группе (включая подгруппы)
|
||
Nodes: Word;
|
||
ID : LongWord;
|
||
Links: Word; // число элементов в GLink
|
||
lids : ^LongWord;
|
||
GLink: ^PVirtualNode; // сылки на группы
|
||
Count: LongWord; // число элементов в GTile
|
||
GTile: ^TGroupTile;
|
||
Entries: LongWord; // число элементов в Entry
|
||
Entry: ^PGroupEntry; // сылки на объекты из TilesEntry.xml
|
||
Brushes: LongWord; // число элементов в Brush
|
||
Brush: ^PGroupBrush; // сылки на объекты из TilesBrush.xml
|
||
end;
|
||
PGroupNode = ^TGroupNode;
|
||
|
||
// SurfaceInf.xml types start
|
||
TSurfTile = record
|
||
Tile: ^LongWord; // ID тайлов лендов и итемов
|
||
Hash: ^LongWord; // Surface's тэги для них
|
||
Count: Word;
|
||
end;
|
||
PSurfTile = ^TSurfTile;
|
||
|
||
TSurfGrad = record
|
||
Grad: ^TSurfTile; // списки тайлов в Surface'ах, рассортированные по Category+Type
|
||
Hash: ^LongWord; // SurfaceCategory + ItemType
|
||
Count: Word;
|
||
end;
|
||
PSurfGrad = ^TSurfGrad;
|
||
|
||
TSurfInfo = record
|
||
Name : string;
|
||
TileID: LongWord;
|
||
TileHash: LongWord; // Кеш Имени (Name)
|
||
GradHash: ^LongWord; // Кэши типов тайлов в объекте
|
||
GradCount: Word; // Чмсло GradHash
|
||
end;
|
||
PSurfInfo = ^TSurfInfo;
|
||
|
||
TSurfGroup = record
|
||
Name : string; // Имя категории
|
||
Info : ^TSurfInfo; // Список поверхностей в категории
|
||
Count: Word; // Длинна списка поверхностей
|
||
end;
|
||
PSurfGroup = ^TSurfGroup;
|
||
|
||
TSurfsList = record
|
||
Group: ^TSurfGroup;
|
||
GroupCount: Word;
|
||
|
||
Grads: ^TSurfGrad; // Контейнер для хранения памяти
|
||
GradsCount: Word;
|
||
|
||
Tiles: ^PSurfGrad;
|
||
TilesCount: Word;
|
||
end;
|
||
// SurfaceInf.xml types end
|
||
|
||
TLightTile = record
|
||
image: Byte;
|
||
color: Byte;
|
||
end;
|
||
PLightTile = ^TLightTile;
|
||
|
||
{ TfrmMain }
|
||
|
||
TfrmMain = class(TForm)
|
||
acSelect: TAction;
|
||
acDraw: TAction;
|
||
acMove: TAction;
|
||
acElevate: TAction;
|
||
acDelete: TAction;
|
||
acHue: TAction;
|
||
acBoundaries: TAction;
|
||
acFilter: TAction;
|
||
acFlat: TAction;
|
||
acNoDraw: TAction;
|
||
acLightlevel: TAction;
|
||
acTerrain: TAction;
|
||
acStatics: TAction;
|
||
acSelection: TAction;
|
||
acSurfElevate: TAction;
|
||
acSurfStretch: TAction;
|
||
acSurfSmooth: TAction;
|
||
acFill: TAction;
|
||
acRedo: TAction;
|
||
acWalkable: TAction;
|
||
acUndo: TAction;
|
||
acVirtualLayer: TAction;
|
||
ActionList1: TActionList;
|
||
ApplicationProperties1: TApplicationProperties;
|
||
btnAddLocation: TSpeedButton;
|
||
btnAddRandom: TSpeedButton;
|
||
btnClearLocations: TSpeedButton;
|
||
btnClearRandom: TSpeedButton;
|
||
btnDeleteLocation: TSpeedButton;
|
||
btnDeleteRandom: TSpeedButton;
|
||
btnGoTo: TButton;
|
||
btnRandomPresetDelete: TSpeedButton;
|
||
btnRandomPresetSave: TSpeedButton;
|
||
cbRandomPreset: TComboBox;
|
||
cbStatics: TCheckBox;
|
||
cbTerrain: TCheckBox;
|
||
edChat: TEdit;
|
||
edFilter: TEdit;
|
||
edSearchID: TEdit;
|
||
edX: TSpinEdit;
|
||
edY: TSpinEdit;
|
||
gbRandom: TGroupBox;
|
||
gbGoTo: TGroupBox;
|
||
ImageList1: TImageList;
|
||
lblTileInfoOLabel: TLabel;
|
||
lblTileInfoIDLabel: TLabel;
|
||
lblTileInfoHLabel: TLabel;
|
||
lblTileInfoIDValue: TLabel;
|
||
lblTileInfoCLabel: TLabel;
|
||
lblTileInfoWLabel: TLabel;
|
||
lblTileInfoYLabel: TLabel;
|
||
lblTileInfoXValue: TLabel;
|
||
lblTileInfoXLabel: TLabel;
|
||
lblTileInfoZValue: TLabel;
|
||
lblTileInfoHueValue: TLabel;
|
||
lblTileInfoHueLabel: TLabel;
|
||
lblChatHeaderCaption: TLabel;
|
||
lblFilter: TLabel;
|
||
lblTileInfoZLabel: TLabel;
|
||
lblTileInfoYValue: TLabel;
|
||
lblTileInfoHValue: TLabel;
|
||
lblTileInfoWValue: TLabel;
|
||
lblX: TLabel;
|
||
lblY: TLabel;
|
||
MainMenu1: TMainMenu;
|
||
MenuItem1: TMenuItem;
|
||
mnuMiscTileListLarge: TMenuItem;
|
||
mnuSeparator9: TMenuItem;
|
||
mnuSeparator8: TMenuItem;
|
||
mnuTileListDrawInfo: TMenuItem;
|
||
mnuMiscTileListTable: TMenuItem;
|
||
mnuMiscTileListSmall: TMenuItem;
|
||
mnuSeparator10: TMenuItem;
|
||
mnuMiscTileListCentre: TMenuItem;
|
||
mnuMiscTileListDrawInfo: TMenuItem;
|
||
mnuMiscTileListMidle: TMenuItem;
|
||
mnuMiscTileListClip: TMenuItem;
|
||
mnuMiscTileListStretch: TMenuItem;
|
||
mnuMiscTileList: TMenuItem;
|
||
mnuEng2Com: TMenuItem;
|
||
mnuTileListMidle: TMenuItem;
|
||
mnuTileListTable: TMenuItem;
|
||
mnuTileListSmall: TMenuItem;
|
||
mnuTileListLarge: TMenuItem;
|
||
mnuTileListStretch: TMenuItem;
|
||
mnuTileListClip: TMenuItem;
|
||
mnuTileListCentre: TMenuItem;
|
||
mnuSeparator7: TMenuItem;
|
||
mnuTileList: TMenuItem;
|
||
mnuSeparator6: TMenuItem;
|
||
mnuSetLanguage: TMenuItem;
|
||
mnuAutoShowFilterWindow: TMenuItem;
|
||
mnuSelection: TMenuItem;
|
||
mnuSurfElevate: TMenuItem;
|
||
mnuSurfStretch: TMenuItem;
|
||
mnuSurfSmooth: TMenuItem;
|
||
mnuFill: TMenuItem;
|
||
mnuShowNoDrawTiles: TMenuItem;
|
||
mnuEngCom: TMenuItem;
|
||
mnuRusCom: TMenuItem;
|
||
mnuSupport: TMenuItem;
|
||
mnuSeparator5: TMenuItem;
|
||
mnuDocs: TMenuItem;
|
||
mnuShowBlocks: TMenuItem;
|
||
mnuGrabBoundaries: TMenuItem;
|
||
mnuGrabBoundMinZ: TMenuItem;
|
||
mnuGrabBoundMaxZ: TMenuItem;
|
||
mnuGrabBoundMinX: TMenuItem;
|
||
mnuGrabBoundMaxX: TMenuItem;
|
||
mnuGrabBoundMinY: TMenuItem;
|
||
mnuGrabBoundMaxY: TMenuItem;
|
||
mnuZoom300: TMenuItem;
|
||
mnuZoom400: TMenuItem;
|
||
mnuZoom033: TMenuItem;
|
||
mnuZoom025: TMenuItem;
|
||
mnuZoom150: TMenuItem;
|
||
mnuZoom200: TMenuItem;
|
||
mnuZoom075: TMenuItem;
|
||
mnuZoom050: TMenuItem;
|
||
mnuZoom100: TMenuItem;
|
||
mnuShowBridges: TMenuItem;
|
||
mnuWindowedMode: TMenuItem;
|
||
mnuMakeScreenShot: TMenuItem;
|
||
mnuShowWater: TMenuItem;
|
||
mnuShowSurfaces: TMenuItem;
|
||
mnuShowRoofs: TMenuItem;
|
||
mnuShowFoliage: TMenuItem;
|
||
mnuAutoHideRandomList: TMenuItem;
|
||
mnuAutoHideGroupList: TMenuItem;
|
||
mnuSeparator4: TMenuItem;
|
||
mnuReloadGroups: TMenuItem;
|
||
mnuGrabFilterTileID: TMenuItem;
|
||
mnuGrabFilterHue: TMenuItem;
|
||
mnuGrabVirtualLayerZ: TMenuItem;
|
||
mnuShowGrid: TMenuItem;
|
||
mnuShowWalls: TMenuItem;
|
||
mnuShowLightSource: TMenuItem;
|
||
mnuWhiteBackground: TMenuItem;
|
||
mnuSecurityQuestion: TMenuItem;
|
||
mnuShowAnimations: TMenuItem;
|
||
mnuSettings: TMenuItem;
|
||
mnuFlatShowHeight: TMenuItem;
|
||
mnuGrabHue: TMenuItem;
|
||
mnuGrabTileID: TMenuItem;
|
||
mnuRegionControl: TMenuItem;
|
||
mnuVirtualLayer: TMenuItem;
|
||
mnuLargeScaleCommands: TMenuItem;
|
||
mnuSetHue: TMenuItem;
|
||
mnuGoToClient: TMenuItem;
|
||
mnuAbout: TMenuItem;
|
||
mnuHelp: TMenuItem;
|
||
mnuSeparator3: TMenuItem;
|
||
mnuBoundaries: TMenuItem;
|
||
mnuSelect: TMenuItem;
|
||
mnuDraw: TMenuItem;
|
||
mnuMove: TMenuItem;
|
||
mnuElevate: TMenuItem;
|
||
mnuDelete: TMenuItem;
|
||
mnuAddToRandom: TMenuItem;
|
||
mnuFlush: TMenuItem;
|
||
mnuShutdown: TMenuItem;
|
||
mnuSeparator2: TMenuItem;
|
||
mnuAccountControl: TMenuItem;
|
||
mnuAdministration: TMenuItem;
|
||
mnuSeparator1: TMenuItem;
|
||
mnuExit: TMenuItem;
|
||
mnuDisconnect: TMenuItem;
|
||
mnuCentrED: TMenuItem;
|
||
oglGameWindow: TOpenGLControl;
|
||
pbRadar: TPaintBox;
|
||
pcLeft: TPageControl;
|
||
pmZoomSettings: TPopupMenu;
|
||
pmViewTerrainSettings: TPopupMenu;
|
||
pmGrabTileInfo: TPopupMenu;
|
||
pmNoDrawSettings: TPopupMenu;
|
||
pmViewStaticSettings: TPopupMenu;
|
||
pmTileList: TPopupMenu;
|
||
pmTools: TPopupMenu;
|
||
pmClients: TPopupMenu;
|
||
pnlChat: TPanel;
|
||
pnlChatHeader: TPanel;
|
||
pmFlatViewSettings: TPopupMenu;
|
||
spChat: TSplitter;
|
||
spGroupList1: TSplitter;
|
||
spTileList: TSplitter;
|
||
spGroupList: TSplitter;
|
||
tbFill: TToolButton;
|
||
tbSurfSmooth: TToolButton;
|
||
tbSurfStretch: TToolButton;
|
||
tbSurfElevate: TToolButton;
|
||
tbSelection: TToolButton;
|
||
tbFilter: TToolButton;
|
||
tbFlat: TToolButton;
|
||
tbSeparator6: TToolButton;
|
||
tbSeparator7: TToolButton;
|
||
tbSeparator8: TToolButton;
|
||
tbSeparator9: TToolButton;
|
||
tbRedo: TToolButton;
|
||
tbZoom: TToolButton;
|
||
tbNoDraw: TToolButton;
|
||
tbSeparator2: TToolButton;
|
||
tbUndo: TToolButton;
|
||
tbLightlevel: TToolButton;
|
||
tbWalkable: TToolButton;
|
||
tmSelectNode: TTimer;
|
||
tmSettingsClose: TTimer;
|
||
tsNavigation: TTabSheet;
|
||
tbSetHue: TToolButton;
|
||
tmGrabTileInfo: TTimer;
|
||
tmMovement: TTimer;
|
||
tbSeparator5: TToolButton;
|
||
tbRadarMap: TToolButton;
|
||
tbVirtualLayer: TToolButton;
|
||
tsObjects: TTabSheet;
|
||
tbMain: TToolBar;
|
||
tbDisconnect: TToolButton;
|
||
tbSeparator1: TToolButton;
|
||
tbSelect: TToolButton;
|
||
tbDrawTile: TToolButton;
|
||
tbMoveTile: TToolButton;
|
||
tbElevateTile: TToolButton;
|
||
tbDeleteTile: TToolButton;
|
||
tbSeparator3: TToolButton;
|
||
tbBoundaries: TToolButton;
|
||
tbSeparator4: TToolButton;
|
||
tbTerrain: TToolButton;
|
||
tbStatics: TToolButton;
|
||
tsTiles: TTabSheet;
|
||
tvGroups: TLazVirtualStringTree;
|
||
vdtTiles: TVirtualList;
|
||
vdtRandom: TLazVirtualDrawTree;
|
||
vdlRandom: TVirtualList;
|
||
vstChat: TLazVirtualStringTree;
|
||
vstLocations: TLazVirtualStringTree;
|
||
vstClients: TLazVirtualStringTree;
|
||
XMLPropStorage1: TXMLPropStorage;
|
||
procedure acBoundariesExecute(Sender: TObject);
|
||
procedure acDeleteExecute(Sender: TObject);
|
||
procedure acDrawExecute(Sender: TObject);
|
||
procedure acElevateExecute(Sender: TObject);
|
||
procedure acFillExecute(Sender: TObject);
|
||
procedure acFilterExecute(Sender: TObject);
|
||
procedure acFlatExecute(Sender: TObject);
|
||
procedure acHueExecute(Sender: TObject);
|
||
procedure acLightlevelExecute(Sender: TObject);
|
||
procedure acMoveExecute(Sender: TObject);
|
||
procedure acNoDrawExecute(Sender: TObject);
|
||
procedure acSelectExecute(Sender: TObject);
|
||
procedure acSelectionExecute(Sender: TObject);
|
||
procedure acStaticsExecute(Sender: TObject);
|
||
procedure acSurfElevateExecute(Sender: TObject);
|
||
procedure acSurfSmoothExecute(Sender: TObject);
|
||
procedure acSurfStretchExecute(Sender: TObject);
|
||
procedure acTerrainExecute(Sender: TObject);
|
||
procedure acUndoExecute(Sender: TObject);
|
||
procedure acVirtualLayerExecute(Sender: TObject);
|
||
procedure acWalkableExecute(Sender: TObject);
|
||
procedure ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);
|
||
procedure ApplicationProperties1ShowHint(var HintStr: string;
|
||
var CanShow: Boolean; var HintInfo: THintInfo);
|
||
procedure btnAddLocationClick(Sender: TObject);
|
||
procedure btnAddRandomClick(Sender: TObject);
|
||
procedure btnClearLocationsClick(Sender: TObject);
|
||
procedure btnClearRandomClick(Sender: TObject);
|
||
procedure btnDeleteLocationClick(Sender: TObject);
|
||
procedure btnDeleteRandomClick(Sender: TObject);
|
||
procedure btnGoToClick(Sender: TObject);
|
||
procedure btnRandomPresetDeleteClick(Sender: TObject);
|
||
procedure btnRandomPresetSaveClick(Sender: TObject);
|
||
procedure cbRandomPresetChange(Sender: TObject);
|
||
procedure cbStaticsChange(Sender: TObject);
|
||
procedure cbTerrainChange(Sender: TObject);
|
||
procedure edChatKeyPress(Sender: TObject; var Key: char);
|
||
procedure edFilterEditingDone(Sender: TObject);
|
||
procedure FormActivate(Sender: TObject);
|
||
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
|
||
procedure FormCreate(Sender: TObject);
|
||
procedure FormDestroy(Sender: TObject);
|
||
procedure edSearchIDExit(Sender: TObject);
|
||
procedure edSearchIDKeyPress(Sender: TObject; var Key: char);
|
||
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
procedure FormShow(Sender: TObject);
|
||
procedure FormWindowStateChange(Sender: TObject);
|
||
procedure lblChatHeaderCaptionClick(Sender: TObject);
|
||
procedure lblChatHeaderCaptionMouseEnter(Sender: TObject);
|
||
procedure lblChatHeaderCaptionMouseLeave(Sender: TObject);
|
||
procedure mnuAboutClick(Sender: TObject);
|
||
procedure mnuAccountControlClick(Sender: TObject);
|
||
procedure mnuAutoHideGroupListClick(Sender: TObject);
|
||
procedure mnuAutoHideRandomListClick(Sender: TObject);
|
||
procedure mnuDisconnectClick(Sender: TObject);
|
||
procedure mnuDocsClick(Sender: TObject);
|
||
procedure mnuEng2ComClick(Sender: TObject);
|
||
procedure mnuEngComClick(Sender: TObject);
|
||
procedure mnuExitClick(Sender: TObject);
|
||
procedure mnuFlatShowHeightClick(Sender: TObject);
|
||
procedure mnuFlushClick(Sender: TObject);
|
||
procedure mnuGoToClientClick(Sender: TObject);
|
||
procedure GrabBoundaries(Sender: TObject);
|
||
procedure mnuGrabFilterHueClick(Sender: TObject);
|
||
procedure mnuGrabFilterTileIDClick(Sender: TObject);
|
||
procedure mnuGrabHueClick(Sender: TObject);
|
||
procedure mnuGrabTileIDClick(Sender: TObject);
|
||
procedure mnuGrabVirtualLayerZClick(Sender: TObject);
|
||
procedure mnuLargeScaleCommandsClick(Sender: TObject);
|
||
procedure mnuMakeScreenShotClick(Sender: TObject);
|
||
procedure mnuRegionControlClick(Sender: TObject);
|
||
procedure mnuReloadGroupsClick(Sender: TObject);
|
||
procedure mnuRusComClick(Sender: TObject);
|
||
procedure mnuSetLanguageClick(Sender: TObject);
|
||
procedure mnuShowAnimationsClick(Sender: TObject);
|
||
procedure mnuShowBlocksClick(Sender: TObject);
|
||
procedure mnuShowGridClick(Sender: TObject);
|
||
procedure mnuShowLightSourceClick(Sender: TObject);
|
||
procedure mnuShowNoDrawTilesClick(Sender: TObject);
|
||
procedure mnuShowStaticsOptionClick(Sender: TObject);
|
||
procedure mnuShutdownClick(Sender: TObject);
|
||
procedure mnuTileListDrawClick(Sender: TObject);
|
||
procedure mnuTileListViewClick(Sender: TObject);
|
||
procedure mnuWhiteBackgroundClick(Sender: TObject);
|
||
procedure mnuWindowedModeClick(Sender: TObject);
|
||
procedure mnuZoomClick(Sender: TObject);
|
||
procedure oglGameWindowDblClick(Sender: TObject);
|
||
procedure oglGameWindowKeyDown(Sender: TObject; var Key: Word;
|
||
Shift: TShiftState);
|
||
procedure oglGameWindowMouseDown(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
procedure oglGameWindowMouseEnter(Sender: TObject);
|
||
procedure oglGameWindowMouseLeave(Sender: TObject);
|
||
procedure oglGameWindowMouseMove(Sender: TObject; Shift: TShiftState; X,
|
||
Y: Integer);
|
||
procedure oglGameWindowMouseUp(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
procedure oglGameWindowMouseWheel(Sender: TObject; Shift: TShiftState;
|
||
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
|
||
procedure oglGameWindowPaint(Sender: TObject);
|
||
procedure oglGameWindowResize(Sender: TObject);
|
||
procedure pbRadarMouseDown(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
procedure pbRadarPaint(Sender: TObject);
|
||
procedure pcLeftResize(Sender: TObject);
|
||
procedure pmGrabTileInfoPopup(Sender: TObject);
|
||
procedure DropedownMenusClose(Sender: TObject);
|
||
procedure spGroupListMoved(Sender: TObject);
|
||
procedure spTileListMoved(Sender: TObject);
|
||
procedure tbFilterMouseDown(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
procedure tbFilterMouseUp(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
procedure tbRadarMapClick(Sender: TObject);
|
||
procedure tmGrabTileInfoTimer(Sender: TObject);
|
||
procedure tmMovementTimer(Sender: TObject);
|
||
procedure tmSelectNodeTimer(Sender: TObject);
|
||
procedure tmSettingsCloseTimer(Sender: TObject);
|
||
procedure tvGroupFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||
procedure tvGroupsChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||
procedure tvGroupsDrawText(Sender: TBaseVirtualTree; TargetCanvas: TCanvas;
|
||
Node: PVirtualNode; Column: TColumnIndex; const CellText: String;
|
||
const CellRect: TRect; var DefaultDraw: Boolean);
|
||
procedure tvGroupsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||
Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
|
||
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
|
||
);
|
||
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
|
||
Y: Integer);
|
||
procedure tvSelectGroupsChanged(Sender: TObject);
|
||
procedure vdtRandomClick(Sender: TObject);
|
||
procedure vdtRandomDragDrop(Sender: TBaseVirtualTree; Source: TObject;
|
||
DataObject: IDataObject; Formats: TFormatArray; Shift: TShiftState;
|
||
Pt: TPoint; var Effect: Integer; Mode: TDropMode);
|
||
procedure vdtRandomDragOver(Sender: TBaseVirtualTree; Source: TObject;
|
||
Shift: TShiftState; State: TDragState; Pt: TPoint; Mode: TDropMode;
|
||
var Effect: Integer; var Accept: Boolean);
|
||
procedure vdtRandomLoadNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||
Stream: TStream);
|
||
procedure vdtRandomSaveNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||
Stream: TStream);
|
||
procedure vdtRandomUpdating(Sender: TBaseVirtualTree; State: TVTUpdateState);
|
||
procedure vdtTilesChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||
procedure vdtTilesClick(Sender: TObject);
|
||
procedure vdtTilesDragAllowed(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||
Column: TColumnIndex; var Allowed: Boolean);
|
||
procedure vdtTilesDrawHint(Sender: TBaseVirtualTree; HintCanvas: TCanvas;
|
||
Node: PVirtualNode; const R: TRect; Column: TColumnIndex);
|
||
procedure vdtTilesDrawNode(Sender: TBaseVirtualTree;
|
||
const PaintInfo: TVTPaintInfo);
|
||
procedure vdtTilesEnter(Sender: TObject);
|
||
procedure vdtTilesGetHintSize(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||
Column: TColumnIndex; var R: TRect);
|
||
procedure vdtTilesKeyPress(Sender: TObject; var Key: char);
|
||
procedure vdtTilesScroll(Sender: TBaseVirtualTree; DeltaX, DeltaY: Integer);
|
||
procedure vstChatClick(Sender: TObject);
|
||
procedure vstChatFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||
procedure vstChatGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||
Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
|
||
procedure vstChatPaintText(Sender: TBaseVirtualTree;
|
||
const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
|
||
TextType: TVSTTextType);
|
||
procedure vstClientsGetImageIndex(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
|
||
var Ghosted: Boolean; var ImageIndex: Integer);
|
||
procedure vstClientsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||
Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
|
||
procedure vstLocationsDblClick(Sender: TObject);
|
||
procedure vstLocationsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode
|
||
);
|
||
procedure vstLocationsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||
Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
|
||
procedure vstLocationsLoadNode(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Stream: TStream);
|
||
procedure vstLocationsNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||
Column: TColumnIndex; const NewText: String);
|
||
procedure vstLocationsSaveNode(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Stream: TStream);
|
||
procedure XMLPropStorage1RestoreProperties(Sender: TObject);
|
||
procedure XMLPropStorage1SavingProperties(Sender: TObject);
|
||
protected
|
||
{ Members }
|
||
FAppDir: String; // .\
|
||
FLocalDir: String; // .\..\LocalData\
|
||
FConfigDir: String; // {$User}\AppData\Local\CentrED-plus\ - зависит от реестра
|
||
FProfileDir: String; // {$User}\AppData\Local\CentrED-plus\Profiles\{$Profile}\ - зависит от реестра
|
||
FX: Integer;
|
||
FY: Integer;
|
||
FDrawDistance: Integer;
|
||
FLowOffsetX: Integer;
|
||
FLowOffsetY: Integer;
|
||
FHighOffsetX: Integer;
|
||
FHighOffsetY: Integer;
|
||
FRangeX: Integer;
|
||
FRangeY: Integer;
|
||
FLandscape: TLandscape;
|
||
FTextureManager: TLandTextureManager;
|
||
FScreenBuffer: TScreenBuffer;
|
||
FScreenBufferState: TScreenBufferStates;
|
||
FCurrentTile: TWorldItem;
|
||
FSelectedTile: TWorldItem;
|
||
FVirtualTiles: TWorldItemList;
|
||
FVLayerImage: TSingleImage;
|
||
FVLayerMaterial: TMaterial;
|
||
FVLightSrcImage: array[1..FVLightSrcImageCount] of TSingleImage;
|
||
FVLightSrcMaterial: ^TMaterial;
|
||
FOverlayUI: TOverlayUI;
|
||
FLocationsFile: string;
|
||
FRandomPresetsFile: string;
|
||
FRandomPresetsDoc: TXMLDocument;
|
||
FLastDraw: TDateTime;
|
||
FAccessChangedListeners: TAccessChangedListeners;
|
||
FRepaintNeeded: Boolean;
|
||
FSelection: TRect;
|
||
FUndoList: PPacketList;
|
||
FUndoListArray: array[1..FUndoListLength] of TPacketList;
|
||
FUndoListFirstIndex: Word;
|
||
FundoListLastIndex: Word;
|
||
FEntryList: TEntryList;
|
||
FBrushList: TBrushList;
|
||
FSurfsList: TSurfsList;
|
||
|
||
FGroupsSelectionUndoRedoCommandGroup: TUndoRedoCommandGroup;
|
||
FGroupsSelectionUndoRedoManager: TUndoRedoManager;
|
||
FTilesSelectionUndoRedoCommandGroup: TUndoRedoCommandGroup;
|
||
FTilesSelectionUndoRedoManager: TUndoRedoManager;
|
||
|
||
FGLFont: TGLFont;
|
||
FSelectionListeners: TSelectionListeners;
|
||
FTileHint: TTileHintInfo;
|
||
FLightManager: TLightManager;
|
||
FVisibleTiles: TBits;
|
||
FLightSourceTiles: PLightTile;
|
||
{ Methods }
|
||
function GetNextUndoList: PPacketList;
|
||
function LoadListError(condition: Boolean; filename, message : string): Boolean;
|
||
procedure LoadVisibleTiles(AFileName: String);
|
||
procedure LoadLightSourceTiles(AFileName: String);
|
||
procedure LoadEntryTilesList;
|
||
procedure LoadBrushTilesList;
|
||
procedure LoadSurfsTilesList;
|
||
procedure BuildGroupList;
|
||
procedure BuildTileList;
|
||
procedure FreeGroupLists;
|
||
function ConfirmAction: Boolean;
|
||
function FindRandomPreset(AName: String): TDOMElement;
|
||
procedure ForceUpdateCurrentTile;
|
||
procedure GetDrawOffset(AX, AY: Integer; out DrawX, DrawY: Integer); inline;
|
||
function GetInternalTileID(ATile: TWorldItem): LongWord;
|
||
function GetSelectedRect: TRect;
|
||
procedure InitRender;
|
||
procedure InitSize;
|
||
procedure LoadLocations;
|
||
procedure LoadRandomPresets;
|
||
procedure MoveBy(AOffsetX, AOffsetY: Integer); inline;
|
||
procedure PrepareMapCell(AMapCell: TMapCell);
|
||
procedure PrepareScreenBlock(ABlockInfo: PBlockInfo);
|
||
procedure ProcessToolState;
|
||
procedure ProcessAccessLevel;
|
||
procedure RebuildScreenBuffer;
|
||
procedure Render;
|
||
procedure SaveLocations;
|
||
procedure SaveRandomPresets;
|
||
procedure SetCurrentTile(const AValue: TWorldItem);
|
||
procedure SetDarkLights; inline;
|
||
procedure SetNormalLights; inline;
|
||
procedure SetSelectedTile(const AValue: TWorldItem);
|
||
procedure SetX(const AValue: Integer);
|
||
procedure SetY(const AValue: Integer);
|
||
procedure UpdateCurrentTile;
|
||
procedure UpdateCurrentTile(AX, AY: Integer);
|
||
procedure UpdateFilter;
|
||
procedure UpdateSelection;
|
||
procedure WriteChatMessage(ASender, AMessage: string);
|
||
{ Events }
|
||
procedure OnClientHandlingPacket(ABuffer: TEnhancedMemoryStream);
|
||
procedure OnLandscapeChanged;
|
||
procedure OnMapChanged(AMapCell: TMapCell);
|
||
procedure OnNewBlock(ABlock: TBlock);
|
||
procedure OnStaticDeleted(AStaticItem: TStaticItem);
|
||
procedure OnStaticElevated(AStaticItem: TStaticItem);
|
||
procedure OnStaticHued(AStaticItem: TStaticItem);
|
||
procedure OnStaticInserted(AStaticItem: TStaticItem);
|
||
procedure OnTileRemoved(ATile: TMulBlock);
|
||
public
|
||
{ Fields }
|
||
property X: Integer read FX write SetX;
|
||
property Y: Integer read FY write SetY;
|
||
property Landscape: TLandscape read FLandscape;
|
||
property CurrentTile: TWorldItem read FCurrentTile write SetCurrentTile;
|
||
property SelectedTile: TWorldItem read FSelectedTile write SetSelectedTile;
|
||
property LightManager: TLightManager read FLightManager;
|
||
property AppDir: string read FAppDir;
|
||
property LocalDir: string read FLocalDir;
|
||
property ConfigDir: string read FConfigDir;
|
||
property ProfileDir: string read FProfileDir;
|
||
|
||
{ Methods }
|
||
procedure InvalidateFilter;
|
||
procedure InvalidateScreenBuffer;
|
||
procedure RegisterAccessChangedListener(AListener: TAccessChangedListener);
|
||
procedure RegisterSelectionListener(AListener: TSelectionListener);
|
||
procedure SetPos(AX, AY: Word);
|
||
procedure SwitchToSelection;
|
||
procedure UnregisterAccessChangedListener(AListener: TAccessChangedListener);
|
||
procedure UnregisterSelectionListener(AListener: TSelectionListener);
|
||
public
|
||
{Localization}
|
||
lbFormTitleAccount: string;
|
||
lbFormTitleProfile: string;
|
||
lbBottomCursorVLayer1: string;
|
||
lbBottomCursorVLayer2: string;
|
||
lbBottomCursorItemID: string;
|
||
lbBottomCursorLandID: string;
|
||
lbBottomCursorPosX: string;
|
||
lbBottomCursorPosY: string;
|
||
lbBottomCursorPosZ: string;
|
||
lbBottomCursorItemHue: string;
|
||
lbToolbarUndo: string;
|
||
|
||
lbDlgWindowedModeSwitchCaption: string;
|
||
lbDlgWindowedModeSwitch: string;
|
||
lbScreenShotMsg: string;
|
||
lbUserLoginedMsg: string;
|
||
lbUserLogoutedMsg: string;
|
||
lbDlgGetDcErrCaption: string;
|
||
lbDlgGetDcErr: string;
|
||
lbDlgFreeDcErrCaption: string;
|
||
lbDlgFreeDcErr: string;
|
||
lbDlgCnangedAccessCaption: string;
|
||
lbDlgCnangedAccess: string;
|
||
lbDlgBlockedAccessCaption: string;
|
||
lbDlgBlockedAccess: string;
|
||
|
||
lbDlgSaveRandPrsCaption: string;
|
||
lbDlgSaveRandPrs: string;
|
||
lbDlgSearchIdErrCaption: string;
|
||
lbDlgSearchIdErr: string;
|
||
lbDlgNotFoundErrCaption: string;
|
||
lbDlgNotFoundErr: string;
|
||
|
||
lbDlgDelConfCaption: string;
|
||
lbDlgDelConf: string;
|
||
lbDlgNewQuerryCaption: string;
|
||
lbDlgNewQuerry: string;
|
||
|
||
end;
|
||
|
||
var
|
||
frmMain: TfrmMain;
|
||
|
||
implementation
|
||
|
||
uses
|
||
UdmNetwork, UArt, UTexture, UHue, UTiledata, UAdminHandling, UPackets,
|
||
UfrmAccountControl, UGraphicHelper, ImagingComponents, UfrmDrawSettings,
|
||
UfrmBoundaries, UfrmElevateSettings, UfrmConfirmation, UfrmMoveSettings,
|
||
UfrmAbout, UPacketHandlers, UfrmHueSettings, UfrmRadar, UfrmLargeScaleCommand,
|
||
UfrmLogin, UResourceManager, UfrmVirtualLayer, UfrmFilter, UfrmRegionControl,
|
||
Logging, LConvEncoding, LCLType, UfrmLightlevel, vinfo, Imaging, Language,
|
||
UfrmEditAccount, UfrmFillSettings, UfrmSelectionSettings, UfrmInitialize,
|
||
UfrmSurfElevateSettings, UfrmSurfStretchSettings, UfrmSurfSmoothSettings, Crc32Hash;
|
||
|
||
{$I version.inc}
|
||
|
||
type
|
||
TGLArrayf4 = array[0..3] of GLfloat;
|
||
PTileInfo = ^TTileInfo;
|
||
TTileInfo = record
|
||
ID: LongWord;
|
||
ptr: Pointer;
|
||
end;
|
||
PChatInfo = ^TChatInfo;
|
||
TChatInfo = record
|
||
Time: TDateTime;
|
||
Sender: string;
|
||
Msg: string;
|
||
end;
|
||
PLocationInfo = ^TLocationInfo;
|
||
TLocationInfo = record
|
||
X: Word;
|
||
Y: Word;
|
||
Name: string;
|
||
end;
|
||
PClientInfo = ^TClientInfo;
|
||
TClientInfo = record
|
||
Name: string;
|
||
AccessLevel: TAccessLevel;
|
||
LogonDateTime : TDateTime;
|
||
//Time: string;
|
||
//Map: Byte;
|
||
//X: Word;
|
||
//Y: Word;
|
||
end;
|
||
|
||
const
|
||
CScreenBufferValid = [sbsValid, sbsIndexed, sbsFiltered];
|
||
|
||
function IsInRect(const AX, AY: Integer; const ARect: TRect): Boolean; inline;
|
||
begin
|
||
Result := (AX >= ARect.Left) and
|
||
(AX <= ARect.Right) and
|
||
(AY >= ARect.Top) and
|
||
(AY <= ARect.Bottom);
|
||
end;
|
||
|
||
{ TfrmMain }
|
||
|
||
procedure TfrmMain.mnuExitClick(Sender: TObject);
|
||
begin
|
||
Close;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuFlatShowHeightClick(Sender: TObject);
|
||
begin
|
||
tbFlat.Down := acFlat.Checked;
|
||
RebuildScreenBuffer;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuShowNoDrawTilesClick(Sender: TObject);
|
||
begin
|
||
tbNoDraw.Down := acNoDraw.Checked;
|
||
RebuildScreenBuffer;
|
||
FRepaintNeeded := True;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuShowLightSourceClick(Sender: TObject);
|
||
begin
|
||
tbNoDraw.Down := acNoDraw.Checked;
|
||
RebuildScreenBuffer;
|
||
FRepaintNeeded := True;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuShowGridClick(Sender: TObject);
|
||
begin
|
||
tbTerrain.Down := acTerrain.Checked;
|
||
mnuShowBlocks.Checked := False;
|
||
RebuildScreenBuffer;
|
||
FRepaintNeeded := True;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuShowBlocksClick(Sender: TObject);
|
||
begin
|
||
tbTerrain.Down := acTerrain.Checked;
|
||
mnuShowGrid.Checked := False;
|
||
RebuildScreenBuffer;
|
||
FRepaintNeeded := True;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuShowStaticsOptionClick(Sender: TObject);
|
||
begin
|
||
tbStatics.Down := acStatics.Checked;
|
||
RebuildScreenBuffer;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuFlushClick(Sender: TObject);
|
||
begin
|
||
dmNetwork.Send(TFlushServerPacket.Create);
|
||
end;
|
||
|
||
procedure TfrmMain.mnuGoToClientClick(Sender: TObject);
|
||
var
|
||
mpos: TPoint;
|
||
node: PVirtualNode;
|
||
clientInfo: PClientInfo;
|
||
begin
|
||
mpos := vstClients.ScreenToClient(Mouse.CursorPos);
|
||
node := vstClients.GetNodeAt(mpos.X, mpos.Y);// .GetFirstSelected;
|
||
if node <> nil then
|
||
begin
|
||
clientInfo := vstClients.GetNodeData(node);
|
||
dmNetwork.Send(TGotoClientPosPacket.Create(clientInfo^.Name));
|
||
end;
|
||
|
||
end;
|
||
|
||
procedure TfrmMain.mnuGrabTileIDClick(Sender: TObject);
|
||
var
|
||
internalTileID: LongWord;
|
||
item: PVirtualItem;
|
||
tileInfo: PTileInfo;
|
||
treeNode: PVirtualNode;
|
||
|
||
function TileInNode(Node: PVirtualNode; TileID: LongWord) : Boolean;
|
||
var
|
||
nodeData: ^TGroupNode;
|
||
i: Integer;
|
||
begin
|
||
Result := False;
|
||
nodeData := tvGroups.GetNodeData(Node);
|
||
for i := 0 to nodeData^.Count - 1 do
|
||
begin
|
||
if nodeData^.GTile[i].ID = TileID then
|
||
begin
|
||
Result := True;
|
||
break;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
begin
|
||
Logger.Send([lcClient, lcDebug], 'TfrmMain.mnuGrabTileIDClick', TRUE);
|
||
if CurrentTile <> nil then
|
||
begin
|
||
internalTileID := GetInternalTileID(CurrentTile);
|
||
|
||
// Выбираем группы
|
||
if (not cbStatics.Checked) and (not cbTerrain.Checked) then
|
||
begin
|
||
treeNode := tvGroups.GetFirst();
|
||
while treeNode <> nil do
|
||
begin
|
||
if TileInNode(treeNode, internalTileID) then
|
||
begin
|
||
tvGroups.Selected[treeNode] := True;
|
||
tvGroups.FocusedNode := treeNode;
|
||
if toMultiSelect in tvGroups.TreeOptions.SelectionOptions
|
||
then break;
|
||
end;
|
||
treeNode := tvGroups.GetNext(treeNode);
|
||
end;
|
||
end;
|
||
|
||
Logger.Send([lcClient, lcDebug], 'TfrmMain.mnuGrabTileIDClick', internalTileID);
|
||
// Выбираем тайл
|
||
item := vdtTiles.GetFirst;
|
||
while item <> nil do
|
||
begin
|
||
tileInfo := vdtTiles.GetNodeData(item);
|
||
if tileInfo^.ID = internalTileID then
|
||
begin
|
||
vdtTiles.ClearSelection;
|
||
vdtTiles.Selected[item] := True;
|
||
vdtTiles.FocusedNode := item;
|
||
Break;
|
||
end;
|
||
item := vdtTiles.GetNext(item);
|
||
end;
|
||
end;
|
||
Logger.Send([lcClient, lcDebug], 'TfrmMain.mnuGrabTileIDClick', FALSE);
|
||
end;
|
||
|
||
procedure TfrmMain.mnuGrabHueClick(Sender: TObject);
|
||
begin
|
||
if CurrentTile is TStaticItem then
|
||
begin
|
||
frmHueSettings.lbHue.ItemIndex := TStaticItem(CurrentTile).Hue;
|
||
frmFilter.JumpToHue(TStaticItem(CurrentTile).Hue);
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuGrabFilterTileIDClick(Sender: TObject);
|
||
begin
|
||
if CurrentTile is TStaticItem then
|
||
begin
|
||
frmFilter.AddTile(GetInternalTileID(CurrentTile));
|
||
frmFilter.cbTileFilter.Checked := True;
|
||
frmMain.InvalidateFilter;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuGrabFilterHueClick(Sender: TObject);
|
||
begin
|
||
if CurrentTile is TStaticItem then
|
||
begin
|
||
frmFilter.AddHue(TStaticItem(CurrentTile).Hue);
|
||
frmFilter.cbHueFilter.Checked := True;
|
||
frmMain.InvalidateFilter;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuGrabVirtualLayerZClick(Sender: TObject);
|
||
begin
|
||
frmVirtualLayer.seZ.Value := CurrentTile.Z;
|
||
frmVirtualLayer.seZChange(frmVirtualLayer.seZ);
|
||
if not frmVirtualLayer.cbShowLayer.Checked then
|
||
begin
|
||
frmVirtualLayer.cbShowLayer.Checked := True;
|
||
frmMain.InvalidateScreenBuffer;
|
||
end;
|
||
//cursorNeedsUpdate := True;
|
||
//Handled := True;
|
||
end;
|
||
|
||
procedure TfrmMain.GrabBoundaries(Sender: TObject);
|
||
begin
|
||
if Sender = mnuGrabBoundMinZ then begin
|
||
frmBoundaries.seMinZ.Value := CurrentTile.Z; frmBoundaries.seMinZChange(nil); end
|
||
else if Sender = mnuGrabBoundMaxZ then begin
|
||
frmBoundaries.seMaxZ.Value := CurrentTile.Z; frmBoundaries.seMaxZChange(nil); end
|
||
else if Sender = mnuGrabBoundMinX then begin
|
||
frmBoundaries.seMinX.Value := CurrentTile.X; frmBoundaries.seMinXChange(nil); end
|
||
else if Sender = mnuGrabBoundMaxX then begin
|
||
frmBoundaries.seMaxX.Value := CurrentTile.X; frmBoundaries.seMaxXChange(nil); end
|
||
else if Sender = mnuGrabBoundMinY then begin
|
||
frmBoundaries.seMinY.Value := CurrentTile.Y; frmBoundaries.seMinYChange(nil); end
|
||
else if Sender = mnuGrabBoundMaxY then begin
|
||
frmBoundaries.seMaxY.Value := CurrentTile.Y; frmBoundaries.seMaxYChange(nil); end;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuLargeScaleCommandsClick(Sender: TObject);
|
||
begin
|
||
frmLargeScaleCommand.Show;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuRegionControlClick(Sender: TObject);
|
||
begin
|
||
frmRegionControl.Show;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuShowAnimationsClick(Sender: TObject);
|
||
begin
|
||
FTextureManager.UseAnims := mnuShowAnimations.Checked;
|
||
RebuildScreenBuffer;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuShutdownClick(Sender: TObject);
|
||
begin
|
||
dmNetwork.Send(TQuitServerPacket.Create(''));
|
||
end;
|
||
|
||
|
||
|
||
procedure TfrmMain.mnuWhiteBackgroundClick(Sender: TObject);
|
||
begin
|
||
FRepaintNeeded := True;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuWindowedModeClick(Sender: TObject);
|
||
var btn: Integer;
|
||
begin
|
||
btn := MessageDlg(lbDlgWindowedModeSwitchCaption, lbDlgWindowedModeSwitch,
|
||
mtConfirmation, mbYesNoCancel, 0);
|
||
// btn=2=mbCancel; btn=6=mbYes; btn=7=mbNo;
|
||
// Почему так хз, по идее btn=ord(mbCancel) или TMsgDlgBtn(btn)=mbCancel,
|
||
// но этой чертовой среде ничего нравитсо ("Pascale must die")
|
||
if btn = 2 then mnuWindowedMode.Checked := not mnuWindowedMode.Checked else begin
|
||
XMLPropStorage1.Save;
|
||
if btn = 6 then begin
|
||
XMLPropStorage1.Restore;
|
||
dmNetwork.Disconnect;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuZoomClick(Sender: TObject);
|
||
var
|
||
zoom : Single;
|
||
cache: Integer;
|
||
begin
|
||
|
||
if Sender = tbZoom then begin
|
||
if tbZoom.Down then mnuZoomClick(mnuZoom100)
|
||
else case tbZoom.Tag of
|
||
250: mnuZoomClick(mnuZoom025);
|
||
333: mnuZoomClick(mnuZoom033);
|
||
500: mnuZoomClick(mnuZoom050);
|
||
750: mnuZoomClick(mnuZoom075);
|
||
1000: mnuZoomClick(mnuZoom100);
|
||
1500: mnuZoomClick(mnuZoom150);
|
||
2000: mnuZoomClick(mnuZoom200);
|
||
3000: mnuZoomClick(mnuZoom300);
|
||
4000: mnuZoomClick(mnuZoom400);
|
||
end;
|
||
exit;
|
||
end;
|
||
|
||
if (Sender as TMenuItem).Checked then begin
|
||
if mnuZoom100 <> Sender then
|
||
mnuZoomClick(mnuZoom100);
|
||
exit;
|
||
end;
|
||
|
||
(Sender as TMenuItem).Checked := True;
|
||
if mnuZoom025 <> Sender then mnuZoom025.Checked:= False else begin zoom:=0.250; cache:=4096; end;
|
||
if mnuZoom033 <> Sender then mnuZoom033.Checked:= False else begin zoom:=0.333; cache:=2048; end;
|
||
if mnuZoom050 <> Sender then mnuZoom050.Checked:= False else begin zoom:=0.500; cache:=1024; end;
|
||
if mnuZoom075 <> Sender then mnuZoom075.Checked:= False else begin zoom:=0.750; cache:= 512; end;
|
||
if mnuZoom100 <> Sender then mnuZoom100.Checked:= False else begin zoom:=1.000; cache:= 256; end;
|
||
if mnuZoom150 <> Sender then mnuZoom150.Checked:= False else begin zoom:=1.500; cache:= 128; end;
|
||
if mnuZoom200 <> Sender then mnuZoom200.Checked:= False else begin zoom:=2.000; cache:= 64; end;
|
||
if mnuZoom300 <> Sender then mnuZoom300.Checked:= False else begin zoom:=3.000; cache:= 32; end;
|
||
if mnuZoom400 <> Sender then mnuZoom400.Checked:= False else begin zoom:=4.000; cache:= 16; end;
|
||
|
||
cache := 2 * Trunc(Sqrt(oglGameWindow.Width * oglGameWindow.Width +
|
||
oglGamewindow.Height * oglGamewindow.Height) / (44 * zoom));
|
||
cache := cache*cache;
|
||
|
||
//cache := 4096;
|
||
FLandscape.ResizeBlockCache(cache);
|
||
|
||
if zoom < 1.0 then tbZoom.ImageIndex:= 37 else
|
||
if zoom > 1.0 then tbZoom.ImageIndex:= 36 else
|
||
tbZoom.ImageIndex:= 35;
|
||
tbZoom.Down := zoom <> 1.0;
|
||
if zoom <> 1.0 then
|
||
tbZoom.Tag := Trunc(zoom * 1000.0);
|
||
|
||
FRepaintNeeded := True;
|
||
RebuildScreenBuffer;
|
||
end;
|
||
|
||
procedure TfrmMain.oglGameWindowDblClick(Sender: TObject);
|
||
begin
|
||
if (acSelect.Checked) and (CurrentTile <> nil) then
|
||
btnAddRandomClick(Sender);
|
||
end;
|
||
|
||
procedure TfrmMain.oglGameWindowKeyDown(Sender: TObject; var Key: Word;
|
||
Shift: TShiftState);
|
||
var step, zoomfactor: Integer;
|
||
begin
|
||
if tbZoom.Down then zoomfactor := tbZoom.Tag else zoomfactor := 1000;
|
||
if Shift = [ssShift]
|
||
then step := 1
|
||
else if Shift = []
|
||
then step := 8000 div zoomfactor
|
||
else exit;
|
||
|
||
case Key of
|
||
VK_W, VK_NUMPAD8, VK_UP: MoveBy(-step, -step);
|
||
VK_S, VK_NUMPAD2, VK_DOWN: MoveBy(+step, +step);
|
||
VK_A, VK_NUMPAD4, VK_LEFT: MoveBy(-step, +step);
|
||
VK_D, VK_NUMPAD6, VK_RIGHT: MoveBy(+step, -step);
|
||
VK_Q, VK_NUMPAD7: MoveBy(-step, 0);
|
||
VK_E, VK_NUMPAD9: MoveBy(0, -step);
|
||
VK_Y, VK_NUMPAD1: MoveBy(0, +step);
|
||
VK_G, VK_NUMPAD3: MoveBy(+step, 0);
|
||
VK_SPACE: if frmFilter.Visible then begin
|
||
frmFilter.Locked := True;
|
||
frmFilter.Hide;
|
||
frmFilter.Locked := False;
|
||
end else frmFilter.Show;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.oglGameWindowMouseDown(Sender: TObject;
|
||
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
||
begin
|
||
Logger.EnterMethod([lcClient, lcDebug], 'MouseDown');
|
||
try
|
||
if Button = mbRight then
|
||
pmTools.PopUp(Mouse.CursorPos.X, Mouse.CursorPos.Y);
|
||
|
||
if Button = mbMiddle then
|
||
tmGrabTileInfoTimer(Sender);
|
||
|
||
if Button <> mbLeft then
|
||
Exit;
|
||
|
||
UpdateCurrentTile(X, Y);
|
||
if FOverlayUI.ActiveArrow > -1 then
|
||
tmMovement.Enabled := True;
|
||
|
||
SelectedTile := CurrentTile;
|
||
if CurrentTile = nil then Exit;
|
||
|
||
if acSelect.Checked then //***** Selection Mode *****//
|
||
tmGrabTileInfo.Enabled := True;
|
||
|
||
FRepaintNeeded := True;
|
||
finally
|
||
Logger.ExitMethod([lcClient, lcDebug], 'MouseDown');
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.oglGameWindowMouseEnter(Sender: TObject);
|
||
begin
|
||
if Active then
|
||
oglGameWindow.SetFocus;
|
||
|
||
FOverlayUI.Visible := True;
|
||
|
||
if (frmFilter.Visible and mnuAutoShowFilterWindow.Checked) then
|
||
begin
|
||
frmFilter.Locked := True;
|
||
frmFilter.Hide;
|
||
frmFilter.Locked := False;
|
||
end;
|
||
|
||
FRepaintNeeded := True;
|
||
end;
|
||
|
||
procedure TfrmMain.oglGameWindowMouseLeave(Sender: TObject);
|
||
begin
|
||
if not (frmConfirmation.Visible or
|
||
(frmMoveSettings.Visible and (fsModal in frmMoveSettings.FormState))
|
||
) then //during confirmation the mouse would leave ...
|
||
begin
|
||
CurrentTile := nil;
|
||
FOverlayUI.Visible := False;
|
||
end;
|
||
|
||
FRepaintNeeded := True;
|
||
end;
|
||
|
||
procedure TfrmMain.oglGameWindowMouseMove(Sender: TObject; Shift: TShiftState;
|
||
X, Y: Integer);
|
||
var
|
||
lastTile: TWorldItem;
|
||
offsetX, offsetY: Integer;
|
||
begin
|
||
//Logger.EnterMethod([lcClient, lcDebug], 'MouseMove');
|
||
lastTile := CurrentTile;
|
||
|
||
if ssMiddle in Shift then
|
||
begin
|
||
UpdateCurrentTile(X, Y);
|
||
if (lastTile <> nil) and (CurrentTile <> nil) and (lastTile <> CurrentTile) then
|
||
begin
|
||
offsetX := lastTile.X - CurrentTile.X;
|
||
offsetY := lastTile.Y - CurrentTile.Y;
|
||
if InRange(offsetX, -8, 8) and InRange(offsetY, -8, 8) then
|
||
SetPos(FX - offsetX, FY - offsetY);
|
||
end;
|
||
end;
|
||
|
||
UpdateCurrentTile(X, Y);
|
||
|
||
FRepaintNeeded := True;
|
||
//Logger.ExitMethod([lcClient, lcDebug], 'MouseMove');
|
||
end;
|
||
|
||
procedure TfrmMain.oglGameWindowMouseUp(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
var
|
||
map: TMapCell;
|
||
i: Integer;
|
||
z: ShortInt;
|
||
blockInfo: PBlockInfo;
|
||
targetRect: TRect;
|
||
offsetX, offsetY: Integer;
|
||
item: TWorldItem;
|
||
tileX, tileY, newX, newY: Word;
|
||
targetBlocks: TBlockInfoList; //а в чем разница с targetTiles: TWorldItemList; ?
|
||
targetTile: TWorldItem;
|
||
begin
|
||
Logger.EnterMethod([lcClient, lcDebug], 'MouseUp');
|
||
if Button <> mbLeft then
|
||
begin
|
||
Logger.ExitMethod([lcClient, lcDebug], 'MouseUp');
|
||
Exit;
|
||
end;
|
||
|
||
UpdateCurrentTile(X, Y);
|
||
tmMovement.Enabled := False;
|
||
if CurrentTile = nil then
|
||
begin
|
||
SelectedTile := nil;
|
||
Logger.ExitMethod([lcClient, lcDebug], 'MouseUp');
|
||
Exit;
|
||
end;
|
||
|
||
targetTile := CurrentTile;
|
||
|
||
if acSelect.Checked then
|
||
begin
|
||
if tmGrabTileInfo.Enabled then
|
||
begin
|
||
tmGrabTileInfo.Enabled := False;
|
||
mnuGrabTileIDClick(nil);
|
||
end;
|
||
|
||
for i := FSelectionListeners.Count - 1 downto 0 do
|
||
FSelectionListeners[i](CurrentTile);
|
||
end;
|
||
|
||
if (not acSelect.Checked) and (targetTile <> nil) and (SelectedTile <> nil) then
|
||
begin
|
||
targetRect := GetSelectedRect;
|
||
FUndoList := GetNextUndoList;
|
||
|
||
if (SelectedTile = targetTile) or ConfirmAction then
|
||
begin
|
||
if acDraw.Checked then //***** Drawing Mode *****//
|
||
begin
|
||
for tileX := FSelection.Left-1 to FSelection.Right do
|
||
for tileY := FSelection.Top-1 to FSelection.Bottom do
|
||
begin
|
||
map := FLandscape.MapCell[tileX, tileY];
|
||
if map.IsGhost then
|
||
begin
|
||
FUndoList^.Add(TDrawMapPacket.Create(tileX, tileY, map.RawZ, map.RawTileID));
|
||
dmNetwork.Send(TDrawMapPacket.Create(tileX, tileY, map.Z, map.TileID));
|
||
end;
|
||
end;
|
||
|
||
Logger.Send([lcClient, lcDebug], 'Virtual tiles', FVirtualTiles.Count);
|
||
for i := 0 to FVirtualTiles.Count - 1 do
|
||
begin
|
||
item := FVirtualTiles[i];
|
||
if item is TGhostTile then
|
||
begin
|
||
dmNetwork.Send(TInsertStaticPacket.Create(item.X, item.Y, item.Z, item.TileID, TGhostTile(item).Hue));
|
||
FUndoList^.Add(TDeleteStaticPacket.Create(TGhostTile(item)));
|
||
end;
|
||
end;
|
||
end else if (SelectedTile <> targetTile) or targetTile.CanBeEdited then
|
||
begin
|
||
if (not acMove.Checked) or (SelectedTile <> targetTile) or
|
||
(not frmMoveSettings.cbAsk.Checked) or ConfirmAction then
|
||
begin
|
||
targetBlocks := TBlockInfoList.Create;
|
||
if SelectedTile = targetTile then
|
||
begin
|
||
blockInfo := nil;
|
||
while FScreenBuffer.Iterate(blockInfo) do
|
||
begin
|
||
if blockInfo^.Item = targetTile then
|
||
begin
|
||
targetBlocks.Add(blockInfo);
|
||
Break;
|
||
end;
|
||
end;
|
||
end else
|
||
begin
|
||
blockInfo := nil;
|
||
while FScreenBuffer.Iterate(blockInfo) do
|
||
begin
|
||
if (blockInfo^.State = ssNormal) and
|
||
blockInfo^.Item.CanBeEdited and
|
||
IsInRect(blockInfo^.Item.X, blockInfo^.Item.Y, targetRect) then
|
||
begin
|
||
targetBlocks.Add(blockInfo);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
if acMove.Checked then //***** Move item *****//
|
||
begin
|
||
offsetX := frmMoveSettings.GetOffsetX;
|
||
offsetY := frmMoveSettings.GetOffsetY;
|
||
|
||
if (frmMoveSettings.cbLand.Checked) then begin
|
||
if offsetX >= 0 then newX := $7FFF else newX := 0;
|
||
if offsetY >= 0 then newY := $7FFF else newY := 0;
|
||
for i := 0 to targetBlocks.Count - 1 do if (targetBlocks.Items[i]^.Item is TMapCell) then begin
|
||
if offsetX >= 0 then newX := min(newX, targetBlocks.Items[i]^.Item.X) else newX := max(newX, targetBlocks.Items[i]^.Item.X - 1);
|
||
if offsetY >= 0 then newY := min(newY, targetBlocks.Items[i]^.Item.Y) else newY := max(newY, targetBlocks.Items[i]^.Item.Y - 1);
|
||
end;
|
||
|
||
tileX := 0;
|
||
if offsetY > 0 then for i := newY to newY + offsetY do inc(tileX, FLandscape.MapCell[newX,i].RawZ+128) else
|
||
if offsetY < 0 then for i := newY + offsetY to newY do inc(tileX, FLandscape.MapCell[newX,i].RawZ+128);
|
||
if offsetX > 0 then for i := newX to newX + offsetX do inc(tileX, FLandscape.MapCell[i,newY].RawZ+128) else
|
||
if offsetX < 0 then for i := newX + offsetX to newX do inc(tileX, FLandscape.MapCell[i,newY].RawZ+128);
|
||
if (offsetX <> 0) and (offsetY <> 0)
|
||
then tileY := tileX div (abs(offsetX) + abs(offsetY) + 2)
|
||
else tileY := tileX div (abs(offsetX) + abs(offsetY) + 1);
|
||
z := max(-128, min(tileY - 128, +127));
|
||
end;
|
||
|
||
for i := 0 to targetBlocks.Count - 1 do
|
||
begin
|
||
if frmMoveSettings.cbLand.Checked and (((offsetY > 0) or (offsetX > 0)) and not ((offsetY > 0) and (offsetX < 0)))
|
||
then tileY := abs(i - targetBlocks.Count + 1) else tileY := i;
|
||
item := targetBlocks.Items[tileY]^.Item;
|
||
|
||
if (frmMoveSettings.cbItem.Checked) and (item is TStaticItem) then begin
|
||
newX := EnsureRange(item.X + offsetX, 0, FLandscape.CellWidth - 1);
|
||
newY := EnsureRange(item.Y + offsetY, 0, FLandscape.CellHeight - 1);
|
||
FUndoList^.Add(TMoveStaticPacket.Create(newX, newY, item.Z, item.TileID, TStaticItem(item).Hue, item.X, item.Y));
|
||
dmNetwork.Send(TMoveStaticPacket.Create(TStaticItem(item), newX, newY));
|
||
end;
|
||
if (frmMoveSettings.cbLand.Checked) and (item is TMapCell) then begin
|
||
newX := EnsureRange(item.X + offsetX, 0, FLandscape.CellWidth - 1);
|
||
newY := EnsureRange(item.Y + offsetY, 0, FLandscape.CellHeight - 1);
|
||
map := FLandscape.MapCell[newX, newY];
|
||
|
||
// Это не очень хорошо, для оптимизации следует ввести специальный пакет TMoveMapPacket
|
||
FUndoList^.Add(TDrawMapPacket.Create(item.X, item.Y, item.Z, item.TileID));
|
||
FUndoList^.Add(TDrawMapPacket.Create(newX, newY, map.RawZ, map.TileID));
|
||
dmNetwork.Send(TDrawMapPacket.Create(item.X, item.Y, z, $0001));
|
||
dmNetwork.Send(TDrawMapPacket.Create(newX, newY, item.Z, item.TileID));
|
||
|
||
end;
|
||
end;
|
||
end else if acElevate.Checked then //***** Elevate item *****//
|
||
begin
|
||
for i := 0 to targetBlocks.Count - 1 do
|
||
begin
|
||
item := targetBlocks.Items[i]^.Item;
|
||
|
||
z := frmElevateSettings.seZ.Value;
|
||
if frmElevateSettings.rbRaise.Checked then
|
||
z := EnsureRange(item.Z + z, -128, 127)
|
||
else if frmElevateSettings.rbLower.Checked then
|
||
z := EnsureRange(item.Z - z, -128, 127);
|
||
|
||
if item is TMapCell then
|
||
begin
|
||
if frmElevateSettings.cbRandomHeight.Checked then
|
||
Inc(z, Random(frmElevateSettings.seRandomHeight.Value));
|
||
FUndoList^.Add(TDrawMapPacket.Create(item.X, item.Y, item.Z,
|
||
item.TileID));
|
||
dmNetwork.Send(TDrawMapPacket.Create(item.X, item.Y, z,
|
||
item.TileID));
|
||
end else
|
||
begin
|
||
FUndoList^.Add(TElevateStaticPacket.Create(item.X, item.Y,
|
||
z, item.TileID, TStaticItem(item).Hue, item.Z));
|
||
dmNetwork.Send(TElevateStaticPacket.Create(TStaticItem(item), z));
|
||
end;
|
||
end;
|
||
end else if acDelete.Checked then //***** Delete item *****//
|
||
begin
|
||
Logger.Send([lcClient, lcDebug], 'targetBlocks.Count', targetBlocks.Count);
|
||
for i := 0 to targetBlocks.Count - 1 do
|
||
begin
|
||
item := targetBlocks.Items[i]^.Item;
|
||
if item is TStaticItem then
|
||
begin
|
||
FUndoList^.Add(TInsertStaticPacket.Create(item.X, item.Y,
|
||
item.Z, item.TileID, TStaticItem(item).Hue));
|
||
dmNetwork.Send(TDeleteStaticPacket.Create(TStaticItem(item)));
|
||
end;
|
||
end;
|
||
end else if acHue.Checked then //***** Hue item *****//
|
||
begin
|
||
for i := 0 to targetBlocks.Count - 1 do
|
||
begin
|
||
blockInfo := targetBlocks.Items[i];
|
||
item := blockInfo^.Item;
|
||
|
||
if blockInfo^.HueOverride and (item is TStaticItem) then
|
||
begin
|
||
if TStaticItem(item).Hue <> blockInfo^.Hue then
|
||
begin
|
||
FUndoList^.Add(THueStaticPacket.Create(item.X, item.Y, item.Z,
|
||
item.TileID, blockInfo^.Hue, TStaticItem(item).Hue));
|
||
dmNetwork.Send(THueStaticPacket.Create(TStaticItem(item),
|
||
blockInfo^.Hue));
|
||
end;
|
||
end;
|
||
end;
|
||
blockInfo := nil;
|
||
end;
|
||
|
||
targetBlocks.Free;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
acUndo.Enabled := FUndoList^.Count > 0;
|
||
SelectedTile := nil;
|
||
FRepaintNeeded := True;
|
||
Logger.ExitMethod([lcClient, lcDebug], 'MouseUp');
|
||
end;
|
||
|
||
procedure TfrmMain.oglGameWindowMouseWheel(Sender: TObject; Shift: TShiftState;
|
||
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
|
||
var
|
||
cursorNeedsUpdate: Boolean;
|
||
newZ: ShortInt;
|
||
begin
|
||
//We want single steps ...
|
||
WheelDelta := WheelDelta div WHEEL_DELTA;
|
||
|
||
if ((Word(GetKeyState(VK_X)) and $8000)<>0) then begin
|
||
if (Shift = [ssCtrl]) then begin
|
||
frmBoundaries.seMinX.Value := frmBoundaries.seMinX.Value + min(max(WheelDelta,
|
||
frmBoundaries.seMinX.MinValue-frmBoundaries.seMinX.Value),
|
||
frmBoundaries.seMinX.MaxValue-frmBoundaries.seMinX.Value);
|
||
frmBoundaries.seMinXChange(nil); exit; end
|
||
else if (Shift = [ssShift]) then begin
|
||
frmBoundaries.seMaxX.Value := frmBoundaries.seMaxX.Value + min(max(WheelDelta,
|
||
frmBoundaries.seMaxX.MinValue-frmBoundaries.seMaxX.Value),
|
||
frmBoundaries.seMaxX.MaxValue-frmBoundaries.seMaxX.Value);
|
||
frmBoundaries.seMaxXChange(nil); exit; end;
|
||
end else if ((Word(GetKeyState(VK_C)) and $8000)<>0) then begin
|
||
if (Shift = [ssCtrl]) then begin
|
||
frmBoundaries.seMinY.Value := frmBoundaries.seMinY.Value + min(max(WheelDelta,
|
||
frmBoundaries.seMinY.MinValue-frmBoundaries.seMinY.Value),
|
||
frmBoundaries.seMinY.MaxValue-frmBoundaries.seMinY.Value);
|
||
frmBoundaries.seMinYChange(nil); exit; end
|
||
else if (Shift = [ssShift]) then begin
|
||
frmBoundaries.seMaxY.Value := frmBoundaries.seMaxY.Value + min(max(WheelDelta,
|
||
frmBoundaries.seMaxY.MinValue-frmBoundaries.seMaxY.Value),
|
||
frmBoundaries.seMaxY.MaxValue-frmBoundaries.seMaxY.Value);
|
||
frmBoundaries.seMaxYChange(nil); exit; end;
|
||
end else begin
|
||
if (Shift = [ssCtrl]) then begin
|
||
frmBoundaries.seMinZ.Value := frmBoundaries.seMinZ.Value + min(max(WheelDelta,
|
||
frmBoundaries.seMinZ.MinValue-frmBoundaries.seMinZ.Value),
|
||
frmBoundaries.seMinZ.MaxValue-frmBoundaries.seMinZ.Value);
|
||
frmBoundaries.seMinZChange(nil); exit; end
|
||
else if (Shift = [ssShift]) then begin
|
||
frmBoundaries.seMaxZ.Value := frmBoundaries.seMaxZ.Value + min(max(WheelDelta,
|
||
frmBoundaries.seMaxZ.MinValue-frmBoundaries.seMaxZ.Value),
|
||
frmBoundaries.seMaxZ.MaxValue-frmBoundaries.seMaxZ.Value);
|
||
frmBoundaries.seMaxZChange(nil); exit; end;
|
||
end;
|
||
|
||
|
||
if CurrentTile = nil then
|
||
Exit;
|
||
|
||
cursorNeedsUpdate := False;
|
||
if (CurrentTile is TVirtualTile) or ((ssCtrl in Shift) and
|
||
(frmVirtualLayer.cbShowLayer.Checked)) then
|
||
begin
|
||
frmVirtualLayer.seZ.Value := EnsureRange(frmVirtualLayer.seZ.Value +
|
||
WheelDelta, -128, 127);
|
||
frmVirtualLayer.seZChange(frmVirtualLayer.seZ);
|
||
cursorNeedsUpdate := True;
|
||
Handled := True;
|
||
end else if not (ssCtrl in Shift) then
|
||
begin
|
||
FUndoList := GetNextUndoList;
|
||
newZ := EnsureRange(CurrentTile.Z + WheelDelta, -128, 127);
|
||
if CurrentTile is TStaticItem then
|
||
begin
|
||
FUndoList^.Add(TElevateStaticPacket.Create(CurrentTile.X, CurrentTile.Y,
|
||
newZ, CurrentTile.TileID, TStaticItem(CurrentTile).Hue,
|
||
CurrentTile.Z));
|
||
dmNetwork.Send(TElevateStaticPacket.Create(TStaticItem(CurrentTile),
|
||
newZ));
|
||
cursorNeedsUpdate := True;
|
||
Handled := True;
|
||
end else if CurrentTile is TMapCell then
|
||
begin
|
||
FUndoList^.Add(TDrawMapPacket.Create(CurrentTile.X, CurrentTile.Y,
|
||
CurrentTile.Z, CurrentTile.TileID));
|
||
dmNetwork.Send(TDrawMapPacket.Create(CurrentTile.X, CurrentTile.Y,
|
||
newZ, CurrentTile.TileID));
|
||
Handled := True;
|
||
end;
|
||
acUndo.Enabled := FUndoList^.Count > 0;
|
||
end;
|
||
|
||
if cursorNeedsUpdate then
|
||
begin
|
||
SetCursorPos(Mouse.CursorPos.X, Mouse.CursorPos.Y - 4 * WheelDelta);
|
||
UpdateCurrentTile(MousePos.X, MousePos.Y - 4 * WheelDelta);
|
||
end;
|
||
|
||
FRepaintNeeded := True;
|
||
end;
|
||
|
||
procedure TfrmMain.FormCreate(Sender: TObject);
|
||
var
|
||
i : Integer;
|
||
ARegistry: TRegistry;
|
||
begin
|
||
Logger.EnterMethod([lcLandscape, lcDebug], 'TfrmMain.FormCreate(Sender: TObject)');
|
||
|
||
// Подменяем TLazVirtualDrawTree на его перегруженный аналог TVirtualList
|
||
vdtTiles := TVirtualList.Create(vdtTiles);
|
||
vdtRandom := TVirtualList.Create(vdtRandom);
|
||
vdlRandom := TVirtualList(vdtRandom); // Лазареусу пчмуто не нравиться если поменять тип у vdtRandom
|
||
|
||
oglGameWindow.Cursor := +01;
|
||
pcLeft.ActivePageIndex := tsNavigation.PageIndex;
|
||
|
||
LanguageTranslate(Self);
|
||
Application.TaskBarBehavior := tbSingleButton;
|
||
|
||
{
|
||
BorderStyle := bsNone;
|
||
FormStyle := fsStayOnTop;
|
||
WindowState := wsMaximized;
|
||
Left:=0; Top:=0;
|
||
Width:=1920;
|
||
Height:=1200; }
|
||
//oglGameWindow.Visible:= false;
|
||
//oglGameWindowResize(Sender);
|
||
|
||
FConfigDir := GetAppConfigDir(False);
|
||
|
||
(*ARegistry := TRegistry.Create();
|
||
ARegistry.RootKey := HKEY_LOCAL_MACHINE;
|
||
ARegistry.OpenKey('\SOFTWARE\Quintessence\UO CentrED+', False);
|
||
|
||
FAppDir := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName));
|
||
FLocalDir := FAppDir + '..' + PathDelim + 'LocalData' + PathDelim;
|
||
if ARegistry.ReadBool('UseConfigDir')
|
||
then FConfigDir := GetAppConfigDir(False)
|
||
else FConfigDir := FLocalDir + 'UsersData' + PathDelim;
|
||
ARegistry.Free;*) //TODO cross platform
|
||
|
||
if (sprofile <> '')
|
||
then FProfileDir := FConfigDir + 'Profiles' + PathDelim + UTF8ToCP1251(sprofile) + PathDelim
|
||
else FProfileDir := '';
|
||
ForceDirectories(FConfigDir);
|
||
|
||
if (FProfileDir <> '')
|
||
then XMLPropStorage1.FileName := FProfileDir + 'Config.xml'
|
||
else XMLPropStorage1.FileName := FConfigDir + 'Config.xml';
|
||
XMLPropStorage1.Active := True;
|
||
|
||
FLandscape := ResMan.Landscape;
|
||
FLandscape.OnChange := @OnLandscapeChanged;
|
||
FLandscape.OnMapChanged := @OnMapChanged;
|
||
FLandscape.OnNewBlock := @OnNewBlock;
|
||
FLandscape.OnStaticDeleted := @OnStaticDeleted;
|
||
FLandscape.OnStaticElevated := @OnStaticElevated;
|
||
FLandscape.OnStaticHued := @OnStaticHued;
|
||
FLandscape.OnStaticInserted := @OnStaticInserted;
|
||
|
||
Logger.Send([lcClient, lcInfo], 'LoadNoDrawMap()...');
|
||
if FileExists(FProfileDir + 'VirtualTiles.xml') then
|
||
FLandscape.LoadNoDrawMap(FProfileDir + 'VirtualTiles.xml')
|
||
else begin
|
||
if FileExists(FLocalDir + 'VirtualTiles.xml') then
|
||
FLandscape.LoadNoDrawMap(FLocalDir + 'VirtualTiles.xml');
|
||
if FileExists(FConfigDir + 'VirtualTiles.xml') then
|
||
FLandscape.LoadNoDrawMap(FConfigDir + 'VirtualTiles.xml');
|
||
if FileExists(ResMan.GetFile('VirtualTiles.xml')) then
|
||
FLandscape.LoadNoDrawMap(ResMan.GetFile('VirtualTiles.xml'));
|
||
end;
|
||
|
||
FTextureManager := TLandTextureManager.Create;
|
||
FScreenBuffer := TScreenBuffer.Create;
|
||
FScreenBufferState := [];
|
||
X := 0;
|
||
Y := 0;
|
||
edX.MaxValue := FLandscape.CellWidth;
|
||
edY.MaxValue := FLandscape.CellHeight;
|
||
FOverlayUI := TOverlayUI.Create;
|
||
FLightManager := TLightManager.Create(@GetDrawOffset);
|
||
|
||
ProcessAccessLevel;
|
||
|
||
Logger.Send([lcClient, lcInfo], 'LoadLightSourceTiles()...');
|
||
if FileExists(FProfileDir + 'VirtualTiles.xml') then
|
||
LoadLightSourceTiles (FProfileDir + 'VirtualTiles.xml')
|
||
else begin
|
||
if FileExists(FLocalDir + 'VirtualTiles.xml') then
|
||
LoadLightSourceTiles (FLocalDir + 'VirtualTiles.xml');
|
||
if FileExists(FConfigDir + 'VirtualTiles.xml') then
|
||
LoadLightSourceTiles (FConfigDir + 'VirtualTiles.xml');
|
||
if FileExists(ResMan.GetFile('VirtualTiles.xml')) then
|
||
LoadLightSourceTiles (ResMan.GetFile('VirtualTiles.xml'));
|
||
end;
|
||
|
||
Logger.Send([lcClient, lcInfo], 'LoadVisibleTiles()...');
|
||
if FileExists(FProfileDir + 'VirtualTiles.xml') then
|
||
LoadVisibleTiles(FProfileDir + 'VirtualTiles.xml')
|
||
else begin
|
||
if FileExists(FLocalDir + 'VirtualTiles.xml') then
|
||
LoadVisibleTiles(FLocalDir + 'VirtualTiles.xml');
|
||
if FileExists(FConfigDir + 'VirtualTiles.xml') then
|
||
LoadVisibleTiles(FConfigDir + 'VirtualTiles.xml');
|
||
if FileExists(ResMan.GetFile('VirtualTiles.xml')) then
|
||
LoadVisibleTiles(ResMan.GetFile('VirtualTiles.xml'));
|
||
end;
|
||
|
||
Logger.Send([lcClient, lcInfo], 'LoadColorLight()...');
|
||
if FileExists(FProfileDir + 'ColorLight.xml') then
|
||
FLightManager.LoadConfig(FProfileDir + 'ColorLight.xml')
|
||
else begin
|
||
if FileExists(FLocalDir + 'ColorLight.xml') then
|
||
FLightManager.LoadConfig(FLocalDir + 'ColorLight.xml');
|
||
if FileExists(FConfigDir + 'ColorLight.xml') then
|
||
FLightManager.LoadConfig(FConfigDir + 'ColorLight.xml');
|
||
if FileExists(ResMan.GetFile('ColorLight.xml')) then
|
||
FLightManager.LoadConfig(ResMan.GetFile('ColorLight.xml'));
|
||
end;
|
||
|
||
FTilesSelectionUndoRedoCommandGroup := TUndoRedoCommandGroup.Create;
|
||
FGroupsSelectionUndoRedoCommandGroup := TUndoRedoCommandGroup.Create;
|
||
FTilesSelectionUndoRedoManager := TUndoRedoManager.Create;
|
||
FGroupsSelectionUndoRedoManager := TUndoRedoManager.Create;
|
||
tvGroups.NodeDataSize := SizeOf(TGroupNode);
|
||
vdtTiles.NodeDataSize := SizeOf(TTileInfo);
|
||
vdlRandom.NodeDataSize := SizeOf(TTileInfo);
|
||
//mnuTileListViewClick(nil);
|
||
LoadEntryTilesList;
|
||
LoadBrushTilesList;
|
||
LoadSurfsTilesList;
|
||
BuildGroupList;
|
||
BuildTileList;
|
||
Randomize;
|
||
|
||
vstChat.NodeDataSize := SizeOf(TChatInfo);
|
||
pnlChatHeader.AnchorSide[akBottom].Control := pcLeft;
|
||
pnlChatHeader.AnchorSide[akBottom].Side := asrBottom;
|
||
|
||
if FProfileDir <> ''
|
||
then FLocationsFile := FProfileDir + 'Locations.xml'
|
||
else FLocationsFile := FConfigDir + 'Locations.xml';
|
||
vstLocations.NodeDataSize := SizeOf(TLocationInfo);
|
||
LoadLocations;
|
||
|
||
vstClients.NodeDataSize := SizeOf(TClientInfo);
|
||
|
||
Logger.Send([lcClient, lcInfo], 'RegisterPacketHandler()...');
|
||
RegisterPacketHandler($0C, TPacketHandler.Create(0, @OnClientHandlingPacket));
|
||
|
||
FVLayerImage := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/VirtualLayer.tga'));
|
||
FVLightSrcImage[ 1] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24nn.tga'));
|
||
FVLightSrcImage[ 2] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24bw.tga'));
|
||
FVLightSrcImage[ 3] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24tw.tga'));
|
||
FVLightSrcImage[ 4] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24bo.tga'));
|
||
FVLightSrcImage[ 5] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24to.tga'));
|
||
FVLightSrcImage[ 6] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24by.tga'));
|
||
FVLightSrcImage[ 7] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24ty.tga'));
|
||
FVLightSrcImage[ 8] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24ny.tga'));
|
||
FVLightSrcImage[ 9] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24bl.tga'));
|
||
FVLightSrcImage[10] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24bb.tga'));
|
||
FVLightSrcImage[11] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24tb.tga'));
|
||
FVLightSrcImage[12] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24bg.tga'));
|
||
FVLightSrcImage[13] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24tg.tga'));
|
||
FVLightSrcImage[14] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24br.tga'));
|
||
FVLightSrcImage[15] := TSingleImage.CreateFromStream(ResourceManager.GetResource('Overlay/LightBulb_24bp.tga'));
|
||
|
||
FGLFont := TGLFont.Create;
|
||
FGLFont.LoadImage(ResourceManager.GetResource('GLFont/DejaVu.png'));
|
||
FGLFont.LoadFontInfo(ResourceManager.GetResource('GLFont/DejaVu.fnt'));
|
||
|
||
Logger.Send([lcClient, lcInfo], 'TWorldItemList.Create(True)...');
|
||
FVirtualTiles := TWorldItemList.Create(True);
|
||
|
||
for i:=1 to FUndoListLength do
|
||
FUndoListArray[i] := TPacketList.Create(True);
|
||
FUndoList := @FUndoListArray[1];
|
||
FUndoListFirstIndex := 0;
|
||
FundoListLastIndex := 0;
|
||
|
||
if FProfileDir <> ''
|
||
then FRandomPresetsFile := FProfileDir + 'RandomPresets.xml'
|
||
else FRandomPresetsFile := FConfigDir + 'RandomPresets.xml';
|
||
LoadRandomPresets;
|
||
|
||
Logger.Send([lcClient, lcInfo], 'Завершение загрузки...');
|
||
DoubleBuffered := True;
|
||
//pnlBottom.DoubleBuffered := True;
|
||
|
||
FAccessChangedListeners := TAccessChangedListeners.Create;
|
||
FSelectionListeners := TSelectionListeners.Create;
|
||
|
||
FLastDraw := Now;
|
||
|
||
Logger.ExitMethod([lcLandscape, lcDebug], 'TfrmMain.FormCreate(Sender: TObject)');
|
||
end;
|
||
|
||
procedure TfrmMain.btnGoToClick(Sender: TObject);
|
||
begin
|
||
SetPos(edX.Value, edY.Value);
|
||
end;
|
||
|
||
procedure TfrmMain.btnRandomPresetDeleteClick(Sender: TObject);
|
||
var
|
||
preset: TDOMElement;
|
||
begin
|
||
if cbRandomPreset.ItemIndex > -1 then
|
||
begin
|
||
preset := TDOMElement(cbRandomPreset.Items.Objects[cbRandomPreset.ItemIndex]);
|
||
FRandomPresetsDoc.DocumentElement.RemoveChild(preset);
|
||
cbRandomPreset.Items.Delete(cbRandomPreset.ItemIndex);
|
||
cbRandomPreset.ItemIndex := -1;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.btnRandomPresetSaveClick(Sender: TObject);
|
||
var
|
||
presetName: string;
|
||
i: Integer;
|
||
presetElement, tileElement: TDOMElement;
|
||
children: TDOMNodeList;
|
||
tileNode: PVirtualItem;
|
||
tileInfo: PTileInfo;
|
||
begin
|
||
presetName := cbRandomPreset.Text;
|
||
if InputQuery(lbDlgSaveRandPrsCaption, lbDlgSaveRandPrs, presetName) then
|
||
begin
|
||
presetElement := FindRandomPreset(presetName);
|
||
if presetElement = nil then
|
||
begin
|
||
presetElement := FRandomPresetsDoc.CreateElement('PresetElement');
|
||
presetElement.AttribStrings['Name'] := UTF8ToCP1251(presetName);
|
||
FRandomPresetsDoc.DocumentElement.AppendChild(presetElement);
|
||
cbRandomPreset.Items.AddObject(presetName, presetElement);
|
||
end else
|
||
begin
|
||
children := presetElement.ChildNodes;
|
||
for i := children.Count - 1 downto 0 do
|
||
presetElement.RemoveChild(children[i]);
|
||
end;
|
||
|
||
tileNode := vdlRandom.GetFirst;
|
||
while tileNode <> nil do
|
||
begin
|
||
tileInfo := vdlRandom.GetNodeData(tileNode);
|
||
tileElement := FRandomPresetsDoc.CreateElement('TileElement');
|
||
tileElement.AttribStrings['ID'] := IntToStr(tileInfo^.ID);
|
||
presetElement.AppendChild(tileElement);
|
||
tileNode := vdlRandom.GetNext(tileNode);
|
||
end;
|
||
|
||
cbRandomPreset.ItemIndex := cbRandomPreset.Items.IndexOfObject(presetElement);
|
||
|
||
SaveRandomPresets;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.cbRandomPresetChange(Sender: TObject);
|
||
var
|
||
presetElement, tileElement: TDOMElement;
|
||
tiles: TDOMNodeList;
|
||
tileNode: PVirtualItem;
|
||
tileInfo: PTileInfo;
|
||
i, id: Integer;
|
||
begin
|
||
if cbRandomPreset.ItemIndex > -1 then
|
||
begin
|
||
vdlRandom.Clear;
|
||
presetElement := TDOMElement(cbRandomPreset.Items.Objects[cbRandomPreset.ItemIndex]);
|
||
tiles := presetElement.ChildNodes;
|
||
for i := 0 to tiles.Count - 1 do
|
||
begin
|
||
tileElement := TDOMElement(tiles[i]);
|
||
if (tileElement.NodeName = 'TileElement') and
|
||
TryStrToInt(tileElement.AttribStrings['ID'], id) and
|
||
(id < FLandscape.MaxStaticID + $4000) then
|
||
begin
|
||
tileNode := vdlRandom.AddItem(nil);
|
||
tileInfo := vdlRandom.GetNodeData(tileNode);
|
||
tileInfo^.ID := id;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.btnAddRandomClick(Sender: TObject);
|
||
var
|
||
selected: PVirtualItem;
|
||
node: PVirtualItem;
|
||
sourceTileInfo, targetTileInfo: PTileInfo;
|
||
begin
|
||
vdlRandom.BeginUpdate;
|
||
selected := vdtTiles.GetFirstSelected;
|
||
while selected <> nil do
|
||
begin
|
||
sourceTileInfo := vdtTiles.GetNodeData(selected);
|
||
node := vdlRandom.AddItem(nil);
|
||
targetTileInfo := vdlRandom.GetNodeData(node);
|
||
targetTileInfo^.ID := sourceTileInfo^.ID;
|
||
targetTileInfo^.ptr := sourceTileInfo^.ptr;
|
||
selected := vdtTiles.GetNextSelected(selected);
|
||
end;
|
||
vdlRandom.EndUpdate;
|
||
end;
|
||
|
||
procedure TfrmMain.btnClearLocationsClick(Sender: TObject);
|
||
begin
|
||
if MessageDlg(lbDlgDelConfCaption, lbDlgDelConf,
|
||
mtConfirmation, [mbYes, mbNo], 0) = mrYes then
|
||
begin
|
||
vstLocations.Clear;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);
|
||
begin
|
||
if (FScreenBufferState <> CScreenBufferValid) or
|
||
((FRepaintNeeded or mnuShowAnimations.Checked) and
|
||
(MilliSecondsBetween(Now, FLastDraw) > 50)) then
|
||
begin
|
||
//Logger.Send([lcClient, lcDebug], 'Repainting Game Window');
|
||
oglGameWindow.Repaint;
|
||
FLastDraw := Now;
|
||
FRepaintNeeded := False;
|
||
end;
|
||
Sleep(1);
|
||
Done := False;
|
||
end;
|
||
|
||
procedure TfrmMain.ApplicationProperties1ShowHint(var HintStr: string;
|
||
var CanShow: Boolean; var HintInfo: THintInfo);
|
||
begin
|
||
//that check is a bit dirty, but serves its purpose
|
||
//(i.e. to set the timeout for the tile info hints)
|
||
if HintStr = '-' then
|
||
HintInfo.HideTimeout := Application.HintHidePause +
|
||
Application.HintHidePausePerChar * (Length(FTileHint.Name) +
|
||
Length(FTileHint.Obj) + Length(FTileHint.Flags));
|
||
end;
|
||
|
||
procedure TfrmMain.btnAddLocationClick(Sender: TObject);
|
||
var
|
||
locationName: string;
|
||
locationInfo: PLocationInfo;
|
||
begin
|
||
locationName := '';
|
||
if InputQuery(lbDlgNewQuerryCaption, lbDlgNewQuerry,
|
||
locationName) then
|
||
begin
|
||
locationInfo := vstLocations.GetNodeData(vstLocations.AddChild(nil));
|
||
locationInfo^.X := X;
|
||
locationInfo^.Y := Y;
|
||
locationInfo^.Name := locationName;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.acSelectExecute(Sender: TObject);
|
||
begin
|
||
acSelect.Checked := True;
|
||
tbSelect.Down := True;
|
||
mnuSelect.Checked := True;
|
||
ProcessToolState;
|
||
end;
|
||
|
||
procedure TfrmMain.acSelectionExecute(Sender: TObject);
|
||
begin
|
||
acSelection.Checked := True;
|
||
tbSelection.Down := True;
|
||
mnuSelection.Checked := True;
|
||
frmSelectionSettings.Show;
|
||
ProcessToolState;
|
||
end;
|
||
|
||
function TfrmMain.GetNextUndoList: PPacketList;
|
||
var
|
||
i: Integer;
|
||
begin
|
||
Inc(FUndoListLastIndex, 1);
|
||
if FUndoListLastIndex > FUndoListLength
|
||
then FUndoListLastIndex := 1;
|
||
|
||
if (FUndoListFirstIndex = FUndoListLastIndex) or (FUndoListFirstIndex = 0)
|
||
then Inc(FUndoListFirstIndex, 1);
|
||
if FUndoListFirstIndex > FUndoListLength
|
||
then FUndoListFirstIndex := 1;
|
||
|
||
if FUndoListFirstIndex <= FUndoListLastIndex
|
||
then i := FUndoListLastIndex - FUndoListFirstIndex + 1
|
||
else i := FUndoListLastIndex + FUndoListLength - FUndoListFirstIndex + 1;
|
||
tbUndo.Hint := lbToolbarUndo + ' (' + IntToStr(i) + ').';
|
||
|
||
FUndoListArray[FundoListLastIndex].Clear;
|
||
GetNextUndoList := @FUndoListArray[FundoListLastIndex];
|
||
end;
|
||
|
||
procedure TfrmMain.acUndoExecute(Sender: TObject);
|
||
var
|
||
i: Integer;
|
||
begin
|
||
for i := FUndoList^.Count - 1 downto 0 do
|
||
begin
|
||
dmNetwork.Send(FUndoList^[i]);
|
||
FUndoList^[i] := nil;
|
||
end;
|
||
FUndoList^.Clear;
|
||
|
||
if FUndoListLastIndex = FUndoListFirstIndex then
|
||
begin
|
||
FUndoListFirstIndex:= 0;
|
||
FUndoListLastIndex := 0;
|
||
tbUndo.Hint := lbToolbarUndo + ' (0).';
|
||
acUndo.Enabled := False;
|
||
end
|
||
else
|
||
begin
|
||
Inc(FUndoListLastIndex, -1);
|
||
if FUndoListLastIndex = 0
|
||
then FUndoListLastIndex := FUndoListLength;
|
||
FUndoList := @FUndoListArray[FundoListLastIndex];
|
||
if FUndoListFirstIndex <= FUndoListLastIndex
|
||
then i := FUndoListLastIndex - FUndoListFirstIndex + 1
|
||
else i := FUndoListLastIndex + FUndoListLength - FUndoListFirstIndex + 1;
|
||
tbUndo.Hint := lbToolbarUndo + ' (' + IntToStr(i) + ').';
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.acVirtualLayerExecute(Sender: TObject);
|
||
begin
|
||
frmVirtualLayer.Show;
|
||
end;
|
||
|
||
procedure TfrmMain.acTerrainExecute(Sender: TObject);
|
||
begin
|
||
acTerrain.Checked := not acTerrain.Checked;
|
||
//tbTerrain.Down := acTerrain.Checked;
|
||
RebuildScreenBuffer;
|
||
end;
|
||
|
||
procedure TfrmMain.acStaticsExecute(Sender: TObject);
|
||
begin
|
||
acStatics.Checked := not acStatics.Checked;
|
||
RebuildScreenBuffer;
|
||
end;
|
||
|
||
procedure TfrmMain.acWalkableExecute(Sender: TObject);
|
||
begin
|
||
InvalidateFilter;
|
||
FRepaintNeeded := True;
|
||
end;
|
||
|
||
procedure TfrmMain.acDrawExecute(Sender: TObject);
|
||
begin
|
||
acDraw.Checked := True;
|
||
tbDrawTile.Down := True;
|
||
mnuDraw.Checked := True;
|
||
frmDrawSettings.Show;
|
||
ProcessToolState;
|
||
end;
|
||
|
||
procedure TfrmMain.acFillExecute(Sender: TObject);
|
||
begin
|
||
acFill.Checked := True;
|
||
tbFill.Down := True;
|
||
mnuFill.Checked := True;
|
||
frmFillSettings.Show;
|
||
ProcessToolState;
|
||
end;
|
||
|
||
procedure TfrmMain.acDeleteExecute(Sender: TObject);
|
||
begin
|
||
acDelete.Checked := True;
|
||
tbDeleteTile.Down := True;
|
||
mnuDelete.Checked := True;
|
||
ProcessToolState;
|
||
end;
|
||
|
||
procedure TfrmMain.acBoundariesExecute(Sender: TObject);
|
||
begin
|
||
frmBoundaries.Show;
|
||
end;
|
||
|
||
procedure TfrmMain.acElevateExecute(Sender: TObject);
|
||
begin
|
||
acElevate.Checked := True;
|
||
tbElevateTile.Down := True;
|
||
mnuElevate.Checked := True;
|
||
ProcessToolState;
|
||
frmElevateSettings.Show;
|
||
end;
|
||
|
||
|
||
|
||
procedure TfrmMain.acSurfElevateExecute(Sender: TObject);
|
||
begin
|
||
acSurfElevate.Checked := True;
|
||
tbSurfElevate.Down := True;
|
||
mnuSurfElevate.Checked := True;
|
||
frmSurfElevateSettings.Show;
|
||
ProcessToolState;
|
||
end;
|
||
|
||
procedure TfrmMain.acSurfStretchExecute(Sender: TObject);
|
||
begin
|
||
acSurfStretch.Checked := True;
|
||
tbSurfStretch.Down := True;
|
||
mnuSurfStretch.Checked := True;
|
||
frmSurfStretchSettings.Show;
|
||
ProcessToolState;
|
||
end;
|
||
|
||
procedure TfrmMain.acSurfSmoothExecute(Sender: TObject);
|
||
begin
|
||
acSurfSmooth.Checked := True;
|
||
tbSurfSmooth.Down := True;
|
||
mnuSurfSmooth.Checked := True;
|
||
frmSurfSmoothSettings.Show;
|
||
ProcessToolState;
|
||
end;
|
||
|
||
procedure TfrmMain.acFilterExecute(Sender: TObject);
|
||
begin
|
||
if acFilter.Checked then
|
||
begin
|
||
frmFilter.Show;
|
||
frmFilter.Locked := False;
|
||
if (tbFilter.Down) then begin
|
||
frmFilter.tFormClose.Interval := 1500;
|
||
frmFilter.tFormClose.Tag := PtrInt(True);
|
||
frmFilter.tFormClose.Enabled := True;
|
||
end;
|
||
end else
|
||
frmFilter.Hide;
|
||
InvalidateFilter;
|
||
end;
|
||
|
||
procedure TfrmMain.acFlatExecute(Sender: TObject);
|
||
begin
|
||
acFlat.Checked := not acFlat.Checked;
|
||
RebuildScreenBuffer;
|
||
end;
|
||
|
||
procedure TfrmMain.acHueExecute(Sender: TObject);
|
||
begin
|
||
acHue.Checked := True;
|
||
tbSetHue.Down := True;
|
||
mnuSetHue.Checked := True;
|
||
ProcessToolState;
|
||
frmHueSettings.Show;
|
||
end;
|
||
|
||
procedure TfrmMain.acLightlevelExecute(Sender: TObject);
|
||
begin
|
||
frmLightlevel.Show;
|
||
end;
|
||
|
||
procedure TfrmMain.acMoveExecute(Sender: TObject);
|
||
begin
|
||
acMove.Checked := True;
|
||
tbMoveTile.Down := True;
|
||
mnuMove.Checked := True;
|
||
ProcessToolState;
|
||
frmMoveSettings.Show;
|
||
end;
|
||
|
||
procedure TfrmMain.acNoDrawExecute(Sender: TObject);
|
||
begin
|
||
acNoDraw.Checked := not acNoDraw.Checked;
|
||
RebuildScreenBuffer;
|
||
end;
|
||
|
||
procedure TfrmMain.btnClearRandomClick(Sender: TObject);
|
||
begin
|
||
vdlRandom.BeginUpdate;
|
||
vdlRandom.Clear;
|
||
vdlRandom.EndUpdate;
|
||
end;
|
||
|
||
procedure TfrmMain.btnDeleteLocationClick(Sender: TObject);
|
||
begin
|
||
vstLocations.DeleteSelectedNodes;
|
||
end;
|
||
|
||
procedure TfrmMain.btnDeleteRandomClick(Sender: TObject);
|
||
begin
|
||
vdlRandom.BeginUpdate;
|
||
vdlRandom.DeleteSelectedNodes;
|
||
vdlRandom.EndUpdate;
|
||
end;
|
||
|
||
procedure TfrmMain.cbStaticsChange(Sender: TObject);
|
||
begin
|
||
//tvGroups.Enabled := not (cbStatics.Checked or cbTerrain.Checked);
|
||
if mnuAutoHideGroupList.Checked then begin
|
||
if (((cbStatics.Checked) or (cbTerrain.Checked)) = spGroupList.Enabled)
|
||
then mnuAutoHideGroupListClick(Sender);
|
||
end else if (cbStatics.Checked or cbTerrain.Checked)
|
||
then tvGroups.ClearSelection;
|
||
|
||
//if (not cbStatics.Checked) and (not cbTerrain.Checked) then
|
||
// cbTerrain.Checked := True;
|
||
|
||
//if tvGroups.Selected <> nil then
|
||
// tvGroups.Selected := nil
|
||
//else
|
||
BuildTileList;
|
||
end;
|
||
|
||
procedure TfrmMain.cbTerrainChange(Sender: TObject);
|
||
begin
|
||
if mnuAutoHideGroupList.Checked then
|
||
if (((cbStatics.Checked) or (cbTerrain.Checked)) = spGroupList.Enabled)
|
||
then mnuAutoHideGroupListClick(Sender);
|
||
//if (not cbTerrain.Checked) and (not cbStatics.Checked) then
|
||
// cbStatics.Checked := True;
|
||
|
||
//if tvGroups.Selected <> nil then
|
||
// tvGroups.Selected := nil
|
||
//else
|
||
BuildTileList;
|
||
end;
|
||
|
||
procedure TfrmMain.tvSelectGroupsChanged(Sender: TObject);
|
||
begin
|
||
if (not cbTerrain.Checked) and (not cbStatics.Checked) then
|
||
BuildTileList;
|
||
// if Sender = cbStatics then
|
||
// MessageDlg('Ошибка', 'Тайл с указанным ID не был найден.' +
|
||
// LineEnding + 'Проверте конфликты настроек фильтров.', mtError, [mbOK], 0);
|
||
if cbTerrain.Checked then cbTerrain.Checked := False;
|
||
if cbStatics.Checked then cbStatics.Checked := False;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuReloadGroupsClick(Sender: TObject);
|
||
var
|
||
fPath : string;
|
||
begin
|
||
FreeGroupLists;
|
||
LoadEntryTilesList;
|
||
LoadBrushTilesList;
|
||
LoadSurfsTilesList;
|
||
BuildGroupList;
|
||
|
||
if FileExists(FProfileDir + 'ColorLight.xml')
|
||
then fPath := (FProfileDir + 'ColorLight.xml')
|
||
else if FileExists(FLocalDir + 'ColorLight.xml')
|
||
then fPath := (FLocalDir + 'ColorLight.xml')
|
||
else if FileExists(FConfigDir + 'ColorLight.xml')
|
||
then fPath := (FConfigDir + 'ColorLight.xml')
|
||
else if FileExists(ResMan.GetFile('ColorLight.xml'))
|
||
then fPath := (ResMan.GetFile('ColorLight.xml'))
|
||
else Exit;
|
||
FLightManager.LoadConfig(fPath);
|
||
|
||
if FileExists(FProfileDir + 'VirtualTiles.xml')
|
||
then fPath := (FProfileDir + 'VirtualTiles.xml')
|
||
else if FileExists(FLocalDir + 'VirtualTiles.xml')
|
||
then fPath := (FLocalDir + 'VirtualTiles.xml')
|
||
else if FileExists(FConfigDir + 'VirtualTiles.xml')
|
||
then fPath := (FConfigDir + 'VirtualTiles.xml')
|
||
else if FileExists(ResMan.GetFile('VirtualTiles.xml'))
|
||
then fPath := (ResMan.GetFile('VirtualTiles.xml'))
|
||
else Exit;
|
||
LoadLightSourceTiles(fPath);
|
||
LoadVisibleTiles(fPath);
|
||
end;
|
||
|
||
procedure TfrmMain.mnuSetLanguageClick(Sender: TObject);
|
||
var
|
||
settings: TIniFile;
|
||
begin
|
||
LanguageSet(Integer(TMenuItem(Sender).Tag));
|
||
ReloadLanguageTranslation();
|
||
frmMain.Menu := nil; // Перерисовываем главное меню
|
||
frmMain.Menu := MainMenu1;
|
||
ProcessAccessLevel; // Обновляем заголовок формы
|
||
|
||
// Запоминаем выбранный язык
|
||
settings := TIniFile.Create(FConfigDir + 'LoginSettings.ini');
|
||
settings.WriteString('Profile', 'Lang', TMenuItem(Sender).Caption);
|
||
settings.Free;
|
||
end;
|
||
|
||
//procedure ssrSaveHandle(handle: HWND; filepath: PChar); external 'SSRender';
|
||
//function GetDesktopWindow(): HWND; external 'SSRender';
|
||
//function GetDesktopWindow:HWND; external 'user32' name 'GetDesktopWindow';
|
||
procedure TfrmMain.mnuMakeScreenShotClick(Sender: TObject);
|
||
var
|
||
Bitmap: TBitmap;
|
||
Image: TJPEGImage;
|
||
ScreenWND: HWND;
|
||
ScreenDC: HDC;
|
||
DateTime: TDateTime;
|
||
FolderPath: string;
|
||
Refocus: Boolean;
|
||
srcRect, destRect: TRect;
|
||
oglPoint: TPoint;
|
||
begin
|
||
Bitmap:= TBitmap.Create;
|
||
Image := TJPEGImage.Create;
|
||
// We remove the focus from the window (to remove the arrows)
|
||
Refocus := oglGameWindow.Focused;
|
||
if Refocus then begin
|
||
oglGameWindowMouseLeave(Sender);
|
||
oglGameWindow.Paint;
|
||
end;
|
||
// Obtaining device context
|
||
oglGameWindow.HandleNeeded;
|
||
//TODO : ScreenWND := GetDesktopWindow();// oglGameWindow.Handle; //Handle;//0;//
|
||
ScreenDC := GetDC(ScreenWND); //GetDeviceContext(ScreenWND);
|
||
if ScreenDC<>0 then try
|
||
// We get the "buffer" screen
|
||
Bitmap.LoadFromDevice(ScreenDC);
|
||
// The size of the stored image
|
||
destRect.Left :=0;
|
||
destRect.Top :=0;
|
||
destRect.Right :=oglGameWindow.Width;
|
||
destRect.Bottom:=oglGameWindow.Height;
|
||
Image.SetSize(destRect.Right, destRect.Bottom);
|
||
// Keep the area on the screen
|
||
oglPoint.x := 0; oglPoint.y := 0;
|
||
oglPoint := oglGameWindow.ClientToScreen(oglPoint);
|
||
srcRect.Left := oglPoint.x;
|
||
srcRect.Top := oglPoint.y;
|
||
srcRect.Right := srcRect.Left + destRect.Right;
|
||
srcRect.Bottom := srcRect.Top + destRect.Bottom;
|
||
// Copy the area from the screen to the stored image
|
||
Image.Canvas.CopyRect(destRect, Bitmap.Canvas, srcRect);
|
||
// Save the file
|
||
DateTime := Now;
|
||
FolderPath := FAppDir + '../ScreenShots/' + FormatDateTime('YYYY-MM-DD', DateTime) + '/';
|
||
ForceDirectories(FolderPath);
|
||
Image.SaveToFile(FolderPath + FormatDateTime('HHNN-SSZZZ', DateTime) + '.jpg');
|
||
WriteChatMessage('System', Format('%s "./../ScreenShots/%s/%s.jpg"',
|
||
[lbScreenShotMsg, FormatDateTime('YYYY-MM-DD', DateTime), FormatDateTime('HHNN-SSZZZ', DateTime)]));
|
||
finally
|
||
if ReleaseDC(ScreenWND, ScreenDC)<>1 then
|
||
MessageDlg(lbDlgFreeDcErrCaption, lbDlgFreeDcErr, mtError, [mbOK], 0);
|
||
Bitmap.Free;
|
||
Image.Free;
|
||
end else
|
||
MessageDlg(lbDlgGetDcErrCaption, lbDlgGetDcErr, mtError, [mbOK], 0);
|
||
// Return back to the focus window (if necessary)
|
||
if Refocus then begin
|
||
oglGameWindowMouseEnter(Sender);
|
||
oglGameWindow.Paint;
|
||
end;
|
||
|
||
//DateTime := Now;
|
||
//FolderPath := FAppDir + 'ScreenShots/' + FormatDateTime('YYYY-MM-DD', DateTime) + '/';
|
||
//ForceDirectories(FolderPath);
|
||
//MessageDlg('Ошибка', Format('Handle: %d File: "%s"', [ScreenWND, FolderPath + FormatDateTime('HHNN-SSZZZ', DateTime) + '.bmp']), mtError, [mbOK], 0);
|
||
|
||
//ssrSaveHandle(ScreenWND, PChar(FolderPath + FormatDateTime('HHNN-SSZZZ', DateTime) + '.bmp'));
|
||
//oglGameWindowResize(Sender);
|
||
end;
|
||
|
||
procedure TfrmMain.edChatKeyPress(Sender: TObject; var Key: char);
|
||
begin
|
||
if Key = #13 then
|
||
begin
|
||
Key := #0;
|
||
if edChat.Text <> '' then
|
||
begin
|
||
dmNetwork.Send(TChatMessagePacket.Create(edChat.Text));
|
||
edChat.Text := '';
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.edFilterEditingDone(Sender: TObject);
|
||
var
|
||
chrtemp: char;
|
||
strtemp: string;
|
||
inttemp: Integer;
|
||
begin
|
||
strtemp := edFilter.Text;
|
||
if (Length(strtemp) > 2) and (strtemp[1] = '0') and ((strtemp[2] = 'x') or (strtemp[2] = 'X'))
|
||
then begin Delete(strtemp, 1, 1); strtemp[1] := '$'; end;
|
||
if (TryStrToInt(strtemp, inttemp)) then begin
|
||
edSearchID.Text := strtemp;
|
||
chrtemp := #13;
|
||
Self.edSearchIDKeyPress(nil, chrtemp);
|
||
edSearchID.Text := '';
|
||
edFilter.Text := '';
|
||
Exit;
|
||
end;
|
||
|
||
BuildTileList;
|
||
end;
|
||
|
||
procedure TfrmMain.FormActivate(Sender: TObject);
|
||
begin
|
||
Logger.EnterMethod([lcLandscape, lcDebug], 'TfrmMain.FormActivate(Sender: TObject)');
|
||
if oglGameWindow.MouseEntered then
|
||
oglGameWindowMouseEnter(Sender);
|
||
Logger.ExitMethod([lcLandscape, lcDebug], 'TfrmMain.FormActivate(Sender: TObject)');
|
||
end;
|
||
|
||
procedure TfrmMain.FormClose(Sender: TObject; var CloseAction: TCloseAction);
|
||
begin
|
||
frmDrawSettings.rbTileList.Checked := True;
|
||
frmDrawSettings.rbRandom.Checked := False;
|
||
dmNetwork.CheckClose(Self);
|
||
end;
|
||
|
||
procedure TfrmMain.FormDestroy(Sender: TObject);
|
||
var
|
||
i: Integer;
|
||
begin
|
||
CurrentTile := nil;
|
||
SelectedTile := nil;
|
||
|
||
SaveLocations;
|
||
SaveRandomPresets;
|
||
|
||
FreeAndNil(FTextureManager);
|
||
FreeAndNil(FScreenBuffer);
|
||
FreeAndNil(FOverlayUI);
|
||
FreeAndNil(FLightManager);
|
||
FreeAndNil(FVLayerImage);
|
||
FreeAndNil(FVLayerMaterial);
|
||
for i:=1 to FVLightSrcImageCount do
|
||
FreeAndNil(FVLightSrcImage[i]);
|
||
if FVLightSrcMaterial <> nil then begin
|
||
for i := 0 to FVLightSrcImageCount - 1 do
|
||
FreeAndNil(FVLightSrcMaterial[i]);
|
||
freemem(FVLightSrcMaterial);
|
||
FVLightSrcMaterial := nil;
|
||
end;
|
||
FreeAndNil(FVirtualTiles);
|
||
for i:=1 to FUndoListLength do
|
||
FreeAndNil(FUndoListArray[i]);
|
||
FreeAndNil(FGLFont);
|
||
FreeAndNil(FRandomPresetsDoc);
|
||
FreeAndNil(FAccessChangedListeners);
|
||
FreeAndNil(FSelectionListeners);
|
||
|
||
FreeAndNil(FTilesSelectionUndoRedoManager);
|
||
FreeAndNil(FGroupsSelectionUndoRedoManager);
|
||
FreeAndNil(FTilesSelectionUndoRedoCommandGroup);
|
||
FreeAndNil(FGroupsSelectionUndoRedoCommandGroup);
|
||
|
||
RegisterPacketHandler($0C, nil);
|
||
end;
|
||
|
||
procedure TfrmMain.edSearchIDExit(Sender: TObject);
|
||
begin
|
||
edSearchID.Visible := False;
|
||
edSearchID.Text := '';
|
||
end;
|
||
|
||
procedure TfrmMain.edSearchIDKeyPress(Sender: TObject; var Key: char);
|
||
var
|
||
enteredText: String;
|
||
tileID: Integer;
|
||
tileType: Char;
|
||
item: PVirtualItem;
|
||
tileInfo: PTileInfo;
|
||
begin
|
||
if Key = #13 then
|
||
begin
|
||
Key := #0;
|
||
enteredText := edSearchID.Text;
|
||
tileType := #0;
|
||
if Length(enteredText) > 1 then
|
||
tileType := enteredText[Length(enteredText)];
|
||
|
||
if not (tileType in ['S', 'T']) then
|
||
begin
|
||
if cbTerrain.Checked then
|
||
tileType := 'T'
|
||
else
|
||
tileType := 'S';
|
||
end else
|
||
Delete(enteredText, Length(enteredText), 1);
|
||
|
||
tileID := 0;
|
||
if not TryStrToInt(enteredText, tileID) then
|
||
begin
|
||
MessageDlg(lbDlgSearchIdErrCaption, lbDlgSearchIdErr, mtError, [mbOK], 0);
|
||
vdtTiles.SetFocus;
|
||
Exit;
|
||
end;
|
||
|
||
if tileType = 'S' then
|
||
Inc(tileID, $4000);
|
||
|
||
item := vdtTiles.GetFirst;
|
||
while item <> nil do
|
||
begin
|
||
tileInfo := vdtTiles.GetNodeData(item);
|
||
if tileInfo^.ID = tileID then
|
||
begin
|
||
vdtTiles.ClearSelection;
|
||
vdtTiles.Selected[item] := True;
|
||
vdtTiles.FocusedNode := item;
|
||
Break;
|
||
end;
|
||
item := vdtTiles.GetNext(item);
|
||
end;
|
||
|
||
if item = nil then
|
||
begin
|
||
MessageDlg(lbDlgNotFoundErrCaption, lbDlgNotFoundErr, mtError, [mbOK], 0);
|
||
vdtTiles.SetFocus;
|
||
Exit;
|
||
end;
|
||
edSearchID.Visible := False;
|
||
end else if Key = #27 then
|
||
begin
|
||
edSearchID.Visible := False;
|
||
Key := #0;
|
||
end else if not (Key in ['$', '0'..'9', 'a'..'f', 'A'..'F', 's', 'S', 't', 'T', #8])
|
||
then Key := #0;
|
||
end;
|
||
|
||
procedure TfrmMain.FormMouseDown(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
var UndoRedoManager: TUndoRedoManager;
|
||
begin
|
||
if Sender=tvGroups then UndoRedoManager:=FGroupsSelectionUndoRedoManager
|
||
else if Sender=vdtTiles then UndoRedoManager:=FTilesSelectionUndoRedoManager;
|
||
|
||
if Button = mbExtra1 then UndoRedoManager.Undo;
|
||
if Button = mbExtra2 then UndoRedoManager.Redo;
|
||
end;
|
||
|
||
procedure TfrmMain.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
|
||
var UndoRedoManager: TUndoRedoManager;
|
||
begin
|
||
if Sender=tvGroups then UndoRedoManager:=FGroupsSelectionUndoRedoManager
|
||
else if Sender=vdtTiles then UndoRedoManager:=FTilesSelectionUndoRedoManager;
|
||
|
||
if Key = VK_OEM_PLUS then UndoRedoManager.Redo;
|
||
if Key = VK_OEM_MINUS then UndoRedoManager.Undo;
|
||
if Key = VK_SPACE then if frmFilter.Visible then begin
|
||
frmFilter.Locked := True;
|
||
frmFilter.Hide;
|
||
frmFilter.Locked := False;
|
||
end else frmFilter.Show;
|
||
end;
|
||
|
||
procedure TfrmMain.FormShow(Sender: TObject);
|
||
begin
|
||
//XMLPropStorage1.Restore;
|
||
XMLPropStorage1RestoreProperties(nil);
|
||
mnuAutoHideGroupListClick(nil);
|
||
mnuAutoHideRandomListClick(nil);
|
||
end;
|
||
|
||
procedure TfrmMain.FormWindowStateChange(Sender: TObject);
|
||
//var
|
||
// ws: TWindowState;
|
||
// h: HWND;
|
||
begin
|
||
// <20>диотизм тот еще, но иначе приложение не коректно сворачивается
|
||
// Logger.Send([lcClient, lcDebug], 'Main Window State Chancged');
|
||
if frmMain.WindowState = wsMinimized then begin
|
||
if frmRadarMap.Visible then frmRadarMap.WindowState := wsMinimized;
|
||
//if frmRegionControl.Visible then frmRegionControl.WindowState := wsMinimized;
|
||
//if frmLargeScaleCommand.Visible then frmLargeScaleCommand.WindowState := wsMinimized;
|
||
//if frmAccountControl.Visible then frmAccountControl.WindowState := wsMinimized;
|
||
//if frmAbout.Visible then frmAbout.WindowState := wsMinimized;
|
||
Application.Minimize;
|
||
end; // else Application.Restore;
|
||
|
||
{h:=frmMain.Handle;
|
||
if frmMain.WindowState = wsMinimized then begin
|
||
ShowWindow(h,SW_HIDE);
|
||
SetWindowLong(h, GWL_EXSTYLE, GetWindowLong(h, GWL_EXSTYLE) and not WS_EX_OVERLAPPEDWINDOW or WS_EX_STATICEDGE);
|
||
ShowWindow(h,SW_SHOWMINIMIZED);
|
||
end else begin
|
||
//ShowInTaskBar := stDefault;
|
||
ShowWindow(h,SW_HIDE);
|
||
SetWindowLong(h, GWL_EXSTYLE, GetWindowLong(h, GWL_EXSTYLE) and not WS_EX_STATICEDGE or WS_EX_OVERLAPPEDWINDOW);
|
||
//ShowInTaskBar := stDefault;
|
||
ShowWindow(h,SW_RESTORE);
|
||
end;}
|
||
|
||
end;
|
||
|
||
procedure TfrmMain.lblChatHeaderCaptionClick(Sender: TObject);
|
||
begin
|
||
if pnlChat.Visible then
|
||
begin
|
||
pnlChat.Visible := False;
|
||
spChat.Visible := False;
|
||
pnlChatHeader.AnchorSide[akBottom].Control := pcLeft;
|
||
pnlChatHeader.AnchorSide[akBottom].Side := asrBottom;
|
||
end else
|
||
begin
|
||
spChat.Visible := True;
|
||
pnlChat.Visible := True;
|
||
spChat.Top := pnlChat.Top - spChat.Height;
|
||
pnlChatHeader.AnchorSide[akBottom].Control := spChat;
|
||
pnlChatHeader.AnchorSide[akBottom].Side := asrTop;
|
||
|
||
lblChatHeaderCaption.Font.Bold := False;
|
||
lblChatHeaderCaption.Font.Italic := False;
|
||
lblChatHeaderCaption.Font.Color := clWindowText;
|
||
|
||
edChat.SetFocus;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.lblChatHeaderCaptionMouseEnter(Sender: TObject);
|
||
begin
|
||
lblChatHeaderCaption.Font.Underline := True;
|
||
end;
|
||
|
||
procedure TfrmMain.lblChatHeaderCaptionMouseLeave(Sender: TObject);
|
||
begin
|
||
lblChatHeaderCaption.Font.Underline := False;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuAboutClick(Sender: TObject);
|
||
begin
|
||
frmAbout.ShowModal;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuAccountControlClick(Sender: TObject);
|
||
begin
|
||
frmAccountControl.Show;
|
||
frmAccountControl.BringToFront;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuTileListViewClick(Sender: TObject);
|
||
var
|
||
ViewMode: Word;
|
||
MainTile: Boolean;
|
||
AddHeight: Boolean;
|
||
|
||
function UpdateProps(VTList: TVirtualList; ViewMode: Word; AddHeight: Boolean; Update: Boolean): Boolean;
|
||
var
|
||
ColumIdx: Word;
|
||
begin
|
||
Result := False;
|
||
if ((not Update) and (Word(VTList.Tag) = ViewMode))
|
||
then Exit;
|
||
|
||
for ColumIdx := 0 to 11 do begin
|
||
VTList.Header.Columns[ColumIdx].Tag := PtrInt(-1);
|
||
VTList.Header.Columns[ColumIdx].Options := VTList.Header.Columns[ColumIdx].Options - [coVisible];
|
||
end;
|
||
|
||
case ViewMode of
|
||
4: ColumIdx := 44;
|
||
3: ColumIdx := 80;
|
||
2: ColumIdx := 96;
|
||
1: ColumIdx := 44;
|
||
end;
|
||
if (AddHeight)
|
||
then inc(ColumIdx, 14);
|
||
VTList.DefaultNodeHeight := ColumIdx;
|
||
VTList.Tag := PtrInt(ViewMode);
|
||
if (ViewMode = 1) then begin
|
||
VTList.Header.Options := VTList.Header.Options + [hoVisible];
|
||
VTList.TreeOptions.SelectionOptions := VTList.TreeOptions.SelectionOptions + [toFullRowSelect];
|
||
VTList.TreeOptions.MiscOptions := VTList.TreeOptions.MiscOptions + [toFullRowDrag];
|
||
VTList.Header.Columns[3].Options := VTList.Header.Columns[3].Options - [coVisible];
|
||
VTList.Header.Columns[13].Options := VTList.Header.Columns[13].Options - [coVisible];
|
||
end else begin
|
||
VTList.Header.Options := VTList.Header.Options - [hoVisible];
|
||
VTList.TreeOptions.SelectionOptions := VTList.TreeOptions.SelectionOptions - [toFullRowSelect];
|
||
VTList.TreeOptions.MiscOptions := VTList.TreeOptions.MiscOptions - [toFullRowDrag];
|
||
VTList.Header.Columns[3].Options := VTList.Header.Columns[3].Options + [coVisible];
|
||
VTList.Header.Columns[13].Options := VTList.Header.Columns[13].Options + [coVisible];
|
||
end;
|
||
|
||
case ViewMode of
|
||
4: begin ColumIdx := 4; ViewMode := 7; end;
|
||
3: begin ColumIdx := 8; ViewMode := 10; end;
|
||
2: begin ColumIdx := 11; ViewMode := 12; end;
|
||
1: begin ColumIdx := 0; ViewMode := 2; end;
|
||
end;
|
||
for ColumIdx := ColumIdx to ViewMode do begin
|
||
if (ViewMode <> 2)
|
||
then VTList.Header.Columns[ColumIdx].Tag := PtrInt(Word(VTList.Tag) + ColumIdx - ViewMode - 1)
|
||
else VTList.Header.Columns[ColumIdx].Tag := PtrInt(0);
|
||
VTList.Header.Columns[ColumIdx].Options := VTList.Header.Columns[ColumIdx].Options + [coVisible];
|
||
end;
|
||
|
||
VTList.BeginUpdate;
|
||
VTList.UpdateTileColumn(Word(VTList.Tag), Update);
|
||
VTList.EndUpdate;
|
||
Result := True;
|
||
end;
|
||
|
||
begin
|
||
if (Sender <> nil) then begin
|
||
mnuTileListDrawInfo.Enabled := (Sender <> mnuTileListTable);
|
||
mnuMiscTileListDrawInfo.Enabled := (Sender <> mnuMiscTileListTable);
|
||
end;
|
||
MainTile := (Sender = mnuTileListTable) or (Sender = mnuTileListSmall)
|
||
or (Sender = mnuTileListMidle) or (Sender = mnuTileListLarge);
|
||
if ((Sender = mnuTileListTable) or (Sender = mnuMiscTileListTable)) then ViewMode := 1 else
|
||
if ((Sender = mnuTileListSmall) or (Sender = mnuMiscTileListSmall)) then ViewMode := 4 else
|
||
if ((Sender = mnuTileListMidle) or (Sender = mnuMiscTileListMidle)) then ViewMode := 3 else
|
||
if ((Sender = mnuTileListLarge) or (Sender = mnuMiscTileListLarge)) then ViewMode := 2;
|
||
|
||
if ((MainTile) or (Sender = nil)) then begin
|
||
if ((Sender = nil) and (mnuTileListTable.Checked)) then ViewMode := 1 else
|
||
if ((Sender = nil) and (mnuTileListSmall.Checked)) then ViewMode := 4 else
|
||
if ((Sender = nil) and (mnuTileListMidle.Checked)) then ViewMode := 3 else
|
||
if ((Sender = nil) and (mnuTileListLarge.Checked)) then ViewMode := 2;
|
||
AddHeight := mnuTileListDrawInfo.Enabled and mnuTileListDrawInfo.Checked;
|
||
UpdateProps(vdtTiles, ViewMode, AddHeight, Sender = nil);
|
||
end;
|
||
if ((not MainTile) or (Sender = nil)) then begin
|
||
if ((Sender = nil) and (mnuMiscTileListTable.Checked)) then ViewMode := 1 else
|
||
if ((Sender = nil) and (mnuMiscTileListSmall.Checked)) then ViewMode := 4 else
|
||
if ((Sender = nil) and (mnuMiscTileListMidle.Checked)) then ViewMode := 3 else
|
||
if ((Sender = nil) and (mnuMiscTileListLarge.Checked)) then ViewMode := 2;
|
||
AddHeight := mnuMiscTileListDrawInfo.Enabled and mnuMiscTileListDrawInfo.Checked;
|
||
UpdateProps(vdlRandom, ViewMode, AddHeight, Sender = nil);
|
||
UpdateProps(frmFilter.vdtFilter, ViewMode, AddHeight, Sender = nil);
|
||
UpdateProps(frmLargeScaleCommand.vdlTerrainTiles, ViewMode, AddHeight, Sender = nil);
|
||
UpdateProps(frmLargeScaleCommand.vdlInsertStaticsTiles, ViewMode, AddHeight, Sender = nil);
|
||
UpdateProps(frmLargeScaleCommand.vdlDeleteStaticsTiles, ViewMode, AddHeight, Sender = nil);
|
||
end;
|
||
|
||
// vdtTiles.Clear;
|
||
// BuildTileList;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuTileListDrawClick(Sender: TObject);
|
||
var
|
||
dheight: Integer;
|
||
|
||
procedure UpdateHeight(TVList: TVirtualList; height: integer);
|
||
var
|
||
TVTree: TLazVirtualDrawTree;
|
||
node: PVirtualNode;
|
||
begin
|
||
TVTree := TLazVirtualDrawTree(TVList);
|
||
TVList.BeginUpdate;
|
||
TVList.DefaultNodeHeight := TVList.DefaultNodeHeight + height;
|
||
node := TVTree.GetFirst();
|
||
while (node <> nil) do begin
|
||
node^.NodeHeight := node^.NodeHeight + height;
|
||
node := TVTree.GetNext(node);
|
||
end;
|
||
TVList.EndUpdate;
|
||
end;
|
||
|
||
begin
|
||
if (Sender = mnuTileListDrawInfo) then begin
|
||
if (mnuTileListDrawInfo.Checked)
|
||
then UpdateHeight(vdtTiles, +14)
|
||
else UpdateHeight(vdtTiles, -14);
|
||
|
||
end else if (Sender = mnuMiscTileListDrawInfo) then begin
|
||
if (mnuMiscTileListDrawInfo.Checked)
|
||
then dheight := +14
|
||
else dheight := -14;
|
||
UpdateHeight(vdlRandom, dheight);
|
||
UpdateHeight(frmFilter.vdtFilter, dheight);
|
||
UpdateHeight(frmLargeScaleCommand.vdlTerrainTiles, dheight);
|
||
UpdateHeight(frmLargeScaleCommand.vdlInsertStaticsTiles, dheight);
|
||
UpdateHeight(frmLargeScaleCommand.vdlDeleteStaticsTiles, dheight);
|
||
end;
|
||
// Код является частью отрисовки OnDrawNode => ее надо принудительно вызвать
|
||
vdtTiles.Repaint;
|
||
vdlRandom.Repaint;
|
||
frmFilter.vdtFilter.Repaint;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuAutoHideGroupListClick(Sender: TObject);
|
||
begin
|
||
if mnuAutoHideGroupList.Checked then
|
||
begin
|
||
spGroupList.Enabled := (not cbTerrain.Checked) and (not cbStatics.Checked);
|
||
tvGroups.Visible := spGroupList.Enabled;
|
||
if not spGroupList.Enabled
|
||
then mnuAutoHideGroupList.Tag := spGroupList.Top;
|
||
//else mnuAutoHideGroupList.Tag := 0;
|
||
end else
|
||
begin
|
||
if mnuAutoHideGroupList.Tag > 0
|
||
then spGroupList.Top := mnuAutoHideGroupList.Tag;
|
||
mnuAutoHideGroupList.Tag := 0;
|
||
spGroupList.Enabled := True;
|
||
tvGroups.Visible := True;
|
||
end;
|
||
|
||
if spGroupList.Enabled then
|
||
begin
|
||
spGroupList.Cursor := crVSplit;
|
||
//if spGroupList.Tag > 0 then
|
||
// spGroupList.Height := spGroupList.Tag;
|
||
spGroupList.Height := 5;
|
||
end else
|
||
begin
|
||
spGroupList.Cursor := crDefault;
|
||
//spGroupList.Tag := spGroupList.Height;
|
||
spGroupList.Height := 1;
|
||
end;
|
||
|
||
spGroupListMoved(Sender);
|
||
end;
|
||
|
||
procedure TfrmMain.mnuAutoHideRandomListClick(Sender: TObject);
|
||
begin
|
||
if mnuAutoHideRandomList.Checked then
|
||
begin
|
||
if (not frmDrawSettings.rbRandom.Checked) and (Sender <> nil)
|
||
then mnuAutoHideRandomList.Tag := spTileList.Top;
|
||
//else mnuAutoHideRandomList.Tag := 0;
|
||
spTileList.Enabled := frmDrawSettings.rbRandom.Checked;
|
||
//gbRandom.Visible := frmDrawSettings.rbRandom.Checked;
|
||
cbRandomPreset.Visible := frmDrawSettings.rbRandom.Checked;
|
||
btnRandomPresetSave.Visible := frmDrawSettings.rbRandom.Checked;
|
||
btnRandomPresetDelete.Visible := frmDrawSettings.rbRandom.Checked;
|
||
vdlRandom.Visible := frmDrawSettings.rbRandom.Checked;
|
||
end else
|
||
begin
|
||
if mnuAutoHideRandomList.Tag > 0
|
||
then spTileList.Top := mnuAutoHideRandomList.Tag;
|
||
mnuAutoHideRandomList.Tag := 0;
|
||
spTileList.Enabled := True;
|
||
//gbRandom.Visible := True;
|
||
cbRandomPreset.Visible := True;
|
||
btnRandomPresetSave.Visible := True;
|
||
btnRandomPresetDelete.Visible := True;
|
||
vdlRandom.Visible := True;
|
||
end;
|
||
|
||
if spTileList.Enabled then
|
||
begin
|
||
spTileList.Cursor := crVSplit;
|
||
//if spTileList.Tag > 0 then
|
||
// spTileList.Height := spTileList.Tag;
|
||
spTileList.Height := 5;
|
||
end else
|
||
begin
|
||
spTileList.Cursor := crDefault;
|
||
//spTileList.Tag := spTileList.Height;
|
||
spTileList.Height := 1;
|
||
end;
|
||
|
||
spTileListMoved(Sender);
|
||
end;
|
||
|
||
procedure TfrmMain.spGroupListMoved(Sender: TObject);
|
||
var
|
||
anchor: integer;
|
||
begin
|
||
if mnuAutoHideGroupList.Checked then
|
||
if (spGroupList.Enabled) and (mnuAutoHideGroupList.Tag > 0) then
|
||
begin
|
||
spGroupList.Top := mnuAutoHideGroupList.Tag;
|
||
mnuAutoHideGroupList.Tag := 0;
|
||
end
|
||
else if not spGroupList.Enabled then
|
||
begin
|
||
spGroupList.Top := tvGroups.Top + 4;
|
||
Exit;
|
||
end;
|
||
|
||
if spGroupList.Enabled then
|
||
if spGroupList.Top <= tvGroups.Top then
|
||
spGroupList.Top := tvGroups.Top
|
||
else begin
|
||
anchor := spTileList.Top - spGroupList.Height - vdtTiles.Constraints.MinHeight;
|
||
if spGroupList.Top > anchor then spGroupList.Top := (anchor - 1);
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.spTileListMoved(Sender: TObject);
|
||
var
|
||
anchor: integer;
|
||
begin
|
||
if mnuAutoHideRandomList.Checked then
|
||
if (spTileList.Enabled) and (mnuAutoHideRandomList.Tag > 0) then
|
||
begin
|
||
spTileList.Top := mnuAutoHideRandomList.Tag;
|
||
mnuAutoHideRandomList.Tag := 0;
|
||
end
|
||
else if not spTileList.Enabled then
|
||
begin
|
||
spTileList.Top := gbRandom.Top + gbRandom.Height - spTileList.Tag + 3;
|
||
Exit;
|
||
end;
|
||
|
||
if spTileList.Enabled then
|
||
if spTileList.Top + spTileList.Height >= gbRandom.Top + gbRandom.Height then
|
||
spTileList.Top := gbRandom.Top + gbRandom.Height - spTileList.Height
|
||
else begin
|
||
anchor := spGroupList.Top + spGroupList.Height + vdtTiles.Constraints.MinHeight;
|
||
if spTileList.Top < anchor then spTileList.Top := (anchor + 1);
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.tbFilterMouseDown(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
begin
|
||
If Button = mbRight then
|
||
tbFilter.Tag := PtrInt(GetTickCount);
|
||
end;
|
||
|
||
procedure TfrmMain.tbFilterMouseUp(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
begin
|
||
if acFilter.Checked and (not frmFilter.Visible) and ((GetTickCount - DWORD(tbFilter.Tag)) < 1000) then begin
|
||
tbFilter.Tag := PtrInt(False);
|
||
frmFilter.Show;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.pcLeftResize(Sender: TObject);
|
||
begin
|
||
spGroupListMoved(Sender);
|
||
spTileListMoved(Sender);
|
||
end;
|
||
|
||
procedure TfrmMain.mnuDisconnectClick(Sender: TObject);
|
||
begin
|
||
dmNetwork.Disconnect;
|
||
end;
|
||
|
||
procedure TfrmMain.mnuDocsClick(Sender: TObject);
|
||
begin
|
||
//TODO ShellExecute(Handle, 'open', PChar('http://dev.uoquint.ru/projects/centred/wiki'), nil, nil, 1 {SW_SHOWNORMAL});
|
||
end;
|
||
|
||
procedure TfrmMain.mnuRusComClick(Sender: TObject);
|
||
begin
|
||
//TODO ShellExecute(Handle, 'open', PChar('http://forum.uokit.com/index.php?showforum=207'), nil, nil, 1 {SW_SHOWNORMAL});
|
||
end;
|
||
|
||
procedure TfrmMain.mnuEng2ComClick(Sender: TObject);
|
||
begin
|
||
//TODO ShellExecute(Handle, 'open', PChar('http://craftuo.com/threads/centred.888'), nil, nil, 1 {SW_SHOWNORMAL});
|
||
end;
|
||
|
||
procedure TfrmMain.mnuEngComClick(Sender: TObject);
|
||
begin
|
||
//TODO ShellExecute(Handle, 'open', PChar('http://board.uoquint.ru/'), nil, nil, 1 {SW_SHOWNORMAL});
|
||
end;
|
||
|
||
procedure TfrmMain.oglGameWindowPaint(Sender: TObject);
|
||
begin
|
||
if mnuWhiteBackground.Checked then
|
||
glClearColor(1, 1, 1, 1)
|
||
else
|
||
glClearColor(0, 0, 0, 1);
|
||
glClear(GL_COLOR_BUFFER_BIT);
|
||
|
||
InitRender;
|
||
InitSize;
|
||
|
||
glDisable(GL_DEPTH_TEST);
|
||
Render;
|
||
|
||
oglGameWindow.SwapBuffers;
|
||
end;
|
||
|
||
procedure TfrmMain.oglGameWindowResize(Sender: TObject);
|
||
begin
|
||
InvalidateScreenBuffer;
|
||
end;
|
||
|
||
procedure TfrmMain.pbRadarMouseDown(Sender: TObject; Button: TMouseButton;
|
||
Shift: TShiftState; X, Y: Integer);
|
||
var posx, posy: Integer;
|
||
begin
|
||
posx := self.X+4 * Trunc((Y+X - (pbRadar.Height+pbRadar.Width)div 2)*cos(45));
|
||
posy := self.Y+4 * Trunc((Y-X - (pbRadar.Height-pbRadar.Width)div 2)*cos(45));
|
||
//if (posx < 0) then posx := 0 else if (posx >= 8*Landscape.Width) then posx := 8*Landscape.Width-1;
|
||
//if (posy < 0) then posy := 0 else if (posy >= 8*Landscape.Height) then posy := 8*Landscape.Height-1;
|
||
if (posx>=0)and(posy>=0)and(posx<8*Landscape.Width)and(posy<8*Landscape.Height)
|
||
then SetPos(posx, posy);
|
||
end;
|
||
|
||
procedure TfrmMain.pbRadarPaint(Sender: TObject);
|
||
var
|
||
posX, posY, scrW, scrH: Integer;
|
||
zoom: Single;
|
||
image: TSingleImage;
|
||
begin
|
||
posX := (X div 8) - (pbRadar.Width div 4);
|
||
posY := (Y div 8) - (pbRadar.Height div 4);
|
||
|
||
// NOTE: Не очень-то хорошо каждый раз создавать Image...
|
||
image := TSingleImage.CreateFromParams(pbRadar.Width+84, pbRadar.Height+84, ifA8R8G8B8);
|
||
StretchRect(frmRadarMap.Radar.ImageDataPointer^, posX, posY, pbRadar.Width div 2, pbRadar.Height div 2,
|
||
image.ImageDataPointer^, 0, 0, image.Width, image.Height, rfBicubic);
|
||
RotateImage(image.ImageDataPointer^, -45.0);
|
||
|
||
DisplayImage(pbRadar.Canvas, (pbRadar.Width-image.Width) div 2, (pbRadar.Height-image.Height) div 2, image);
|
||
image.Free;
|
||
|
||
posX := pbRadar.Width div 2;
|
||
posY := pbRadar.Width div 2;
|
||
if tbZoom.Down then zoom := tbZoom.Tag / 1000.0 else zoom := 1.0;
|
||
scrW := Trunc(0.25 * oglGameWindow.Width / 44.0 / zoom);
|
||
scrH := Trunc(0.25 * oglGameWindow.Height/ 44.0 / zoom);
|
||
|
||
pbRadar.Canvas.Pen.Color := clBlack;
|
||
pbRadar.Canvas.Pen.Style := psSolid;
|
||
pbRadar.Canvas.Line(posX-scrW, posY-scrH, posX+scrW, posY-scrH);
|
||
pbRadar.Canvas.Line(posX+scrW, posY-scrH, posX+scrW, posY+scrH);
|
||
pbRadar.Canvas.Line(posX+scrW, posY+scrH, posX-scrW, posY+scrH);
|
||
pbRadar.Canvas.Line(posX-scrW, posY+scrH, posX-scrW, posY-scrH);
|
||
|
||
pbRadar.Canvas.Pen.Color := clSilver;
|
||
pbRadar.Canvas.Pen.Style := psSolid;
|
||
pbRadar.Canvas.Line(posX-scrW-1, posY-scrH-1, posX+scrW+1, posY-scrH-1);
|
||
pbRadar.Canvas.Line(posX+scrW+1, posY-scrH-1, posX+scrW+1, posY+scrH+1);
|
||
pbRadar.Canvas.Line(posX+scrW+1, posY+scrH+1, posX-scrW-1, posY+scrH+1);
|
||
pbRadar.Canvas.Line(posX-scrW-1, posY+scrH+1, posX-scrW-1, posY-scrH-1);
|
||
end;
|
||
|
||
procedure TfrmMain.pmGrabTileInfoPopup(Sender: TObject);
|
||
var
|
||
isStatic: Boolean;
|
||
begin
|
||
isStatic := CurrentTile is TStaticItem;
|
||
mnuGrabHue.Enabled := isStatic;
|
||
mnuGrabFilterTileID.Enabled := isStatic;
|
||
mnuGrabFilterHue.Enabled := isStatic;
|
||
end;
|
||
|
||
procedure TfrmMain.tbRadarMapClick(Sender: TObject);
|
||
begin
|
||
frmRadarMap.Show;
|
||
frmRadarMap.BringToFront;
|
||
end;
|
||
|
||
procedure TfrmMain.tmGrabTileInfoTimer(Sender: TObject);
|
||
begin
|
||
tmGrabTileInfo.Enabled := False;
|
||
if CurrentTile <> nil then
|
||
pmGrabTileInfo.PopUp(Mouse.CursorPos.X, Mouse.CursorPos.Y);
|
||
|
||
SelectedTile := nil;
|
||
end;
|
||
|
||
procedure TfrmMain.tmMovementTimer(Sender: TObject);
|
||
begin
|
||
case FOverlayUI.ActiveArrow of
|
||
0: MoveBy(-1, 0);
|
||
1: MoveBy(-1, -1);
|
||
2: MoveBy( 0, -1);
|
||
3: MoveBy(+1, -1);
|
||
4: MoveBy(+1, 0);
|
||
5: MoveBy(+1, +1);
|
||
6: MoveBy( 0, +1);
|
||
7: MoveBy(-1, +1);
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.tmSettingsCloseTimer(Sender: TObject);
|
||
begin
|
||
tmSettingsClose.Enabled := False;
|
||
tbTerrain.Down := acTerrain.Checked;
|
||
tbStatics.Down := acStatics.Checked;
|
||
tbNoDraw.Down := acNoDraw.Checked;
|
||
tbFlat.Down := acFlat.Checked;
|
||
end;
|
||
|
||
procedure TfrmMain.FormMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
|
||
begin
|
||
if Sender is TWinControl then
|
||
if not (TWinControl(Sender)).Focused
|
||
then (TWinControl(Sender)).SetFocus;
|
||
end;
|
||
|
||
procedure TfrmMain.tvGroupsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||
Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
|
||
var
|
||
nodeData : PGroupNode;
|
||
begin
|
||
nodeData := tvGroups.GetNodeData(Node);
|
||
CellText := nodeData^.Name;
|
||
end;
|
||
|
||
procedure TfrmMain.tvGroupsDrawText(Sender: TBaseVirtualTree;
|
||
TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
|
||
const CellText: String; const CellRect: TRect; var DefaultDraw: Boolean);
|
||
var
|
||
nodeData : PGroupNode;
|
||
TextWidth: Integer;
|
||
begin
|
||
nodeData := tvGroups.GetNodeData(Node);
|
||
|
||
TargetCanvas.Font.Color := nodeData^.Color;
|
||
TargetCanvas.Font.Bold := nodeData^.Bold;
|
||
TargetCanvas.Font.Italic:= nodeData^.Ital;
|
||
TargetCanvas.TextOut(CellRect.Left, CellRect.Top+2, CellText);
|
||
|
||
TextWidth := TargetCanvas.TextWidth(CellText);
|
||
TargetCanvas.Font.Color := TColor($00BBBBBB);
|
||
TargetCanvas.Font.Bold := False;
|
||
TargetCanvas.Font.Italic:= False;
|
||
TargetCanvas.TextOut(CellRect.Left + TextWidth + 6, CellRect.Top + 2,
|
||
Format('(%u)', [nodeData^.Items]));
|
||
|
||
DefaultDraw := False;
|
||
end;
|
||
|
||
procedure TfrmMain.tmSelectNodeTimer(Sender: TObject);
|
||
begin
|
||
tmSelectNode.Enabled := False;
|
||
if (FGroupsSelectionUndoRedoCommandGroup.UndoRedoCommands.Count > 0) then begin
|
||
if not FGroupsSelectionUndoRedoManager.Enabled then begin
|
||
tmSelectNode.Enabled := True;
|
||
Exit;
|
||
end;
|
||
FGroupsSelectionUndoRedoManager.ExecCommand(FGroupsSelectionUndoRedoCommandGroup);
|
||
FGroupsSelectionUndoRedoCommandGroup := TUndoRedoCommandGroup.Create;
|
||
end;
|
||
//if (FTilesSelectionUndoRedoCommandGroup.UndoRedoCommands.Count > 0) then
|
||
begin
|
||
if not FTilesSelectionUndoRedoManager.Enabled then begin
|
||
tmSelectNode.Enabled := True;
|
||
Exit;
|
||
end;
|
||
FTilesSelectionUndoRedoManager.ExecCommand(FTilesSelectionUndoRedoCommandGroup);
|
||
FTilesSelectionUndoRedoCommandGroup := TUndoRedoCommandGroup.Create;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.vdtTilesChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||
begin
|
||
if (Node <> nil) and (FTilesSelectionUndoRedoManager.Enabled) then begin
|
||
FTilesSelectionUndoRedoCommandGroup.Add(
|
||
TUndoRedoSelectVirtualNodeCommand.Create(
|
||
FTilesSelectionUndoRedoManager, Sender, Node)
|
||
);
|
||
if not FTilesSelectionUndoRedoManager.Enabled
|
||
then vdtTiles.FocusedNode := PVirtualItem(Node);
|
||
if not tmSelectNode.Enabled
|
||
then tmSelectNode.Enabled := True
|
||
else tmSelectNode.Interval:= 250;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.tvGroupsChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||
var
|
||
item: PVirtualNode;
|
||
begin
|
||
if (Node <> nil) and (FGroupsSelectionUndoRedoManager.Enabled) then begin
|
||
FGroupsSelectionUndoRedoCommandGroup.Add(
|
||
TUndoRedoSelectVirtualNodeCommand.Create(
|
||
FGroupsSelectionUndoRedoManager, Sender, Node)
|
||
);
|
||
if not tmSelectNode.Enabled
|
||
then tmSelectNode.Enabled := True
|
||
else tmSelectNode.Interval:= 250;
|
||
|
||
if ((cbStatics.Checked or cbTerrain.Checked) and Sender.Selected[Node]) then begin
|
||
cbStatics.Checked := False;
|
||
cbTerrain.Checked := False;
|
||
Exit;
|
||
end;
|
||
end;
|
||
|
||
BuildTileList;
|
||
end;
|
||
|
||
procedure TfrmMain.tvGroupFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||
var
|
||
groupData: PGroupNode;
|
||
begin
|
||
groupData := Sender.GetNodeData(Node);
|
||
groupData^.Name := EmptyStr;
|
||
FreeMem(groupData^.GLink);
|
||
FreeMem(groupData^.GTile);
|
||
FreeMem(groupData^.Brush);
|
||
FreeMem(groupData^.Entry);
|
||
end;
|
||
|
||
procedure TfrmMain.DropedownMenusClose(Sender: TObject);
|
||
begin
|
||
tmSettingsClose.Enabled := True;
|
||
end;
|
||
|
||
procedure TfrmMain.vdtRandomClick(Sender: TObject);
|
||
var
|
||
item: PVirtualItem;
|
||
node: PVirtualItem;
|
||
treeNode: PVirtualNode;
|
||
tileInfo: PTileInfo;
|
||
selectedID: Integer;
|
||
|
||
function TileInNode(Node: PVirtualNode; TileID: LongWord) : Boolean;
|
||
var
|
||
nodeData: ^TGroupNode;
|
||
i: Integer;
|
||
begin
|
||
Result := False;
|
||
nodeData := tvGroups.GetNodeData(Node);
|
||
for i := 0 to nodeData^.Count - 1 do
|
||
begin
|
||
if nodeData^.GTile[i].ID = TileID then
|
||
begin
|
||
Result := True;
|
||
break;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
begin
|
||
if vdlRandom.SelectedCount = 1 then
|
||
begin
|
||
node := vdlRandom.GetFirstSelected;
|
||
if node <> nil then
|
||
begin
|
||
tileInfo := vdlRandom.GetNodeData(node);
|
||
selectedID := tileInfo^.ID;
|
||
|
||
// Выбираем группы
|
||
if (not cbStatics.Checked) and (not cbTerrain.Checked) then
|
||
begin
|
||
treeNode := tvGroups.GetFirst();
|
||
while treeNode <> nil do
|
||
begin
|
||
if TileInNode(treeNode, selectedID) then
|
||
begin
|
||
tvGroups.Selected[treeNode] := True;
|
||
tvGroups.FocusedNode := treeNode;
|
||
if toMultiSelect in tvGroups.TreeOptions.SelectionOptions
|
||
then Break;
|
||
end;
|
||
treeNode := tvGroups.GetNext(treeNode);
|
||
end;
|
||
end;
|
||
|
||
// Выбираем тайл
|
||
item := vdtTiles.GetFirst;
|
||
while item <> nil do
|
||
begin
|
||
tileInfo := vdtTiles.GetNodeData(item);
|
||
if tileInfo^.ID = selectedID then
|
||
begin
|
||
vdtTiles.ClearSelection;
|
||
vdtTiles.Selected[item] := True;
|
||
vdtTiles.FocusedNode := item;
|
||
item := nil;
|
||
end else
|
||
item := vdtTiles.GetNext(item);
|
||
end;
|
||
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.vdtRandomDragDrop(Sender: TBaseVirtualTree; Source: TObject;
|
||
DataObject: IDataObject; Formats: TFormatArray; Shift: TShiftState;
|
||
Pt: TPoint; var Effect: Integer; Mode: TDropMode);
|
||
begin
|
||
if Source = vdtTiles then
|
||
btnAddRandomClick(Sender);
|
||
end;
|
||
|
||
procedure TfrmMain.vdtRandomDragOver(Sender: TBaseVirtualTree; Source: TObject;
|
||
Shift: TShiftState; State: TDragState; Pt: TPoint; Mode: TDropMode;
|
||
var Effect: Integer; var Accept: Boolean);
|
||
begin
|
||
if source = vdtTiles then Accept := True;
|
||
end;
|
||
|
||
procedure TfrmMain.vdtRandomLoadNode(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Stream: TStream);
|
||
var
|
||
tileInfo: PTileInfo;
|
||
begin
|
||
tileInfo := Sender.GetNodeData(Node);
|
||
Stream.Read(tileInfo^.ID, SizeOf(tileInfo^.ID));
|
||
end;
|
||
|
||
procedure TfrmMain.vdtRandomSaveNode(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Stream: TStream);
|
||
var
|
||
tileInfo: PTileInfo;
|
||
begin
|
||
tileInfo := Sender.GetNodeData(Node);
|
||
Stream.Write(tileInfo^.ID, SizeOf(tileInfo^.ID));
|
||
end;
|
||
|
||
procedure TfrmMain.vdtRandomUpdating(Sender: TBaseVirtualTree;
|
||
State: TVTUpdateState);
|
||
begin
|
||
if acDraw.Checked then
|
||
ProcessToolState;
|
||
end;
|
||
|
||
procedure TfrmMain.vdtTilesClick(Sender: TObject);
|
||
begin
|
||
if acDraw.Checked then
|
||
ProcessToolState;
|
||
end;
|
||
|
||
procedure TfrmMain.vdtTilesDragAllowed(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean);
|
||
begin
|
||
//vdtTiles.auto
|
||
Allowed := True;
|
||
end;
|
||
|
||
procedure TfrmMain.vdtTilesDrawHint(Sender: TBaseVirtualTree;
|
||
HintCanvas: TCanvas; Node: PVirtualNode; const R: TRect; Column: TColumnIndex
|
||
);
|
||
var
|
||
m_name : string;
|
||
begin
|
||
vdtTiles.UpdateHintCanvas(HintCanvas);
|
||
|
||
HintCanvas.Font.Assign(Sender.Font);
|
||
HintCanvas.Font.Style := [fsBold];
|
||
m_name := CP1251ToUTF8(FTileHint.Name);
|
||
DrawText(HintCanvas.Handle, PChar(m_name), Length(m_name), FTileHint.NameRect, 0);
|
||
HintCanvas.Font.Style := [];
|
||
DrawText(HintCanvas.Handle, PChar(FTileHint.Obj), Length(FTileHint.Obj), FTileHint.ObjRect, 0);
|
||
HintCanvas.Font.Style := [fsItalic];
|
||
DrawText(HintCanvas.Handle, PChar(FTileHint.Flags), Length(FTileHint.Flags),
|
||
FTileHint.FlagsRect, DT_WORDBREAK);
|
||
end;
|
||
|
||
procedure TfrmMain.vdtTilesDrawNode(Sender: TBaseVirtualTree; const PaintInfo: TVTPaintInfo);
|
||
var
|
||
tileInfo: PTileInfo;
|
||
textStyle: TTextStyle;
|
||
artEntry: TArt;
|
||
tileData: TTileData;
|
||
id: LongWord;
|
||
rect, CellRect:TRect;
|
||
image: TSingleImage;
|
||
colorOld, colorNew: Word;
|
||
DrawInfo: Boolean;
|
||
oldcolor: DWORD;
|
||
newcolor: DWORD;
|
||
srcCanvas, dstCanvas: TFastARGB32Canvas;
|
||
tmpImage : TSingleImage;
|
||
bit: Integer;
|
||
|
||
procedure DisplayNodeImage(main: Boolean; const Canvas: TCanvas; const CellRect: TRect; Image: TBaseImage; ForceStretch: Boolean = False);
|
||
var
|
||
Resised: Float;
|
||
DstSize: TSize;
|
||
DstRect: TRect;
|
||
//SrcRect: TRect;
|
||
begin
|
||
if (main and mnuTileListStretch.Checked) or (not main and mnuMiscTileListStretch.Checked) or (ForceStretch) then begin
|
||
|
||
if ForceStretch or (DstSize.cy <> 44) then begin
|
||
DstSize.cx := CellRect.Right - CellRect.Left;
|
||
DstSize.cy := CellRect.Bottom - CellRect.Top;
|
||
if ForceStretch then begin
|
||
if (DstSize.cx <= 44) then id := 2
|
||
else if (DstSize.cx <= 80) then id := 3
|
||
else id := 4;
|
||
DstSize.cx := DstSize.cx - id;
|
||
DstSize.cy := DstSize.cy - id;
|
||
end;
|
||
Resised := Min(Min(Float(DstSize.cx)/Float(Image.Width), Float(DstSize.cy)/Float(Image.Height)), 1.0);
|
||
DstSize.cx := Trunc(Resised * Float(Image.Width));
|
||
DstSize.cy := Trunc(Resised * Float(Image.Height));
|
||
DstRect.Left := Trunc((CellRect.Left + CellRect.Right - DstSize.cx) / 2);
|
||
DstRect.Right := DstRect.Left + DstSize.cx;
|
||
if not ForceStretch
|
||
then DstRect.Bottom := CellRect.Bottom
|
||
else DstRect.Bottom := (CellRect.Bottom - CellRect.Top + DstSize.cy) div 2;
|
||
DstRect.Top := DstRect.Bottom - DstSize.cy
|
||
end else begin
|
||
DstRect := CellRect;
|
||
end;
|
||
DisplayImage(Canvas, DstRect, Image);
|
||
end else
|
||
if (main and mnuTileListClip.Checked) or (not main and mnuMiscTileListClip.Checked) then begin
|
||
//DstSize.cx := CellRect.Right - CellRect.Left;
|
||
//DstSize.cy := CellRect.Bottom - CellRect.Top;
|
||
//DstRect := CellRect;
|
||
//SrcRect.Top := 0;
|
||
//if (DstSize.cy <= Image.Height) then begin
|
||
// SrcRect.Bottom := DstSize.cy;
|
||
//end else begin
|
||
// SrcRect.Bottom := Image.Height;
|
||
// DstRect.Bottom := DstRect.Top + Image.Height;
|
||
//end;
|
||
//if (DstSize.cx <= Image.Width) then begin
|
||
// SrcRect.Left := (Image.Width - DstSize.cx) div 2;
|
||
// SrcRect.Right:= SrcRect.Left + DstSize.cx;
|
||
//end else begin
|
||
// SrcRect.Left := 0;
|
||
// SrcRect.Right:= Image.Width;
|
||
// DstRect.Left := DstRect.Left + (DstSize.cx - Image.Width) div 2;
|
||
// DstRect.Right:= DstRect.Left + Image.Width;
|
||
//end;
|
||
//Logger.Send([lcClient, lcDebug], 'TfrmMain.vdtTilesDrawNode [%d,%d,%d,%d](%d,%d) - [%d,%d,%d,%d](%d,%d) I(%d,%d) C[%d,%d,%d,%d](%d,%d)',
|
||
//[SrcRect.Top, SrcRect.Left, SrcRect.Bottom, SrcRect.Right, SrcRect.Right - SrcRect.Left, SrcRect.Bottom - SrcRect.Top,
|
||
// DstRect.Top, DstRect.Left, DstRect.Bottom, DstRect.Right, DstRect.Right - DstRect.Left, DstRect.Bottom - DstRect.Top,
|
||
// Image.Width, Image.Height,
|
||
// CellRect.Top, CellRect.Left, CellRect.Bottom, CellRect.Right, CellRect.Right - CellRect.Left, CellRect.Bottom - CellRect.Top]);
|
||
|
||
//DisplayImage(Canvas, DstRect, Image, SrcRect);
|
||
DisplayImage(Canvas, Trunc((CellRect.Left + CellRect.Right - Image.Width) / 2), CellRect.Top, Image);
|
||
Canvas.FillRect(CellRect.Left, CellRect.Bottom, CellRect.Right, CellRect.Bottom + 14);
|
||
end else
|
||
if (main and mnuTileListCentre.Checked) or (not main and mnuMiscTileListCentre.Checked) then begin
|
||
// TODO: ....
|
||
end;
|
||
end;
|
||
|
||
begin
|
||
if (not (Sender is TVirtualList))
|
||
then tileInfo := Sender.GetNodeData(PaintInfo.Node)
|
||
else tileInfo := vdtTiles.GetNodeData(PVirtualItem(PaintInfo.Node));
|
||
|
||
//if (sender <> vdtTiles) then begin
|
||
//Logger.Send([lcClient, lcDebug], 'TfrmMain.vdtTilesDrawNode %.8x at cell [%d,%d]', [tileInfo^.ID, PaintInfo.Column, PaintInfo.Node^.Index]);
|
||
//Exit;
|
||
//end;
|
||
// Logger.Send([lcClient, lcDebug], 'TfrmMain.vdtTilesDrawNode %d', [tileInfo^.ID]);
|
||
|
||
if (tileInfo^.ID = $FFFFFFFF) then exit;
|
||
|
||
textStyle := PaintInfo.Canvas.TextStyle;
|
||
textStyle.Alignment := taCenter;
|
||
textStyle.Layout := tlCenter;
|
||
textStyle.Wordbreak := True;
|
||
PaintInfo.Canvas.Font.Color := Sender.Font.Color;
|
||
if (Sender = vdtTiles) then
|
||
PaintInfo.Canvas.Font.Color := TColor($808080);
|
||
|
||
//Logger.Send([lcClient, lcDebug], 'vdtTilesDrawNode %.4x', [tileInfo^.ID]);
|
||
|
||
case PaintInfo.Column of
|
||
0:
|
||
begin
|
||
id := tileInfo^.ID;
|
||
if id > $2F000000 then
|
||
PaintInfo.Canvas.TextRect(PaintInfo.CellRect, 0, 0, Format('BL%.3d', [id - $2F000000]), textStyle)
|
||
else if id > $1F000000 then
|
||
PaintInfo.Canvas.TextRect(PaintInfo.CellRect, 0, 0, Format('ET%.3d', [id - $1F000000]), textStyle)
|
||
else begin
|
||
if id > $00003FFF then Dec(id, $00004000);
|
||
//PaintInfo.Canvas.TextRect(PaintInfo.CellRect, 0, 0, '4x', textStyle);
|
||
PaintInfo.Canvas.TextRect(PaintInfo.CellRect, 0, 0, Format('$%.4x', [id]), textStyle);
|
||
end;
|
||
end;
|
||
2:
|
||
begin
|
||
textStyle.Alignment := taLeftJustify;
|
||
if (tileInfo^.ID > $2F000000) then begin // Кисти
|
||
PaintInfo.Canvas.TextRect(PaintInfo.CellRect, PaintInfo.CellRect.Left + 4,
|
||
PaintInfo.CellRect.Top, PGroupBrush(tileInfo^.ptr)^.Name, textStyle);
|
||
end else if (tileInfo^.ID > $1F000000) then begin // Объекты
|
||
PaintInfo.Canvas.TextRect(PaintInfo.CellRect, PaintInfo.CellRect.Left + 4,
|
||
PaintInfo.CellRect.Top, PGroupEntry(tileInfo^.ptr)^.Name, textStyle);
|
||
end else begin // Тайлы
|
||
tileData := TTileData(ResMan.Tiledata.Block[tileInfo^.ID]);
|
||
PaintInfo.Canvas.TextRect(PaintInfo.CellRect, PaintInfo.CellRect.Left + 4,
|
||
PaintInfo.CellRect.Top, CP1251ToUTF8(Trim(tileData.TileName)),
|
||
textStyle);
|
||
tileData.Free;
|
||
end;
|
||
end;
|
||
3: begin Exit; end;
|
||
13: begin Exit; end;
|
||
// 1: - 3: 4: 5: 6: - 7: 8: 9: - 10: 11:
|
||
else
|
||
begin
|
||
CellRect := PaintInfo.CellRect;
|
||
if (PaintInfo.Column = 1)
|
||
then DrawInfo := False
|
||
else if (sender = vdtTiles)
|
||
then DrawInfo := mnuTileListDrawInfo.Enabled and mnuTileListDrawInfo.Checked
|
||
else DrawInfo := mnuMiscTileListDrawInfo.Enabled and mnuMiscTileListDrawInfo.Checked;
|
||
if DrawInfo then begin
|
||
CellRect.Bottom := CellRect.Bottom - 14;
|
||
end;
|
||
|
||
if (tileInfo^.ID > $2F000000) then begin // Кисти
|
||
//image := TSingleImage.CreateFromImage(PGroupBrush(tileInfo^.ptr)^.Image);
|
||
colorOld := $0000; colorNew := RGB2ARGB(PaintInfo.Canvas.Pixels[CellRect.Left,CellRect.Top]);
|
||
PGroupBrush(tileInfo^.ptr)^.Image.ReplaceColor(0,0,PGroupBrush(tileInfo^.ptr)^.Image.Width,PGroupBrush(tileInfo^.ptr)^.Image.Height,
|
||
@colorOld, @colorNew);
|
||
image := TSingleImage.CreateFromImage(PGroupBrush(tileInfo^.ptr)^.Image);
|
||
|
||
image.Format := ifDefault;
|
||
DisplayNodeImage((Sender = vdtTiles), PaintInfo.Canvas, CellRect, image, True);
|
||
//DisplayImage(PaintInfo.Canvas, CellRect, image);
|
||
image.Free;
|
||
end else if (tileInfo^.ID > $1F000000) then begin// Объекты
|
||
//colorOld := $0000; colorNew := RGB2ARGB($00FFFFFF);
|
||
//PGroupEntry(tileInfo^.ptr)^.Image.ReplaceColor(0,0,PGroupEntry(tileInfo^.ptr)^.Image.Width,PGroupEntry(tileInfo^.ptr)^.Image.Height,
|
||
//@colorOld, @colorNew);
|
||
image := TSingleImage.CreateFromImage(PGroupEntry(tileInfo^.ptr)^.Image);
|
||
//oldcolor := PDWORD(Image.Bits)^;
|
||
//newcolor := $00FF0000;//PDWORD(Image.)^;
|
||
//image.ReplaceColor(0,0,Image.Width,Image.Height,@oldcolor,@newcolor);
|
||
//image.Format := ifDefault;
|
||
DisplayNodeImage((Sender = vdtTiles), PaintInfo.Canvas, CellRect, image, True);
|
||
image.Free;
|
||
end else if ResMan.Art.Exists(tileInfo^.ID) then // Тайлы
|
||
begin
|
||
artEntry := ResMan.Art.GetArt(tileInfo^.ID,
|
||
RGB2ARGB(PaintInfo.Canvas.Pixels[CellRect.Left, CellRect.Top]), nil, False);
|
||
DisplayNodeImage((Sender = vdtTiles), PaintInfo.Canvas, CellRect, artEntry.Graphic);
|
||
artEntry.Free;
|
||
if tileInfo^.ID > $3FFF then
|
||
if (FLightSourceTiles[tileInfo^.ID - $4000].image > 0) then // Источники света
|
||
begin
|
||
bit := FLightSourceTiles[tileInfo^.ID - $4000].image;
|
||
//rect.Right:=CellRect.Right;
|
||
//rect.Bottom:=CellRect.Bottom;
|
||
//rect.Left:=CellRect.Right - 24;
|
||
//rect.Top:=CellRect.Bottom - 24;
|
||
//DisplayImage(PaintInfo.Canvas, rect, FVLightSrcImage);
|
||
|
||
//DisplayNodeImage((Sender = vdtTiles), PaintInfo.Canvas, CellRect, FVLightSrcImage, True);
|
||
|
||
rect.Left := 0;
|
||
rect.Top := 0;
|
||
rect.Right:= FVLightSrcImage[bit].Width;
|
||
rect.Bottom:=FVLightSrcImage[bit].Height;
|
||
tmpImage := TSingleImage.CreateFromParams(rect.Right, rect.Bottom, ifA8R8G8B8);
|
||
srcCanvas := TFastARGB32Canvas.CreateForImage(FVLightSrcImage[bit]);
|
||
dstCanvas := TFastARGB32Canvas.CreateForImage(tmpImage);
|
||
|
||
dstCanvas.FillColor32 := PaintInfo.Canvas.Pixels[CellRect.Left+4,CellRect.Top+4];
|
||
dstCanvas.FillRect(rect);
|
||
srcCanvas.DrawAlpha(rect, dstCanvas, 0,0);
|
||
srcCanvas.Free;
|
||
dstCanvas.Free;
|
||
DisplayNodeImage((Sender = vdtTiles), PaintInfo.Canvas, CellRect, tmpImage, True);
|
||
tmpImage.Free;
|
||
end;
|
||
end;
|
||
|
||
if DrawInfo then begin // Подписи тайлов
|
||
CellRect.Bottom := PaintInfo.CellRect.Bottom;
|
||
rect := PaintInfo.CellRect;
|
||
rect.Top := rect.Bottom - 14;;
|
||
id := tileInfo^.ID;
|
||
if id > $2F000000 then
|
||
PaintInfo.Canvas.TextRect(rect, 0, 0, Format('BL%.3d', [id - $2F000000]), textStyle)
|
||
else if id > $1F000000 then
|
||
PaintInfo.Canvas.TextRect(rect, 0, 0, Format('ET%.3d', [id - $1F000000]), textStyle)
|
||
else begin
|
||
if id > $00003FFF then Dec(id, $00004000);
|
||
//PaintInfo.Canvas.TextRect(rect, 0, 0, '4x', textStyle);
|
||
PaintInfo.Canvas.TextRect(rect, 0, 0, Format('0x%.4x', [id]), textStyle);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.vdtTilesEnter(Sender: TObject);
|
||
begin
|
||
if acFilter.Checked and mnuAutoShowFilterWindow.Checked and (not frmFilter.Visible) and (not frmFilter.Locked) then
|
||
begin
|
||
frmFilter.Locked := True;
|
||
frmFilter.Show;
|
||
frmMain.SetFocus;
|
||
frmFilter.Locked := False;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.vdtTilesGetHintSize(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Column: TColumnIndex; var R: TRect);
|
||
var
|
||
tileInfo: PTileInfo;
|
||
tileData: TTiledata;
|
||
prefix, flags: string;
|
||
id: LongWord;
|
||
cmHint: TCMHintShow;
|
||
|
||
procedure UpdateFlags(AFlag: TTileDataFlag; AName: string);
|
||
begin
|
||
if AFlag in tileData.Flags then
|
||
begin
|
||
if flags <> '' then
|
||
flags := flags + ', ' + AName
|
||
else
|
||
flags := AName;
|
||
end;
|
||
end;
|
||
|
||
begin
|
||
case Word(Sender.Tag) of
|
||
1: id := 0;
|
||
2: id := min(max(0, Column - 10), 2);
|
||
3: id := min(max(0, Column - 7), 3);
|
||
4: id := min(max(0, Column - 3), 4);
|
||
end;
|
||
//Logger.Send([lcClient, lcDebug], 'vdtTilesGetHintSize', Column);
|
||
tileInfo := (TVirtualList(Sender)).GetNodeData(vdtTiles.GetItemAt(Node, Column));// @PTileInfo(Sender.GetNodeData(Node))[id];
|
||
flags := '';
|
||
// if (FTileHint.Column = id) then Exit;
|
||
// FTileHint.Column := id;
|
||
|
||
if (tileInfo^.ID > $2F000000) then begin
|
||
FTileHint.Name := UTF8ToCP1251(PGroupBrush(tileInfo^.ptr)^.Name);
|
||
FTileHint.Obj := Format('Brush ID: 0x%.4x (%.5d)', [tileInfo^.ID-$2F000000, tileInfo^.ID-$2F000000]);
|
||
//flags := 'Brush';
|
||
end else if (tileInfo^.ID > $1F000000) then begin
|
||
FTileHint.Name := UTF8ToCP1251(PGroupEntry(tileInfo^.ptr)^.Name);
|
||
FTileHint.Obj := Format('Entry ID: 0x%.4x (%.5d)', [tileInfo^.ID-$1F000000, tileInfo^.ID-$1F000000]);
|
||
//flags := 'Entry';
|
||
end else
|
||
begin
|
||
tileData := ResMan.Tiledata.TileData[tileInfo^.ID];
|
||
if tileInfo^.ID < $4000 then begin
|
||
if TLandTiledata(tileData).TextureID > 0 then
|
||
flags := 'Stretchable';
|
||
FTileHint.Obj := Format('LandT ID: 0x%.4x (%.5d)', [tileInfo^.ID, tileInfo^.ID]);
|
||
end else begin
|
||
FTileHint.Obj := Format('ItemT ID: 0x%.4x (%.5d)', [tileInfo^.ID-$4000, tileInfo^.ID-$4000]);
|
||
end;
|
||
|
||
|
||
if tdfArticleA in tileData.Flags then
|
||
prefix := 'a '
|
||
else if tdfArticleAn in tileData.Flags then
|
||
prefix := 'an '
|
||
else
|
||
prefix := '';
|
||
|
||
FTileHint.Name := AnsiProperCase(Format('%s%s', [prefix, tileData.TileName]), [' ']);
|
||
|
||
UpdateFlags(tdfBackground, 'Background');
|
||
UpdateFlags(tdfWeapon, 'Weapon');
|
||
UpdateFlags(tdfTransparent, 'Transparent');
|
||
UpdateFlags(tdfTranslucent, 'Translucent');
|
||
UpdateFlags(tdfWall, 'Wall');
|
||
UpdateFlags(tdfDamaging, 'Damaging');
|
||
UpdateFlags(tdfImpassable, 'Impassable');
|
||
UpdateFlags(tdfWet, 'Wet');
|
||
UpdateFlags(tdfSurface, 'Surface');
|
||
UpdateFlags(tdfBridge, 'Bridge');
|
||
UpdateFlags(tdfGeneric, 'Generic');
|
||
UpdateFlags(tdfWindow, 'Window');
|
||
UpdateFlags(tdfNoShoot, 'NoShoot');
|
||
UpdateFlags(tdfInternal, 'Internal');
|
||
UpdateFlags(tdfFoliage, 'Foliage');
|
||
UpdateFlags(tdfPartialHue, 'PartialHue');
|
||
UpdateFlags(tdfMap, 'Map');
|
||
UpdateFlags(tdfContainer, 'Container');
|
||
UpdateFlags(tdfWearable, 'Wearable');
|
||
UpdateFlags(tdfLightSource, 'Lightsource');
|
||
UpdateFlags(tdfAnimation, 'Animation');
|
||
UpdateFlags(tdfNoDiagonal, 'NoDiagonal'); //HoverOver
|
||
UpdateFlags(tdfArmor, 'Armor');
|
||
UpdateFlags(tdfRoof, 'Roof');
|
||
UpdateFlags(tdfDoor, 'Door');
|
||
UpdateFlags(tdfStairBack, 'StairBack');
|
||
UpdateFlags(tdfStairRight, 'StairRight');
|
||
end;
|
||
|
||
FTileHint.NameRect.Left := 5;
|
||
FTileHint.NameRect.Top := 5;
|
||
Sender.Canvas.Font.Style := [fsBold];
|
||
DrawText(Sender.Canvas.Handle, PChar(CP1251ToUTF8(FTileHint.Name)), Length(CP1251ToUTF8(FTileHint.Name)),
|
||
FTileHint.NameRect, DT_CALCRECT);
|
||
FTileHint.ObjRect.Left := 5;
|
||
FTileHint.ObjRect.Top := FTileHint.NameRect.Bottom + 6;
|
||
Sender.Canvas.Font.Style := [];
|
||
DrawText(Sender.Canvas.Handle, PChar(FTileHint.Obj), Length(FTileHint.Obj), FTileHint.ObjRect, DT_CALCRECT);
|
||
FTileHint.Flags := Format('Flags = [%s]', [flags]);
|
||
FTileHint.FlagsRect.Left := 5;
|
||
FTileHint.FlagsRect.Top := FTileHint.ObjRect.Bottom + 2;
|
||
FTileHint.FlagsRect.Right := 145;
|
||
Sender.Canvas.Font.Style := [fsItalic];
|
||
DrawText(Sender.Canvas.Handle, PChar(FTileHint.Flags), Length(FTileHint.Flags),
|
||
FTileHint.FlagsRect, DT_CALCRECT or DT_WORDBREAK);
|
||
|
||
R := Rect(0, 0, Max(Max(FTileHint.NameRect.Right, FTileHint.ObjRect.Right), FTileHint.FlagsRect.Right) + 5,
|
||
FTileHint.FlagsRect.Bottom + 5);
|
||
end;
|
||
|
||
procedure TfrmMain.vdtTilesKeyPress(Sender: TObject; var Key: char);
|
||
begin
|
||
if Key in ['$', '0'..'9'] then
|
||
begin
|
||
edSearchID.Text := Key;
|
||
edSearchID.Visible := True;
|
||
edSearchID.SetFocus;
|
||
edSearchID.SelStart := 1;
|
||
Key := #0;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.vdtTilesScroll(Sender: TBaseVirtualTree; DeltaX,
|
||
DeltaY: Integer);
|
||
begin
|
||
if Sender.CanFocus and Sender.MouseEntered then
|
||
Sender.SetFocus;
|
||
end;
|
||
|
||
procedure TfrmMain.vstChatClick(Sender: TObject);
|
||
begin
|
||
edChat.SetFocus;
|
||
end;
|
||
|
||
procedure TfrmMain.vstChatFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||
var
|
||
chatInfo: PChatInfo;
|
||
begin
|
||
chatInfo := Sender.GetNodeData(Node);
|
||
chatInfo^.Sender := '';
|
||
chatInfo^.Msg := '';
|
||
end;
|
||
|
||
procedure TfrmMain.vstChatGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||
Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
|
||
var
|
||
chatInfo: PChatInfo;
|
||
begin
|
||
chatInfo := Sender.GetNodeData(Node);
|
||
case Column of
|
||
0: CellText := TimeToStr(chatInfo^.Time);
|
||
1: CellText := chatInfo^.Sender;
|
||
2: CellText := chatInfo^.Msg;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.vstChatPaintText(Sender: TBaseVirtualTree;
|
||
const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
|
||
TextType: TVSTTextType);
|
||
var
|
||
chatInfo: PChatInfo;
|
||
begin
|
||
chatInfo := Sender.GetNodeData(Node);
|
||
if chatInfo^.Sender = 'System' then
|
||
begin
|
||
if Column = 1 then
|
||
TargetCanvas.Font.Style := TargetCanvas.Font.Style + [fsItalic, fsBold]
|
||
else
|
||
TargetCanvas.Font.Style := TargetCanvas.Font.Style + [fsItalic];
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.vstClientsGetText(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
|
||
var CellText: String);
|
||
var
|
||
clientInfo: PClientInfo;
|
||
begin
|
||
clientInfo := Sender.GetNodeData(Node);
|
||
case Column of
|
||
1: CellText := clientInfo^.Name;//Format('%d, %d', [locationInfo^.X, locationInfo^.Y]);
|
||
2: CellText := FormatDateTime('mm\dd - hh:mm:ss', clientInfo^.LogonDateTime);
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.vstClientsGetImageIndex(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
|
||
var Ghosted: Boolean; var ImageIndex: Integer);
|
||
var
|
||
clientInfo: PClientInfo;
|
||
begin
|
||
clientInfo := Sender.GetNodeData(Node);
|
||
case Column of
|
||
0: frmAccountControl.GetAccountImageIndex(clientInfo^.AccessLevel, ImageIndex);
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.vstLocationsDblClick(Sender: TObject);
|
||
var
|
||
node: PVirtualNode;
|
||
locationInfo: PLocationInfo;
|
||
begin
|
||
node := vstLocations.GetFirstSelected;
|
||
if node <> nil then
|
||
begin
|
||
locationInfo := vstLocations.GetNodeData(node);
|
||
SetPos(locationInfo^.X, locationInfo^.Y);
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.vstLocationsFreeNode(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode);
|
||
var
|
||
locationInfo: PLocationInfo;
|
||
begin
|
||
locationInfo := Sender.GetNodeData(Node);
|
||
locationInfo^.Name := EmptyStr;
|
||
end;
|
||
|
||
procedure TfrmMain.vstLocationsGetText(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
|
||
var CellText: String);
|
||
var
|
||
locationInfo: PLocationInfo;
|
||
begin
|
||
locationInfo := Sender.GetNodeData(Node);
|
||
case Column of
|
||
0: CellText := Format('%d, %d', [locationInfo^.X, locationInfo^.Y]);
|
||
1: CellText := locationInfo^.Name;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.vstLocationsLoadNode(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Stream: TStream);
|
||
var
|
||
locationInfo: PLocationInfo;
|
||
stringLength: Integer;
|
||
s: string;
|
||
begin
|
||
locationInfo := Sender.GetNodeData(Node);
|
||
Stream.Read(locationInfo^.X, SizeOf(Word));
|
||
Stream.Read(locationInfo^.Y, SizeOf(Word));
|
||
stringLength := 0;
|
||
Stream.Read(stringLength, SizeOf(Integer));
|
||
SetLength(s, stringLength);
|
||
Stream.Read(s[1], stringLength);
|
||
locationInfo^.Name := s;
|
||
end;
|
||
|
||
procedure TfrmMain.vstLocationsNewText(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Column: TColumnIndex; const NewText: String);
|
||
var
|
||
locationInfo: PLocationInfo;
|
||
begin
|
||
if Column = 1 then
|
||
begin
|
||
locationInfo := Sender.GetNodeData(Node);
|
||
locationInfo^.Name := NewText;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.vstLocationsSaveNode(Sender: TBaseVirtualTree;
|
||
Node: PVirtualNode; Stream: TStream);
|
||
var
|
||
locationInfo: PLocationInfo;
|
||
stringLength: Integer;
|
||
begin
|
||
locationInfo := Sender.GetNodeData(Node);
|
||
Stream.Write(locationInfo^.X, SizeOf(Word));
|
||
Stream.Write(locationInfo^.Y, SizeOf(Word));
|
||
stringLength := Length(locationInfo^.Name);
|
||
Stream.Write(stringLength, SizeOf(Integer));
|
||
Stream.Write(locationInfo^.Name[1], stringLength);
|
||
end;
|
||
|
||
procedure TfrmMain.XMLPropStorage1RestoreProperties(Sender: TObject);
|
||
var ws: Integer;
|
||
begin
|
||
Logger.EnterMethod([lcLandscape, lcDebug], 'TfrmMain.XMLPropStorage1RestoreProperties(Sender: TObject);');
|
||
|
||
if Sender = nil then begin
|
||
FTextureManager.UseAnims := mnuShowAnimations.Checked;
|
||
tbTerrain.Down := acTerrain.Checked;
|
||
frmLightLevel.tbLightlevel.Position:=acLightLevel.Tag;
|
||
end;
|
||
|
||
if mnuWindowedMode.Checked then begin
|
||
BorderStyle := bsSizeable;
|
||
FormStyle := fsNormal;
|
||
{if ((Tag<>0) and (mnuWindowedMode.Tag<>0)) then begin
|
||
ws := (Tag and $3);
|
||
if ws = 1 then WindowState := wsNormal else
|
||
if ws = 2 then WindowState := wsMinimized else
|
||
if ws = 3 then WindowState := wsMaximized;
|
||
Left := ((mnuWindowedMode.Tag shr 15) and $7FFF);
|
||
Top := (mnuWindowedMode.Tag and $7FFF);
|
||
Width := ((Tag shr 16) and $3FFF);
|
||
Height:= ((Tag shr 2) and $3FFF);
|
||
Tag := 0; mnuWindowedMode.Tag := 0;
|
||
end; }
|
||
end else begin
|
||
{if ((Tag = 0) and (mnuWindowedMode.Tag = 0)) then begin
|
||
if WindowState = wsNormal then ws := 1 else
|
||
if WindowState = wsMinimized then ws := 2 else
|
||
if WindowState = wsMaximized then ws := 3 else ws := 0;
|
||
Tag := ((Width and $3FFF) shl 16) or ((Height and $3FFF) shl 2) or (ws and $3);
|
||
mnuWindowedMode.Tag := ((Left and $7FFF) shl 15) or ((Top and $7FFF) shl 0);
|
||
end; }
|
||
BorderStyle := bsNone;
|
||
FormStyle := fsStayOnTop;
|
||
WindowState := wsMaximized;
|
||
end;
|
||
|
||
//mnuTileListViewClick(nil);
|
||
//mnuAutoHideGroupListClick(nil);
|
||
//mnuAutoHideRandomListClick(nil);
|
||
Logger.ExitMethod([lcLandscape, lcDebug], 'TfrmMain.XMLPropStorage1RestoreProperties(Sender: TObject);');
|
||
end;
|
||
|
||
procedure TfrmMain.XMLPropStorage1SavingProperties(Sender: TObject);
|
||
var ws: Integer;
|
||
begin
|
||
Logger.EnterMethod([lcLandscape, lcDebug], 'TfrmMain.XMLPropStorage1SavingProperties(Sender: TObject);');
|
||
//Hide;
|
||
if mnuWindowedMode.Checked then begin
|
||
if ((Tag<>0) and (mnuWindowedMode.Tag<>0)) then begin
|
||
ws := (Tag and $3);
|
||
if ws = 1 then WindowState := wsNormal else
|
||
if ws = 2 then WindowState := wsMinimized else
|
||
if ws = 3 then WindowState := wsMaximized;
|
||
Left := ((mnuWindowedMode.Tag shr 15) and $7FFF);
|
||
Top := (mnuWindowedMode.Tag and $7FFF);
|
||
Width := ((Tag shr 16) and $3FFF);
|
||
Height:= ((Tag shr 2) and $3FFF);
|
||
Tag := 0; mnuWindowedMode.Tag := 0;
|
||
end;
|
||
end else begin
|
||
if ((Tag = 0) and (mnuWindowedMode.Tag = 0)) then begin
|
||
if WindowState = wsNormal then ws := 1 else
|
||
if WindowState = wsMinimized then ws := 2 else
|
||
if WindowState = wsMaximized then ws := 3 else ws := 0;
|
||
Tag := ((Width and $3FFF) shl 16) or ((Height and $3FFF) shl 2) or (ws and $3);
|
||
mnuWindowedMode.Tag := ((Left and $7FFF) shl 15) or ((Top and $7FFF) shl 0);
|
||
end;
|
||
end;
|
||
//Show;
|
||
if spTileList.Top > spTileList.Parent.Height then
|
||
spTileList.Top := spTileList.Parent.Height - 200;
|
||
Logger.ExitMethod([lcLandscape, lcDebug], 'TfrmMain.XMLPropStorage1SavingProperties(Sender: TObject);');
|
||
end;
|
||
|
||
procedure TfrmMain.SetX(const AValue: Integer);
|
||
begin
|
||
SetPos(AValue, FY);
|
||
end;
|
||
|
||
procedure TfrmMain.SetY(const AValue: Integer);
|
||
begin
|
||
SetPos(FX, AValue);
|
||
end;
|
||
|
||
procedure TfrmMain.SetPos(AX, AY: Word);
|
||
begin
|
||
if InRange(AX, 0, FLandscape.CellWidth - 1) and InRange(AY, 0,
|
||
FLandscape.CellHeight - 1) then
|
||
begin
|
||
FX := AX;
|
||
edX.Value := FX;
|
||
FY := AY;
|
||
edY.Value := FY;
|
||
dmNetwork.Send(TUpdateClientPosPacket.Create(AX, AY));
|
||
InvalidateScreenBuffer;
|
||
if frmRadarMap <> nil then frmRadarMap.Repaint;
|
||
pbRadar.Repaint;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.SwitchToSelection;
|
||
begin
|
||
acSelect.Checked := True;
|
||
BringToFront;
|
||
end;
|
||
|
||
procedure TfrmMain.RegisterAccessChangedListener(
|
||
AListener: TAccessChangedListener);
|
||
begin
|
||
if FAccessChangedListeners.IndexOf(AListener) < 0 then
|
||
FAccessChangedListeners.Add(AListener);
|
||
end;
|
||
|
||
procedure TfrmMain.RegisterSelectionListener(AListener: TSelectionListener);
|
||
begin
|
||
if FSelectionListeners.IndexOf(AListener) < 0 then
|
||
FSelectionListeners.Add(AListener);
|
||
end;
|
||
|
||
procedure TfrmMain.UnregisterAccessChangedListener(
|
||
AListener: TAccessChangedListener);
|
||
begin
|
||
FAccessChangedListeners.Remove(AListener);
|
||
end;
|
||
|
||
procedure TfrmMain.UnregisterSelectionListener(AListener: TSelectionListener);
|
||
begin
|
||
FSelectionListeners.Remove(AListener);
|
||
end;
|
||
|
||
procedure TfrmMain.SetCurrentTile(const AValue: TWorldItem);
|
||
var
|
||
sRect: TRect;
|
||
w, h: Integer;
|
||
begin
|
||
//Logger.EnterMethod([lcClient, lcDebug], 'SetCurrentTile');
|
||
if AValue = FCurrentTile then
|
||
begin
|
||
//Logger.ExitMethod([lcClient, lcDebug], 'SetCurrentTile');
|
||
Exit;
|
||
end;
|
||
//Logger.Send([lcClient, lcDebug], 'Value', AValue);
|
||
|
||
if FCurrentTile <> nil then
|
||
FCurrentTile.OnDestroy.UnregisterEvent(@OnTileRemoved);
|
||
FCurrentTile := AValue;
|
||
|
||
if FCurrentTile = nil then
|
||
begin
|
||
lblTileInfoIDLabel.Caption:= '';
|
||
lblTileInfoIDValue.Caption:= '';
|
||
lblTileInfoXLabel.Caption := '';
|
||
lblTileInfoXValue.Caption := '';
|
||
lblTileInfoYLabel.Caption := '';
|
||
lblTileInfoYValue.Caption := '';
|
||
lblTileInfoZLabel.Caption := '';
|
||
lblTileInfoZValue.Caption := '';
|
||
lblTileInfoHueLabel.Caption := '';
|
||
lblTileInfoHueValue.Caption := '';
|
||
lblTileInfoOLabel.Visible := False;
|
||
lblTileInfoWLabel.Visible := False;
|
||
lblTileInfoWValue.Visible := False;
|
||
lblTileInfoHLabel.Visible := False;
|
||
lblTileInfoHValue.Visible := False;
|
||
lblTileInfoCLabel.Visible := False;
|
||
end else
|
||
begin
|
||
FCurrentTile.OnDestroy.RegisterEvent(@OnTileRemoved);
|
||
lblTileInfoIDValue.Caption := Format('0x%.4x', [FCurrentTile.TileID]);
|
||
lblTileInfoIDValue.Font.Bold := True;
|
||
lblTileInfoXLabel.Caption := lbBottomCursorPosX;
|
||
lblTileInfoYLabel.Caption := lbBottomCursorPosY;
|
||
lblTileInfoZLabel.Caption := lbBottomCursorPosZ;
|
||
lblTileInfoXValue.Caption := Format('%d', [FCurrentTile.X]);
|
||
lblTileInfoYValue.Caption := Format('%d', [FCurrentTile.Y]);
|
||
lblTileInfoZValue.Caption := Format('%d', [FCurrentTile.Z]);
|
||
if FCurrentTile is TVirtualTile then begin
|
||
lblTileInfoIDLabel.Caption := lbBottomCursorVLayer1;
|
||
lblTileInfoIDValue.Font.Bold := False;
|
||
lblTileInfoIDValue.Caption := lbBottomCursorVLayer2;
|
||
lblTileInfoHueLabel.Caption:= '';
|
||
lblTileInfoHueValue.Caption:= '';
|
||
end
|
||
else if FCurrentTile is TMapCell then begin
|
||
lblTileInfoIDLabel.Caption := lbBottomCursorLandID;
|
||
lblTileInfoHueLabel.Caption:= '';
|
||
lblTileInfoHueValue.Caption:= '';
|
||
end
|
||
else if FCurrentTile is TStaticItem then begin
|
||
lblTileInfoIDLabel.Caption := lbBottomCursorItemID;
|
||
lblTileInfoHueLabel.Caption:= lbBottomCursorItemHue;
|
||
lblTileInfoHueValue.Caption:= Format('%.3x', [TStaticItem(FCurrentTile).Hue]);
|
||
end;
|
||
sRect := GetSelectedRect;
|
||
w := sRect.Right - sRect.Left + 1;
|
||
h := sRect.Bottom - sRect.Top + 1;
|
||
if ((w > 1) or (h > 1)) then begin
|
||
lblTileInfoOLabel.Visible := True;
|
||
lblTileInfoWLabel.Visible := True;
|
||
lblTileInfoWValue.Visible := True;
|
||
lblTileInfoHLabel.Visible := True;
|
||
lblTileInfoHValue.Visible := True;
|
||
lblTileInfoCLabel.Visible := True;
|
||
lblTileInfoWValue.Caption := Format('%d', [w]);
|
||
lblTileInfoHValue.Caption := Format('%d', [h]);
|
||
end else begin
|
||
lblTileInfoOLabel.Visible := False;
|
||
lblTileInfoWLabel.Visible := False;
|
||
lblTileInfoWValue.Visible := False;
|
||
lblTileInfoHLabel.Visible := False;
|
||
lblTileInfoHValue.Visible := False;
|
||
lblTileInfoCLabel.Visible := False;
|
||
end;
|
||
end;
|
||
|
||
UpdateSelection;
|
||
|
||
//Logger.Send([lcClient, lcDebug], 'CurrentTile: %.5x (%.6d)', [CurrentTile.TileID, CurrentTile.TileID]);
|
||
//Logger.ExitMethod([lcClient, lcDebug], 'SetCurrentTile');
|
||
end;
|
||
|
||
procedure TfrmMain.SetSelectedTile(const AValue: TWorldItem);
|
||
begin
|
||
//Logger.EnterMethod([lcClient, lcDebug], 'SetSelectedTile');
|
||
if AValue = FSelectedTile then
|
||
begin
|
||
Logger.ExitMethod([lcClient, lcDebug], 'SetSelectedTile');
|
||
Exit;
|
||
end;
|
||
//Logger.Send([lcClient, lcDebug], 'Value', AValue);
|
||
|
||
if FSelectedTile <> nil then
|
||
FSelectedTile.OnDestroy.UnregisterEvent(@OnTileRemoved);
|
||
FSelectedTile := AValue;
|
||
if FSelectedTile <> nil then
|
||
FSelectedTile.OnDestroy.RegisterEvent(@OnTileRemoved);
|
||
|
||
UpdateSelection;
|
||
//Logger.ExitMethod([lcClient, lcDebug], 'SetSelectedTile');
|
||
end;
|
||
|
||
procedure TfrmMain.SetNormalLights;
|
||
const
|
||
specular: TGLArrayf4 = (2, 2, 2, 1);
|
||
ambient: TGLArrayf4 = (1, 1, 1, 1);
|
||
begin
|
||
glLightfv(GL_LIGHT0, GL_AMBIENT, @specular);
|
||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @ambient);
|
||
end;
|
||
|
||
procedure TfrmMain.SetDarkLights;
|
||
const
|
||
specularDark: TGLArrayf4 = (0.5, 0.5, 0.5, 1);
|
||
ambientDark: TGLArrayf4 = (0.25, 0.25, 0.25, 1);
|
||
begin
|
||
glLightfv(GL_LIGHT0, GL_AMBIENT, @specularDark);
|
||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @ambientDark);
|
||
end;
|
||
|
||
procedure TfrmMain.InitRender;
|
||
const
|
||
lightPosition: TGLArrayf4 = (-1, -1, 0.5, 0);
|
||
begin
|
||
glEnable(GL_ALPHA_TEST);
|
||
glAlphaFunc(GL_GREATER, 0.1);
|
||
glEnable(GL_TEXTURE_2D);
|
||
glDisable(GL_DITHER);
|
||
glEnable(GL_BLEND); // Enable alpha blending of textures
|
||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||
glShadeModel(GL_SMOOTH);
|
||
glEnable(GL_NORMALIZE);
|
||
|
||
glEnable(GL_LIGHT0);
|
||
glLightfv(GL_LIGHT0, GL_POSITION, @lightPosition);
|
||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
|
||
end;
|
||
|
||
procedure TfrmMain.InitSize;
|
||
begin
|
||
glViewport(0, 0, oglGameWindow.Width, oglGameWindow.Height);
|
||
glMatrixMode(GL_PROJECTION);
|
||
glLoadIdentity;
|
||
gluOrtho2D(0, oglGameWindow.Width, oglGameWindow.Height, 0);
|
||
glMatrixMode(GL_MODELVIEW);
|
||
glLoadIdentity;
|
||
end;
|
||
|
||
procedure TfrmMain.LoadLocations;
|
||
var
|
||
xmlDoc: TXMLDocument;
|
||
location: TDOMElement;
|
||
locationNode: PVirtualNode;
|
||
locationInfo: PLocationInfo;
|
||
locations: TDOMNodeList;
|
||
i, j: Integer;
|
||
begin
|
||
vstLocations.Clear;
|
||
|
||
if FileExists(FLocationsFile) then
|
||
begin
|
||
ReadXMLFile(xmlDoc, FLocationsFile);
|
||
if xmlDoc.DocumentElement.NodeName = 'Locations' then
|
||
begin
|
||
locations := xmlDoc.DocumentElement.ChildNodes;
|
||
for i := 0 to locations.Count - 1 do
|
||
begin
|
||
location := TDOMElement(locations[i]);
|
||
if location.NodeName = 'Location' then
|
||
begin
|
||
locationNode := vstLocations.AddChild(nil);
|
||
locationInfo := vstLocations.GetNodeData(locationNode);
|
||
locationInfo^.Name := CP1251ToUTF8(location.AttribStrings['Name']);
|
||
|
||
if TryStrToInt(location.AttribStrings['X'], j) then
|
||
locationInfo^.X := j
|
||
else
|
||
locationInfo^.X := 0;
|
||
|
||
if TryStrToInt(location.AttribStrings['Y'], j) then
|
||
locationInfo^.Y := j
|
||
else
|
||
locationInfo^.Y := 0;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
xmlDoc.Free;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.LoadRandomPresets;
|
||
var
|
||
presets: TDOMNodeList;
|
||
i: Integer;
|
||
begin
|
||
cbRandomPreset.Clear;
|
||
|
||
FreeAndNil(FRandomPresetsDoc);
|
||
if FileExists(FRandomPresetsFile) then
|
||
begin
|
||
ReadXMLFile(FRandomPresetsDoc, FRandomPresetsFile);
|
||
presets := FRandomPresetsDoc.DocumentElement.ChildNodes;
|
||
for i := 0 to presets.Count - 1 do
|
||
begin
|
||
if presets[i].NodeName = 'Preset' then
|
||
begin
|
||
cbRandomPreset.Items.AddObject(
|
||
CP1251ToUTF8(TDOMElement(presets[i]).AttribStrings['Name']), presets[i]);
|
||
end;
|
||
end;
|
||
end else
|
||
begin
|
||
FRandomPresetsDoc := TXMLDocument.Create;
|
||
FRandomPresetsDoc.AppendChild(FRandomPresetsDoc.CreateElement('RandomPresets'));
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.MoveBy(AOffsetX, AOffsetY: Integer); inline;
|
||
begin
|
||
SetPos(EnsureRange(FX + AOffsetX, 0, FLandscape.CellWidth - 1),
|
||
EnsureRange(FY + AOffsetY, 0, FLandscape.CellHeight - 1));
|
||
UpdateCurrentTile;
|
||
end;
|
||
|
||
procedure TfrmMain.PrepareMapCell(AMapCell: TMapCell);
|
||
var
|
||
current, north, east, west, tile1, tile4, tile3, tile6: PBlockInfo;
|
||
cell: TMapCell;
|
||
begin
|
||
current := FScreenBuffer.UpdateSortOrder(AMapCell);
|
||
if current = nil then
|
||
Exit; //off-screen update
|
||
|
||
PrepareScreenBlock(current);
|
||
Exclude(FScreenBufferState, sbsIndexed);
|
||
|
||
//Find surrounding cells
|
||
current := nil;
|
||
north := nil;
|
||
east := nil;
|
||
west := nil;
|
||
tile1 := nil;
|
||
tile4 := nil;
|
||
tile3 := nil;
|
||
tile6 := nil;
|
||
while ((north = nil) or (east = nil) or (west = nil) or
|
||
(tile1 = nil) or (tile3 = nil) or (tile4 = nil) or (tile6 = nil)) and
|
||
FScreenBuffer.Iterate(current) do
|
||
begin
|
||
if current^.Item is TMapCell then
|
||
begin
|
||
cell := TMapCell(current^.Item);
|
||
if (cell.X = AMapCell.X - 1) and (cell.Y = AMapCell.Y - 1) then
|
||
north := current
|
||
else if (cell.X = AMapCell.X) and (cell.Y = AMapCell.Y - 1) then
|
||
east := current
|
||
else if (cell.X = AMapCell.X - 1) and (cell.Y = AMapCell.Y) then
|
||
west := current
|
||
else if (cell.X = AMapCell.X) and (cell.Y = AMapCell.Y + 1) then
|
||
tile1 := current
|
||
else if (cell.X = AMapCell.X + 1) and (cell.Y = AMapCell.Y) then
|
||
tile3 := current
|
||
else if (cell.X = AMapCell.X - 1) and (cell.Y = AMapCell.Y + 1) then
|
||
tile4 := current
|
||
else if (cell.X = AMapCell.X + 1) and (cell.Y = AMapCell.Y - 1) then
|
||
tile6 := current;
|
||
end;
|
||
end;
|
||
|
||
if north <> nil then PrepareScreenBlock(north);
|
||
if east <> nil then PrepareScreenBlock(east);
|
||
if west <> nil then PrepareScreenBlock(west);
|
||
if tile1 <> nil then PrepareScreenBlock(tile1);
|
||
if tile3 <> nil then PrepareScreenBlock(tile3);
|
||
if tile4 <> nil then PrepareScreenBlock(tile4);
|
||
if tile6 <> nil then PrepareScreenBlock(tile6);
|
||
|
||
end;
|
||
|
||
procedure TfrmMain.InvalidateFilter;
|
||
begin
|
||
Exclude(FScreenBufferState, sbsFiltered);
|
||
end;
|
||
|
||
procedure TfrmMain.InvalidateScreenBuffer;
|
||
begin
|
||
Exclude(FScreenBufferState, sbsValid);
|
||
end;
|
||
|
||
procedure TfrmMain.PrepareScreenBlock(ABlockInfo: PBlockInfo);
|
||
|
||
procedure GetLandAlt(const AX, AY: Integer; const ADefaultZ,
|
||
ADefaultRaw: SmallInt; out Z, RawZ: SmallInt);
|
||
var
|
||
cell: TMapCell;
|
||
begin
|
||
cell := FLandscape.MapCell[AX, AY];
|
||
if cell <> nil then
|
||
begin
|
||
Z := cell.Z;
|
||
RawZ := cell.RawZ;
|
||
end else
|
||
begin
|
||
Z := ADefaultZ;
|
||
RawZ := ADefaultRaw;
|
||
end;
|
||
end;
|
||
|
||
var
|
||
item: TWorldItem;
|
||
drawX, drawY: Integer;
|
||
z, west, south, east, tileNorth, tileWest, tileLeft, tileRight: SmallInt;
|
||
rawZ, rawWest, rawSouth, rawEast, rawTileNorth, rawTileWest, rawTileLeft, rawTileRight: SmallInt;
|
||
staticItem: TStaticItem;
|
||
zoom: Single;
|
||
begin
|
||
//add normals to map tiles and materials where possible
|
||
|
||
item := ABlockInfo^.Item;
|
||
|
||
GetDrawOffset(item.X , item.Y, drawX, drawY);
|
||
|
||
if acFlat.Checked then
|
||
begin
|
||
z := 0;
|
||
rawZ := 0;
|
||
end else
|
||
begin
|
||
z := item.Z;
|
||
rawZ := item.RawZ;
|
||
end;
|
||
|
||
if ABlockInfo^.HighRes <> nil then ABlockInfo^.HighRes.DelRef;
|
||
if ABlockInfo^.LowRes <> nil then ABlockInfo^.LowRes.DelRef;
|
||
|
||
ABlockInfo^.HighRes := nil;
|
||
ABlockInfo^.CheckRealQuad := False;
|
||
ABlockInfo^.Text.Free;
|
||
|
||
if item is TMapCell then
|
||
begin
|
||
if not acFlat.Checked then
|
||
begin
|
||
GetLandAlt(item.X, item.Y + 1, z, rawZ, west, rawWest);
|
||
GetLandAlt(item.X + 1, item.Y + 1, z, rawZ, south, rawSouth);
|
||
GetLandAlt(item.X + 1, item.Y, z, rawZ, east, rawEast);
|
||
|
||
if (west <> z) or (south <> z) or (east <> z) then
|
||
ABlockInfo^.HighRes := FTextureManager.GetTexMaterial(item.TileID);
|
||
|
||
if (rawWest <> rawZ) or (rawSouth <> rawZ) or (rawEast <> rawZ) then
|
||
begin
|
||
ABlockInfo^.RealQuad[0][0] := drawX;
|
||
ABlockInfo^.RealQuad[0][1] := drawY - rawZ * 4;
|
||
ABlockInfo^.RealQuad[1][0] := drawX + 22;
|
||
ABlockInfo^.RealQuad[1][1] := drawY + 22 - rawEast * 4;
|
||
ABlockInfo^.RealQuad[2][0] := drawX;
|
||
ABlockInfo^.RealQuad[2][1] := drawY + 44 - rawSouth * 4;
|
||
ABlockInfo^.RealQuad[3][0] := drawX - 22;
|
||
ABlockInfo^.RealQuad[3][1] := drawY + 22 - rawWest * 4;
|
||
|
||
with ABlockInfo^ do
|
||
begin
|
||
with ScreenRect do
|
||
begin
|
||
Left := drawX - 22;
|
||
Right := drawX + 22;
|
||
Top := RealQuad[0][1];
|
||
Bottom := RealQuad[0][1];
|
||
|
||
if RealQuad[1][1] < Top then Top := RealQuad[1][1];
|
||
if RealQuad[1][1] > Bottom then Bottom := RealQuad[1][1];
|
||
|
||
if RealQuad[2][1] < Top then Top := RealQuad[2][1];
|
||
if RealQuad[2][1] > Bottom then Bottom := RealQuad[2][1];
|
||
|
||
if RealQuad[3][1] < Top then Top := RealQuad[3][1];
|
||
if RealQuad[3][1] > Bottom then Bottom := RealQuad[3][1];
|
||
end;
|
||
CheckRealQuad := True;
|
||
end;
|
||
end;
|
||
end else
|
||
begin
|
||
if mnuFlatShowHeight.Checked then
|
||
ABlockInfo^.Text := TGLText.Create(FGLFont, IntToStr(item.Z));
|
||
end;
|
||
|
||
if not ABlockInfo^.CheckRealQuad then
|
||
ABlockInfo^.ScreenRect := Bounds(Trunc(drawX - 22),
|
||
Trunc(drawY - rawZ * 4), 44, 44);
|
||
|
||
ABlockInfo^.LowRes := FTextureManager.GetArtMaterial(item.TileID);
|
||
|
||
if ABlockInfo^.HighRes <> nil then
|
||
begin
|
||
if ABlockInfo^.Normals = nil then
|
||
New(ABlockInfo^.Normals);
|
||
FLandscape.GetNormals(item.X, item.Y, ABlockInfo^.Normals^);
|
||
ABlockInfo^.DrawQuad[0][0] := drawX;
|
||
ABlockInfo^.DrawQuad[0][1] := drawY - z * 4;
|
||
ABlockInfo^.DrawQuad[1][0] := drawX + 22;
|
||
ABlockInfo^.DrawQuad[1][1] := drawY + 22 - east * 4;
|
||
ABlockInfo^.DrawQuad[2][0] := drawX;
|
||
ABlockInfo^.DrawQuad[2][1] := drawY + 44 - south * 4;
|
||
ABlockInfo^.DrawQuad[3][0] := drawX - 22;
|
||
ABlockInfo^.DrawQuad[3][1] := drawY + 22 - west * 4;
|
||
|
||
// Подготовка сетки рельефа для текстур
|
||
if mnuShowGrid.Checked or mnuShowBlocks.Checked then
|
||
begin
|
||
ABlockInfo^.LineWidth[0] := 0.9;
|
||
ABlockInfo^.LineDraw[0][0] := ABlockInfo^.DrawQuad[0];
|
||
ABlockInfo^.LineDraw[0][1] := ABlockInfo^.DrawQuad[1];
|
||
ABlockInfo^.LineWidth[1] := 0.9;
|
||
ABlockInfo^.LineDraw[1][0] := ABlockInfo^.DrawQuad[0];
|
||
ABlockInfo^.LineDraw[1][1] := ABlockInfo^.DrawQuad[3];
|
||
ABlockInfo^.LineWidth[2] := 0.8;
|
||
//ABlockInfo^.LineDraw[2][0] := ABlockInfo^.DrawQuad[0];
|
||
//ABlockInfo^.LineDraw[2][1] := ABlockInfo^.DrawQuad[2];
|
||
ABlockInfo^.LineDraw[2][0] := ABlockInfo^.DrawQuad[1];
|
||
ABlockInfo^.LineDraw[2][1] := ABlockInfo^.DrawQuad[3];
|
||
end;
|
||
end else
|
||
begin
|
||
ABlockInfo^.DrawQuad[0][0] := drawX - 22;
|
||
ABlockInfo^.DrawQuad[0][1] := drawY - z * 4;
|
||
ABlockInfo^.DrawQuad[1][0] := drawX - 22 + ABlockInfo^.LowRes.Width;
|
||
ABlockInfo^.DrawQuad[1][1] := drawY - z * 4;
|
||
ABlockInfo^.DrawQuad[2][0] := drawX - 22 + ABlockInfo^.LowRes.Width;
|
||
ABlockInfo^.DrawQuad[2][1] := drawY + ABlockInfo^.LowRes.Height - z * 4;
|
||
ABlockInfo^.DrawQuad[3][0] := drawX - 22;
|
||
ABlockInfo^.DrawQuad[3][1] := drawY + ABlockInfo^.LowRes.Height - z * 4;
|
||
|
||
// Подготовка сетки рельефа для лендов
|
||
if mnuShowGrid.Checked or mnuShowBlocks.Checked then
|
||
begin
|
||
GetLandAlt(item.X, item.Y - 1, z, rawZ, tileNorth, rawTileNorth);
|
||
GetLandAlt(item.X - 1, item.Y, z, rawZ, tileWest, rawTileWest);
|
||
GetLandAlt(item.X - 1, item.Y + 1, z, rawZ, tileLeft, rawTileLeft);
|
||
GetLandAlt(item.X + 1, item.Y - 1, z, rawZ, tileRight, rawTileRight);
|
||
if (tileNorth <> z) or (tileRight <> z)
|
||
then ABlockInfo^.LineWidth[0] := 0.9
|
||
else ABlockInfo^.LineWidth[0] := 0.8;
|
||
ABlockInfo^.LineDraw[0][0][0] := drawX;
|
||
ABlockInfo^.LineDraw[0][0][1] := ABlockInfo^.DrawQuad[0][1];
|
||
ABlockInfo^.LineDraw[0][1][0] := ABlockInfo^.DrawQuad[1][0];
|
||
ABlockInfo^.LineDraw[0][1][1] := ABlockInfo^.DrawQuad[1][1] + 22;
|
||
if (tileWest <> z) or (tileLeft <> z)
|
||
then ABlockInfo^.LineWidth[1] := 0.9
|
||
else ABlockInfo^.LineWidth[1] := 0.8;
|
||
ABlockInfo^.LineDraw[1][0][0] := drawX;
|
||
ABlockInfo^.LineDraw[1][0][1] := ABlockInfo^.DrawQuad[0][1];
|
||
ABlockInfo^.LineDraw[1][1][0] := ABlockInfo^.DrawQuad[3][0];
|
||
ABlockInfo^.LineDraw[1][1][1] := ABlockInfo^.DrawQuad[3][1] - 22;
|
||
ABlockInfo^.LineWidth[2] := 0.0;
|
||
end;
|
||
end;
|
||
end else
|
||
// Виртуальный пол
|
||
if item is TVirtualTile then
|
||
begin
|
||
ABlockInfo^.LowRes := FVLayerMaterial;
|
||
ABlockInfo^.LowRes.AddRef;
|
||
ABlockInfo^.ScreenRect := Bounds(Trunc(drawX - 22), Trunc(drawY - z * 4),
|
||
44, 44);
|
||
ABlockInfo^.DrawQuad[0][0] := drawX - 22;
|
||
ABlockInfo^.DrawQuad[0][1] := drawY - z * 4;
|
||
ABlockInfo^.DrawQuad[1][0] := drawX - 22 + ABlockInfo^.LowRes.Width;
|
||
ABlockInfo^.DrawQuad[1][1] := drawY - z * 4;
|
||
ABlockInfo^.DrawQuad[2][0] := drawX - 22 + ABlockInfo^.LowRes.Width;
|
||
ABlockInfo^.DrawQuad[2][1] := drawY + ABlockInfo^.LowRes.Height - z * 4;
|
||
ABlockInfo^.DrawQuad[3][0] := drawX - 22;
|
||
ABlockInfo^.DrawQuad[3][1] := drawY + ABlockInfo^.LowRes.Height - z * 4;
|
||
|
||
// Подготовка сетки блоков на виртуальном полу
|
||
if (frmVirtualLayer.cbShowBlocks.Checked) then
|
||
begin
|
||
if (item.Y mod 8) <> 0 then
|
||
ABlockInfo^.LineWidth[0] := 0
|
||
else begin
|
||
ABlockInfo^.LineWidth[0] := 1.6;
|
||
ABlockInfo^.LineDraw[0][0][0] := drawX;
|
||
ABlockInfo^.LineDraw[0][0][1] := ABlockInfo^.DrawQuad[0][1];
|
||
ABlockInfo^.LineDraw[0][1][0] := ABlockInfo^.DrawQuad[1][0];
|
||
ABlockInfo^.LineDraw[0][1][1] := ABlockInfo^.DrawQuad[1][1] + 22;
|
||
end;
|
||
if (item.X mod 8) <> 0 then
|
||
ABlockInfo^.LineWidth[1] := 0
|
||
else begin
|
||
ABlockInfo^.LineWidth[1] := 1.6;
|
||
ABlockInfo^.LineDraw[1][0][0] := drawX;
|
||
ABlockInfo^.LineDraw[1][0][1] := ABlockInfo^.DrawQuad[0][1];
|
||
ABlockInfo^.LineDraw[1][1][0] := ABlockInfo^.DrawQuad[3][0];
|
||
ABlockInfo^.LineDraw[1][1][1] := ABlockInfo^.DrawQuad[3][1] - 22;
|
||
end;
|
||
|
||
end;
|
||
|
||
end else
|
||
begin
|
||
staticItem := TStaticItem(item);
|
||
|
||
// Тайл виртуального источника света
|
||
if acNoDraw.Checked and mnuShowLightSource.Checked and (staticItem.TileID <= FLandscape.MaxStaticID)
|
||
and (FLightSourceTiles[staticItem.TileID].image > 0) then
|
||
begin
|
||
ABlockInfo^.LowRes := FVLightSrcMaterial[FLightSourceTiles[staticItem.TileID].image - 1];
|
||
ABlockInfo^.LowRes.AddRef;
|
||
ABlockInfo^.ScreenRect := Bounds(Trunc(drawX - 12), Trunc(drawY - z * 4), 24, 24);
|
||
ABlockInfo^.DrawQuad[0][0] := drawX - 12;
|
||
ABlockInfo^.DrawQuad[0][1] := drawY + 12 - z * 4;
|
||
ABlockInfo^.DrawQuad[1][0] := drawX - 12 + ABlockInfo^.LowRes.Width;
|
||
ABlockInfo^.DrawQuad[1][1] := drawY + 12 - z * 4;
|
||
ABlockInfo^.DrawQuad[2][0] := drawX - 12 + ABlockInfo^.LowRes.Width;
|
||
ABlockInfo^.DrawQuad[2][1] := drawY + 12 + ABlockInfo^.LowRes.Height - z * 4;
|
||
ABlockInfo^.DrawQuad[3][0] := drawX - 12;
|
||
ABlockInfo^.DrawQuad[3][1] := drawY + 12 + ABlockInfo^.LowRes.Height - z * 4;
|
||
end else
|
||
// Тайлы обычной статики
|
||
begin
|
||
ABlockInfo^.LowRes := FTextureManager.GetStaticMaterial(staticItem);
|
||
ABlockInfo^.HueOverride := False;
|
||
|
||
ABlockInfo^.ScreenRect := Bounds(Trunc(drawX - ABlockInfo^.LowRes.RealWidth / 2),
|
||
Trunc(drawY + 44 - ABlockInfo^.LowRes.RealHeight - z * 4),
|
||
ABlockInfo^.LowRes.RealWidth,
|
||
ABlockInfo^.LowRes.RealHeight);
|
||
|
||
ABlockInfo^.Translucent := tdfTranslucent in
|
||
ResMan.Tiledata.StaticTiles[staticItem.TileID].Flags;
|
||
|
||
south := ABlockInfo^.LowRes.RealHeight;
|
||
east := ABlockInfo^.LowRes.RealWidth div 2;
|
||
|
||
ABlockInfo^.DrawQuad[0][0] := drawX - east;
|
||
ABlockInfo^.DrawQuad[0][1] := drawY + 44 - south - z * 4;
|
||
ABlockInfo^.DrawQuad[1][0] := drawX - east + ABlockInfo^.LowRes.Width;
|
||
ABlockInfo^.DrawQuad[1][1] := drawY + 44 - south - z * 4;
|
||
ABlockInfo^.DrawQuad[2][0] := drawX - east + ABlockInfo^.LowRes.Width;
|
||
ABlockInfo^.DrawQuad[2][1] := drawY + 44 - south + ABlockInfo^.LowRes.Height - z * 4;
|
||
ABlockInfo^.DrawQuad[3][0] := drawX - east;
|
||
ABlockInfo^.DrawQuad[3][1] := drawY + 44 - south + ABlockInfo^.LowRes.Height - z * 4;
|
||
end;
|
||
end;
|
||
|
||
|
||
if tbZoom.Down then begin
|
||
zoom := tbZoom.Tag / 1000.0;
|
||
|
||
ABlockInfo^.ScreenRect.Left := Trunc(zoom * (ABlockInfo^.ScreenRect.Left -drawX)+drawX);
|
||
ABlockInfo^.ScreenRect.Top := Trunc(zoom * (ABlockInfo^.ScreenRect.Top -drawY)+drawY);;
|
||
ABlockInfo^.ScreenRect.Right := Trunc(zoom * (ABlockInfo^.ScreenRect.Right -drawX)+drawX);
|
||
ABlockInfo^.ScreenRect.Bottom := Trunc(zoom * (ABlockInfo^.ScreenRect.Bottom -drawY)+drawY);
|
||
|
||
//south:= Trunc(zoom*(ABlockInfo^.DrawQuad[2][1] - ABlockInfo^.DrawQuad[0][1]));
|
||
//east := Trunc(zoom*(ABlockInfo^.DrawQuad[2][0] - ABlockInfo^.DrawQuad[0][0]));
|
||
|
||
for z:=0 to 3 do begin
|
||
ABlockInfo^.DrawQuad[z][0] := Trunc(zoom * (ABlockInfo^.DrawQuad[z][0] -drawX)+drawX);
|
||
ABlockInfo^.DrawQuad[z][1] := Trunc(zoom * (ABlockInfo^.DrawQuad[z][1] -drawY)+drawY);
|
||
end;
|
||
if item is TMapCell then begin
|
||
inc(ABlockInfo^.DrawQuad[0][1], -1);
|
||
inc(ABlockInfo^.DrawQuad[1][0], +1);
|
||
inc(ABlockInfo^.DrawQuad[2][1], +1);
|
||
inc(ABlockInfo^.DrawQuad[3][0], -1);
|
||
end else if zoom < 1.0 then begin
|
||
inc(ABlockInfo^.DrawQuad[0][0], -1);
|
||
inc(ABlockInfo^.DrawQuad[0][1], -1);
|
||
//inc(ABlockInfo^.DrawQuad[1][0], +1);
|
||
inc(ABlockInfo^.DrawQuad[1][1], -1);
|
||
//inc(ABlockInfo^.DrawQuad[2][0], +1);
|
||
//inc(ABlockInfo^.DrawQuad[2][1], +1);
|
||
inc(ABlockInfo^.DrawQuad[3][0], -1);
|
||
//inc(ABlockInfo^.DrawQuad[3][1], +1);
|
||
end;
|
||
|
||
if not acFlat.Checked and (item is TMapCell) and
|
||
((rawWest <> rawZ) or (rawSouth <> rawZ) or (rawEast <> rawZ)) then
|
||
for z:=0 to 3 do begin
|
||
ABlockInfo^.RealQuad[z][0] := Trunc(zoom * (ABlockInfo^.RealQuad[z][0] -drawX)+drawX);
|
||
ABlockInfo^.RealQuad[z][1] := Trunc(zoom * (ABlockInfo^.RealQuad[z][1] -drawY)+drawY);
|
||
end;
|
||
|
||
rawZ := -1;
|
||
if ((mnuShowGrid.Checked or mnuShowBlocks.Checked) and (item is TMapCell))
|
||
then if (ABlockInfo^.HighRes <> nil) then rawZ:=2 else rawZ:= 1
|
||
else if (frmVirtualLayer.cbShowBlocks.Checked and (item is TVirtualTile))
|
||
then if ((item.Y mod 8 = 0) or (item.X mod 8 = 0)) then rawZ := 1;
|
||
|
||
for z:=0 to rawZ do begin
|
||
//ABlockInfo^.LineWidth[z] := zoom * ABlockInfo^.LineWidth[z];
|
||
ABlockInfo^.LineDraw[z][0][0] := TGLint(Trunc(zoom *(ABlockInfo^.LineDraw[z][0][0] -drawX)+drawX));
|
||
ABlockInfo^.LineDraw[z][0][1] := TGLint(Trunc(zoom *(ABlockInfo^.LineDraw[z][0][1] -drawY)+drawY));
|
||
ABlockInfo^.LineDraw[z][1][0] := TGLint(Trunc(zoom *(ABlockInfo^.LineDraw[z][1][0] -drawX)+drawX));
|
||
ABlockInfo^.LineDraw[z][1][1] := TGLint(Trunc(zoom *(ABlockInfo^.LineDraw[z][1][1] -drawY)+drawY));
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.Render;
|
||
var
|
||
highlight: Boolean;
|
||
intensity, red, green, blue: GLfloat;
|
||
blockInfo: PBlockInfo;
|
||
item: TWorldItem;
|
||
i : byte;
|
||
zoom: Single;
|
||
begin
|
||
if tbZoom.Down then zoom := tbZoom.Tag / 1000.0 else zoom:=1.0;
|
||
|
||
if not (sbsValid in FScreenBufferState) then
|
||
RebuildScreenBuffer;
|
||
|
||
if not (sbsIndexed in FScreenBufferState) then
|
||
begin
|
||
FScreenBuffer.UpdateShortcuts;
|
||
Include(FScreenBufferState, sbsIndexed);
|
||
end;
|
||
|
||
if not (sbsFiltered in FScreenBufferState) then
|
||
UpdateFilter;
|
||
|
||
blockInfo := nil;
|
||
while FScreenBuffer.Iterate(blockInfo) do
|
||
begin
|
||
if blockInfo^.State = ssFiltered then
|
||
Continue;
|
||
|
||
item := blockInfo^.Item;
|
||
|
||
if acSelect.Checked or item.CanBeEdited or (item is TVirtualTile) then
|
||
begin
|
||
intensity := 1.0;
|
||
SetNormalLights;
|
||
end else
|
||
begin
|
||
intensity := 0.5;
|
||
SetDarkLights;
|
||
end;
|
||
|
||
case blockInfo^.WalkRestriction of
|
||
wrNone:
|
||
begin
|
||
red := 1;
|
||
green := 1;
|
||
blue := 1;
|
||
end;
|
||
wrCanWalk:
|
||
begin
|
||
red := 0.5;
|
||
green := 1;
|
||
blue := 0.5;
|
||
end;
|
||
wrCannotWalk:
|
||
begin
|
||
red := 1;
|
||
green := 0.5;
|
||
blue := 0.5;
|
||
end;
|
||
end;
|
||
|
||
if blockInfo^.Translucent then
|
||
glColor4f(intensity * red, intensity * green, intensity * blue, 0.8)
|
||
else
|
||
glColor4f(intensity * red, intensity * green, intensity * blue, 1.0);
|
||
|
||
highlight := blockInfo^.Highlighted and item.CanBeEdited;
|
||
|
||
if highlight then
|
||
begin
|
||
glEnable(GL_COLOR_LOGIC_OP);
|
||
glLogicOp(GL_COPY_INVERTED);
|
||
end;
|
||
|
||
if blockInfo^.HighRes <> nil then
|
||
begin
|
||
glBindTexture(GL_TEXTURE_2D, blockInfo^.HighRes.Texture);
|
||
|
||
if not highlight and (blockInfo^.WalkRestriction = wrNone) then
|
||
glEnable(GL_LIGHTING);
|
||
|
||
glBegin(GL_QUADS);
|
||
glNormal3fv(@blockInfo^.Normals^[0]);
|
||
glTexCoord2i(0, 0); glVertex2iv(@blockInfo^.DrawQuad[0]);
|
||
glNormal3fv(@blockInfo^.Normals^[3]);
|
||
glTexCoord2i(0, 1); glVertex2iv(@blockInfo^.DrawQuad[3]);
|
||
glNormal3fv(@blockInfo^.Normals^[2]);
|
||
glTexCoord2i(1, 1); glVertex2iv(@blockInfo^.DrawQuad[2]);
|
||
glNormal3fv(@blockInfo^.Normals^[1]);
|
||
glTexCoord2i(1, 0); glVertex2iv(@blockInfo^.DrawQuad[1]);
|
||
glEnd;
|
||
|
||
if not highlight and (blockInfo^.WalkRestriction = wrNone) then
|
||
glDisable(GL_LIGHTING);
|
||
end else
|
||
begin
|
||
glBindTexture(GL_TEXTURE_2D, blockInfo^.LowRes.Texture);
|
||
glBegin(GL_QUADS);
|
||
glTexCoord2i(0, 0); glVertex2iv(@blockInfo^.DrawQuad[0]);
|
||
glTexCoord2i(1, 0); glVertex2iv(@blockInfo^.DrawQuad[1]);
|
||
glTexCoord2i(1, 1); glVertex2iv(@blockInfo^.DrawQuad[2]);
|
||
glTexCoord2i(0, 1); glVertex2iv(@blockInfo^.DrawQuad[3]);
|
||
glEnd;
|
||
end;
|
||
|
||
if highlight then
|
||
glDisable(GL_COLOR_LOGIC_OP);
|
||
|
||
if (blockInfo^.Text <> nil) then
|
||
blockInfo^.Text.Render(blockInfo^.ScreenRect);
|
||
|
||
/////////////////
|
||
// Рендинг сетки рельефа
|
||
if (mnuShowGrid.Checked) and (blockInfo^.Item is TMapCell) then
|
||
begin
|
||
glDisable(GL_TEXTURE_2D); // не использовать цвет текстуры
|
||
glEnable(GL_LINE_SMOOTH); // сглаживание линий
|
||
//glDisable(GL_LINE_SMOOTH);
|
||
|
||
if (tbFlat.Down) then
|
||
begin
|
||
glColor4f(0.8, 0.8, 0.8, 0.9); // цвет линий
|
||
glLineWidth(0.1); // ширина линий
|
||
glBegin(GL_LINES);
|
||
glVertex2iv(@blockInfo^.LineDraw[0][0]);
|
||
glVertex2iv(@blockInfo^.LineDraw[0][1]);
|
||
glVertex2iv(@blockInfo^.LineDraw[1][0]);
|
||
glVertex2iv(@blockInfo^.LineDraw[1][1]);
|
||
glEnd;
|
||
end else
|
||
begin
|
||
if blockInfo^.LineWidth[0] < 0.85
|
||
then glColor4f(1.0, 1.0, 0.0, 0.5) // цвет линий
|
||
else glColor4f(1.0, 1.0, 1.0, 1.0); // цвет линий
|
||
glLineWidth(blockInfo^.LineWidth[0]); // ширина линий
|
||
glBegin(GL_LINES);
|
||
glVertex2iv(@blockInfo^.LineDraw[0][0]);
|
||
glVertex2iv(@blockInfo^.LineDraw[0][1]);
|
||
glEnd;
|
||
if blockInfo^.LineWidth[1] < 0.85
|
||
then glColor4f(1.0, 1.0, 0.0, 0.5) // цвет линий
|
||
else glColor4f(1.0, 1.0, 1.0, 1.0); // цвет линий
|
||
glLineWidth(blockInfo^.LineWidth[1]); // ширина линий
|
||
glBegin(GL_LINES);
|
||
glVertex2iv(@blockInfo^.LineDraw[1][0]);
|
||
glVertex2iv(@blockInfo^.LineDraw[1][1]);
|
||
glEnd;
|
||
if blockInfo^.LineWidth[2] > 0 then
|
||
begin
|
||
glColor4f(1.3281, 0.2510, 1.0, 0.8); // цвет линий
|
||
glLineWidth(blockInfo^.LineWidth[2]);// ширина линий
|
||
glBegin(GL_LINES);
|
||
glVertex2iv(@blockInfo^.LineDraw[2][0]);
|
||
glVertex2iv(@blockInfo^.LineDraw[2][1]);
|
||
glEnd;
|
||
end;
|
||
end;
|
||
|
||
glDisable(GL_LINE_SMOOTH);
|
||
glEnable(GL_TEXTURE_2D);
|
||
end else if (mnuShowBlocks.Checked) and (blockInfo^.Item is TMapCell) then
|
||
begin // Рендинг сетки блоков
|
||
glDisable(GL_TEXTURE_2D); // не использовать цвет текстуры
|
||
glEnable(GL_LINE_SMOOTH); // сглаживание линий
|
||
|
||
if (blockInfo^.Item.X mod 8 = 0) then begin
|
||
glLineWidth(2.0);
|
||
glColor4f(1.0, 1.0, 0.0, 0.5);
|
||
end else begin
|
||
glColor4f(0.8, 0.8, 0.8, 0.9);
|
||
glLineWidth(0.1);
|
||
end;
|
||
glBegin(GL_LINES);
|
||
glVertex2iv(@blockInfo^.LineDraw[1][0]);
|
||
glVertex2iv(@blockInfo^.LineDraw[1][1]);
|
||
glEnd;
|
||
if (blockInfo^.Item.Y mod 8 = 0) then begin
|
||
glLineWidth(2.0);
|
||
glColor4f(1.0, 1.0, 0.0, 0.5);
|
||
end else begin
|
||
glColor4f(0.8, 0.8, 0.8, 0.9);
|
||
glLineWidth(0.1);
|
||
end;
|
||
glBegin(GL_LINES);
|
||
glVertex2iv(@blockInfo^.LineDraw[0][0]);
|
||
glVertex2iv(@blockInfo^.LineDraw[0][1]);
|
||
glEnd;
|
||
|
||
glDisable(GL_LINE_SMOOTH);
|
||
glEnable(GL_TEXTURE_2D);
|
||
end else if (frmVirtualLayer.cbShowBlocks.Checked) and (blockInfo^.Item is TVirtualTile) then
|
||
begin
|
||
glDisable(GL_TEXTURE_2D); // не использовать цвет текстуры
|
||
glEnable(GL_LINE_SMOOTH); // сглаживание линий
|
||
|
||
for i := 0 to 1 do if blockInfo^.LineWidth[i] > 0 then begin
|
||
glColor4f(0.0, 0.65, 0.68, 0.50); // цвет линий
|
||
glLineWidth(blockInfo^.LineWidth[i]); // ширина линий
|
||
glBegin(GL_LINES);
|
||
glVertex2iv(@blockInfo^.LineDraw[i][0]);
|
||
glVertex2iv(@blockInfo^.LineDraw[i][1]);
|
||
glEnd;
|
||
end;
|
||
|
||
glDisable(GL_LINE_SMOOTH);
|
||
glEnable(GL_TEXTURE_2D);
|
||
end;
|
||
|
||
////////////////
|
||
end;
|
||
|
||
if (FLightManager.LightLevel > 0) and not acFlat.Checked then
|
||
FLightManager.Draw(oglGameWindow.ClientRect, zoom);
|
||
FOverlayUI.Draw(oglGameWindow);
|
||
|
||
FLandscape.ResizeBlockCache(0);
|
||
end;
|
||
|
||
procedure TfrmMain.SaveLocations;
|
||
var
|
||
xmlDoc: TXMLDocument;
|
||
location: TDOMElement;
|
||
locationNode: PVirtualNode;
|
||
locationInfo: PLocationInfo;
|
||
begin
|
||
xmlDoc := TXMLDocument.Create;
|
||
xmlDoc.AppendChild(xmlDoc.CreateElement('Locations'));
|
||
|
||
locationNode := vstLocations.GetFirst;
|
||
while locationNode <> nil do
|
||
begin
|
||
locationInfo := vstLocations.GetNodeData(locationNode);
|
||
location := xmlDoc.CreateElement('Location');
|
||
location.AttribStrings['Name'] := UTF8ToCP1251(locationInfo^.Name);
|
||
location.AttribStrings['X'] := IntToStr(locationInfo^.X);
|
||
location.AttribStrings['Y'] := IntToStr(locationInfo^.Y);
|
||
xmlDoc.DocumentElement.AppendChild(location);
|
||
|
||
locationNode := vstLocations.GetNext(locationNode);
|
||
end;
|
||
|
||
WriteXMLFile(xmlDoc, FLocationsFile);
|
||
xmlDoc.Free;
|
||
end;
|
||
|
||
procedure TfrmMain.SaveRandomPresets;
|
||
begin
|
||
WriteXMLFile(FRandomPresetsDoc, FRandomPresetsFile);
|
||
end;
|
||
|
||
procedure TfrmMain.OnLandscapeChanged;
|
||
begin
|
||
InvalidateScreenBuffer;
|
||
oglGameWindow.Repaint;
|
||
UpdateCurrentTile;
|
||
end;
|
||
|
||
procedure TfrmMain.OnMapChanged(AMapCell: TMapCell);
|
||
begin
|
||
PrepareMapCell(AMapCell);
|
||
ForceUpdateCurrentTile;
|
||
InvalidateFilter
|
||
end;
|
||
|
||
procedure TfrmMain.OnNewBlock(ABlock: TBlock);
|
||
begin
|
||
InvalidateScreenBuffer;
|
||
end;
|
||
|
||
procedure TfrmMain.OnStaticDeleted(AStaticItem: TStaticItem);
|
||
begin
|
||
FScreenBuffer.Delete(AStaticItem);
|
||
FRepaintNeeded := True;
|
||
ForceUpdateCurrentTile;
|
||
InvalidateFilter
|
||
end;
|
||
|
||
procedure TfrmMain.OnStaticElevated(AStaticItem: TStaticItem);
|
||
var
|
||
blockInfo: PBlockInfo;
|
||
begin
|
||
AStaticItem.PrioritySolver := FScreenBuffer.GetSerial;
|
||
blockInfo := FScreenBuffer.UpdateSortOrder(AStaticItem);
|
||
if blockInfo <> nil then
|
||
begin
|
||
PrepareScreenBlock(blockInfo);
|
||
Exclude(FScreenBufferState, sbsIndexed);
|
||
ForceUpdateCurrentTile;
|
||
InvalidateFilter
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.OnStaticHued(AStaticItem: TStaticItem);
|
||
var
|
||
blockInfo: PBlockInfo;
|
||
begin
|
||
blockInfo := nil;
|
||
while FScreenBuffer.Iterate(blockInfo) do
|
||
begin
|
||
if blockInfo^.Item = AStaticItem then
|
||
begin
|
||
PrepareScreenBlock(blockInfo);
|
||
FRepaintNeeded := True;
|
||
ForceUpdateCurrentTile;
|
||
Break;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.OnStaticInserted(AStaticItem: TStaticItem);
|
||
begin
|
||
if (AStaticItem.X >= FX + FLowOffsetX) and
|
||
(AStaticItem.X <= FX + FHighOffsetX) and
|
||
(AStaticItem.Y >= FY + FLowOffsetY) and
|
||
(AStaticItem.Y <= FY + FHighOffsetY) then
|
||
begin
|
||
AStaticItem.PrioritySolver := FScreenBuffer.GetSerial;
|
||
PrepareScreenBlock(FScreenBuffer.Insert(AStaticItem));
|
||
FRepaintNeeded := True;
|
||
ForceUpdateCurrentTile;
|
||
InvalidateFilter
|
||
end;
|
||
end;
|
||
|
||
function TfrmMain.LoadListError(condition: Boolean; filename, message : string): Boolean; inline;
|
||
var
|
||
answer: Word;
|
||
l, c: Word;
|
||
begin
|
||
result := False;
|
||
if not condition
|
||
then Exit;
|
||
|
||
l := Length(filename);
|
||
for c := l downto 1 do
|
||
if (filename[c] = '\') or (filename[c] = '/')
|
||
then break;
|
||
if c > 1 then inc(c);
|
||
answer := MessageDlg(Format(GetParseErText('MessageDlgCaption'), [Copy(filename, c, l-c+1)]),
|
||
Format(GetParseErText('MessageDlgTxtLine1')+sLineBreak+
|
||
GetParseErText('MessageDlgTxtLine2')+sLineBreak+sLineBreak+
|
||
GetParseErText('MessageDlgTxtLine3'),
|
||
[message, filename]), mtError, [mbAbort, mbRetry, mbIgnore], 0);
|
||
if answer = mrAbort
|
||
then begin
|
||
Application.Terminate;
|
||
Halt;
|
||
end;
|
||
result := (answer = mrRetry);
|
||
end;
|
||
|
||
procedure TfrmMain.LoadVisibleTiles(AFileName: String);
|
||
var
|
||
XMLDoc: TXMLDocument;
|
||
iNode, node: TDOMNode;
|
||
s: string;
|
||
i, id: Integer;
|
||
begin
|
||
frmInitialize.SetStatusLabel(Format(frmInitialize.SplashLoading, ['VirtualTiles.xml']));
|
||
FVisibleTiles := TBits.Create($4000 + FLandscape.MaxStaticID);
|
||
for i := 0 to FVisibleTiles.Size - 1 do
|
||
FVisibleTiles[i] := True;
|
||
|
||
// Читаем xml файл с жесткого диска
|
||
ReadXMLFile(XMLDoc, AFileName);
|
||
if LowerCase(XMLDoc.DocumentElement.NodeName) = 'virtualtiles' then
|
||
begin
|
||
iNode := XMLDoc.DocumentElement.FirstChild;
|
||
while iNode <> nil do
|
||
begin
|
||
if LowerCase(iNode.NodeName) = 'unused' then
|
||
begin
|
||
node := iNode.FirstChild;
|
||
while node <> nil do
|
||
begin
|
||
s := LowerCase(node.NodeName);
|
||
if (s = 'tile') or (s = 'land') or (s = 'item') then
|
||
for i := node.Attributes.Length - 1 downto 0 do
|
||
if LowerCase(node.Attributes[i].NodeName) = 'id' then
|
||
if TryStrToInt(node.Attributes[i].NodeValue, id) then
|
||
begin
|
||
if s = 'item'
|
||
then Inc(id, $4000);
|
||
if (id >= 0) and (id < FVisibleTiles.Size)
|
||
then FVisibleTiles[id] := False;
|
||
end;
|
||
node := node.NextSibling;
|
||
end;
|
||
end;
|
||
iNode := iNode.NextSibling;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.LoadLightSourceTiles(AFileName: String);
|
||
var
|
||
XMLDoc: TXMLDocument;
|
||
iNode, node: TDOMNode;
|
||
s: string;
|
||
i, id, bit: Integer;
|
||
begin
|
||
frmInitialize.SetStatusLabel(Format(frmInitialize.SplashLoading, ['VirtualTiles.xml']));
|
||
if (FLightSourceTiles = nil) then begin
|
||
getmem(FLightSourceTiles, (FLandscape.MaxStaticID + 1) * SizeOf(TLightTile));
|
||
for i := 0 to FLandscape.MaxStaticID - 1 do
|
||
FillByte(FLightSourceTiles[i], SizeOf(TLightTile), 0);
|
||
end;
|
||
|
||
// Читаем xml файл с жесткого диска
|
||
ReadXMLFile(XMLDoc, AFileName);
|
||
if LowerCase(XMLDoc.DocumentElement.NodeName) = 'virtualtiles' then
|
||
begin
|
||
iNode := XMLDoc.DocumentElement.FirstChild;
|
||
while iNode <> nil do
|
||
begin
|
||
if LowerCase(iNode.NodeName) = 'lightsource' then
|
||
begin
|
||
node := iNode.FirstChild;
|
||
while node <> nil do
|
||
begin
|
||
s := LowerCase(node.NodeName);
|
||
if (s = 'tile') or (s = 'item') then begin
|
||
id :=-1;
|
||
bit := 1;
|
||
for i := node.Attributes.Length - 1 downto 0 do
|
||
begin
|
||
if LowerCase(node.Attributes[i].NodeName) = 'id' then
|
||
if TryStrToInt(node.Attributes[i].NodeValue, id) then
|
||
begin
|
||
if s = 'tile'
|
||
then Inc(id, -$4000);
|
||
//if (id >= 0) and (id < FLightSourceTiles.Size)
|
||
// then FLightSourceTiles[id] := True;
|
||
end;
|
||
if LowerCase(node.Attributes[i].NodeName) = 'icon' then
|
||
if TryStrToInt(node.Attributes[i].NodeValue, bit) then
|
||
if (bit < 1) or (bit > FVLightSrcImageCount) then
|
||
bit := 1;
|
||
end;
|
||
if (id >= 0) and (id <= FLandscape.MaxStaticID) then
|
||
begin
|
||
FLightSourceTiles[id].image := bit;
|
||
end;
|
||
end;
|
||
node := node.NextSibling;
|
||
end;
|
||
end;
|
||
iNode := iNode.NextSibling;
|
||
end;
|
||
end;
|
||
|
||
end;
|
||
|
||
procedure TfrmMain.LoadSurfsTilesList;
|
||
begin
|
||
frmInitialize.SetStatusLabel(Format(frmInitialize.SplashLoading, ['SurfaceInf.xml']));
|
||
end;
|
||
|
||
{
|
||
|
||
procedure TfrmMain.LoadSurfsTilesList;
|
||
var
|
||
fPath, str, attribute : string;
|
||
XMLDoc: TXMLDocument;
|
||
cNode, sNode, eNode : TDOMNode;
|
||
c, s, e, a : Integer;
|
||
|
||
tCount: Integer;
|
||
tHash1: ^DWORD;
|
||
tHash2: ^DWORD;
|
||
tIndex: ^LongWord;
|
||
|
||
|
||
value : Integer;
|
||
//e, t, a, value : Integer;
|
||
|
||
// cCount : Word;
|
||
sCount : ^Word;
|
||
eCount : ^PWord;
|
||
begin
|
||
if FileExists(FProfileDir + 'SurfaceInf.xml')
|
||
then fPath := (FProfileDir + 'SurfaceInf.xml')
|
||
else if FileExists(FLocalDir + 'SurfaceInf.xml')
|
||
then fPath := (FLocalDir + 'SurfaceInf.xml')
|
||
else if FileExists(FConfigDir + 'SurfaceInf.xml')
|
||
then fPath := (FConfigDir + 'SurfaceInf.xml')
|
||
else if FileExists(ResMan.GetFile('SurfaceInf.xml'))
|
||
then fPath := (ResMan.GetFile('SurfaceInf.xml'))
|
||
else Exit;
|
||
|
||
|
||
|
||
|
||
|
||
// Читаем xml файл с жесткого диска
|
||
ReadXMLFile(XMLDoc, fPath);
|
||
if LowerCase(XMLDoc.DocumentElement.NodeName) = 'surfaceinf' then
|
||
begin
|
||
// Подсчет категорий
|
||
FSurfsList.GroupCount := 0;
|
||
cNode := XMLDoc.DocumentElement.FirstChild;
|
||
while cNode <> nil do
|
||
begin
|
||
if LowerCase(cNode.NodeName) = 'category' then
|
||
inc(FSurfsList.GroupCount);
|
||
cNode := cNode.NextSibling;
|
||
end;
|
||
getmem(sCount, FSurfsList.GroupCount * SizeOf( Word));
|
||
getmem(eCount, FSurfsList.GroupCount * SizeOf(PWord));
|
||
|
||
// Подсчет объектов
|
||
cNode := XMLDoc.DocumentElement.FirstChild;
|
||
while cNode <> nil do
|
||
begin
|
||
if LowerCase(cNode.NodeName) = 'category' then
|
||
begin
|
||
sNode := cNode.FirstChild;
|
||
while sNode <> nil do
|
||
begin
|
||
|
||
|
||
|
||
sNode := sNode.NextSibling;
|
||
end;
|
||
end;
|
||
|
||
cNode := cNode.NextSibling;
|
||
end;
|
||
////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
// Создание списка
|
||
FSurfsList.TilesCount := $4000 + FLandscape.MaxStaticID;
|
||
getmem(FSurfsList.Tiles, FSurfsList.TilesCount * SizeOf(PSurfGrad));
|
||
getmem(FSurfsList.Grads, FSurfsList.GradsCount * SizeOf(TSurfGrad));
|
||
getmem(FSurfsList.Group, FSurfsList.GroupCount * SizeOf(TSurfGroup));
|
||
|
||
tCount := 0;
|
||
|
||
c := 0; // -------------- 1
|
||
cNode := XMLDoc.DocumentElement.FirstChild;
|
||
while cNode <> nil do
|
||
begin
|
||
if LowerCase(cNode.NodeName) = 'category' then begin
|
||
FSurfsList.Group[c].Name := 'NoName';
|
||
for a := cNode.Attributes.Length - 1 downto 0 do begin
|
||
if LowerCase(cNode.Attributes[a].NodeName) = 'name' then
|
||
FSurfsList.Group[c].Name := CP1251ToUTF8(cNode.Attributes[a].NodeValue);
|
||
end;
|
||
// ?????? FSurfsList.Group[c].Count
|
||
getmem(FSurfsList.Group[c].Info, FSurfsList.Group[c].Count * SizeOf(TSurfGroup));
|
||
|
||
s := 0; // -------------- 2
|
||
sNode := cNode.FirstChild;
|
||
while sNode <> nil do
|
||
begin
|
||
if LowerCase(sNode.NodeName) = 'surafece' then begin
|
||
FSurfsList.Group[c].Info[s].Name := 'NoName';
|
||
FSurfsList.Group[c].Info[s].TileID := $4001;
|
||
for a := sNode.Attributes.Length - 1 downto 0 do begin
|
||
if LowerCase(sNode.Attributes[a].NodeName) = 'name' then
|
||
FSurfsList.Group[c].Info[s].Name := CP1251ToUTF8(sNode.Attributes[a].NodeValue);
|
||
if LowerCase(sNode.Attributes[a].NodeName) = 'tileid' then
|
||
if TryStrToInt(sNode.Attributes[a].NodeValue, value) then
|
||
FSurfsList.Group[c].Info[s].TileID := value;
|
||
end;
|
||
CalcStringCRC32(LowerCase(FSurfsList.Group[c].Info[s].Name),
|
||
FSurfsList.Group[c].Info[s].TileHash);
|
||
// ?????? FSurfsList.Group[c].Info[s].GradCount
|
||
getmem(FSurfsList.Group[c].Info[s].GradHash, FSurfsList.Group[c].Info[s].GradCount * SizeOf(LongWord));
|
||
|
||
e := 0; // -------------- 3
|
||
eNode := sNode.FirstChild;
|
||
while eNode <> nil do
|
||
begin
|
||
str := LowerCase(eNode.NodeName);
|
||
if (str = 'item') or (str = 'land') or (str = 'tile') then begin
|
||
str := 'NoType';
|
||
for a := eNode.Attributes.Length - 1 downto 0 do begin
|
||
if LowerCase(sNode.Attributes[a].NodeName) = 'type' then
|
||
str := CP1251ToUTF8(eNode.Attributes[a].NodeValue);
|
||
end;
|
||
CalcStringCRC32(LowerCase(FSurfsList.Group[c].Name + '|' + str),
|
||
FSurfsList.Group[c].Info[s].GradHash[e]);
|
||
inc(tCount);
|
||
end else if str = 'brush' then begin
|
||
// TODO
|
||
|
||
end;
|
||
inc(e);
|
||
eNode := eNode.NextSibling;
|
||
end; // -------------- 3
|
||
|
||
end;
|
||
inc(s);
|
||
sNode := sNode.NextSibling;
|
||
end; // -------------- 2
|
||
|
||
end;
|
||
inc(c);
|
||
cNode := cNode.NextSibling;
|
||
end; // -------------- 1
|
||
|
||
////////////////////////////////////////////////////////////////////////////
|
||
|
||
// Построение списка TSurfGrad
|
||
getmem(tHash, tCount * SizeOf(DWORD));
|
||
tCount := 0;
|
||
for c := 0 to FSurfsList.GroupCount do
|
||
for s := 0 to FSurfsList.Group[c].Count do
|
||
for e := 0 to FSurfsList.Group[c].Info[s].GradCount do
|
||
begin
|
||
for a := tCount-1 downto -1 do
|
||
if a < 0 then begin
|
||
tHash[tCount] = FSurfsList.Group[c].Info[s].GradHash[e];
|
||
inc(tCount);
|
||
end else if tHash[a] = FSurfsList.Group[c].Info[s].GradHash[e]
|
||
then break;
|
||
end;
|
||
|
||
FSurfsList.GradsCount := tCount;
|
||
getmem(FSurfsList.Grads, FSurfsList.GradsCount * SizeOf(TSurfGrad));
|
||
|
||
|
||
|
||
|
||
freemem(gHash);
|
||
|
||
|
||
|
||
getmem(sCount, FSurfsList.GroupCount * SizeOf( Word));
|
||
getmem(eCount, FSurfsList.GroupCount * SizeOf(PWord));
|
||
|
||
// Подсчет объектов
|
||
cNode := XMLDoc.DocumentElement.FirstChild;
|
||
while cNode <> nil do
|
||
begin
|
||
if LowerCase(cNode.NodeName) = 'category' then
|
||
begin
|
||
sNode := cNode.FirstChild;
|
||
while sNode <> nil do
|
||
begin
|
||
|
||
|
||
|
||
sNode := sNode.NextSibling;
|
||
end;
|
||
end;
|
||
|
||
cNode := cNode.NextSibling;
|
||
end;
|
||
|
||
|
||
|
||
end;
|
||
|
||
|
||
end;
|
||
|
||
}
|
||
|
||
procedure TfrmMain.LoadEntryTilesList;
|
||
var
|
||
fPath, s, attribute : string;
|
||
XMLDoc: TXMLDocument;
|
||
eNode, tNode : TDOMNode;
|
||
e, t, a, value : Integer;
|
||
// Создание миниатюр
|
||
id : Integer;
|
||
hue : Word;
|
||
alt : integer;
|
||
|
||
artHue : THue;
|
||
artEntry : TArt;
|
||
dSize: TSize;
|
||
entHash: QWORD;
|
||
Resised: Float;
|
||
tCRC32, CacheLen: DWORD;
|
||
cacheHash, cachePost: PDWORD;
|
||
imageData: TImageData;
|
||
imageCache: TFileStream;
|
||
imageTemp: TSingleImage;
|
||
dX, dY, dZ, dW, dH : Integer;
|
||
entStack, entFirst, entLast, entPrev, entNext: PByte;
|
||
dstCanvas: TFastARGB32Canvas;
|
||
srcCanvas: TFastARGB32Canvas;
|
||
begin
|
||
frmInitialize.SetStatusLabel(Format(frmInitialize.SplashLoading, ['TilesEntry.xml']));
|
||
if FileExists(FProfileDir + 'TilesEntry.xml')
|
||
then fPath := (FProfileDir + 'TilesEntry.xml')
|
||
else if FileExists(FLocalDir + 'TilesEntry.xml')
|
||
then fPath := (FLocalDir + 'TilesEntry.xml')
|
||
else if FileExists(FConfigDir + 'TilesEntry.xml')
|
||
then fPath := (FConfigDir + 'TilesEntry.xml')
|
||
else if FileExists(ResMan.GetFile('TilesEntry.xml'))
|
||
then fPath := (ResMan.GetFile('TilesEntry.xml'))
|
||
else Exit;
|
||
|
||
FEntryList.Count := 0;
|
||
|
||
// Читаем xml файл с жесткого диска
|
||
ReadXMLFile(XMLDoc, fPath);
|
||
if LowerCase(XMLDoc.DocumentElement.NodeName) = 'tilesentry' then
|
||
begin
|
||
// Подсчет объектов
|
||
eNode := XMLDoc.DocumentElement.FirstChild;
|
||
while eNode <> nil do
|
||
begin
|
||
if LowerCase(eNode.NodeName) = 'entry' then
|
||
inc(FEntryList.Count);
|
||
eNode := eNode.NextSibling;
|
||
end;
|
||
getmem(FEntryList.Entry, FEntryList.Count * SizeOf(PGroupEntry));
|
||
|
||
// Построение списка
|
||
eNode := XMLDoc.DocumentElement.FirstChild;
|
||
for e := 0 to FEntryList.Count - 1 do begin
|
||
//Logger.Send([lcInfo], 'Entry: %d / %d - Start...', [e, FEntryList.Count]);
|
||
|
||
new (FEntryList.Entry[e]);
|
||
FEntryList.Entry[e]^.Name := 'NoName';
|
||
for a := eNode.Attributes.Length - 1 downto 0 do begin
|
||
if LowerCase(eNode.Attributes[a].NodeName) = 'id' then
|
||
if TryStrToInt(eNode.Attributes[a].NodeValue, value) then
|
||
FEntryList.Entry[e]^.ID := value;
|
||
if LowerCase(eNode.Attributes[a].NodeName) = 'name' then
|
||
FEntryList.Entry[e]^.Name := CP1251ToUTF8(eNode.Attributes[a].NodeValue);
|
||
end;
|
||
|
||
// Подсчет тайлов
|
||
tNode := eNode.FirstChild;
|
||
FEntryList.Entry[e]^.Count := 0;
|
||
while tNode <> nil do begin
|
||
s := LowerCase(tNode.NodeName);
|
||
if (s = 'tile') or (s = 'item') or (s = 'land') then
|
||
inc(FEntryList.Entry[e]^.Count);
|
||
tNode := tNode.NextSibling;
|
||
end;
|
||
getmem(FEntryList.Entry[e]^.ETile, FEntryList.Entry[e]^.Count * SizeOf(TEntryTile));
|
||
|
||
// Чтение списка тайлов
|
||
tNode := eNode.FirstChild;
|
||
for t := 0 to FEntryList.Entry[e]^.Count - 1 do
|
||
begin
|
||
//Logger.Send([lcInfo], 'Entry: %d - Item: %d / %d', [e, t, FEntryList.Entry[e]^.Count]);
|
||
FEntryList.Entry[e]^.ETile[t].ID := 0;
|
||
FEntryList.Entry[e]^.ETile[t].Hue := 0;
|
||
FEntryList.Entry[e]^.ETile[t].X := 0;
|
||
FEntryList.Entry[e]^.ETile[t].Y := 0;
|
||
FEntryList.Entry[e]^.ETile[t].Z := 0;
|
||
for a := tNode.Attributes.Length - 1 downto 0 do begin
|
||
attribute := LowerCase(tNode.Attributes[a].NodeName);
|
||
if attribute = 'id' then begin
|
||
if TryStrToInt(tNode.Attributes[a].NodeValue, value) then begin
|
||
if s = 'item' then Inc(value, $4000);
|
||
FEntryList.Entry[e]^.ETile[t].ID := value;
|
||
end;
|
||
end else if attribute = 'hue' then begin
|
||
if TryStrToInt(tNode.Attributes[a].NodeValue, value)
|
||
then FEntryList.Entry[e]^.ETile[t].Hue := value;
|
||
end else if attribute = 'x' then begin
|
||
if TryStrToInt(tNode.Attributes[a].NodeValue, value)
|
||
then FEntryList.Entry[e]^.ETile[t].X := value;
|
||
end else if attribute = 'y' then begin
|
||
if TryStrToInt(tNode.Attributes[a].NodeValue, value)
|
||
then FEntryList.Entry[e]^.ETile[t].Y := value;
|
||
end else if attribute = 'z' then begin
|
||
if TryStrToInt(tNode.Attributes[a].NodeValue, value)
|
||
then FEntryList.Entry[e]^.ETile[t].Z := value;
|
||
end;
|
||
end;
|
||
|
||
while (tNode <> nil) do begin
|
||
tNode := tNode.NextSibling;
|
||
if tNode <> nil then begin
|
||
s := LowerCase(tNode.NodeName);
|
||
if (s = 'tile') or (s = 'item') or (s = 'land')
|
||
then break;
|
||
end;
|
||
end;
|
||
|
||
end;
|
||
|
||
while (eNode <> nil) do begin
|
||
eNode := eNode.NextSibling;
|
||
if (eNode <> nil) and (LowerCase(eNode.NodeName) = 'entry')
|
||
then break;
|
||
end;
|
||
end;
|
||
end;
|
||
XMLDoc.Free;
|
||
|
||
Logger.Send([lcInfo], 'TfrmMain.LoadEntryTilesList SizeOf(TImageFormat)', SizeOf(TImageFormat));
|
||
// Создание миниатюр
|
||
if (FProfileDir <> '')
|
||
then fPath := FProfileDir
|
||
else fPath := FConfigDir;
|
||
fPath := fPath + 'TilesEntry.cache';
|
||
if not FileExists(fPath)
|
||
then FileClose(FileCreate(fPath));
|
||
imageCache := TFileStream.Create(fPath, fmOpenReadWrite);
|
||
if (imageCache.Size < 4) then begin
|
||
value := 0;
|
||
cacheHash := nil;
|
||
cachePost := nil;
|
||
imageCache.WriteDWord(value);
|
||
end else begin
|
||
value := imageCache.ReadDWord;
|
||
getmem(cacheHash, 4 * value);
|
||
getmem(cachePost, 4 * value);
|
||
end;
|
||
|
||
t := 0;
|
||
CacheLen := value;
|
||
while (t < value) do begin
|
||
cacheHash[t] := imageCache.ReadDWord;
|
||
cachePost[t] := imageCache.Position;
|
||
imageCache.Position := imageCache.Position + 12;
|
||
e := imageCache.ReadDWord;
|
||
imageCache.Position := imageCache.Position + e;
|
||
inc(t);
|
||
end;
|
||
|
||
for e := 0 to FEntryList.Count - 1 do begin
|
||
s := Format('e:%d|n:%s|', [FEntryList.Entry[e]^.ID, FEntryList.Entry[e]^.Name]);
|
||
for t := 0 to FEntryList.Entry[e]^.Count - 1 do
|
||
s := s + Format('i:%d|h:%d|x:%d|y:%d|z:%d|', [FEntryList.Entry[e]^.ETile[t].ID, FEntryList.Entry[e]^.ETile[t].Hue,
|
||
FEntryList.Entry[e]^.ETile[t].X, FEntryList.Entry[e]^.ETile[t].Y, FEntryList.Entry[e]^.ETile[t].Z]);
|
||
CalcStringCRC32(s, tCRC32);
|
||
FEntryList.Entry[e]^.Image := nil;
|
||
// Чтение изображения из кэша
|
||
for t := 0 to value - 1 do
|
||
if (cacheHash[t] = tCRC32) then begin
|
||
imageCache.Position := cachePost[t];
|
||
imageCache.Read(imageData, 16);
|
||
getmem(imageData.Bits, imageData.Size);
|
||
imageCache.Read(PByte(imageData.Bits)^, imageData.Size);
|
||
imageData.Palette := nil;
|
||
FEntryList.Entry[e]^.Image := TSingleImage.CreateFromData(imageData);
|
||
freemem(imageData.Bits);
|
||
//Logger.Send([lcInfo], 'TfrmMain.LoadEntryTilesList entry %d Loaded from Cache', [FEntryList.Entry[e]^.ID]);
|
||
//FEntryList.Entry[e]^.Image.Format := ifA1R5G5B5;
|
||
Break;
|
||
end;
|
||
if (FEntryList.Entry[e]^.Image <> nil)
|
||
then Continue;
|
||
|
||
// Сортировка тайлов для отрисовки
|
||
dW := 0;
|
||
dH := 0;
|
||
alt:= 0;
|
||
getmem(entStack, FEntryList.Entry[e]^.Count * 12);
|
||
FillByte(entStack^, FEntryList.Entry[e]^.Count * 12, 0);
|
||
entFirst := entStack;
|
||
entLast := entStack;
|
||
for t := 0 to FEntryList.Entry[e]^.Count - 1 do begin
|
||
dSize := ResMan.Art.GetArtSize(FEntryList.Entry[e]^.ETile[t].ID);
|
||
dX := 44 * (FEntryList.Entry[e]^.ETile[t].X - FEntryList.Entry[e]^.ETile[t].Y);
|
||
dY := -22 * (FEntryList.Entry[e]^.ETile[t].X + FEntryList.Entry[e]^.ETile[t].Y) + 4 * FEntryList.Entry[e]^.ETile[t].Z;
|
||
if (dY >= 0) then begin
|
||
dH := max(dH, alt + dY + dSize.cy);
|
||
end else begin
|
||
a := alt;
|
||
alt:= max(alt, Abs(dY));
|
||
dH := alt + max(dH - a, max(0, dSize.cy + dY));
|
||
end;
|
||
dW := max(dW, Abs(dX) + dSize.cx);
|
||
dX := min(max(0, FEntryList.Entry[e]^.ETile[t].X + 1023), 2047);
|
||
dY := min(max(0, FEntryList.Entry[e]^.ETile[t].Y + 1023), 2047);
|
||
dZ := min(max(0, FEntryList.Entry[e]^.ETile[t].Z + 255), 513);
|
||
|
||
entHash := DWORD(dX) * 1064440 + DWORD(dY) * 520 + DWORD(dZ + 7);
|
||
if (tdfFoliage in ResMan.Tiledata.TileData[FEntryList.Entry[e]^.ETile[t].ID].Flags)
|
||
then Inc(entHash, +1);
|
||
PDWord(entLast)^ := entHash;
|
||
PDWord(entLast + 4)^ := DWord(t);
|
||
|
||
if (entLast = entStack) then begin
|
||
inc(entLast, 12);
|
||
end else begin
|
||
entNext := entFirst;
|
||
entPrev := nil;
|
||
while True do begin
|
||
if (entNext = nil) then begin
|
||
PDWord(entPrev + 8)^ := PtrInt(entLast);
|
||
inc(entLast, 12);
|
||
Break;
|
||
end else if (PDWord(entNext)^ >= entHash) then begin
|
||
if (entPrev <> nil) then begin
|
||
PDWord(entPrev + 8)^ := PtrInt(entLast);
|
||
end else begin
|
||
entFirst := entLast;
|
||
end;
|
||
PDWord(entLast + 8)^ := PtrInt(entNext);
|
||
inc(entLast, 12);
|
||
Break;
|
||
end;
|
||
entPrev := entNext;
|
||
entNext := PByte(PDWord(entNext + 8)^);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
// Отрисовка изображения миниатюры
|
||
//Logger.Send([lcInfo], 'TfrmMain.LoadEntryTilesList %d dW: %d dH: %d', [FEntryList.Entry[e]^.ID, dW, dH]);
|
||
FEntryList.Entry[e]^.Image := TSingleImage.CreateFromParams(dW, dH, ifA8R8G8B8);
|
||
dstCanvas := TFastARGB32Canvas.CreateForImage(FEntryList.Entry[e]^.Image);
|
||
dstCanvas.FillColor32 := $00404040;
|
||
dstCanvas.FillRect(Rect(0,0,FEntryList.Entry[e]^.Image.Width,FEntryList.Entry[e]^.Image.Height));
|
||
entNext := entFirst;
|
||
while (entNext <> nil) do begin
|
||
|
||
//if ((FEntryList.Entry[e]^.ID < 9120) and (FEntryList.Entry[e]^.ID > 9025))
|
||
//then break;
|
||
t := PDWord(entNext + 4)^;
|
||
//Logger.Send([lcInfo], 'TfrmMain.LoadEntryTilesList t: %d [%d/%d]', [t, alt, FEntryList.Entry[e]^.Image.Height]);
|
||
entNext := PByte(PDWord(entNext + 8)^);
|
||
id := FEntryList.Entry[e]^.ETile[t].ID;
|
||
hue := FEntryList.Entry[e]^.ETile[t].Hue;
|
||
if ResMan.Art.Exists(id) then begin
|
||
if hue > 0
|
||
then artHue := ResMan.Hue.Hues[hue - 1]
|
||
else artHue := nil;
|
||
|
||
artEntry := ResMan.Art.GetArt(id, EncodeUOColor($0FF0F000), artHue, tdfPartialHue in TTileData(ResMan.Tiledata.Block[id]).Flags);
|
||
srcCanvas := TFastARGB32Canvas.CreateForImage(artEntry.Graphic);
|
||
dX := (FEntryList.Entry[e]^.Image.Width - artEntry.Graphic.Width) div 2 + 22 * (FEntryList.Entry[e]^.ETile[t].X - FEntryList.Entry[e]^.ETile[t].Y);
|
||
dY := FEntryList.Entry[e]^.Image.Height - artEntry.Graphic.Height - alt +
|
||
22 * (FEntryList.Entry[e]^.ETile[t].X + FEntryList.Entry[e]^.ETile[t].Y) - 4 * FEntryList.Entry[e]^.ETile[t].Z;
|
||
srcCanvas.DrawAlpha(Rect(0,0,artEntry.Graphic.Width,artEntry.Graphic.Height), dstCanvas, dX,dY);
|
||
srcCanvas.Free;
|
||
artEntry.Free;
|
||
end;
|
||
end;
|
||
|
||
|
||
// Уменьшение изоображения
|
||
dW := 93;
|
||
dH := 96;
|
||
dSize.cx := FEntryList.Entry[e]^.Image.Width;
|
||
dSize.cy := FEntryList.Entry[e]^.Image.Height;
|
||
Resised := Min(Min(Float(dW)/Float(dSize.cx), Float(dH)/Float(dSize.cy)), 1.0);
|
||
dSize.cx := Trunc(Resised * Float(dSize.cx));
|
||
dSize.cy := Trunc(Resised * Float(dSize.cy));
|
||
imageTemp := TSingleImage.CreateFromParams(dSize.cx, dSize.cy, ifA8R8G8B8);
|
||
srcCanvas := TFastARGB32Canvas.CreateForImage(imageTemp);
|
||
dstCanvas.StretchDrawAdd(Rect(0,0,FEntryList.Entry[e]^.Image.Width,FEntryList.Entry[e]^.Image.Height),
|
||
srcCanvas, Rect(0,0,dSize.cx,dSize.cy), rfNearest);//rfBilinear);
|
||
srcCanvas.Free;
|
||
dstCanvas.Free;
|
||
freemem(entStack);
|
||
FEntryList.Entry[e]^.Image.Free;
|
||
FEntryList.Entry[e]^.Image := imageTemp;
|
||
|
||
// Сохранение изоображение в кэше
|
||
imageCache.Position := imageCache.Size;
|
||
imageCache.WriteDWord(tCRC32);
|
||
imageData := FEntryList.Entry[e]^.Image.ImageDataPointer^;
|
||
imageCache.Write(imageData, 16);
|
||
imageCache.Write(imageData.Bits^, imageData.Size);
|
||
inc(CacheLen, +1);
|
||
//Logger.Send([lcInfo], 'TfrmMain.LoadEntryTilesList imageData.Palette <> nil', imageData.Palette <> nil);
|
||
|
||
//
|
||
Application.ProcessMessages;
|
||
end;
|
||
|
||
if (value > 0) then begin
|
||
freemem(cacheHash);
|
||
freemem(cachePost);
|
||
end;
|
||
imageCache.Position := 0;
|
||
imageCache.WriteDWord(CacheLen);
|
||
imageCache.Free;
|
||
|
||
{ // Отладка - проверка считанного файла
|
||
Logger.EnterMethod([lcInfo, lcDebug], 'TfrmMain.LoadEntryTilesList');
|
||
Logger.Send([lcInfo], 'Entries Number: %x', [FEntryList.Count]);
|
||
for e := 0 to FEntryList.Count - 1 do begin
|
||
Logger.Send([lcInfo], '<Entry Id="%.4d" Name="%s" Tiles="%x">',
|
||
[FEntryList.Entry[e]^.ID, FEntryList.Entry[e]^.Name, FEntryList.Entry[e]^.Count]);
|
||
for t := 0 to FEntryList.Entry[e]^.Count - 1 do
|
||
Logger.Send([lcInfo], ' <Tile Id="0x%.5x" Hue="0x%.3x" X="%d" Y="%d" Z="%d">',
|
||
[FEntryList.Entry[e]^.ETile[t].ID, FEntryList.Entry[e]^.ETile[t].Hue,
|
||
FEntryList.Entry[e]^.ETile[t].X, FEntryList.Entry[e]^.ETile[t].Y, FEntryList.Entry[e]^.ETile[t].Z]);
|
||
Logger.Send([lcInfo], '</Entry>');
|
||
end;
|
||
Logger.ExitMethod([lcInfo, lcDebug], 'TfrmMain.LoadEntryTilesList');
|
||
}
|
||
end;
|
||
|
||
procedure TfrmMain.LoadBrushTilesList;
|
||
var
|
||
fPath, s, attribute : string;
|
||
XMLDoc: TXMLDocument;
|
||
bNode, tNode, eNode : TDOMNode;
|
||
z, b, t, a, e, value: Integer;
|
||
uu, ur, ll, ul, dl, dr : Word;
|
||
valueF : Single;
|
||
brushTile: TBrushTile;
|
||
// Создание миниатюр
|
||
id : Integer;
|
||
destColor, hue : Word;
|
||
destRect: TRect;
|
||
|
||
texmEntry : TTexture;
|
||
dX, dY, dW, dH : Integer;
|
||
begin
|
||
frmInitialize.SetStatusLabel(Format(frmInitialize.SplashLoading, ['TilesBrush.xml']));
|
||
if FileExists(FProfileDir + 'TilesBrush.xml')
|
||
then fPath := (FProfileDir + 'TilesBrush.xml')
|
||
else if FileExists(FLocalDir + 'TilesBrush.xml')
|
||
then fPath := (FLocalDir + 'TilesBrush.xml')
|
||
else if FileExists(FConfigDir + 'TilesBrush.xml')
|
||
then fPath := (FConfigDir + 'TilesBrush.xml')
|
||
else if FileExists(ResMan.GetFile('TilesBrush.xml'))
|
||
then fPath := (ResMan.GetFile('TilesBrush.xml'))
|
||
else Exit;
|
||
|
||
FBrushList.Count := 0;
|
||
|
||
// Читаем xml файл с жесткого диска
|
||
ReadXMLFile(XMLDoc, fPath);
|
||
if LowerCase(XMLDoc.DocumentElement.NodeName) = 'tilesbrush' then
|
||
begin
|
||
// Подсчет объектов
|
||
bNode := XMLDoc.DocumentElement.FirstChild;
|
||
while bNode <> nil do
|
||
begin
|
||
if LowerCase(bNode.NodeName) = 'brush' then
|
||
inc(FBrushList.Count);
|
||
bNode := bNode.NextSibling;
|
||
end;
|
||
getmem(FBrushList.Brush, FBrushList.Count * SizeOf(PGroupBrush));
|
||
|
||
// Построение списка
|
||
bNode := XMLDoc.DocumentElement.FirstChild;
|
||
for b := 0 to FBrushList.Count - 1 do begin
|
||
//Logger.Send([lcInfo], 'Brush: %d / %d - Start...', [b+1, FBrushList.Count]);
|
||
new (FBrushList.Brush[b]);
|
||
FBrushList.Brush[b]^.ID := 0;
|
||
FBrushList.Brush[b]^.Name := 'NoName';
|
||
for a := bNode.Attributes.Length - 1 downto 0 do begin
|
||
if LowerCase(bNode.Attributes[a].NodeName) = 'id' then
|
||
if TryStrToInt(bNode.Attributes[a].NodeValue, value) then
|
||
FBrushList.Brush[b]^.ID := value;
|
||
if LowerCase(bNode.Attributes[a].NodeName) = 'name' then
|
||
FBrushList.Brush[b]^.Name := CP1251ToUTF8(bNode.Attributes[a].NodeValue);
|
||
end;
|
||
|
||
// Тестирование...
|
||
if LoadListError((FBrushList.Brush[b]^.ID = 0) or (FBrushList.Brush[b]^.ID > 9999),
|
||
fPath, Format(GetParseErText('blTagBrushAttrID'), [FBrushList.Brush[b]^.ID, FBrushList.Brush[b]^.Name]))
|
||
//'Missmatch or wrong <ID> attribute in BrushID: %.4d ("%s"). Brush ID must be larger 0 and less than 9999', [FBrushList.Brush[b]^.ID, FBrushList.Brush[b]^.Name]))
|
||
then begin LoadBrushTilesList; Exit; end;
|
||
if b > 0 then for z := b-1 downto 0 do begin
|
||
if LoadListError(FBrushList.Brush[z]^.ID = FBrushList.Brush[b]^.ID,
|
||
fPath, Format(GetParseErText('blTagBrushDuplicate'), [FBrushList.Brush[b]^.ID]))
|
||
then begin LoadBrushTilesList; Exit; end;
|
||
end;
|
||
|
||
// Подсчет тайлов и переходов
|
||
tNode := bNode.FirstChild;
|
||
FBrushList.Brush[b]^.Count := 0;
|
||
FBrushList.Brush[b]^.ECount := 0;
|
||
while tNode <> nil do begin
|
||
s := LowerCase(tNode.NodeName);
|
||
if (s = 'brushTile') or (s = 'land') then
|
||
inc(FBrushList.Brush[b]^.Count)
|
||
else if (s = 'edge') then
|
||
inc(FBrushList.Brush[b]^.ECount);
|
||
tNode := tNode.NextSibling;
|
||
end;
|
||
getmem(FBrushList.Brush[b]^.BTile, FBrushList.Brush[b]^.Count * SizeOf(PBrushTile));
|
||
getmem(FBrushList.Brush[b]^.EdgeId, FBrushList.Brush[b]^.ECount * SizeOf(PWord));
|
||
getmem(FBrushList.Brush[b]^.BEdges, FBrushList.Brush[b]^.ECount * SizeOf(PGroupBrushEdge));
|
||
|
||
// Тестирование...
|
||
if LoadListError(FBrushList.Brush[b]^.Count = 0,
|
||
fPath, Format(GetParseErText('blTagBrushEmpty'), [FBrushList.Brush[b]^.ID]))
|
||
then begin LoadBrushTilesList; Exit; end;
|
||
|
||
|
||
// Чтение списка тайлов
|
||
tNode := bNode.FirstChild;
|
||
t := 0; e := 0;
|
||
while tNode <> nil do
|
||
begin
|
||
s := LowerCase(tNode.NodeName);
|
||
if (s = 'brushTile') or (s = 'land') then begin
|
||
//Logger.Send([lcInfo], 'Brush: %d - Land: %d / %d', [b+1, t+1, FBrushList.Brush[b]^.Count]);
|
||
brushTile.ID := $FFFF;
|
||
brushTile.Chance := 1.0;
|
||
for a := tNode.Attributes.Length - 1 downto 0 do begin
|
||
attribute := LowerCase(tNode.Attributes[a].NodeName);
|
||
if attribute = 'id' then begin
|
||
if TryStrToInt(tNode.Attributes[a].NodeValue, value)
|
||
then brushTile.ID := value;
|
||
end else if attribute = 'chance' then begin
|
||
if TryStrToFloat(tNode.Attributes[a].NodeValue, valueF)
|
||
then brushTile.Chance := valueF;
|
||
end;
|
||
end;
|
||
brushTile.Mask := $0F;
|
||
brushTile.Brush1 := FBrushList.Brush[b];
|
||
brushTile.Brush2 := FBrushList.Brush[b];
|
||
|
||
// Тестирование...
|
||
if LoadListError(brushTile.ID = $FFFF,
|
||
fPath, Format(GetParseErText('blTagTileAttrID'), [FBrushList.Brush[b]^.ID]))
|
||
then begin LoadBrushTilesList; Exit; end;
|
||
if LoadListError(brushTile.ID > $3FFF,
|
||
fPath, Format(GetParseErText('blTagTileAttrIDOutOfRange'), [brushTile.ID, brushTile.ID, FBrushList.Brush[b]^.ID]))
|
||
then begin LoadBrushTilesList; Exit; end;
|
||
if LoadListError(FBrushList.Tiles[brushTile.ID].ID = brushTile.ID,
|
||
fPath, Format(GetParseErText('blTagTileRedeclaration'), [brushTile.ID, brushTile.ID, FBrushList.Brush[b]^.ID]))
|
||
then begin LoadBrushTilesList; Exit; end;
|
||
|
||
FBrushList.Tiles[brushTile.ID] := brushTile;
|
||
FBrushList.Brush[b]^.BTile[t] := @FBrushList.Tiles[brushTile.ID];
|
||
inc(t);
|
||
end else if (s = 'edge') then begin
|
||
//Logger.Send([lcInfo], 'Brush: %d - Edge: %d / %d', [b+1, e+1, FBrushList.Brush[b]^.ECount]);
|
||
//new (FBrushList.Brush[b]^.EdgeId[e]);
|
||
new (FBrushList.Brush[b]^.BEdges[e]);
|
||
FBrushList.Brush[b]^.BEdges[e]^.ID := 0;
|
||
for a := tNode.Attributes.Length - 1 downto 0 do begin
|
||
attribute := LowerCase(tNode.Attributes[a].NodeName);
|
||
if attribute = 'to' then begin
|
||
if TryStrToInt(tNode.Attributes[a].NodeValue, value)
|
||
then FBrushList.Brush[b]^.BEdges[e]^.ID := value;
|
||
end;
|
||
end;
|
||
// Тестирование...
|
||
if LoadListError((FBrushList.Brush[b]^.BEdges[e]^.ID = 0) or (FBrushList.Brush[b]^.BEdges[e]^.ID > 9999),
|
||
fPath, Format(GetParseErText('blTagEdgeAttrTo'), [FBrushList.Brush[b]^.ID]))
|
||
then begin LoadBrushTilesList; Exit; end;
|
||
|
||
// Подсчет тайлов в переходе
|
||
eNode := tNode.FirstChild;
|
||
FBrushList.Brush[b]^.BEdges[e]^.CountUU := 0;
|
||
FBrushList.Brush[b]^.BEdges[e]^.CountUR := 0;
|
||
FBrushList.Brush[b]^.BEdges[e]^.CountLL := 0;
|
||
FBrushList.Brush[b]^.BEdges[e]^.CountUL := 0;
|
||
FBrushList.Brush[b]^.BEdges[e]^.CountDL := 0;
|
||
FBrushList.Brush[b]^.BEdges[e]^.CountDR := 0;
|
||
while eNode <> nil do begin
|
||
s := LowerCase(eNode.NodeName);
|
||
if (s = 'brushTile') or (s = 'land') then begin
|
||
attribute := '';
|
||
for a := eNode.Attributes.Length - 1 downto 0 do begin
|
||
attribute := LowerCase(eNode.Attributes[a].NodeName);
|
||
if attribute = 'type' then begin
|
||
s := LowerCase(CP1251ToUTF8(eNode.Attributes[a].NodeValue));
|
||
if s = 'uu' then inc(FBrushList.Brush[b]^.BEdges[e]^.CountUU)
|
||
else if s = 'ur' then inc(FBrushList.Brush[b]^.BEdges[e]^.CountUR)
|
||
else if s = 'll' then inc(FBrushList.Brush[b]^.BEdges[e]^.CountLL)
|
||
else if s = 'ul' then inc(FBrushList.Brush[b]^.BEdges[e]^.CountUL)
|
||
else if s = 'dl' then inc(FBrushList.Brush[b]^.BEdges[e]^.CountDL)
|
||
else if s = 'dr' then inc(FBrushList.Brush[b]^.BEdges[e]^.CountDR);
|
||
break;
|
||
end;
|
||
end;
|
||
|
||
if LoadListError((attribute<>'type') or ((s<>'uu')and(s<>'ur')and(s<>'ll')and(s<>'ul')and(s<>'dl')and(s<>'dr')),
|
||
fPath, Format(GetParseErText('blTagTile2AttrType'), [brushTile.ID, brushTile.ID, FBrushList.Brush[b]^.BEdges[e]^.ID, FBrushList.Brush[b]^.ID]))
|
||
then begin LoadBrushTilesList; Exit; end;
|
||
end;
|
||
eNode := eNode.NextSibling;
|
||
end;
|
||
getmem(FBrushList.Brush[b]^.BEdges[e]^.BTileUU, FBrushList.Brush[b]^.BEdges[e]^.CountUU * SizeOf(PBrushTile));
|
||
getmem(FBrushList.Brush[b]^.BEdges[e]^.BTileUR, FBrushList.Brush[b]^.BEdges[e]^.CountUR * SizeOf(PBrushTile));
|
||
getmem(FBrushList.Brush[b]^.BEdges[e]^.BTileLL, FBrushList.Brush[b]^.BEdges[e]^.CountLL * SizeOf(PBrushTile));
|
||
getmem(FBrushList.Brush[b]^.BEdges[e]^.BTileUL, FBrushList.Brush[b]^.BEdges[e]^.CountUL * SizeOf(PBrushTile));
|
||
getmem(FBrushList.Brush[b]^.BEdges[e]^.BTileDL, FBrushList.Brush[b]^.BEdges[e]^.CountDL * SizeOf(PBrushTile));
|
||
getmem(FBrushList.Brush[b]^.BEdges[e]^.BTileDR, FBrushList.Brush[b]^.BEdges[e]^.CountDR * SizeOf(PBrushTile));
|
||
// Чтение списка тайлов в переходе
|
||
uu := 0; ur := 0; ll := 0; ul := 0; dl := 0; dr := 0;
|
||
eNode := tNode.FirstChild;
|
||
while eNode <> nil do begin
|
||
s := LowerCase(eNode.NodeName);
|
||
if (s = 'brushTile') or (s = 'land') then begin
|
||
//Logger.Send([lcInfo], 'Brush: %d - Edge: %d - Land: %d / %d', [b+1, e+1, uu+ur+ll+ul+dl+dr+1, FBrushList.Brush[b]^.BEdges[e]^.CountUU+FBrushList.Brush[b]^.BEdges[e]^.CountUR+FBrushList.Brush[b]^.BEdges[e]^.CountLL+FBrushList.Brush[b]^.BEdges[e]^.CountUL+FBrushList.Brush[b]^.BEdges[e]^.CountDL+FBrushList.Brush[b]^.BEdges[e]^.CountDR]);
|
||
brushTile.ID := $FFFF;
|
||
brushTile.Chance := 1.0;
|
||
for a := eNode.Attributes.Length - 1 downto 0 do begin
|
||
attribute := LowerCase(eNode.Attributes[a].NodeName);
|
||
if attribute = 'type' then begin
|
||
s := LowerCase(CP1251ToUTF8(eNode.Attributes[a].NodeValue));
|
||
if s = 'uu' then brushTile.Mask := $03
|
||
else if s = 'ur' then brushTile.Mask := $07
|
||
else if s = 'll' then brushTile.Mask := $09
|
||
else if s = 'ul' then brushTile.Mask := $0B
|
||
else if s = 'dl' then brushTile.Mask := $0D
|
||
else if s = 'dr' then brushTile.Mask := $0E;
|
||
end else if attribute = 'id' then begin
|
||
if TryStrToInt(eNode.Attributes[a].NodeValue, value)
|
||
then brushTile.ID := value;
|
||
end else if attribute = 'chance' then begin
|
||
if TryStrToFloat(eNode.Attributes[a].NodeValue, valueF)
|
||
then brushTile.Chance := valueF;
|
||
end;
|
||
end;
|
||
|
||
// Тестирование...
|
||
if LoadListError(brushTile.ID = $FFFF,
|
||
fPath, Format(GetParseErText('blTagTile2AttrID'), [FBrushList.Brush[b]^.ID]))
|
||
then begin LoadBrushTilesList; Exit; end;
|
||
if LoadListError(brushTile.ID > $3FFF,
|
||
fPath, Format(GetParseErText('blTagTile2AttrIDOutOfRange'), [brushTile.ID, brushTile.ID, FBrushList.Brush[b]^.ID]))
|
||
then begin LoadBrushTilesList; Exit; end;
|
||
if LoadListError(FBrushList.Tiles[brushTile.ID].ID = brushTile.ID,
|
||
fPath, Format(GetParseErText('blTagTile2Redeclaration'), [brushTile.ID, brushTile.ID, FBrushList.Brush[b]^.ID]))
|
||
then begin LoadBrushTilesList; Exit; end;
|
||
|
||
brushTile.Brush1 := FBrushList.Brush[b];
|
||
brushTile.Brush2 := nil;
|
||
FBrushList.Tiles[brushTile.ID] := brushTile;
|
||
if brushTile.Mask = $03 then begin
|
||
FBrushList.Brush[b]^.BEdges[e]^.BTileUU[uu] := @FBrushList.Tiles[brushTile.ID]; inc(uu);
|
||
end else if brushTile.Mask = $07 then begin
|
||
FBrushList.Brush[b]^.BEdges[e]^.BTileUR[ur] := @FBrushList.Tiles[brushTile.ID]; inc(ur);
|
||
end else if brushTile.Mask = $09 then begin
|
||
FBrushList.Brush[b]^.BEdges[e]^.BTileLL[ll] := @FBrushList.Tiles[brushTile.ID]; inc(ll);
|
||
end else if brushTile.Mask = $0B then begin
|
||
FBrushList.Brush[b]^.BEdges[e]^.BTileUL[ul] := @FBrushList.Tiles[brushTile.ID]; inc(ul);
|
||
end else if brushTile.Mask = $0D then begin
|
||
FBrushList.Brush[b]^.BEdges[e]^.BTileDL[dl] := @FBrushList.Tiles[brushTile.ID]; inc(dl);
|
||
end else if brushTile.Mask = $0E then begin
|
||
FBrushList.Brush[b]^.BEdges[e]^.BTileDR[dr] := @FBrushList.Tiles[brushTile.ID]; inc(dr);
|
||
end;
|
||
FBrushList.Tiles[brushTile.ID].ID := FBrushList.Brush[b]^.BEdges[e]^.ID; // Временно запоминаем ID перехода (позже востанавливаем ID тайла)
|
||
end;
|
||
eNode := eNode.NextSibling;
|
||
end;
|
||
FBrushList.Brush[b]^.EdgeId[e] := @(FBrushList.Brush[b]^.BEdges[e]^.ID);
|
||
inc(e);
|
||
end;
|
||
tNode := tNode.NextSibling;
|
||
end;
|
||
bNode := bNode.NextSibling;
|
||
end;
|
||
end;
|
||
XMLDoc.Free;
|
||
|
||
// Задание вторичных кистей
|
||
for t := 0 to $3FFF do begin
|
||
if (FBrushList.Tiles[t].Brush1 <> nil) and (FBrushList.Tiles[t].Brush2 = nil)
|
||
then begin
|
||
for b := 0 to FBrushList.Count - 1 do
|
||
if FBrushList.Brush[b]^.ID = FBrushList.Tiles[t].ID then begin
|
||
FBrushList.Tiles[t].Brush2 := FBrushList.Brush[b];
|
||
break;
|
||
end;
|
||
|
||
// Тестирование...
|
||
if LoadListError((FBrushList.Tiles[t].Brush2 = nil),
|
||
fPath, Format(GetParseErText('blTagEdgeUnknown'), [FBrushList.Tiles[t].Brush1^.ID, FBrushList.Tiles[t].ID]))
|
||
then begin LoadBrushTilesList; Exit; end;
|
||
|
||
FBrushList.Tiles[t].ID := t;
|
||
end else if (FBrushList.Tiles[t].Brush1 = nil) and (FBrushList.Tiles[t].Brush2 = nil)
|
||
then begin // Пустые тайлы
|
||
FBrushList.Tiles[t].ID:= $FFFF;
|
||
FBrushList.Tiles[t].Mask:= $00;
|
||
end;
|
||
end;
|
||
|
||
// Тестирование...
|
||
// for t := 0 to $3FFF do
|
||
// if LoadListError((FBrushList.Tiles[t].Brush1 <> nil) and (FBrushList.Tiles[t].Brush2 = nil),
|
||
// fPath, Format(GetParseErText('blTagTile2Redeclaration'), [FBrushList.Brush[b]^.ID]))
|
||
// then begin LoadBrushTilesList; Exit; end;
|
||
|
||
|
||
// Создание миниатюр
|
||
for b := 0 to FBrushList.Count - 1 do begin
|
||
//FBrushList.Brush[b]^.Image := TTexture(ResMan.Texmaps.Block[t]).Graphic;
|
||
FBrushList.Brush[b]^.Image := TSingleImage.CreateFromParams(96, 96, ifA1R5G5B5);
|
||
|
||
//FBrushList.Brush[b]^.Image.Bits .Canvas.Brush.Color := $00FF9000;//DecodeUOColor(destColor);
|
||
//FBrushList.Brush[b]^.Image.Canvas.Clear;
|
||
|
||
//if FBrushList.Brush[b]^.Image.FormatInfo.BytesPerPixel = 2
|
||
// then FillWord(FBrushList.Brush[b]^.Image.Bits^,
|
||
// FBrushList.Brush[b]^.Image.Width * FBrushList.Brush[b]^.Image.Height,
|
||
// $0000)
|
||
// else FillDWord(FBrushList.Brush[b]^.Image.Bits^,
|
||
// FBrushList.Brush[b]^.Image.Width * FBrushList.Brush[b]^.Image.Height,
|
||
// $00000000);
|
||
|
||
t := ResMan.Tiledata.LandTiles[FBrushList.Brush[b]^.BTile[0]^.ID].TextureID;
|
||
texmEntry := TTexture(ResMan.Texmaps.Block[t]);
|
||
//texmEntry.Graphic.CopyTo(0, 0, texmEntry.Graphic.Width, texmEntry.Graphic.Height,
|
||
// FBrushList.Brush[b]^.Image, 0, 0);
|
||
texmEntry.Graphic.StretchTo(0, 0, texmEntry.Graphic.Width, texmEntry.Graphic.Height,
|
||
FBrushList.Brush[b]^.Image, 2, 2,
|
||
FBrushList.Brush[b]^.Image.Width-4, FBrushList.Brush[b]^.Image.Height-4,
|
||
rfNearest);
|
||
texmEntry.Free;
|
||
end;
|
||
|
||
{ // Отладка - проверка считанного файла
|
||
Logger.EnterMethod([lcInfo, lcDebug], 'TfrmMain.LoadBrushTilesList');
|
||
Logger.Send([lcInfo], 'Brushes Number: %x', [FBrushList.Count]);
|
||
for b := 0 to FBrushList.Count - 1 do begin
|
||
Logger.Send([lcInfo], '<Brush Id="%.4d" Name="%s" Tiles="%d" Edges="%d">',
|
||
[FBrushList.Brush[b]^.ID, FBrushList.Brush[b]^.Name, FBrushList.Brush[b]^.Count, FBrushList.Brush[b]^.ECount]);
|
||
for t := 0 to FBrushList.Brush[b]^.Count - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BTile[t]^.ID, FBrushList.Brush[b]^.BTile[t]^.Chance, FBrushList.Brush[b]^.BTile[t]^.Mask]);
|
||
for e := 0 to FBrushList.Brush[b]^.ECount - 1 do begin
|
||
Logger.Send([lcInfo], ' <Edge To="%d" Tiles="%d">',
|
||
[FBrushList.Brush[b]^.EdgeId[e]^, FBrushList.Brush[b]^.BEdges[e]^.CountUU+FBrushList.Brush[b]^.BEdges[e]^.CountUR+FBrushList.Brush[b]^.BEdges[e]^.CountLL+FBrushList.Brush[b]^.BEdges[e]^.CountUL+FBrushList.Brush[b]^.BEdges[e]^.CountDL+FBrushList.Brush[b]^.BEdges[e]^.CountDR]);
|
||
for t := 0 to FBrushList.Brush[b]^.BEdges[e]^.CountUU - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BEdges[e]^.BTileUU[t]^.ID, FBrushList.Brush[b]^.BEdges[e]^.BTileUU[t]^.Chance, FBrushList.Brush[b]^.BEdges[e]^.BTileUU[t]^.Mask]);
|
||
for t := 0 to FBrushList.Brush[b]^.BEdges[e]^.CountUR - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BEdges[e]^.BTileUR[t]^.ID, FBrushList.Brush[b]^.BEdges[e]^.BTileUR[t]^.Chance, FBrushList.Brush[b]^.BEdges[e]^.BTileUR[t]^.Mask]);
|
||
for t := 0 to FBrushList.Brush[b]^.BEdges[e]^.CountLL - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BEdges[e]^.BTileLL[t]^.ID, FBrushList.Brush[b]^.BEdges[e]^.BTileLL[t]^.Chance, FBrushList.Brush[b]^.BEdges[e]^.BTileLL[t]^.Mask]);
|
||
for t := 0 to FBrushList.Brush[b]^.BEdges[e]^.CountUL - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BEdges[e]^.BTileUL[t]^.ID, FBrushList.Brush[b]^.BEdges[e]^.BTileUL[t]^.Chance, FBrushList.Brush[b]^.BEdges[e]^.BTileUL[t]^.Mask]);
|
||
for t := 0 to FBrushList.Brush[b]^.BEdges[e]^.CountDL - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BEdges[e]^.BTileDL[t]^.ID, FBrushList.Brush[b]^.BEdges[e]^.BTileDL[t]^.Chance, FBrushList.Brush[b]^.BEdges[e]^.BTileDL[t]^.Mask]);
|
||
for t := 0 to FBrushList.Brush[b]^.BEdges[e]^.CountDR - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BEdges[e]^.BTileDR[t]^.ID, FBrushList.Brush[b]^.BEdges[e]^.BTileDR[t]^.Chance, FBrushList.Brush[b]^.BEdges[e]^.BTileDR[t]^.Mask]);
|
||
Logger.Send([lcInfo], ' </Edge>');
|
||
end;
|
||
Logger.Send([lcInfo], '</Brush>');
|
||
end;
|
||
Logger.ExitMethod([lcInfo, lcDebug], 'TfrmMain.LoadBrushTilesList');
|
||
}
|
||
end;
|
||
|
||
procedure TfrmMain.BuildGroupList;
|
||
var
|
||
XMLDoc: TXMLDocument;
|
||
iNode : TDOMNode;
|
||
fPath : string;
|
||
vNode : PVirtualNode;
|
||
bTemp : array[0..$E000] of Word;
|
||
gTemp : array[0..$FFFF] of Boolean;
|
||
|
||
procedure SumItems(Node: PVirtualNode; Count: Integer; var Items: LongWord);
|
||
var
|
||
i : Integer;
|
||
item : PVirtualNode;
|
||
group: PGroupNode;
|
||
begin
|
||
group := tvGroups.GetNodeData(Node);
|
||
Items += group^.Count;
|
||
Items += group^.Entries;
|
||
Items += group^.Brushes;
|
||
|
||
for i := 0 to group^.Links - 1 do
|
||
if group^.GLink[i] <> nil then
|
||
SumItems(group^.GLink[i], 0, Items);
|
||
|
||
if (Count > 0) then
|
||
begin
|
||
item := tvGroups.GetFirstChild(Node);
|
||
while item <> nil do
|
||
begin
|
||
SumItems(item, Count - 1, Items);
|
||
item := tvGroups.GetNextSibling(item);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
procedure ProcessNode(Node: TDOMNode; TreeNode: PVirtualNode);
|
||
var
|
||
element: TDOMElement;
|
||
cNode: TDOMNode;
|
||
s: string;
|
||
i, j, k, e, b, d, q, id: Integer;
|
||
group: PGroupNode;
|
||
begin
|
||
if Node = nil then Exit; // выходим, если достигнут конец документа
|
||
if LowerCase(Node.NodeName) <> 'group' then Exit;
|
||
|
||
// добавляем узел в дерево
|
||
TreeNode := tvGroups.AddChild(TreeNode);
|
||
group := tvGroups.GetNodeData(TreeNode);
|
||
|
||
// сохраняем данные узла
|
||
e := 0; b := 0; d := 0;
|
||
group^.Count := 0;
|
||
cNode := Node.FirstChild;
|
||
while cNode <> nil do
|
||
begin
|
||
s := LowerCase(cNode.NodeName);
|
||
if (s = 'tile') or (s = 'land') or (s = 'item')
|
||
then Inc(group^.Count, 1)
|
||
else if (s = 'entry') then Inc(e, 1)
|
||
else if (s = 'brush') then Inc(b, 1)
|
||
else if (s = 'link') then // Inc(d, 1);
|
||
for i := 0 to cNode.Attributes.Length - 1 do
|
||
if LowerCase(cNode.Attributes[i].NodeName) = 'groupid' then Inc(d, 1)
|
||
else if LowerCase(cNode.Attributes[i].NodeName) = 'brushid' then
|
||
if TryStrToInt(cNode.Attributes[i].NodeValue, id) then begin
|
||
for j := 0 to Length(FBrushList.Tiles) - 1 do
|
||
if (FBrushList.Tiles[j].ID <> $FFFF) and
|
||
((id = FBrushList.Tiles[j].Brush1^.ID) or (id = FBrushList.Tiles[j].Brush2^.ID))
|
||
then Inc(group^.Count, 1);
|
||
end;
|
||
cNode := cNode.NextSibling;
|
||
end;
|
||
|
||
group^.Entries := e; group^.Brushes := b; group^.Links := d;
|
||
k := 0; e := 0; b := 0; d := 0;
|
||
getmem(group^.lids, group^.Links * SizeOf(LongWord));
|
||
getmem(group^.GLink, group^.Links * SizeOf(PVirtualnode));
|
||
getmem(group^.GTile, group^.Count * SizeOf(TGroupTile));
|
||
getmem(group^.Entry, group^.Entries * SizeOf(PGroupEntry));
|
||
getmem(group^.Brush, group^.Brushes * SizeOf(PGroupBrush));
|
||
cNode := Node.FirstChild;
|
||
while cNode <> nil do
|
||
begin
|
||
s := LowerCase(cNode.NodeName);
|
||
if (s = 'tile') or (s = 'land') or (s = 'item') then
|
||
begin
|
||
for i := cNode.Attributes.Length - 1 downto 0 do
|
||
begin
|
||
if LowerCase(cNode.Attributes[i].NodeName) = 'id' then
|
||
if TryStrToInt(cNode.Attributes[i].NodeValue, id) then
|
||
begin
|
||
if s = 'item' then
|
||
Inc(id, $4000);
|
||
group^.GTile[k].ID := id;
|
||
Inc(k, 1);
|
||
end;
|
||
end;
|
||
end
|
||
else if (s = 'entry') then
|
||
begin
|
||
for i := cNode.Attributes.Length - 1 downto 0 do
|
||
begin
|
||
if LowerCase(cNode.Attributes[i].NodeName) = 'id' then
|
||
if TryStrToInt(cNode.Attributes[i].NodeValue, id) then
|
||
begin
|
||
group^.Entry[e] := nil;
|
||
for j := 0 to FEntryList.Count - 1 do
|
||
if FEntryList.Entry[j]^.ID = id then begin
|
||
group^.Entry[e] := FEntryList.Entry[j];
|
||
break;
|
||
end;
|
||
Inc(e, 1);
|
||
end;
|
||
end;
|
||
end
|
||
else if (s = 'brush') then
|
||
begin
|
||
for i := cNode.Attributes.Length - 1 downto 0 do
|
||
begin
|
||
if LowerCase(cNode.Attributes[i].NodeName) = 'id' then
|
||
if TryStrToInt(cNode.Attributes[i].NodeValue, id) then
|
||
begin
|
||
group^.Brush[b] := nil;
|
||
for j := 0 to FBrushList.Count - 1 do
|
||
if FBrushList.Brush[j]^.ID = id then begin
|
||
group^.Brush[b] := FBrushList.Brush[j];
|
||
break;
|
||
end;
|
||
Inc(b, 1);
|
||
end;
|
||
end;
|
||
end
|
||
else if (s = 'link') then
|
||
begin
|
||
for i := 0 to cNode.Attributes.Length - 1 do
|
||
begin
|
||
if LowerCase(cNode.Attributes[i].NodeName) = 'groupid' then
|
||
if TryStrToInt(cNode.Attributes[i].NodeValue, id) then
|
||
begin
|
||
group^.lids[d] := id;
|
||
Inc(d, 1);
|
||
end;
|
||
if LowerCase(cNode.Attributes[i].NodeName) = 'brushid' then //
|
||
if TryStrToInt(cNode.Attributes[i].NodeValue, id) then
|
||
begin
|
||
bTemp[$0000]:=$0000; bTemp[$D000]:=$D000;
|
||
bTemp[$1000]:=$1000; bTemp[$2000]:=$2000; bTemp[$3000]:=$3000; bTemp[$4000]:=$4000;
|
||
bTemp[$5000]:=$5000; bTemp[$6000]:=$6000; bTemp[$7000]:=$7000; bTemp[$8000]:=$8000;
|
||
bTemp[$9000]:=$9000; bTemp[$A000]:=$A000; bTemp[$B000]:=$B000; bTemp[$C000]:=$C000;
|
||
for j := 0 to Length(gTemp)-1 do gTemp[j] := False;
|
||
for j := 0 to Length(FBrushList.Tiles) - 1 do begin
|
||
if (FBrushList.Tiles[j].ID = $FFFF) then Continue;
|
||
if (id = FBrushList.Tiles[j].Brush1^.ID) and (id = FBrushList.Tiles[j].Brush2^.ID) then begin
|
||
inc(bTemp[$0000], 1); bTemp[bTemp[$0000]] := j; Continue;
|
||
end;
|
||
|
||
if (FBrushList.Tiles[j].Mask = $0B) and (id = FBrushList.Tiles[j].Brush2^.ID) then begin
|
||
inc(bTemp[$1000],1); bTemp[bTemp[$1000]]:=j;
|
||
gTemp[FBrushList.Tiles[j].Brush1^.ID]:=True;
|
||
bTemp[bTemp[$1000]+$0800]:=FBrushList.Tiles[j].Brush1^.ID;
|
||
Continue;
|
||
end;
|
||
if (FBrushList.Tiles[j].Mask = $0D) and (id = FBrushList.Tiles[j].Brush2^.ID) then begin
|
||
inc(bTemp[$2000],1); bTemp[bTemp[$2000]]:=j;
|
||
gTemp[FBrushList.Tiles[j].Brush1^.ID]:=True;
|
||
bTemp[bTemp[$2000]+$0800]:=FBrushList.Tiles[j].Brush1^.ID;
|
||
Continue;
|
||
end;
|
||
if (FBrushList.Tiles[j].Mask = $07) and (id = FBrushList.Tiles[j].Brush2^.ID) then begin
|
||
inc(bTemp[$3000],1); bTemp[bTemp[$3000]]:=j;
|
||
gTemp[FBrushList.Tiles[j].Brush1^.ID]:=True;
|
||
bTemp[bTemp[$3000]+$0800]:=FBrushList.Tiles[j].Brush1^.ID;
|
||
Continue;
|
||
end;
|
||
if (FBrushList.Tiles[j].Mask = $0E) and (id = FBrushList.Tiles[j].Brush2^.ID) then begin
|
||
inc(bTemp[$4000],1); bTemp[bTemp[$4000]]:=j;
|
||
gTemp[FBrushList.Tiles[j].Brush1^.ID]:=True;
|
||
bTemp[bTemp[$4000]+$0800]:=FBrushList.Tiles[j].Brush1^.ID;
|
||
Continue;
|
||
end;
|
||
|
||
if (FBrushList.Tiles[j].Mask = $09) and (id = FBrushList.Tiles[j].Brush2^.ID) then begin
|
||
inc(bTemp[$5000],1); bTemp[bTemp[$5000]]:=j;
|
||
gTemp[FBrushList.Tiles[j].Brush1^.ID]:=True;
|
||
bTemp[bTemp[$5000]+$0800]:=FBrushList.Tiles[j].Brush1^.ID;
|
||
Continue;
|
||
end;
|
||
if (FBrushList.Tiles[j].Mask = $03) and (id = FBrushList.Tiles[j].Brush2^.ID) then begin
|
||
inc(bTemp[$6000],1); bTemp[bTemp[$6000]]:=j;
|
||
gTemp[FBrushList.Tiles[j].Brush1^.ID]:=True;
|
||
bTemp[bTemp[$6000]+$0800]:=FBrushList.Tiles[j].Brush1^.ID;
|
||
Continue;
|
||
end;
|
||
if (FBrushList.Tiles[j].Mask = $03) and (id = FBrushList.Tiles[j].Brush1^.ID) then begin
|
||
inc(bTemp[$7000],1); bTemp[bTemp[$7000]]:=j;
|
||
gTemp[FBrushList.Tiles[j].Brush2^.ID]:=True;
|
||
bTemp[bTemp[$7000]+$0800]:=FBrushList.Tiles[j].Brush2^.ID;
|
||
Continue;
|
||
end;
|
||
if (FBrushList.Tiles[j].Mask = $09) and (id = FBrushList.Tiles[j].Brush1^.ID) then begin
|
||
inc(bTemp[$8000],1); bTemp[bTemp[$8000]]:=j;
|
||
gTemp[FBrushList.Tiles[j].Brush2^.ID]:=True;
|
||
bTemp[bTemp[$8000]+$0800]:=FBrushList.Tiles[j].Brush2^.ID;
|
||
Continue;
|
||
end;
|
||
|
||
if (FBrushList.Tiles[j].Mask = $0E) and (id = FBrushList.Tiles[j].Brush1^.ID) then begin
|
||
inc(bTemp[$9000],1); bTemp[bTemp[$9000]]:=j;
|
||
gTemp[FBrushList.Tiles[j].Brush2^.ID]:=True;
|
||
bTemp[bTemp[$9000]+$0800]:=FBrushList.Tiles[j].Brush2^.ID;
|
||
Continue;
|
||
end;
|
||
if (FBrushList.Tiles[j].Mask = $0D) and (id = FBrushList.Tiles[j].Brush1^.ID) then begin
|
||
inc(bTemp[$A000],1); bTemp[bTemp[$A000]]:=j;
|
||
gTemp[FBrushList.Tiles[j].Brush2^.ID]:=True;
|
||
bTemp[bTemp[$A000]+$0800]:=FBrushList.Tiles[j].Brush2^.ID;
|
||
Continue;
|
||
end;
|
||
if (FBrushList.Tiles[j].Mask = $07) and (id = FBrushList.Tiles[j].Brush1^.ID) then begin
|
||
inc(bTemp[$B000],1); bTemp[bTemp[$B000]]:=j;
|
||
gTemp[FBrushList.Tiles[j].Brush2^.ID]:=True;
|
||
bTemp[bTemp[$B000]+$0800]:=FBrushList.Tiles[j].Brush2^.ID;
|
||
Continue;
|
||
end;
|
||
if (FBrushList.Tiles[j].Mask = $0B) and (id = FBrushList.Tiles[j].Brush1^.ID) then begin
|
||
inc(bTemp[$C000],1); bTemp[bTemp[$C000]]:=j;
|
||
gTemp[FBrushList.Tiles[j].Brush2^.ID]:=True;
|
||
bTemp[bTemp[$C000]+$0800]:=FBrushList.Tiles[j].Brush2^.ID;
|
||
Continue;
|
||
end;
|
||
|
||
if (id = FBrushList.Tiles[j].Brush1^.ID) or (id = FBrushList.Tiles[j].Brush2^.ID) then begin
|
||
inc(bTemp[$D000],1); // то что не удалось расортировать (вообще мы никогда не должны сюда попадать)
|
||
bTemp[bTemp[$D000]] := j;
|
||
end;
|
||
|
||
end;
|
||
|
||
for j := $0001 to bTemp[$0000] do begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
|
||
for q := 0 to Length(gTemp)-1 do
|
||
if gTemp[q] then begin
|
||
for j := $1001 to bTemp[$1000] do if (bTemp[j+$0800]=q) then begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
for j := $2001 to bTemp[$2000] do if (bTemp[j+$0800]=q) then begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
for j := $3001 to bTemp[$3000] do if (bTemp[j+$0800]=q) then begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
for j := $4001 to bTemp[$4000] do if (bTemp[j+$0800]=q) then begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
for j := $5001 to bTemp[$5000] do if (bTemp[j+$0800]=q) then begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
for j := $6001 to bTemp[$6000] do if (bTemp[j+$0800]=q) then begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
for j := $7001 to bTemp[$7000] do if (bTemp[j+$0800]=q) then begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
for j := $8001 to bTemp[$8000] do if (bTemp[j+$0800]=q) then begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
for j := $9001 to bTemp[$9000] do if (bTemp[j+$0800]=q) then begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
for j := $A001 to bTemp[$A000] do if (bTemp[j+$0800]=q) then begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
for j := $B001 to bTemp[$B000] do if (bTemp[j+$0800]=q) then begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
for j := $C001 to bTemp[$C000] do if (bTemp[j+$0800]=q) then begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
end;
|
||
|
||
for j := $D001 to bTemp[$D000] do begin
|
||
group^.GTile[k].ID := bTemp[j]; Inc(k, 1);
|
||
end;
|
||
|
||
end;
|
||
end;
|
||
end;
|
||
cNode := cNode.NextSibling;
|
||
end;
|
||
|
||
// переходим к дочернему узлу
|
||
cNode := Node.FirstChild;
|
||
|
||
// проходим по всем дочерним узлам
|
||
while cNode <> nil do
|
||
begin
|
||
ProcessNode(cNode, TreeNode);
|
||
cNode := cNode.NextSibling;
|
||
end;
|
||
|
||
// сохраняем данные узла
|
||
k:= 0;
|
||
group^.ID := 0;
|
||
group^.Nodes:= 0;
|
||
group^.Name := 'NoName';
|
||
group^.Color:= TColor($00000000);
|
||
if tvGroups.ChildCount[TreeNode] = 0
|
||
then group^.Ital := True
|
||
else group^.Ital := False;
|
||
if tvGroups.ChildCount[TreeNode] > 4
|
||
then group^.Bold := True
|
||
else group^.Bold := False;
|
||
if Node.HasAttributes and (Node.Attributes.Length>0) then
|
||
for i := 0 to Node.Attributes.Length - 1 do
|
||
if LowerCase(Node.Attributes[i].NodeName) = 'name' then begin
|
||
group^.Name := CP1251ToUTF8(Node.Attributes[i].NodeValue)
|
||
end else if LowerCase(Node.Attributes[i].NodeName) = 'color' then begin
|
||
if TryStrToInt(Node.Attributes[i].NodeValue, k) then
|
||
group^.Color:=TColor(((k and$0000FF)shl 16)or(k and$00FF00)or((k and$FF0000)shr 16));
|
||
end else if LowerCase(Node.Attributes[i].NodeName) = 'bold' then begin
|
||
TryStrToBool(Node.Attributes[i].NodeValue, group^.Bold);
|
||
end else if LowerCase(Node.Attributes[i].NodeName) = 'ital' then begin
|
||
TryStrToBool(Node.Attributes[i].NodeValue, group^.Ital);
|
||
end else if LowerCase(Node.Attributes[i].NodeName) = 'id' then begin
|
||
if TryStrToInt(Node.Attributes[i].NodeValue, d) then group^.ID := d;
|
||
end else if LowerCase(Node.Attributes[i].NodeName) = 'nodes' then begin
|
||
if TryStrToInt(Node.Attributes[i].NodeValue, k) then
|
||
begin if k=-1 then k:=$FFFF; group^.Nodes := Max(0, k); k:=0; end;
|
||
end;
|
||
end;
|
||
|
||
procedure BuildLinks(Node: PVirtualNode);
|
||
var
|
||
i : Integer;
|
||
item : PVirtualNode;
|
||
group: PGroupNode;
|
||
begin
|
||
group := tvGroups.GetNodeData(Node);
|
||
|
||
for i := 0 to group^.Links - 1 do
|
||
begin
|
||
//Logger.Send([lcClient, lcDebug], 'BuildLinks: %.4d / %.4d - id: %d', [i+1, group^.Links, group^.lids[i]]);
|
||
group^.GLink[i] := nil;
|
||
if group^.lids[i] = 0 then continue;
|
||
|
||
item := tvGroups.GetFirst();
|
||
while item <> nil do
|
||
begin
|
||
if group^.lids[i] = PGroupNode(tvGroups.GetNodeData(item))^.ID then
|
||
begin
|
||
//Logger.Send([lcClient, lcDebug], 'BuildLinks: Group id: %d Found', [group^.lids[i]]);
|
||
group^.GLink[i] := item;
|
||
break;
|
||
end;
|
||
item := tvGroups.GetNext(item);
|
||
end
|
||
end;
|
||
|
||
FreeMem(group^.lids);
|
||
group^.lids := nil;
|
||
end;
|
||
|
||
begin
|
||
tvGroups.BeginUpdate;
|
||
tvGroups.Clear;
|
||
|
||
frmInitialize.SetStatusLabel(Format(frmInitialize.SplashLoading, ['TilesGroup.xml']));
|
||
if FileExists(FProfileDir + 'TilesGroup.xml')
|
||
then fPath := (FProfileDir + 'TilesGroup.xml')
|
||
else if FileExists(FLocalDir + 'TilesGroup.xml')
|
||
then fPath := (FLocalDir + 'TilesGroup.xml')
|
||
else if FileExists(FConfigDir + 'TilesGroup.xml')
|
||
then fPath := (FConfigDir + 'TilesGroup.xml')
|
||
else if FileExists(ResMan.GetFile('TilesGroup.xml'))
|
||
then fPath := (ResMan.GetFile('TilesGroup.xml'))
|
||
else Exit;
|
||
|
||
// Читаем xml файл с жесткого диска
|
||
ReadXMLFile(XMLDoc, fPath);
|
||
if LowerCase(XMLDoc.DocumentElement.NodeName) = 'tilesgroup' then
|
||
begin
|
||
iNode := XMLDoc.DocumentElement.FirstChild;
|
||
while iNode <> nil do
|
||
begin
|
||
if LowerCase(iNode.NodeName) = 'group' then
|
||
ProcessNode(iNode, nil); // Рекурсия
|
||
iNode := iNode.NextSibling;
|
||
end;
|
||
|
||
// Построение Указателей
|
||
vNode := tvGroups.GetFirst();
|
||
while vNode <> nil do
|
||
begin
|
||
BuildLinks(vNode);
|
||
vNode := tvGroups.GetNext(vNode);
|
||
end;
|
||
// Подсчет Items
|
||
vNode := tvGroups.GetFirst();
|
||
while vNode <> nil do
|
||
begin
|
||
SumItems(vNode, PGroupNode(tvGroups.GetNodeData(vNode))^.Nodes,
|
||
PGroupNode(tvGroups.GetNodeData(vNode))^.Items);
|
||
vNode := tvGroups.GetNext(vNode);
|
||
end;
|
||
end;
|
||
|
||
XMLDoc.Free;
|
||
tvGroups.EndUpdate;
|
||
end;
|
||
|
||
procedure TfrmMain.FreeGroupLists;
|
||
var i, j, k : Integer;
|
||
begin
|
||
for i:=0 to FEntryList.Count-1 do begin
|
||
FreeMem(FEntryList.Entry[i]^.ETile);
|
||
FEntryList.Entry[i]^.Image.Destroy;
|
||
end;
|
||
FreeMem(FEntryList.Entry);
|
||
FEntryList.Count:=0;
|
||
|
||
for i:=0 to FBrushList.Count-1 do begin
|
||
//for j:=0 to FBrushList.Brush[i]^.Count-1 do begin
|
||
// FreeMem(FBrushList.Brush[i]^.BTile[j]);
|
||
//end;
|
||
FreeMem(FBrushList.Brush[i]^.BEdges);
|
||
FreeMem(FBrushList.Brush[i]^.BTile);
|
||
FBrushList.Brush[i]^.Image.Destroy;
|
||
FBrushList.Count:=0;
|
||
end;
|
||
|
||
for i:=0 to $3FFF do begin
|
||
FBrushList.Tiles[i].ID := 0;
|
||
FBrushList.Tiles[i].Brush1:=nil;
|
||
FBrushList.Tiles[i].Brush2:=nil;
|
||
end;
|
||
|
||
end;
|
||
|
||
procedure TfrmMain.BuildTileList;
|
||
var
|
||
minID, maxID, i, k, lastID: Integer;
|
||
item : PVirtualItem;
|
||
groupNode : PVirtualNode;
|
||
tileInfo: PTileInfo;
|
||
filter : string;
|
||
nodeData: PGroupNode;
|
||
|
||
procedure AddNodeTiles(Node: PVirtualNode; Count: Integer);
|
||
var
|
||
item: PVirtualItem;
|
||
groupNode: PVirtualNode;
|
||
nodeData: PGroupNode;
|
||
tileInfo: PTileInfo;
|
||
lastID: LongWord;
|
||
i, j: Integer;
|
||
|
||
//b,t,e: Integer;
|
||
begin
|
||
nodeData := tvGroups.GetNodeData(Node);
|
||
Logger.Send([lcInfo], 'Brushes: %d - Entries: %d - Tiles: %d', [nodeData^.Brushes, nodeData^.Entries, nodeData^.Count]);
|
||
{
|
||
Logger.EnterMethod([lcInfo, lcDebug], 'TfrmMain.AddNodeTiles-Entries');
|
||
Logger.Send([lcInfo], 'Entries Number: %d', [FEntryList.Count]);
|
||
for e := 0 to FEntryList.Count - 1 do begin
|
||
Logger.Send([lcInfo], '<Entry Id="%.4d" Name="%s" Tiles="%x">',
|
||
[FEntryList.Entry[e]^.ID, FEntryList.Entry[e]^.Name, FEntryList.Entry[e]^.Count]);
|
||
for t := 0 to FEntryList.Entry[e]^.Count - 1 do
|
||
Logger.Send([lcInfo], ' <Tile Id="0x%.5x" Hue="0x%.3x" X="%d" Y="%d" Z="%d">',
|
||
[FEntryList.Entry[e]^.ETile[t].ID, FEntryList.Entry[e]^.ETile[t].Hue,
|
||
FEntryList.Entry[e]^.ETile[t].X, FEntryList.Entry[e]^.ETile[t].Y, FEntryList.Entry[e]^.ETile[t].Z]);
|
||
Logger.Send([lcInfo], '</Entry>');
|
||
end;
|
||
Logger.ExitMethod([lcInfo, lcDebug], 'TfrmMain.AddNodeTiles-Entries');
|
||
Logger.EnterMethod([lcInfo, lcDebug], 'TfrmMain.AddNodeTiles-Brushes');
|
||
Logger.Send([lcInfo], 'Brushes Number: %x', [FBrushList.Count]);
|
||
for b := 0 to FBrushList.Count - 1 do begin
|
||
Logger.Send([lcInfo], '<Brush Id="%.4d" Name="%s" Tiles="%d" Edges="%d">',
|
||
[FBrushList.Brush[b]^.ID, FBrushList.Brush[b]^.Name, FBrushList.Brush[b]^.Count, FBrushList.Brush[b]^.ECount]);
|
||
for t := 0 to FBrushList.Brush[b]^.Count - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BTile[t]^.ID, FBrushList.Brush[b]^.BTile[t]^.Chance, FBrushList.Brush[b]^.BTile[t]^.Mask]);
|
||
for e := 0 to FBrushList.Brush[b]^.ECount - 1 do begin
|
||
Logger.Send([lcInfo], ' <Edge To="%d" Tiles="%d">',
|
||
[FBrushList.Brush[b]^.EdgeId[e]^, FBrushList.Brush[b]^.BEdges[e]^.CountUU+FBrushList.Brush[b]^.BEdges[e]^.CountUR+FBrushList.Brush[b]^.BEdges[e]^.CountLL+FBrushList.Brush[b]^.BEdges[e]^.CountUL+FBrushList.Brush[b]^.BEdges[e]^.CountDL+FBrushList.Brush[b]^.BEdges[e]^.CountDR]);
|
||
for t := 0 to FBrushList.Brush[b]^.BEdges[e]^.CountUU - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BEdges[e]^.BTileUU[t]^.ID, FBrushList.Brush[b]^.BEdges[e]^.BTileUU[t]^.Chance, FBrushList.Brush[b]^.BEdges[e]^.BTileUU[t]^.Mask]);
|
||
for t := 0 to FBrushList.Brush[b]^.BEdges[e]^.CountUR - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BEdges[e]^.BTileUR[t]^.ID, FBrushList.Brush[b]^.BEdges[e]^.BTileUR[t]^.Chance, FBrushList.Brush[b]^.BEdges[e]^.BTileUR[t]^.Mask]);
|
||
for t := 0 to FBrushList.Brush[b]^.BEdges[e]^.CountLL - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BEdges[e]^.BTileLL[t]^.ID, FBrushList.Brush[b]^.BEdges[e]^.BTileLL[t]^.Chance, FBrushList.Brush[b]^.BEdges[e]^.BTileLL[t]^.Mask]);
|
||
for t := 0 to FBrushList.Brush[b]^.BEdges[e]^.CountUL - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BEdges[e]^.BTileUL[t]^.ID, FBrushList.Brush[b]^.BEdges[e]^.BTileUL[t]^.Chance, FBrushList.Brush[b]^.BEdges[e]^.BTileUL[t]^.Mask]);
|
||
for t := 0 to FBrushList.Brush[b]^.BEdges[e]^.CountDL - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BEdges[e]^.BTileDL[t]^.ID, FBrushList.Brush[b]^.BEdges[e]^.BTileDL[t]^.Chance, FBrushList.Brush[b]^.BEdges[e]^.BTileDL[t]^.Mask]);
|
||
for t := 0 to FBrushList.Brush[b]^.BEdges[e]^.CountDR - 1 do
|
||
Logger.Send([lcInfo], ' <Land Id="0x%.4x" Chance="%.2f" Mask="0x%.2x">',
|
||
[FBrushList.Brush[b]^.BEdges[e]^.BTileDR[t]^.ID, FBrushList.Brush[b]^.BEdges[e]^.BTileDR[t]^.Chance, FBrushList.Brush[b]^.BEdges[e]^.BTileDR[t]^.Mask]);
|
||
Logger.Send([lcInfo], ' </Edge>');
|
||
end;
|
||
Logger.Send([lcInfo], '</Brush>');
|
||
end;
|
||
Logger.ExitMethod([lcInfo, lcDebug], 'TfrmMain.AddNodeTiles-Brushes');
|
||
}
|
||
|
||
for i := 0 to nodeData^.Count - 1 do
|
||
begin
|
||
lastID := nodeData^.GTile[i].ID;
|
||
if FVisibleTiles[lastID] and ResMan.Art.Exists(lastID) then
|
||
begin
|
||
if (filter <> '') and (Pos(filter, AnsiLowerCase(
|
||
ResMan.Tiledata.TileData[lastID].TileName)) = 0) then Continue;
|
||
item := vdtTiles.AddItem(nil);
|
||
tileInfo := vdtTiles.GetNodeData(item);
|
||
tileInfo^.ID := lastID;
|
||
end;
|
||
end;
|
||
|
||
for i := 0 to nodeData^.Brushes - 1 do
|
||
begin
|
||
if nodeData^.Brush[i] = nil then Continue;
|
||
lastID := $2F000000 + LongWord(nodeData^.Brush[i]^.ID);
|
||
//if FVisibleTiles[lastID] and ResMan.Art.Exists(lastID) then
|
||
begin
|
||
if (filter <> '') and (Pos(filter, AnsiLowerCase(
|
||
nodeData^.Brush[i]^.Name)) = 0) then Continue;
|
||
item := vdtTiles.AddItem(nil);
|
||
tileInfo := vdtTiles.GetNodeData(item);
|
||
tileInfo^.ID := lastID;
|
||
tileInfo^.ptr:= nodeData^.Brush[i];
|
||
end;
|
||
end;
|
||
|
||
for i := 0 to nodeData^.Entries - 1 do
|
||
begin
|
||
if nodeData^.Entry[i] = nil then Continue;
|
||
lastID := $1F000000 + LongWord(nodeData^.Entry[i]^.ID);
|
||
//if FVisibleTiles[lastID] and ResMan.Art.Exists(lastID) then
|
||
begin
|
||
if (filter <> '') and (Pos(filter, AnsiLowerCase(
|
||
nodeData^.Entry[i]^.Name)) = 0) then Continue;
|
||
item := vdtTiles.AddItem(nil);
|
||
tileInfo := vdtTiles.GetNodeData(item);
|
||
tileInfo^.ID := lastID;
|
||
tileInfo^.ptr:= nodeData^.Entry[i];
|
||
end;
|
||
end;
|
||
|
||
// Добавление сылок групп
|
||
for i := 0 to nodeData^.Links - 1 do
|
||
if nodeData^.GLink[i] <> nil then
|
||
AddNodeTiles(nodeData^.GLink[i], 0);
|
||
|
||
// Добавление вложенных подгрупп
|
||
if (Count > 0) then
|
||
begin
|
||
groupNode := tvGroups.GetFirstChild(Node);
|
||
while groupNode <> nil do
|
||
begin
|
||
AddNodeTiles(groupNode, Count - 1);
|
||
groupNode := tvGroups.GetNextSibling(groupNode);
|
||
end;
|
||
end;
|
||
|
||
end;
|
||
|
||
begin
|
||
filter := AnsiLowerCase(UTF8ToCP1251(edFilter.Text));
|
||
|
||
Logger.Send([lcInfo], 'TfrmMain.BuildTileList: %s', ['Start']);
|
||
// Сортировка по группам
|
||
if (not cbStatics.Checked) and (not cbTerrain.Checked) then
|
||
begin
|
||
vdtTiles.BeginUpdate;
|
||
vdtTiles.Clear;
|
||
groupNode := tvGroups.GetFirstSelected();
|
||
while groupNode <> nil do
|
||
begin
|
||
nodeData := tvGroups.GetNodeData(groupNode);
|
||
AddNodeTiles(groupNode, nodeData^.Nodes);
|
||
groupNode := tvGroups.GetNextSelected(groupNode);
|
||
end;
|
||
vdtTiles.EndUpdate;
|
||
end else
|
||
// Старое построение - список всех land и\или item тайлов
|
||
begin
|
||
Logger.Send([lcInfo], 'TfrmMain.BuildTileList: start');
|
||
maxID := $3FFF;
|
||
if cbTerrain.Checked then minID := $0 else minID := $4000;
|
||
if cbStatics.Checked then maxID := maxID + FLandscape.MaxStaticID;
|
||
|
||
item := vdtTiles.GetFirstSelected;
|
||
if item <> nil then
|
||
begin
|
||
tileInfo := vdtTiles.GetNodeData(item);
|
||
lastID := tileInfo^.ID;
|
||
end else
|
||
lastID := -1;
|
||
|
||
vdtTiles.BeginUpdate;
|
||
vdtTiles.Clear;
|
||
|
||
Logger.Send([lcInfo], 'TfrmMain.BuildTileList: from %.4x to %.4x', [minID, maxID]);
|
||
for i := minID to maxID do
|
||
begin
|
||
if FVisibleTiles[i] and ResMan.Art.Exists(i) then
|
||
begin
|
||
if (filter <> '') and (Pos(filter, AnsiLowerCase(
|
||
ResMan.Tiledata.TileData[i].TileName)) = 0) then Continue;
|
||
item := vdtTiles.AddItem(nil);
|
||
tileInfo := vdtTiles.GetNodeData(item);
|
||
tileInfo^.ID := i;
|
||
|
||
//Logger.Send([lcInfo], 'TfrmMain.BuildTileList: tileInfo %.4x == %.4x', [i, PTileInfo(vdtTiles.GetNodeData(vdtTiles.GetFirst()))^.ID]);
|
||
|
||
if i = lastID then
|
||
vdtTiles.Selected[item] := True;
|
||
end;
|
||
end;
|
||
|
||
vdtTiles.EndUpdate;
|
||
|
||
item := vdtTiles.GetFirstSelected;
|
||
if item <> nil then
|
||
vdtTiles.FocusedNode := item;
|
||
end;
|
||
|
||
Logger.Send([lcInfo], 'TfrmMain.BuildTileList: %s', ['End']);
|
||
end;
|
||
|
||
procedure TfrmMain.ProcessToolState;
|
||
var
|
||
blockInfo: PBlockInfo;
|
||
begin
|
||
if acSelect.Checked then
|
||
begin
|
||
//lblTip.Caption := 'Нажатие правой кнопки мышки покажет меню со всеми инструментами.';
|
||
//lblTip.Caption := 'Нажмите и удерживайте левую кнопку мышки, чтобы просмотреть список действий.';
|
||
//'Press and hold the left mouse button to show a list with actions (eg. grab hue).';
|
||
oglGameWindow.Cursor := +01;//crDefault;
|
||
|
||
//no highlighted tiles in "selection" mode
|
||
Logger.Send([lcClient, lcDebug], 'Disable highlighting');
|
||
blockInfo := nil;
|
||
while FScreenBuffer.Iterate(blockInfo) do
|
||
if blockInfo^.State = ssNormal then
|
||
blockInfo^.Highlighted := False;
|
||
end else
|
||
begin
|
||
//lblTip.Caption := 'Нажмите и удерживайте левую кнопку мышки, чтобы выбрать область.';
|
||
//'Press and hold the left mouse button to target an area.';
|
||
oglGameWindow.Cursor := +03;//crHandPoint;
|
||
end;
|
||
|
||
FRepaintNeeded := True;
|
||
end;
|
||
|
||
procedure TfrmMain.ProcessAccessLevel;
|
||
begin
|
||
mnuAdministration.Visible := (dmNetwork.AccessLevel >= alDeveloper);
|
||
mnuShutdown.Visible := (dmNetwork.AccessLevel >= alAdministrator);
|
||
mnuAccountControl.Visible := (dmNetwork.AccessLevel >= alAdministrator);
|
||
mnuRegionControl.Visible := (dmNetwork.AccessLevel >= alAdministrator);
|
||
acSelection.Enabled := (dmNetwork.AccessLevel >= alNormal);
|
||
acDraw.Enabled := (dmNetwork.AccessLevel >= alNormal);
|
||
acMove.Enabled := (dmNetwork.AccessLevel >= alNormal);
|
||
acElevate.Enabled := (dmNetwork.AccessLevel >= alNormal);
|
||
acSurfElevate.Enabled := (dmNetwork.AccessLevel >= alNormal);
|
||
acSurfStretch.Enabled := (dmNetwork.AccessLevel >= alNormal);
|
||
acSurfSmooth.Enabled := (dmNetwork.AccessLevel >= alNormal);
|
||
acDelete.Enabled := (dmNetwork.AccessLevel >= alNormal);
|
||
acHue.Enabled := (dmNetwork.AccessLevel >= alNormal);
|
||
acFill.Enabled := (dmNetwork.AccessLevel >= alNormal);
|
||
Caption := Format('UO CentrED+ v%s [%s "%s" (%s) | %s "%s"]',
|
||
//Caption := Format('UO CentrED+ v%s !!! pre-release (not stable version) !!! [%s "%s" (%s) | %s "%s"]',
|
||
[VersionInfo.GetProductVersionString, lbFormTitleAccount, dmNetwork.Username,
|
||
GetAccessLevel(dmNetwork.AccessLevel), lbFormTitleProfile, dmNetwork.Profile]);
|
||
end;
|
||
|
||
procedure TfrmMain.RebuildScreenBuffer;
|
||
var
|
||
blockInfo: PBlockInfo;
|
||
i, tileX, tileY: Integer;
|
||
virtualTile: TVirtualTile;
|
||
zoom: Single;
|
||
begin
|
||
//Logger.EnterMethod([lcClient], 'RebuildScreenBuffer');
|
||
if tbZoom.Down then zoom:= tbZoom.Tag / 1000.0 else zoom:= 1.0;
|
||
|
||
FDrawDistance := Trunc(Sqrt(oglGameWindow.Width * oglGameWindow.Width +
|
||
oglGamewindow.Height * oglGamewindow.Height) / (44 * zoom));
|
||
//Logger.Send([lcClient], 'DrawDistance', FDrawDistance);
|
||
|
||
{$HINTS off}{$WARNINGS off}
|
||
if FX - FDrawDistance < 0 then FLowOffsetX := -FX else FLowOffsetX := -FDrawDistance;
|
||
if FY - FDrawDistance < 0 then FLowOffsetY := -FY else FLowOffsetY := -FDrawDistance;
|
||
if FX + FDrawDistance >= FLandscape.Width * 8 then FHighOffsetX := FLandscape.Width * 8 - FX - 1 else FHighOffsetX := FDrawDistance;
|
||
if FY + FDrawDistance >= FLandscape.Height * 8 then FHighOffsetY := FLandscape.Height * 8 - FY - 1 else FHighOffsetY := FDrawDistance;
|
||
{$HINTS on}{$WARNINGS on}
|
||
|
||
FRangeX := FHighOffsetX - FLowOffsetX;
|
||
FRangeY := FHighOffsetY - FLowOffsetY;
|
||
|
||
FLandscape.PrepareBlocks((FX + FLowOffsetX) div 8, (FY + FLowOffsetY) div 8,
|
||
(FX + FHighOffsetX) div 8 + 1, (FY + FHighOffsetY) div 8 + 1);
|
||
|
||
if frmVirtualLayer.cbShowLayer.Checked then
|
||
begin
|
||
//Logger.Send([lcClient, lcDebug], 'Preparing Virtual Layer');
|
||
|
||
if FVLayerMaterial = nil then
|
||
FVLayerMaterial := TSimpleMaterial.Create(FVLayerImage);
|
||
|
||
i := 0;
|
||
for tileX := FX + FLowOffsetX to FX + FHighOffsetX do
|
||
begin
|
||
for tileY := FY + FLowOffsetY to FY + FHighOffsetY do
|
||
begin
|
||
while (i < FVirtualTiles.Count) and (not (FVirtualTiles[i] is TVirtualTile)) do
|
||
Inc(i);
|
||
|
||
if i < FVirtualTiles.Count then
|
||
begin
|
||
virtualTile := TVirtualTile(FVirtualTiles[i]);
|
||
end else
|
||
begin
|
||
virtualTile := TVirtualTile.Create(nil);
|
||
FVirtualTiles.Add(virtualTile);
|
||
end;
|
||
|
||
virtualTile.X := tileX;
|
||
virtualTile.Y := tileY;
|
||
virtualTile.Z := frmVirtualLayer.seZ.Value;
|
||
virtualTile.Priority := virtualTile.Z;
|
||
virtualTile.PriorityBonus := High(ShortInt);
|
||
|
||
Inc(i);
|
||
end;
|
||
end;
|
||
while i < FVirtualTiles.Count do
|
||
begin
|
||
if FVirtualTiles[i] is TVirtualTile then
|
||
FVirtualTiles.Delete(i)
|
||
else
|
||
Inc(i);
|
||
end;
|
||
end else
|
||
begin
|
||
for i := FVirtualTiles.Count - 1 downto 0 do
|
||
if FVirtualTiles[i] is TVirtualTile then
|
||
FVirtualTiles.Delete(i);
|
||
end;
|
||
|
||
if acNoDraw.Checked and mnuShowLightSource.Checked then
|
||
begin
|
||
if FVLightSrcMaterial = nil then begin
|
||
getmem(FVLightSrcMaterial, FVLightSrcImageCount * SizeOf(TSimpleMaterial));
|
||
for i := 1 to FVLightSrcImageCount do
|
||
FVLightSrcMaterial[i-1] := TSimpleMaterial.Create(FVLightSrcImage[i]);
|
||
end;
|
||
end;
|
||
|
||
//Logger.Send([lcClient, lcDebug], 'VirtualTiles', FVirtualTiles.Count);
|
||
|
||
FLandscape.FillDrawList(FScreenBuffer, FX + FLowOffsetX, FY + FLowOffsetY,
|
||
FRangeX, FRangeY, acTerrain.Checked, acStatics.Checked, mnuShowWalls.Checked,
|
||
mnuShowBridges.Checked, mnuShowRoofs.Checked, mnuShowSurfaces.Checked, mnuShowFoliage.Checked,
|
||
mnuShowWater.Checked, acNoDraw.Checked and mnuShowNoDrawTiles.Checked, FVirtualTiles);
|
||
|
||
//Pre-process the buffer
|
||
blockInfo := nil;
|
||
while FScreenBuffer.Iterate(blockInfo) do
|
||
PrepareScreenBlock(blockInfo);
|
||
|
||
FScreenBuffer.UpdateShortcuts;
|
||
FScreenBufferState := [sbsValid, sbsIndexed];
|
||
|
||
//Logger.ExitMethod([lcClient], 'RebuildScreenBuffer');
|
||
end;
|
||
|
||
procedure TfrmMain.UpdateCurrentTile;
|
||
var
|
||
localPos: TPoint;
|
||
begin
|
||
if oglGameWindow.MouseEntered then
|
||
begin
|
||
localPos := oglGameWindow.ScreenToClient(Mouse.CursorPos);
|
||
UpdateCurrentTile(localPos.X, localPos.Y);
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.UpdateCurrentTile(AX, AY: Integer);
|
||
var
|
||
blockInfo: PBlockInfo;
|
||
zoom: Single;
|
||
begin
|
||
//Logger.EnterMethod([lcClient, lcDebug], 'UpdateCurrentTile');
|
||
FOverlayUI.ActiveArrow := FOverlayUI.HitTest(AX, AY);
|
||
if FOverlayUI.ActiveArrow > -1 then
|
||
begin
|
||
//Logger.Send([lcClient, lcDebug], 'Overlay active');
|
||
CurrentTile := nil;
|
||
//Logger.ExitMethod([lcClient, lcDebug], 'UpdateCurrentTile');
|
||
Exit;
|
||
end;
|
||
|
||
if tbZoom.Down then zoom := tbZoom.Tag / 1000.0 else zoom := 1.0;
|
||
|
||
blockInfo := FScreenBuffer.Find(Point(AX, AY), zoom);
|
||
if blockInfo <> nil then
|
||
CurrentTile := blockInfo^.Item
|
||
else
|
||
CurrentTile := nil;
|
||
|
||
//Logger.ExitMethod([lcClient, lcDebug], 'UpdateCurrentTile');
|
||
end;
|
||
|
||
procedure TfrmMain.UpdateFilter;
|
||
var
|
||
blockInfo: PBlockInfo;
|
||
tileData: TTiledata;
|
||
staticTileData: TStaticTileData;
|
||
lastSurface: PBlockInfo;
|
||
surfaceTop: Integer;
|
||
zoom: Single;
|
||
begin
|
||
blockInfo := nil;
|
||
lastSurface := nil;
|
||
while FScreenBuffer.Iterate(blockInfo) do
|
||
begin
|
||
if blockInfo^.State in [ssNormal, ssFiltered] then
|
||
begin
|
||
blockInfo^.State := ssNormal;
|
||
if (blockInfo^.Item.X < frmBoundaries.seMinX.Value) or
|
||
(blockInfo^.Item.X > frmBoundaries.seMaxX.Value) or
|
||
(blockInfo^.Item.Y < frmBoundaries.seMinY.Value) or
|
||
(blockInfo^.Item.Y > frmBoundaries.seMaxY.Value) or
|
||
(blockInfo^.Item.Z < frmBoundaries.tbMinZ.Position) or
|
||
(blockInfo^.Item.Z > frmBoundaries.tbMaxZ.Position) then
|
||
begin
|
||
blockInfo^.State := ssFiltered;
|
||
end else
|
||
if tbFilter.Down and (blockInfo^.Item is TStaticItem) and
|
||
(not frmFilter.Filter(TStaticItem(blockInfo^.Item))) then
|
||
begin
|
||
blockInfo^.State := ssFiltered;
|
||
end;
|
||
|
||
blockInfo^.WalkRestriction := wrNone;
|
||
if acWalkable.Checked then
|
||
begin
|
||
if blockInfo^.Item is TMapCell then
|
||
begin
|
||
tileData := ResMan.Tiledata.LandTiles[blockInfo^.Item.TileID];
|
||
if tdfImpassable in tileData.Flags then
|
||
begin
|
||
blockInfo^.WalkRestriction := wrCannotWalk;
|
||
lastSurface := nil;
|
||
end else
|
||
begin
|
||
blockInfo^.WalkRestriction := wrCanWalk;
|
||
lastSurface := blockInfo;
|
||
surfaceTop := blockInfo^.Item.Z;
|
||
end;
|
||
end else
|
||
begin
|
||
staticTileData := ResMan.Tiledata.StaticTiles[blockInfo^.Item.TileID];
|
||
if (lastSurface <> nil) and (lastSurface^.WalkRestriction = wrCanWalk) and
|
||
(lastSurface^.Item.X = blockInfo^.Item.X) and
|
||
(lastSurface^.Item.Y = blockInfo^.Item.Y) and ([tdfSurface,
|
||
tdfImpassable] * staticTileData.Flags <> []) then
|
||
begin
|
||
if (blockInfo^.Item.Z < surfaceTop + 16) and
|
||
((blockInfo^.Item.Z > lastSurface^.Item.Z + 2) or
|
||
not (tdfSurface in staticTileData.Flags)) then
|
||
lastSurface^.WalkRestriction := wrCannotWalk;
|
||
end;
|
||
|
||
if tdfSurface in staticTileData.Flags then
|
||
begin
|
||
if tdfImpassable in staticTileData.Flags then
|
||
begin
|
||
blockInfo^.WalkRestriction := wrCannotWalk;
|
||
lastSurface := nil;
|
||
end else
|
||
begin
|
||
blockInfo^.WalkRestriction := wrCanWalk;
|
||
lastSurface := blockInfo;
|
||
surfaceTop := blockInfo^.Item.Z + staticTileData.Height;
|
||
end;
|
||
end;
|
||
end;
|
||
end; //acWalkable.Checked
|
||
|
||
end;
|
||
end;
|
||
|
||
Include(FScreenBufferState, sbsFiltered);
|
||
|
||
if tbZoom.Down then zoom := tbZoom.Tag / 1000.0 else zoom := 1.0;
|
||
if (FLightManager.LightLevel > 0) and not acFlat.Checked then
|
||
FLightManager.UpdateLightMap(FX + FLowOffsetX, FRangeX + 1, FY + FLowOffsetY,
|
||
FRangeY + 1, FScreenBuffer, zoom);
|
||
end;
|
||
|
||
procedure TfrmMain.UpdateSelection;
|
||
|
||
procedure SetHighlight(ABlockInfo: PBlockInfo; AHighlighted: Boolean);
|
||
begin
|
||
if (ABlockInfo^.Item is TStaticItem) and acHue.Checked then
|
||
begin
|
||
if ABlockInfo^.HueOverride <> AHighlighted then
|
||
begin
|
||
ABlockInfo^.HueOverride := AHighlighted;
|
||
if AHighlighted then
|
||
begin
|
||
ABlockInfo^.Hue := frmHueSettings.GetHue;
|
||
ABlockInfo^.LowRes := FTextureManager.GetStaticMaterial(
|
||
TStaticItem(ABlockInfo^.Item), ABlockInfo^.Hue);
|
||
end else
|
||
begin
|
||
ABlockInfo^.LowRes := FTextureManager.GetStaticMaterial(
|
||
TStaticItem(ABlockInfo^.Item));
|
||
end;
|
||
end;
|
||
end else
|
||
begin
|
||
ABlockInfo^.Highlighted := AHighlighted;
|
||
end;
|
||
end;
|
||
|
||
procedure AddGhostTile(AX, AY: Word; ABaseTile: TWorldItem; selecetion: TRect);
|
||
|
||
// Получение ID текстуры для тайлов при использовании кисти
|
||
function GetTileId(brush: PGroupBrush; mask: byte; tileId: LongWord) : Integer;
|
||
var
|
||
i, j : Integer;
|
||
tileMask : Byte;
|
||
tileBrush, tempBrush: PGroupBrush;
|
||
brushEdge: PGroupBrushEdge;
|
||
randnf, chance, factor: Float;
|
||
brushCount: LongWord;
|
||
brushTiles: ^PBrushTile;
|
||
begin
|
||
GetTileId := tileId;
|
||
if FBrushList.Tiles[tileId].ID <> tileId
|
||
then exit;
|
||
|
||
if (FBrushList.Tiles[tileId].Brush1^.ID <> brush^.ID) and (FBrushList.Tiles[tileId].Brush2^.ID <> brush^.ID)
|
||
and (FBrushList.Tiles[tileId].Brush1^.ID <> FBrushList.Tiles[tileId].Brush2^.ID)
|
||
then begin
|
||
i:=0; j:=0;
|
||
tileMask := FBrushList.Tiles[tileId].Mask and not(mask);
|
||
if (tileMask and $01) <> 0 then inc(i);
|
||
if (tileMask and $02) <> 0 then inc(i);
|
||
if (tileMask and $04) <> 0 then inc(i);
|
||
if (tileMask and $08) <> 0 then inc(i);
|
||
tileMask := not(FBrushList.Tiles[tileId].Mask or $F0) and not(mask);
|
||
if (tileMask and $01) <> 0 then inc(j);
|
||
if (tileMask and $02) <> 0 then inc(j);
|
||
if (tileMask and $04) <> 0 then inc(j);
|
||
if (tileMask and $08) <> 0 then inc(j);
|
||
if i > j
|
||
then tileBrush := FBrushList.Tiles[tileId].Brush1
|
||
else tileBrush := FBrushList.Tiles[tileId].Brush2;
|
||
tileMask := $00;
|
||
end else
|
||
if (FBrushList.Tiles[tileId].Brush1^.ID = brush^.ID) and (FBrushList.Tiles[tileId].Brush2^.ID = brush^.ID)
|
||
then begin
|
||
tileBrush := nil;
|
||
end else if (FBrushList.Tiles[tileId].Brush1^.ID = FBrushList.Tiles[tileId].Brush2^.ID)
|
||
then begin
|
||
tileBrush := FBrushList.Tiles[tileId].Brush1;
|
||
tileMask := $00;
|
||
end else begin
|
||
if brush^.ID = FBrushList.Tiles[tileId].Brush1^.ID then begin
|
||
tileBrush := FBrushList.Tiles[tileId].Brush2;
|
||
tileMask := FBrushList.Tiles[tileId].Mask;
|
||
end else
|
||
if brush^.ID = FBrushList.Tiles[tileId].Brush2^.ID then begin
|
||
tileBrush := FBrushList.Tiles[tileId].Brush1;
|
||
tileMask := not(FBrushList.Tiles[tileId].Mask or $F0);
|
||
end;
|
||
end;
|
||
|
||
// Сумирование масок
|
||
if tileBrush = nil then begin
|
||
mask := $0F;
|
||
end else begin
|
||
//Logger.Send([lcInfo], '1 Brush Id= %d Mask= 0x%.2x TileMask= 0x%.2x tileId= 0x%.4x', [brush^.ID, mask, tileMask, tileId]);
|
||
mask := tileMask or mask;
|
||
//Logger.Send([lcInfo], '2 Brush Id= %d Mask= 0x%.2x TileMask= 0x%.2x tileId= 0x%.4x', [brush^.ID, mask, tileMask, tileId]);
|
||
if (mask = $01) or (mask = $02) or (mask = $04) or (mask = $05) or
|
||
(mask = $06) or (mask = $08) or (mask = $0A) or (mask = $0C)
|
||
then begin
|
||
mask := not(mask or $F0);
|
||
tempBrush:= brush;
|
||
brush:= tileBrush;
|
||
tileBrush:= tempBrush;
|
||
end;
|
||
end;
|
||
|
||
// Получение данных кисти
|
||
brushCount:= 0; brushEdge:= nil; brushTiles:= nil;
|
||
if mask = $0F then begin
|
||
brushCount := brush^.Count; brushTiles := brush^.BTile;
|
||
end else begin
|
||
for i := 0 to brush^.ECount-1 do begin
|
||
// Logger.Send([lcInfo], 'i= %d/%d EdgeId= %d BrushId= %d', [i, brush^.ECount-1, mask, brush^.EdgeId[i]^, tileBrush^.ID]);
|
||
if brush^.EdgeId[i]^ = tileBrush^.ID then begin
|
||
brushEdge := brush^.BEdges[i];
|
||
break;
|
||
end; end;
|
||
if brushEdge <> nil then
|
||
case mask of
|
||
$0E: begin brushCount := brushEdge^.CountDR; brushTiles := brushEdge^.BTileDR; end;
|
||
$0D: begin brushCount := brushEdge^.CountDL; brushTiles := brushEdge^.BTileDL; end;
|
||
$0B: begin brushCount := brushEdge^.CountUL; brushTiles := brushEdge^.BTileUL; end;
|
||
$07: begin brushCount := brushEdge^.CountUR; brushTiles := brushEdge^.BTileUR; end;
|
||
$09: begin brushCount := brushEdge^.CountLL; brushTiles := brushEdge^.BTileLL; end;
|
||
$03: begin brushCount := brushEdge^.CountUU; brushTiles := brushEdge^.BTileUU; end;
|
||
end;
|
||
end;
|
||
|
||
//Logger.Send([lcInfo], 'Brush Id= %d Mask= 0x%.2x TileMask= 0x%.2x tileId= 0x%.4x', [brush^.ID, mask, tileMask, tileId]);
|
||
|
||
// Находение ID тайла
|
||
chance := 0; factor := 0;
|
||
for i := 0 to brushCount - 1 do
|
||
chance := chance + brushTiles[i]^.Chance;
|
||
if chance > 0 then
|
||
factor := 1.0 / chance;
|
||
randnf := Random; chance := 0;
|
||
for i := 0 to brushCount - 1 do begin
|
||
chance := chance + factor * brushTiles[i]^.Chance;
|
||
if randnf <= chance then begin
|
||
GetTileId := brushTiles[i]^.ID;
|
||
break;
|
||
end;
|
||
end;
|
||
|
||
//if (FBrushList.Tiles[GetTileId].Mask <> FBrushList.Tiles[tileId].Mask)
|
||
//or (FBrushList.Tiles[GetTileId].ID <> GetTileId) or (FBrushList.Tiles[tileId].ID <> tileId)
|
||
//or (FBrushList.Tiles[GetTileId].Brush1^.ID <> FBrushList.Tiles[tileId].Brush1^.ID)
|
||
//or (FBrushList.Tiles[GetTileId].Brush2^.ID <> FBrushList.Tiles[tileId].Brush2^.ID)
|
||
//or (GetTileId < 0) or (GetTileId > $3FFF) then GetTileId:= -1;
|
||
end;
|
||
|
||
var
|
||
blockInfo: PBlockInfo;
|
||
tileInfo: PTileInfo;
|
||
item: PVirtualItem;
|
||
node: PVirtualItem;
|
||
cell: TMapCell;
|
||
ghostTile: TGhostTile;
|
||
i, randalt: Integer;
|
||
begin
|
||
if frmDrawSettings.cbProbability.Checked and frmDrawSettings.cbProbability.Enabled
|
||
and (frmDrawSettings.seProbability.Value < 100 * Random)
|
||
then exit;
|
||
|
||
tileInfo := nil;
|
||
if frmDrawSettings.rbTileList.Checked then
|
||
begin
|
||
item := vdtTiles.GetFirstSelected;
|
||
if item <> nil then
|
||
tileInfo := vdtTiles.GetNodeData(item);
|
||
end else if frmDrawSettings.rbRandom.Checked then
|
||
begin
|
||
node := vdlRandom.GetFirst;
|
||
for i := 1 to Random(vdlRandom.TilesCount) do
|
||
node := vdlRandom.GetNext(node);
|
||
|
||
if node <> nil then
|
||
tileInfo := vdlRandom.GetNodeData(node);
|
||
end;
|
||
|
||
if tileInfo <> nil then
|
||
begin
|
||
if tileInfo^.ID > $2F000000 then
|
||
begin // **** Кисти ****
|
||
cell := FLandscape.MapCell[AX, AY];
|
||
if cell <> nil then
|
||
begin
|
||
//Logger.Send([lcInfo], '!!! AX= %d AY= %d ', [AX, AY]);
|
||
//Logger.Send([lcInfo], 'MapCell GhostId= 0x%.4x TileId= 0x%.4x Id= 0x%.4x', [cell.RawTileID, cell.TileID, cell.ID]);
|
||
inc(selecetion.Left, -1); inc(selecetion.Top, -1);
|
||
if not IsInRect(AX, AY, selecetion) then exit;
|
||
inc(selecetion.Left, +1); inc(selecetion.Top, +1);
|
||
|
||
if (AX = selecetion.Left) then begin
|
||
AddGhostTile(selecetion.Left-1, AY, ABaseTile, selecetion);
|
||
end;
|
||
if (AY = selecetion.Top) then begin
|
||
AddGhostTile(AX, selecetion.Top-1, ABaseTile, selecetion);
|
||
end;
|
||
if (AX = selecetion.Left) and (AY = selecetion.Top) then begin
|
||
AddGhostTile(selecetion.Left-1, selecetion.Top-1, ABaseTile, selecetion);
|
||
end;
|
||
|
||
if (AX = selecetion.Right) and (AY = selecetion.Bottom)
|
||
then randalt := GetTileId(PGroupBrush(tileInfo^.ptr), $01, cell.RawTileID)
|
||
else if (AX = selecetion.Left-1) and (AY = selecetion.Bottom)
|
||
then randalt := GetTileId(PGroupBrush(tileInfo^.ptr), $02, cell.RawTileID)
|
||
else if (AX = selecetion.Left-1) and (AY = selecetion.Top-1)
|
||
then randalt := GetTileId(PGroupBrush(tileInfo^.ptr), $04, cell.RawTileID)
|
||
else if (AX = selecetion.Right) and (AY = selecetion.Top-1)
|
||
then randalt := GetTileId(PGroupBrush(tileInfo^.ptr), $08, cell.RawTileID)
|
||
else if (AX = selecetion.Right)
|
||
then randalt := GetTileId(PGroupBrush(tileInfo^.ptr), $09, cell.RawTileID)
|
||
else if (AY = selecetion.Bottom)
|
||
then randalt := GetTileId(PGroupBrush(tileInfo^.ptr), $03, cell.RawTileID)
|
||
else if (AY = selecetion.Top-1)
|
||
then randalt := GetTileId(PGroupBrush(tileInfo^.ptr), $0C, cell.RawTileID)
|
||
else if (AX = selecetion.Left-1)
|
||
then randalt := GetTileId(PGroupBrush(tileInfo^.ptr), $06, cell.RawTileID)
|
||
else randalt := GetTileId(PGroupBrush(tileInfo^.ptr), $0F, cell.RawTileID);
|
||
|
||
if (randalt > 0) then begin //Добавление текстур
|
||
cell.IsGhost := True;
|
||
cell.GhostID := randalt;
|
||
if frmDrawSettings.cbForceAltitude.Checked then
|
||
cell.GhostZ := frmDrawSettings.seForceAltitude.Value
|
||
else
|
||
cell.GhostZ := cell.RawZ;
|
||
if frmDrawSettings.cbRandomHeight.Checked then
|
||
cell.GhostZ := cell.GhostZ + Random(frmDrawSettings.seRandomHeight.Value);
|
||
|
||
PrepareMapCell(cell);
|
||
end;
|
||
end;
|
||
end else if tileInfo^.ID > $1F000000 then
|
||
begin // **** Объекты *****
|
||
for i := 0 to PGroupEntry(tileInfo^.ptr)^.Count - 1 do begin
|
||
if frmDrawSettings.cbUseFreeTilesOnly.Checked then begin
|
||
blockInfo := FScreenBuffer.Find(AX + PGroupEntry(tileInfo^.ptr)^.ETile[i].X,
|
||
AY + PGroupEntry(tileInfo^.ptr)^.ETile[i].Y);
|
||
if (blockInfo <> nil) and (blockInfo^.Next <> nil) and
|
||
(blockInfo^.Item.X = blockInfo^.Next^.Item.X) and (blockInfo^.Item.Y = blockInfo^.Next^.Item.Y)
|
||
then exit;
|
||
end;
|
||
end;
|
||
|
||
if frmDrawSettings.cbRandomHeight.Checked
|
||
then randalt := Random(frmDrawSettings.seRandomHeight.Value)
|
||
else randalt := 0;
|
||
for i := 0 to PGroupEntry(tileInfo^.ptr)^.Count - 1 do begin
|
||
ghostTile := TGhostTile.Create(nil, nil, 0, 0);
|
||
ghostTile.TileID := PGroupEntry(tileInfo^.ptr)^.ETile[i].ID - $4000;
|
||
ghostTile.Hue := PGroupEntry(tileInfo^.ptr)^.ETile[i].Hue;
|
||
ghostTile.X := AX + PGroupEntry(tileInfo^.ptr)^.ETile[i].X;
|
||
ghostTile.Y := AY + PGroupEntry(tileInfo^.ptr)^.ETile[i].Y;
|
||
ghostTile.CenterX := AX;
|
||
ghostTile.CenterY := AY;
|
||
if ((not frmDrawSettings.cbForceAltitude.Enabled) or (not frmDrawSettings.cbForceAltitude.Checked)) then
|
||
begin
|
||
if frmDrawSettings.cbUseSurfaceAltitude.Checked then begin
|
||
blockInfo := FScreenBuffer.Find(AX, AY);
|
||
if blockInfo <> nil then
|
||
ABaseTile := blockInfo^.Item;
|
||
ghostTile.Z := ABaseTile.Z;
|
||
end;
|
||
|
||
if ABaseTile is TStaticItem then
|
||
ghostTile.Z := ABaseTile.Z + ResMan.Tiledata.StaticTiles[ABaseTile.TileID].Height
|
||
else if ABaseTile is TMapCell then
|
||
ghostTile.Z := ResMan.Landscape.GetEffectiveAltitude(TMapCell(ABaseTile))
|
||
else // if ABaseTile is TVirtualTile then
|
||
ghostTile.Z := ABaseTile.Z;
|
||
end else
|
||
ghostTile.Z := frmDrawSettings.seForceAltitude.Value;
|
||
ghostTile.Z := ghostTile.Z + randalt + PGroupEntry(tileInfo^.ptr)^.ETile[i].Z;;
|
||
{
|
||
Logger.Send([lcInfo], ' <Entry Id="%.4d Tile %.2d/%.2d - Id="0x%.4x" Hue="0x%.3x" X="%d" Y="%d" Z="%d">',
|
||
[PGroupEntry(tileInfo^.ptr)^.ID, i, PGroupEntry(tileInfo^.ptr)^.Count, ghostTile.TileID,
|
||
ghostTile.Hue, ghostTile.X, ghostTile.Y, ghostTile.Z]);
|
||
}
|
||
ghostTile.UpdatePriorities(ResMan.Tiledata.StaticTiles[ghostTile.TileID], MaxInt);
|
||
ghostTile.CanBeEdited := True;
|
||
|
||
FVirtualTiles.Add(ghostTile);
|
||
blockInfo := FScreenBuffer.Insert(ghostTile);
|
||
blockInfo^.State := ssGhost;
|
||
PrepareScreenBlock(blockInfo);
|
||
end;
|
||
end else if tileInfo^.ID < $4000 then
|
||
begin // **** Текстуры ****
|
||
cell := FLandscape.MapCell[AX, AY];
|
||
if cell <> nil then
|
||
begin
|
||
cell.IsGhost := True;
|
||
cell.GhostID := tileInfo^.ID;
|
||
if frmDrawSettings.cbForceAltitude.Checked then
|
||
cell.GhostZ := frmDrawSettings.seForceAltitude.Value
|
||
else
|
||
cell.GhostZ := cell.RawZ;
|
||
if frmDrawSettings.cbRandomHeight.Checked then
|
||
cell.GhostZ := cell.GhostZ + Random(frmDrawSettings.seRandomHeight.Value);
|
||
|
||
PrepareMapCell(cell);
|
||
end;
|
||
end else
|
||
begin // **** Статика *****
|
||
if frmDrawSettings.cbUseFreeTilesOnly.Checked then begin
|
||
blockInfo := FScreenBuffer.Find(AX, AY);
|
||
if (blockInfo <> nil) and (blockInfo^.Next <> nil) and
|
||
(blockInfo^.Item.X = blockInfo^.Next^.Item.X) and (blockInfo^.Item.Y = blockInfo^.Next^.Item.Y)
|
||
then exit;
|
||
end;
|
||
|
||
ghostTile := TGhostTile.Create(nil, nil, 0, 0);
|
||
ghostTile.TileID := tileInfo^.ID - $4000;
|
||
ghostTile.Hue := frmHueSettings.GetHue;
|
||
ghostTile.X := AX; ghostTile.CenterX := AX;
|
||
ghostTile.Y := AY; ghostTile.CenterY := AY;
|
||
|
||
if ((not frmDrawSettings.cbForceAltitude.Enabled) or (not frmDrawSettings.cbForceAltitude.Checked)) then
|
||
begin
|
||
if frmDrawSettings.cbUseSurfaceAltitude.Checked then begin
|
||
blockInfo := FScreenBuffer.Find(AX, AY);
|
||
if blockInfo <> nil then
|
||
ABaseTile := blockInfo^.Item;
|
||
end;
|
||
//ghostTile.Z := ABaseTile.Z;
|
||
if ABaseTile is TStaticItem then
|
||
ghostTile.Z := ABaseTile.Z + ResMan.Tiledata.StaticTiles[ABaseTile.TileID].Height
|
||
else if ABaseTile is TMapCell then
|
||
ghostTile.Z := ResMan.Landscape.GetEffectiveAltitude(TMapCell(ABaseTile))
|
||
else // if ABaseTile is TVirtualTile then
|
||
ghostTile.Z := ABaseTile.Z;
|
||
end else
|
||
ghostTile.Z := frmDrawSettings.seForceAltitude.Value;
|
||
if frmDrawSettings.cbRandomHeight.Checked then
|
||
ghostTile.Z := ghostTile.Z +
|
||
Random(frmDrawSettings.seRandomHeight.Value);
|
||
|
||
ghostTile.UpdatePriorities(ResMan.Tiledata.StaticTiles[ghostTile.TileID],
|
||
MaxInt);
|
||
ghostTile.CanBeEdited := True;
|
||
|
||
FVirtualTiles.Add(ghostTile);
|
||
blockInfo := FScreenBuffer.Insert(ghostTile);
|
||
blockInfo^.State := ssGhost;
|
||
PrepareScreenBlock(blockInfo);
|
||
end;
|
||
|
||
end;
|
||
end;
|
||
|
||
var
|
||
selectedRect: TRect;
|
||
blockInfo: PBlockInfo;
|
||
item: TWorldItem;
|
||
cell: TMapCell;
|
||
i, tileX, tileY: Integer;
|
||
brushMod: Boolean; // Актевирован Режим работы с кистями
|
||
begin
|
||
//Logger.EnterMethod([lcClient, lcDebug], 'UpdateSelection');
|
||
|
||
//If the current tile is nil, but we still have a selected tile, the
|
||
//procedure is pointless - the selection should stay intact.
|
||
if (CurrentTile <> nil) or (SelectedTile = nil) then
|
||
begin
|
||
brushMod := (vdtTiles.GetFirstSelected <> nil) and (PTileInfo(vdtTiles.GetNodeData(vdtTiles.GetFirstSelected))^.ID >= $2F000000);
|
||
|
||
if CurrentTile = nil then
|
||
selectedRect := Rect(-1, -1, -1, -1)
|
||
else
|
||
selectedRect := GetSelectedRect;
|
||
|
||
//clean up old ghost tiles
|
||
//Logger.Send([lcClient, lcDebug], 'Cleaning ghost tiles');
|
||
for i := FVirtualTiles.Count - 1 downto 0 do
|
||
begin
|
||
item := FVirtualTiles[i];
|
||
if (item is TGhostTile) and not IsInRect((item as TGhostTile).CenterX,
|
||
(item as TGhostTile).CenterY, selectedRect) then
|
||
begin
|
||
FScreenBuffer.Delete(item);
|
||
FVirtualTiles.Delete(i);
|
||
end;
|
||
end;
|
||
//Logger.Send([lcClient, lcDebug], 'FSelection', FSelection);
|
||
if brushMod then begin // Для кистей
|
||
i:= -1; inc(selectedRect.Left, -1); inc(selectedRect.Top, -1);
|
||
end else i:= 0;
|
||
for tileX := FSelection.Left+i to FSelection.Right do
|
||
for tileY := FSelection.Top+i to FSelection.Bottom do
|
||
if not IsInRect(tileX, tileY, selectedRect) then
|
||
begin
|
||
cell := FLandscape.MapCell[tileX, tileY];
|
||
if (cell <> nil) and cell.IsGhost then
|
||
begin
|
||
cell.IsGhost := False;
|
||
PrepareMapCell(cell);
|
||
end;
|
||
end;
|
||
if brushMod then begin // Для кистей
|
||
inc(selectedRect.Left, +1); inc(selectedRect.Top, +1);
|
||
end;
|
||
|
||
if (CurrentTile <> nil) and (not acSelect.Checked) then
|
||
begin
|
||
blockInfo := nil;
|
||
if (SelectedTile <> nil) and (CurrentTile <> SelectedTile) then
|
||
begin
|
||
{Logger.Send([lcClient, lcDebug], 'Multiple Targets');
|
||
Logger.Send([lcClient, lcDebug], 'SelectedRect', selectedRect);}
|
||
//Logger.Send([lcClient, lcDebug], 'SelectedTile: %.5x (%.6d)', [SelectedTile.TileID, SelectedTile.TileID]);
|
||
//set new ghost tiles
|
||
|
||
if acDraw.Checked then begin
|
||
for tileX := selectedRect.Left to selectedRect.Right do
|
||
for tileY := selectedRect.Top to selectedRect.Bottom do
|
||
if not IsInRect(tileX, tileY, FSelection) then
|
||
AddGhostTile(tileX, tileY, SelectedTile, selectedRect);
|
||
if brushMod then begin // Для кистей
|
||
if (selectedRect.Left > FSelection.Left) then
|
||
for tileY := selectedRect.Top to selectedRect.Bottom do
|
||
AddGhostTile(selectedRect.Left, tileY, SelectedTile, selectedRect);
|
||
if (selectedRect.Top > FSelection.Top) then
|
||
for tileX := selectedRect.Left to selectedRect.Right do
|
||
AddGhostTile(tileX, selectedRect.Top, SelectedTile, selectedRect);
|
||
if (selectedRect.Right < FSelection.Right) then
|
||
for tileY := selectedRect.Top to selectedRect.Bottom do
|
||
AddGhostTile(selectedRect.Right, tileY, SelectedTile, selectedRect);
|
||
if (selectedRect.Bottom < FSelection.Bottom) then
|
||
for tileX := selectedRect.Left to selectedRect.Right do
|
||
AddGhostTile(tileX, selectedRect.Bottom, SelectedTile, selectedRect);
|
||
if (selectedRect.Right > FSelection.Right) then
|
||
for tileY := FSelection.Top to FSelection.Bottom do
|
||
AddGhostTile(FSelection.Right, tileY, SelectedTile, selectedRect);
|
||
if (selectedRect.Bottom > FSelection.Bottom) then
|
||
for tileX := FSelection.Left to FSelection.Right do
|
||
AddGhostTile(tileX, FSelection.Bottom, SelectedTile, selectedRect);
|
||
end;
|
||
end;
|
||
while FScreenBuffer.Iterate(blockInfo) do
|
||
if (blockInfo^.State = ssNormal) then
|
||
SetHighlight(blockInfo, IsInRect(blockInfo^.Item.X, blockInfo^.Item.Y,
|
||
selectedRect) and not acDraw.Checked);
|
||
end else
|
||
begin
|
||
//Logger.Send([lcClient, lcDebug], 'Single Target');
|
||
//Logger.Send([lcClient, lcDebug], 'CurrentTile: %.5x (%.6d)', [CurrentTile.TileID, CurrentTile.TileID]);
|
||
if acDraw.Checked and not IsInRect(CurrentTile.X, CurrentTile.Y, FSelection) then
|
||
AddGhostTile(CurrentTile.X, CurrentTile.Y, CurrentTile, selectedRect);
|
||
while FScreenBuffer.Iterate(blockInfo) do
|
||
if blockInfo^.State = ssNormal then
|
||
SetHighlight(blockInfo, (blockInfo^.Item = CurrentTile) and not acDraw.Checked);
|
||
end;
|
||
end;
|
||
FSelection := selectedRect;
|
||
end;
|
||
{Logger.Send([lcClient, lcDebug], 'Virtual Tiles', FVirtualTiles.Count);
|
||
Logger.ExitMethod([lcClient, lcDebug], 'UpdateSelection');}
|
||
end;
|
||
|
||
procedure TfrmMain.OnTileRemoved(ATile: TMulBlock);
|
||
begin
|
||
if ATile = FCurrentTile then
|
||
FCurrentTile := nil
|
||
else if ATile = FSelectedTile then
|
||
FSelectedTile := nil;
|
||
end;
|
||
|
||
procedure TfrmMain.WriteChatMessage(ASender, AMessage: string);
|
||
var
|
||
node: PVirtualNode;
|
||
chatInfo: PChatInfo;
|
||
begin
|
||
node := vstChat.AddChild(nil);
|
||
chatInfo := vstChat.GetNodeData(node);
|
||
chatInfo^.Time := Now;
|
||
chatInfo^.Sender := ASender;
|
||
chatInfo^.Msg := AMessage;
|
||
if vstChat.RootNodeCount > 30 then
|
||
vstChat.DeleteNode(vstChat.GetFirst);
|
||
vstChat.ScrollIntoView(node, False);
|
||
|
||
if not pnlChat.Visible then
|
||
begin
|
||
lblChatHeaderCaption.Font.Bold := True;
|
||
lblChatHeaderCaption.Font.Italic := True;
|
||
lblChatHeaderCaption.Font.Color := clRed;
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.OnClientHandlingPacket(ABuffer: TEnhancedMemoryStream);
|
||
var
|
||
sender, msg: string;
|
||
i: Integer;
|
||
accessLevel: TAccessLevel;
|
||
clientNode: PVirtualNode;
|
||
clientInfo: PClientInfo;
|
||
begin
|
||
case ABuffer.ReadByte of
|
||
$01: //client connected
|
||
begin
|
||
sender := ABuffer.ReadStringNull;
|
||
vstClients.BeginUpdate;
|
||
clientNode := vstClients.AddChild(nil);
|
||
clientInfo := vstClients.GetNodeData(clientNode);
|
||
clientInfo^.Name := sender;
|
||
clientInfo^.AccessLevel := TAccessLevel(ABuffer.ReadByte);
|
||
clientInfo^.LogonDateTime := Now;
|
||
vstClients.EndUpdate;
|
||
if sender <> dmNetwork.Username then
|
||
WriteChatMessage('System', Format(lbUserLoginedMsg, [sender]));
|
||
end;
|
||
$02:
|
||
begin
|
||
sender := ABuffer.ReadStringNull;
|
||
vstClients.BeginUpdate;
|
||
clientNode := vstClients.GetFirst;
|
||
while clientNode <> nil do begin
|
||
clientInfo := vstClients.GetNodeData(clientNode);
|
||
if (clientInfo^.Name = sender)
|
||
then begin
|
||
vstClients.DeleteNode(clientNode);
|
||
break;
|
||
end
|
||
else clientNode := vstClients.GetNext(clientNode);
|
||
end;
|
||
vstClients.EndUpdate;
|
||
if sender <> dmNetwork.Username then
|
||
WriteChatMessage('System', Format(lbUserLogoutedMsg, [sender]));
|
||
end;
|
||
$03: //Client list
|
||
begin
|
||
vstClients.Clear;
|
||
while ABuffer.Position < ABuffer.Size do
|
||
begin
|
||
sender := ABuffer.ReadStringNull;
|
||
clientNode := vstClients.AddChild(nil);
|
||
clientInfo := vstClients.GetNodeData(clientNode);
|
||
clientInfo^.Name := sender;
|
||
clientInfo^.AccessLevel := TAccessLevel(ABuffer.ReadByte);
|
||
clientInfo^.LogonDateTime := IncSecond(dmNetwork.ServerStart, ABuffer.ReadDWord);
|
||
end;
|
||
end;
|
||
$04: //Set pos
|
||
begin
|
||
FX := ABuffer.ReadWord;
|
||
FY := ABuffer.ReadWord;
|
||
SetPos(FX, FY);
|
||
end;
|
||
$05: //chat
|
||
begin
|
||
sender := ABuffer.ReadStringNull;
|
||
msg := ABuffer.ReadStringNull;
|
||
WriteChatMessage(sender, msg);
|
||
end;
|
||
$07: //access changed
|
||
begin
|
||
accessLevel := TAccessLevel(ABuffer.ReadByte);
|
||
FLandscape.UpdateWriteMap(ABuffer);
|
||
FRepaintNeeded := True;
|
||
|
||
if accessLevel <> dmNetwork.AccessLevel then
|
||
begin
|
||
dmNetwork.AccessLevel := accessLevel;
|
||
if accessLevel = alNone then
|
||
begin
|
||
MessageDlg(lbDlgBlockedAccessCaption, lbDlgBlockedAccess, mtWarning, [mbOK], 0);
|
||
mnuDisconnectClick(nil);
|
||
end else
|
||
begin
|
||
ProcessAccessLevel;
|
||
MessageDlg(lbDlgCnangedAccessCaption, Format(lbDlgCnangedAccess, [GetAccessLevel(accessLevel)]), mtWarning, [mbOK], 0);
|
||
end;
|
||
end;
|
||
|
||
for i := FAccessChangedListeners.Count - 1 downto 0 do
|
||
FAccessChangedListeners[i](accessLevel);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
function TfrmMain.GetInternalTileID(ATile: TWorldItem): LongWord;
|
||
begin
|
||
Result := ATile.TileID;
|
||
if ATile is TStaticItem then
|
||
Inc(Result, $4000);
|
||
end;
|
||
|
||
function TfrmMain.GetSelectedRect: TRect;
|
||
begin
|
||
if CurrentTile <> nil then
|
||
begin
|
||
if SelectedTile <> nil then
|
||
begin
|
||
Result.Left := Min(CurrentTile.X, SelectedTile.X);
|
||
Result.Top := Min(CurrentTile.Y, SelectedTile.Y);
|
||
Result.Right := Max(CurrentTile.X, SelectedTile.X);
|
||
Result.Bottom := Max(CurrentTile.Y, SelectedTile.Y);
|
||
end else
|
||
begin
|
||
Result.Left := CurrentTile.X;
|
||
Result.Top := CurrentTile.Y;
|
||
Result.Right := CurrentTile.X;
|
||
Result.Bottom := CurrentTile.Y;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
function TfrmMain.ConfirmAction: Boolean;
|
||
begin
|
||
if acMove.Checked and frmMoveSettings.cbAsk.Checked then
|
||
begin
|
||
Result := frmMoveSettings.ShowModal = mrYes;
|
||
end else
|
||
if not mnuSecurityQuestion.Checked then
|
||
begin
|
||
Result := True;
|
||
end else
|
||
begin
|
||
frmConfirmation.Left := Mouse.CursorPos.x - frmConfirmation.btnYes.Left - frmConfirmation.btnYes.Width div 2;
|
||
frmConfirmation.Top := Mouse.CursorPos.y - frmConfirmation.btnYes.Top - frmConfirmation.btnYes.Height div 2;
|
||
Result := frmConfirmation.ShowModal = mrYes;
|
||
end;
|
||
|
||
if not oglGameWindow.MouseEntered then
|
||
oglGameWindowMouseLeave(nil);
|
||
end;
|
||
|
||
function TfrmMain.FindRandomPreset(AName: String): TDOMElement;
|
||
var
|
||
preset: TDOMElement;
|
||
presets: TDOMNodeList;
|
||
i: Integer;
|
||
begin
|
||
presets := FRandomPresetsDoc.DocumentElement.ChildNodes;
|
||
Result := nil;
|
||
i := 0;
|
||
while (i < presets.Count) and (Result = nil) do
|
||
begin
|
||
preset := TDOMElement(presets[i]);
|
||
if SameText(preset.AttribStrings['Name'], AName) then
|
||
Result := preset
|
||
else
|
||
Inc(i);
|
||
end;
|
||
end;
|
||
|
||
procedure TfrmMain.ForceUpdateCurrentTile;
|
||
begin
|
||
CurrentTile := nil;
|
||
UpdateCurrentTile;
|
||
end;
|
||
|
||
procedure TfrmMain.GetDrawOffset(AX, AY: Integer; out DrawX, DrawY: Integer); inline;
|
||
var
|
||
zoom: Single;
|
||
begin
|
||
if tbZoom.Down then zoom := tbZoom.Tag / 1000.0 else zoom := 1.0;
|
||
|
||
Dec(AX, FX);
|
||
Dec(AY, FY);
|
||
DrawX := (oglGameWindow.Width div 2) + Trunc((AX - AY) * 22 * zoom);
|
||
DrawY := (oglGamewindow.Height div 2) + Trunc((AX + AY) * 22 * zoom);
|
||
end;
|
||
|
||
initialization
|
||
{$I UfrmMain.lrs}
|
||
|
||
end.
|
||
|