| 1 | unit MetaEditor;
 | 
|---|
| 2 | 
 | 
|---|
| 3 | interface
 | 
|---|
| 4 | 
 | 
|---|
| 5 | uses
 | 
|---|
| 6 |   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 | 
|---|
| 7 |   Dialogs, _BaseTemplate, ExtCtrls, VirtualTrees, StdCtrls, ComCtrls, Grids,
 | 
|---|
| 8 |   MPHexEditor, Wrapgrid, VTHeaderPopup, Menus, _TreeElement;
 | 
|---|
| 9 | 
 | 
|---|
| 10 | type
 | 
|---|
| 11 |   TForm_Meta = class(TForm_BaseTemplate)
 | 
|---|
| 12 |     VST: TVirtualStringTree;
 | 
|---|
| 13 |     splitter: TSplitter;
 | 
|---|
| 14 |     rightPages: TPageControl;
 | 
|---|
| 15 |     tab_hex: TTabSheet;
 | 
|---|
| 16 |     tab_meta: TTabSheet;
 | 
|---|
| 17 |     panel_hex_actions: TPanel;
 | 
|---|
| 18 |     hex: TMPHexEditor;
 | 
|---|
| 19 |     splitter_hex_1: TSplitter;
 | 
|---|
| 20 |     value_viewer: TWrapGrid;
 | 
|---|
| 21 |     splitter_hex_2: TSplitter;
 | 
|---|
| 22 |     structviewer: TVirtualStringTree;
 | 
|---|
| 23 |     value_viewer_context: TPopupMenu;
 | 
|---|
| 24 |     value_viewer_context_copy: TMenuItem;
 | 
|---|
| 25 |     value_viewer_context_copyasdec: TMenuItem;
 | 
|---|
| 26 |     value_viewer_context_copyasfloat: TMenuItem;
 | 
|---|
| 27 |     value_viewer_context_copyasbitset: TMenuItem;
 | 
|---|
| 28 |     value_viewer_context_copyasstring: TMenuItem;
 | 
|---|
| 29 |     value_viewer_context_copyashex: TMenuItem;
 | 
|---|
| 30 |     VTHPopup: TVTHeaderPopupMenu;
 | 
|---|
| 31 |     btn_export: TButton;
 | 
|---|
| 32 |     btn_import: TButton;
 | 
|---|
| 33 |     vst_popup: TPopupMenu;
 | 
|---|
| 34 |     vst_newRoot: TMenuItem;
 | 
|---|
| 35 |     vst_setRoot: TMenuItem;
 | 
|---|
| 36 |     procedure FormCreate(Sender: TObject);
 | 
|---|
| 37 |     procedure VSTInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode;
 | 
|---|
| 38 |       var ChildCount: Cardinal);
 | 
|---|
| 39 |     procedure FormClose(Sender: TObject; var Action: TCloseAction);
 | 
|---|
| 40 |     procedure VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
 | 
|---|
| 41 |       Column: TColumnIndex);
 | 
|---|
| 42 |     procedure VSTFocusChanging(Sender: TBaseVirtualTree; OldNode,
 | 
|---|
| 43 |       NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex;
 | 
|---|
| 44 |       var Allowed: Boolean);
 | 
|---|
| 45 |     procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
 | 
|---|
| 46 |       Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
 | 
|---|
| 47 |     procedure VSTPaintText(Sender: TBaseVirtualTree;
 | 
|---|
| 48 |       const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
 | 
|---|
| 49 |       TextType: TVSTTextType);
 | 
|---|
| 50 |     procedure VSTGetPopupMenu(Sender: TBaseVirtualTree; Node: PVirtualNode;
 | 
|---|
| 51 |       Column: TColumnIndex; const P: TPoint; var AskParent: Boolean;
 | 
|---|
| 52 |       var PopupMenu: TPopupMenu);
 | 
|---|
| 53 |     procedure vst_setRootClick(Sender: TObject);
 | 
|---|
| 54 |     procedure vst_newRootClick(Sender: TObject);
 | 
|---|
| 55 |     procedure VSTGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode;
 | 
|---|
| 56 |       Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle;
 | 
|---|
| 57 |       var HintText: WideString);
 | 
|---|
| 58 |   private
 | 
|---|
| 59 |     root: TTreeElement;
 | 
|---|
| 60 |     procedure NewCon(ID: Integer);
 | 
|---|
| 61 |   public
 | 
|---|
| 62 |     procedure SetRoot(TreeElem: TTreeElement);
 | 
|---|
| 63 |   end;
 | 
|---|
| 64 | 
 | 
