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 |
basenode: PVirtualNode; |
104 |
begin |
105 |
if FConnectionID <> TreeElem.ConnectionID then |
106 |
SelectConnection(TreeElem.ConnectionID); |
107 |
root := TreeElem; |
108 |
VST.Clear; |
109 |
VST.BeginUpdate; |
110 |
data.Field := root; |
111 |
basenode := AddVSTEntry(VST, nil, data); |
112 |
for i := 0 to root.ChildCount - 1 do |
113 |
begin |
114 |
data.Field := root.Child[i]; |
115 |
node := AddVSTEntry(VST, basenode, data); |
116 |
if data.Field.ChildCount > 0 then |
117 |
VST.HasChildren[node] := True; |
118 |
end; |
119 |
VST.EndUpdate; |
120 |
end; |
121 |
|
122 |
procedure TForm_Meta.VSTInitChildren(Sender: TBaseVirtualTree; |
123 |
Node: PVirtualNode; var ChildCount: Cardinal); |
124 |
var |
125 |
data: PNodeData; |
126 |
newdata: TNodeData; |
127 |
newnode: PVirtualNode; |
128 |
i: Integer; |
129 |
begin |
130 |
data := Sender.GetNodeData(node); |
131 |
|
132 |
if data.Field.ChildCount > 0 then |
133 |
begin |
134 |
for i := 0 to data.Field.ChildCount - 1 do |
135 |
begin |
136 |
newdata.Field := data.Field.Child[i]; |
137 |
newnode := AddVSTEntry(TCustomVirtualStringTree(Sender), Node, newdata); |
138 |
if newdata.Field.ChildCount > 0 then |
139 |
Sender.HasChildren[newnode] := True; |
140 |
end; |
141 |
end; |
142 |
ChildCount := Sender.ChildCount[Node]; |
143 |
end; |
144 |
|
145 |
|
146 |
|
147 |
procedure TForm_Meta.VSTFocusChanged(Sender: TBaseVirtualTree; |
148 |
Node: PVirtualNode; Column: TColumnIndex); |
149 |
var |
150 |
data: PNodeData; |
151 |
ffile: TResource; |
152 |
//******************************************************************* |
153 |
fs: TFileStream; |
154 |
//******************************************************************* |
155 |
begin |
156 |
data := Sender.GetNodeData(Node); |
157 |
ffile := nil; |
158 |
if data.Field is TResource then |
159 |
ffile := TResource(data.Field); |
160 |
if data.Field is _MetaTypes.TDatLink then |
161 |
if Assigned(_MetaTypes.TDatLink(data.Field).TargetFile) then |
162 |
ffile := TResource(_MetaTypes.TDatLink(data.Field).TargetFile); |
163 |
if Assigned(ffile) then |
164 |
begin |
165 |
if Assigned(ffile.Editor) then |
166 |
begin |
167 |
ffile.Editor.Align := alClient; |
168 |
tab_meta.InsertControl(ffile.Editor); |
169 |
ffile.Opened := True; |
170 |
end; |
171 |
//******************************************************************* |
172 |
// fs := TFileStream.Create('C:\Spiele\Oni\GameDataFolder\tests\'+IntToStr(ffile.FileInfo.ID)+'_recreated.hex', fmCreate); |
173 |
// ffile.ReCreateFile(fs); |
174 |
// fs.Free; |
175 |
//******************************************************************* |
176 |
end; |
177 |
end; |
178 |
|
179 |
|
180 |
procedure TForm_Meta.VSTFocusChanging(Sender: TBaseVirtualTree; OldNode, |
181 |
NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex; |
182 |
var Allowed: Boolean); |
183 |
var |
184 |
data: PNodeData; |
185 |
i: Integer; |
186 |
begin |
187 |
data := Sender.GetNodeData(NewNode); |
188 |
if data.Field is TResource then |
189 |
begin |
190 |
if Assigned(TResource(data.Field).Editor) then |
191 |
Allowed := not TResource(data.Field).Opened |
192 |
else |
193 |
Allowed := True; |
194 |
end; |
195 |
if Allowed and Assigned(OldNode) then |
196 |
begin |
197 |
data := Sender.GetNodeData(OldNode); |
198 |
if data.Field is TResource then |
199 |
begin |
200 |
if TResource(data.Field).Opened then |
201 |
begin |
202 |
if tab_meta.ControlCount > 0 then |
203 |
for i := 0 to tab_meta.ControlCount - 1 do |
204 |
tab_meta.RemoveControl(tab_meta.Controls[i]); |
205 |
TResource(data.Field).Opened := False; |
206 |
end; |
207 |
end; |
208 |
end; |
209 |
end; |
210 |
|
211 |
|
212 |
procedure TForm_Meta.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; |
213 |
Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); |
214 |
var |
215 |
Data: PNodeData; |
216 |
begin |
217 |
Data := Sender.GetNodeData(Node); |
218 |
CellText := ''; |
219 |
if TextType = ttNormal then |
220 |
begin |
221 |
case Column of |
222 |
0: CellText := Data.Field.Caption; |
223 |
1: CellText := data.Field.VType; |
224 |
2: |
225 |
begin |
226 |
if Data.Field is TDataField then |
227 |
CellText := TDataField(Data.Field).ValueAsString; |
228 |
end; |
229 |
end; |
230 |
end; |
231 |
end; |
232 |
|
233 |
|
234 |
procedure TForm_Meta.VSTPaintText(Sender: TBaseVirtualTree; |
235 |
const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; |
236 |
TextType: TVSTTextType); |
237 |
var |
238 |
Data: PNodeData; |
239 |
begin |
240 |
Data := Sender.GetNodeData(Node); |
241 |
if TextType = ttNormal then |
242 |
begin |
243 |
case Column of |
244 |
0: |
245 |
begin |
246 |
if Data.Field is TResource then |
247 |
begin |
248 |
if Length(TResource(Data.Field).FileInfo.Name) = 0 then |
249 |
TargetCanvas.Font.Color := $C06060; |
250 |
if TResource(Data.Field).FileInfo.Size = 0 then |
251 |
TargetCanvas.Font.Color := $2020A0; |
252 |
end; |
253 |
end; |
254 |
end; |
255 |
end; |
256 |
end; |
257 |
|
258 |
|
259 |
|
260 |
procedure TForm_Meta.VSTGetHint(Sender: TBaseVirtualTree; Node: PVirtualNode; |
261 |
Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle; |
262 |
var HintText: WideString); |
263 |
var |
264 |
data: PNodeData; |
265 |
CellText: WideString; |
266 |
|
267 |
i: Integer; |
268 |
links: TStrings; |
269 |
ifile: TResource; |
270 |
begin |
271 |
inherited; |
272 |
if Assigned(Node) then |
273 |
begin |
274 |
VSTGetText(Sender, Node, Column, ttNormal, CellText); |
275 |
if Length(CellText) > 0 then |
276 |
begin |
277 |
data := Sender.GetNodeData(Node); |
278 |
if data.Field is TDataField then |
279 |
begin |
280 |
case Column of |
281 |
0,1: HintText := TDataField(data.Field).Description; |
282 |
2: HintText := ''; |
283 |
end; |
284 |
end; |
285 |
if data.Field is TResource then |
286 |
begin |
287 |
ifile := TResource(data.Field); |
288 |
case Column of |
289 |
0: HintText := |
290 |
'FileID: ' + IntToStr(ifile.FileInfo.ID) + #13#10 + |
291 |
'Name: ' + ifile.FileInfo.Name + #13#10 + |
292 |
'Extension: ' + ifile.FileInfo.Extension + #13#10 + |
293 |
'.dat-size: ' + IntToStr(ifile.FileInfo.Size) + #13#10; |
294 |
end; |
295 |
end; |
296 |
end; |
297 |
end |
298 |
else |
299 |
HintText := ''; |
300 |
end; |
301 |
|
302 |
procedure TForm_Meta.VSTGetPopupMenu(Sender: TBaseVirtualTree; |
303 |
Node: PVirtualNode; Column: TColumnIndex; const P: TPoint; |
304 |
var AskParent: Boolean; var PopupMenu: TPopupMenu); |
305 |
var |
306 |
data: PNodeData; |
307 |
begin |
308 |
inherited; |
309 |
AskParent := False; |
310 |
if Assigned(Node) then |
311 |
begin |
312 |
Sender.Selected[Node] := True; |
313 |
Sender.FocusedNode := Node; |
314 |
data := Sender.GetNodeData(Node); |
315 |
if Column = 0 then |
316 |
begin |
317 |
if TTreeElement(data.Field).ChildCount > 0 then |
318 |
PopupMenu := vst_popup |
319 |
else |
320 |
PopupMenu := nil; |
321 |
end; |
322 |
end; |
323 |
end; |
324 |
|
325 |
procedure TForm_Meta.vst_newRootClick(Sender: TObject); |
326 |
var |
327 |
data: PNodeData; |
328 |
form: TForm_BaseTemplate; |
329 |
begin |
330 |
inherited; |
331 |
data := VST.GetNodeData(VST.FocusedNode); |
332 |
form := nil; |
333 |
form := Form_Main.open_child('meta'); |
334 |
if form is TForm_Meta then |
335 |
TForm_Meta(form).SetRoot(data.Field); |
336 |
end; |
337 |
|
338 |
procedure TForm_Meta.vst_setRootClick(Sender: TObject); |
339 |
var |
340 |
data: PNodeData; |
341 |
begin |
342 |
inherited; |
343 |
data := VST.GetNodeData(VST.FocusedNode); |
344 |
SetRoot(data.Field); |
345 |
end; |
346 |
|
347 |
procedure TForm_Meta.FormClose(Sender: TObject; var Action: TCloseAction); |
348 |
begin |
349 |
// Meta.Free; |
350 |
inherited; |
351 |
end; |
352 |
|
353 |
procedure TForm_Meta.FormCreate(Sender: TObject); |
354 |
begin |
355 |
inherited; |
356 |
OnNewConnection := NewCon; |
357 |
|
358 |
VST.NodeDataSize := SizeOf(TNodeData); |
359 |
VST.Font.Charset := AppSettings.CharSet; |
360 |
VST.Clear; |
361 |
|
362 |
UpdateConList; |
363 |
end; |
364 |
|
365 |
end. |