|---|
| 65 | 
 | 
|---|
| 66 | implementation
 | 
|---|
| 67 | {$R *.dfm}
 | 
|---|
| 68 | uses _MetaManager, _MetaTypes, ConnectionManager, Data, _FileTypes, Main, 
 | 
|---|
| 69 |   TypeDefs;
 | 
|---|
| 70 | 
 | 
|---|
| 71 | type
 | 
|---|
| 72 |   PNodeData = ^TNodeData;
 | 
|---|
| 73 | 
 | 
|---|
| 74 |   TNodeData = record
 | 
|---|
| 75 |     Field: TTreeElement;
 | 
|---|
| 76 |   end;
 | 
|---|
| 77 | 
 | 
|---|
| 78 | function AddVSTEntry(AVST: TCustomVirtualStringTree; ANode: PVirtualNode;
 | 
|---|
| 79 |   ARecord: TNodeData): PVirtualNode;
 | 
|---|
| 80 | var
 | 
|---|
| 81 |   Data: PNodeData;
 | 
|---|
| 82 | begin
 | 
|---|
| 83 |   Result := AVST.AddChild(ANode);
 | 
|---|
| 84 |   Data   := AVST.GetNodeData(Result);
 | 
|---|
| 85 |   AVST.ValidateNode(Result, False);
 | 
|---|
| 86 |   Data^ := ARecord;
 | 
|---|
| 87 | end;
 | 
|---|
| 88 | 
 | 
|---|
| 89 | 
 | 
|---|
| 90 | procedure TForm_Meta.NewCon(ID: Integer);
 | 
|---|
| 91 | begin
 | 
|---|
| 92 |   if ID >= 0 then
 | 
|---|
| 93 |     SetRoot(ConManager.Connection[FConnectionID].MetaData.Root);
 | 
|---|
| 94 | //SetRoot(ConManager.Connection[FConnectionID].MetaData.FileById[454]);
 | 
|---|
| 95 | end;
 | 
|---|
| 96 | 
 | 
|---|
| 97 | 
 | 
|---|
| 98 | procedure TForm_Meta.SetRoot(TreeElem: TTreeElement);
 | 
|---|
| 99 | var
 | 
|---|
| 100 |   i: Integer;
 | 
|---|
| 101 |   data: TNodeData;
 | 
|---|
| 102 |   node: PVirtualNode;
 | 
|---|
| 103 | begin
 | 
|---|
| 104 |   if FConnectionID <> TreeElem.ConnectionID then
 | 
|---|
| 105 |     SelectConnection(TreeElem.ConnectionID);
 | 
|---|
| 106 |   root := TreeElem;
 | 
|---|
| 107 |   VST.Clear;
 | 
|---|
| 108 |   VST.BeginUpdate;
 | 
|---|
| 109 |   for i := 0 to root.ChildCount - 1 do
 | 
|---|
| 110 |   begin
 | 
|---|
| 111 |     data.Field := root.Child[i];
 | 
|---|
| 112 |     node := AddVSTEntry(VST, nil, data);
 | 
|---|
| 113 |     if data.Field.ChildCount > 0 then
 | 
|---|
| 114 |       VST.HasChildren[node] := True;
 | 
|---|
| 115 |   end;
 | 
|---|
| 116 |   VST.EndUpdate;
 | 
|---|
| 117 | end;
 | 
|---|
| 118 | 
 | 
|---|
| 119 | procedure TForm_Meta.VSTInitChildren(Sender: TBaseVirtualTree;
 | 
|---|
| 120 |   Node: PVirtualNode; var ChildCount: Cardinal);
 | 
|---|
| 121 | var
 | 
|---|
| 122 |   data: PNodeData;
 | 
|---|
| 123 |   newdata: TNodeData;
 | 
|---|
| 124 |   newnode: PVirtualNode;
 | 
|---|
| 125 |   i: Integer;
 | 
|---|
| 126 | begin
 | 
|---|
| 127 |   data := Sender.GetNodeData(node);
 | 
|---|
| 128 | 
 | 
|---|
| 129 |   if data.Field.ChildCount > 0 then
 | 
|---|
| 130 |   begin
 | 
|---|
| 131 |     for i := 0 to data.Field.ChildCount - 1 do
 | 
|---|
| 132 |     begin
 | 
|---|
| 133 |       newdata.Field := data.Field.Child[i];
 | 
|---|
| 134 |       newnode := AddVSTEntry(TCustomVirtualStringTree(Sender), Node, newdata);
 | 
|---|
| 135 |       if newdata.Field.ChildCount > 0 then
 | 
|---|
| 136 |         Sender.HasChildren[newnode] := True;
 | 
|---|
| 137 |     end;
 | 
|---|
| 138 |   end;
 | 
|---|
| 139 |   ChildCount := Sender.ChildCount[Node];
 | 
|---|
| 140 | end;
 | 
|---|
| 141 | 
 | 
|---|
| 142 | 
 | 
|---|
| 143 | 
 | 
|---|
| 144 | procedure TForm_Meta.VSTFocusChanged(Sender: TBaseVirtualTree;
 | 
|---|
| 145 |   Node: PVirtualNode; Column: TColumnIndex);
 | 
|---|
| 146 | var
 | 
|---|
| 147 |   data: PNodeData;
 | 
|---|
| 148 |   ffile: TFile;
 | 
|---|
| 149 | //*******************************************************************
 | 
|---|
| 150 |   fs: TFileStream;
 | 
|---|
| 151 | //*******************************************************************
 | 
|---|
| 152 | begin
 | 
|---|
| 153 |   data := Sender.GetNodeData(Node);
 | 
|---|
| 154 |   ffile := nil;
 | 
|---|
| 155 |   if data.Field is TFile then
 | 
|---|
| 156 |     ffile := TFile(data.Field);
 | 
|---|
| 157 |   if data.Field is _MetaTypes.TDatLink then
 | 
|---|
| 158 |     if Assigned(_MetaTypes.TDatLink(data.Field).TargetFile) then
 | 
|---|
| 159 |       ffile := TFile(_MetaTypes.TDatLink(data.Field).TargetFile);
 | 
|---|
| 160 |   if Assigned(ffile) then
 | 
|---|
| 161 |   begin
 | 
|---|
| 162 |     if Assigned(ffile.Editor) then
 | 
|---|
| 163 |     begin
 | 
|---|
| 164 |       ffile.Editor.Align := alClient;
 | 
|---|
| 165 |       tab_meta.InsertControl(ffile.Editor);
 | 
|---|
| 166 |       ffile.Opened := True;
 | 
|---|
| 167 |     end;
 | 
|---|
| 168 | //*******************************************************************
 | 
|---|
| 169 |     fs := TFileStream.Create('C:\Spiele\Oni\GameDataFolder\tests\'+IntToStr(ffile.FileInfo.ID)+'_recreated.hex', fmCreate);
 | 
|---|
| 170 |     ffile.ReCreateFile(fs);
 | 
|---|
| 171 |     fs.Free;
 | 
|---|
| 172 | //*******************************************************************
 | 
|---|
| 173 |   end;
 | 
|---|
| 174 | end;
 | 
|---|
| 175 | 
 | 
|---|
| 176 | 
 | 
|---|
| 177 | procedure TForm_Meta.VSTFocusChanging(Sender: TBaseVirtualTree; OldNode,
 | 
|---|
| 178 |   NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex;
 | 
|---|
| 179 |   var Allowed: Boolean);
 | 
|---|
| 180 | var
 | 
|---|
| 181 |   data: PNodeData;
 | 
|---|
| 182 |   i: Integer;
 | 
|---|
| 183 | begin
 | 
|---|
| 184 |   data := Sender.GetNodeData(NewNode);
 | 
|---|
| 185 |   if data.Field is TFile then
 | 
|---|
| 186 |   begin
 | 
|---|
| 187 |     if Assigned(TFile(data.Field).Editor) then
 | 
|---|
| 188 |       Allowed := not TFile(data.Field).Opened
 | 
|---|
| 189 |     else
 | 
|---|
| 190 |       Allowed := True;
 | 
|---|
| 191 |   end;
 | 
|---|
| 192 |   if Allowed and Assigned(OldNode) then
 | 
|---|
| 193 |   begin
 | 
|---|
| 194 |     data := Sender.GetNodeData(OldNode);
 | 
|---|
| 195 |     if data.Field is TFile then
 | 
|---|
| 196 |     begin
 | 
|---|
| 197 |       if TFile(data.Field).Opened then
 | 
|---|
| 198 |       begin
 | 
|---|
| 199 |         if tab_meta.ControlCount > 0 then
 | 
|---|
| 200 |           for i := 0 to tab_meta.ControlCount - 1 do
 | 
|---|
| 201 |             tab_meta.RemoveControl(tab_meta.Controls[i]);
 | 
|---|
| 202 |         TFile(data.Field).Opened := False;
 | 
|---|
| 203 |       end;
 | 
|---|
| 204 |     end;
 | 
|---|
| 205 |   end;
 | 
|---|
| 206 | end;
 | 
|---|
| 207 | 
 | 
|---|
| 208 | 
 | 
|---|
| 209 | procedure TForm_Meta.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
 | 
|---|
| 210 |   Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
 | 
|---|
| 211 | var
 | 
|---|
| 212 |   Data: PNodeData;
 | 
|---|
| 213 | begin
 | 
|---|
| 214 |   Data     := Sender.GetNodeData(Node);
 | 
|---|
| 215 |   CellText := '';
 | 
|---|
| 216 |   if TextType = ttNormal then
 | 
|---|
| 217 |   begin
 | 
|---|
| 218 |     case Column of
 | 
|---|
| 219 |       0: CellText := Data.Field.Caption;
 | 
|---|
| 220 |       1: CellText := data.Field.VType;
 | 
|---|
| 221 |       2:
 | 
|---|
| 222 |         begin
 | 
|---|
| 223 |           if Data.Field is TDataField then
 | 
|---|
| 224 |             CellText := TDataField(Data.Field).ValueAsString;
 | 
|---|
| 225 |         end;
 | 
|---|
| 226 |     end;
 | 
|---|
| 227 |   end;
 | 
|---|
| 228 | end;
 | 
|---|
| 229 | 
 | 
|---|
| 230 | 
 | 
|---|
| 231 | procedure TForm_Meta.VSTPaintText(Sender: TBaseVirtualTree;
 | 
|---|
| 232 |   const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
 | 
|---|
| 233 |   TextType: TVSTTextType);
 | 
|---|
| 234 | var
 | 
|---|
| 235 |   Data: PNodeData;
 | 
|---|
| 236 | begin
 | 
|---|
| 237 |   Data     := Sender.GetNodeData(Node);
 | 
|---|
| 238 |   if TextType = ttNormal then
 | 
|---|
| 239 |   begin
 | 
|---|
| 240 |     case Column of
 | 
|---|
| 241 |       0:
 | 
|---|
| 242 |         begin
 | 
|---|
| 243 |           if Data.Field is TFile then
 | 
|---|
| 244 |           begin
 | 
|---|
| 245 |             if Length(TFile(Data.Field).FileInfo.Name) = 0 then
 | 
|---|
| 246 |               TargetCanvas.Font.Color := $C06060;
 | 
|---|
| 247 |             if TFile(Data.Field).FileInfo.Size = 0 then
 | 
|---|
| 248 |               TargetCanvas.Font.Color := $2020A0;
 | 
|---|
| 249 |           end;
 | 
|---|
| 250 |         end;
 | 
|---|
| 251 |     end;
 | 
|---|
| 252 |   end;
 | 
|---|
| 253 | end;
 | 
|---|
| 254 | 
 | 
|---|
| 255 | 
 | 
|---|
| 256 | 
 | 
|---|
| 257 | procedure TForm_Meta.VSTGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode;
 | 
|---|
| 258 |   Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle;
 | 
|---|
| 259 |   var HintText: WideString);
 | 
|---|
| 260 | var
 | 
|---|
| 261 |   data: PNodeData;
 | 
|---|
| 262 |   CellText: WideString;
 | 
|---|
| 263 | 
 | 
|---|
| 264 |   i: Integer;
 | 
|---|
| 265 |   links: TStrings;
 | 
|---|
| 266 | begin
 | 
|---|
| 267 |   inherited;
 | 
|---|
| 268 |   if Assigned(Node) then
 | 
|---|
| 269 |   begin
 | 
|---|
| 270 |     VSTGetText(Sender, Node, Column, ttNormal, CellText);
 | 
|---|
| 271 |     if Length(CellText) > 0 then
 | 
|---|
| 272 |     begin
 | 
|---|
| 273 |       data := Sender.GetNodeData(Node);
 | 
|---|
| 274 |       if data.Field is TDataField then
 | 
|---|
| 275 |       begin
 | 
|---|
| 276 |         case Column of
 | 
|---|
| 277 |           0,1: HintText := TDataField(data.Field).Description;
 | 
|---|
| 278 |           2: HintText := '';
 | 
|---|
| 279 |         end;
 | 
|---|
| 280 |       end;
 | 
|---|
| 281 |       if (data.Field is _MetaTypes.TDatLink) and (Column = 2) then
 | 
|---|
| 282 |       begin
 | 
|---|
| 283 |         links := nil;
 | 
|---|
| 284 |         links := ConManager.Connection[FConnectionID].GetFilesList(_MetaTypes.TDatLink(data.Field).PosExts, '', False, ST_NameAsc);
 | 
|---|
| 285 |         HintText := IntToStr(links.Count);
 | 
|---|
| 286 |         for i := 0 to Min(links.Count - 1, 99) do
 | 
|---|
| 287 |         begin
 | 
|---|
| 288 |           if (i mod 5) = 0 then
 | 
|---|
| 289 |             HintText := HintText + #13+#10;
 | 
|---|
| 290 |           HintText := HintText + links.Strings[i] + '       ';
 | 
|---|
| 291 |         end;
 | 
|---|
| 292 |       end;
 | 
|---|
| 293 |     end;
 | 
|---|
| 294 |   end
 | 
|---|
| 295 |   else
 | 
|---|
| 296 |     HintText := '';
 | 
|---|
| 297 | end;
 | 
|---|
| 298 | 
 | 
|---|
| 299 | procedure TForm_Meta.VSTGetPopupMenu(Sender: TBaseVirtualTree;
 | 
|---|
| 300 |   Node: PVirtualNode; Column: TColumnIndex; const P: TPoint;
 | 
|---|
| 301 |   var AskParent: Boolean; var PopupMenu: TPopupMenu);
 | 
|---|
| 302 | var
 | 
|---|
| 303 |   data: PNodeData;
 | 
|---|
| 304 | begin
 | 
|---|
| 305 |   inherited;
 | 
|---|
| 306 |   AskParent := False;
 | 
|---|
| 307 |   if Assigned(Node) then
 | 
|---|
| 308 |   begin
 | 
|---|
| 309 |     Sender.Selected[Node] := True;
 | 
|---|
| 310 |     Sender.FocusedNode := Node;
 | 
|---|
| 311 |     data := Sender.GetNodeData(Node);
 | 
|---|
| 312 |     if Column = 0 then
 | 
|---|
| 313 |     begin
 | 
|---|
| 314 |       if TTreeElement(data.Field).ChildCount > 0 then
 | 
|---|
| 315 |         PopupMenu := vst_popup
 | 
|---|
| 316 |       else
 | 
|---|
| 317 |         PopupMenu := nil;
 | 
|---|
| 318 |     end;
 | 
|---|
| 319 |   end;
 | 
|---|
| 320 | end;
 | 
|---|
| 321 | 
 | 
|---|
| 322 | procedure TForm_Meta.vst_newRootClick(Sender: TObject);
 | 
|---|
| 323 | var
 | 
|---|
| 324 |   data: PNodeData;
 | 
|---|
| 325 |   form: TForm_BaseTemplate;
 | 
|---|
| 326 | begin
 | 
|---|
| 327 |   inherited;
 | 
|---|
| 328 |   data := VST.GetNodeData(VST.FocusedNode);
 | 
|---|
| 329 |   form := nil;
 | 
|---|
| 330 |   form := Form_Main.open_child('meta');
 | 
|---|
| 331 |   if form is TForm_Meta then
 | 
|---|
| 332 |     TForm_Meta(form).SetRoot(data.Field);
 | 
|---|
| 333 | end;
 | 
|---|
| 334 | 
 | 
|---|
| 335 | procedure TForm_Meta.vst_setRootClick(Sender: TObject);
 | 
|---|
| 336 | var
 | 
|---|
| 337 |   data: PNodeData;
 | 
|---|
| 338 | begin
 | 
|---|
| 339 |   inherited;
 | 
|---|
| 340 |   data := VST.GetNodeData(VST.FocusedNode);
 | 
|---|
| 341 |   SetRoot(data.Field);
 | 
|---|
| 342 | end;
 | 
|---|
| 343 | 
 | 
|---|
| 344 | procedure TForm_Meta.FormClose(Sender: TObject; var Action: TCloseAction);
 | 
|---|
| 345 | begin
 | 
|---|
| 346 | //  Meta.Free;
 | 
|---|
| 347 |   inherited;
 | 
|---|
| 348 | end;
 | 
|---|
| 349 | 
 | 
|---|
| 350 | procedure TForm_Meta.FormCreate(Sender: TObject);
 | 
|---|
| 351 | begin
 | 
|---|
| 352 |   inherited;
 | 
|---|
| 353 |   OnNewConnection := NewCon;
 | 
|---|
| 354 | 
 | 
|---|
| 355 |   VST.NodeDataSize := SizeOf(TNodeData);
 | 
|---|
| 356 |   VST.Font.Charset := AppSettings.CharSet;
 | 
|---|
| 357 |   VST.Clear;
 | 
|---|
| 358 | 
 | 
|---|
| 359 |   UpdateConList;
 | 
|---|
| 360 | end;
 | 
|---|
| 361 | 
 | 
|---|
| 362 | end.
 | 
|---|