FPPS4/gui/game_edit.pas

441 lines
7.9 KiB
Plaintext

unit game_edit;
{$mode ObjFPC}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, ExtCtrls,
StdCtrls, Grids,
ms_shell_hack,
game_info,
param_sfo_gui;
type
{ TfrmGameEditor }
TfrmGameEditor = class(TForm)
BtnOk: TButton;
BtnCancel: TButton;
EditPages: TPageControl;
GridMain: TStringGrid;
GridMounts: TStringGrid;
GridParamSfo: TStringGrid;
TabMain: TTabSheet;
TabMounts: TTabSheet;
TabParamSfo: TTabSheet;
procedure BtnOkClick(Sender: TObject);
procedure BtnCancelClick(Sender: TObject);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormInit(UpdateTitle:Boolean);
procedure FormSave;
procedure LoadParamSfo(UpdateTitle:Boolean);
procedure GridSelectEditor(Sender:TObject;aCol,aRow:Integer;var Editor:TWinControl);
procedure GridEditingDone(Sender: TObject);
private
Fapp0_row :Integer;
FName_row :Integer;
FTitleId_row:Integer;
FVersion_row:Integer;
Fapp0p:RawByteString;
public
OnSave :TNotifyEvent;
Item :TGameItem;
ParamSfo:TParamSfoFile;
end;
var
frmGameEditor: TfrmGameEditor;
implementation
{$R *.lfm}
uses
TypInfo,
Rtti;
{ TfrmGameEditor }
type
TFieldInfo=class(TComponent)
procedure SelectEditor(Grid:TStringGrid;aCol,aRow:Integer;var Editor:TWinControl); virtual; abstract;
end;
TFieldInfoPath=class(TFieldInfo)
procedure SelectEditor(Grid:TStringGrid;aCol,aRow:Integer;var Editor:TWinControl); override;
end;
TButtonPath=class(TButton)
public
aRow:Integer;
Form :TWinControl;
Editor:TWinControl;
procedure EditorExit(Sender:TObject);
procedure OpenDir(Sender:TObject);
end;
procedure TButtonPath.EditorExit(Sender:TObject);
begin
Editor.OnEnter:=nil;
Editor.OnExit :=nil;
if not Focused then
begin
Hide;
end;
end;
type
TMyStringGrid=class(TStringGrid)
function NewBtn:TButtonPath;
procedure EditorDirEnter(Sender:TObject);
end;
procedure TButtonPath.OpenDir(Sender:TObject);
var
d:TSelectDirectoryDialog;
Cookie:Pointer;
begin
Cookie:=RegisterDllHack;
d:=nil;
try
d:=TSelectDirectoryDialog.Create(nil);
with TMyStringGrid(Editor.Parent) do
begin
d.InitialDir:=Cells[1,aRow];
end;
d.Options:=[ofPathMustExist,ofEnableSizing,ofViewDetail];
if d.Execute then
with TMyStringGrid(Editor.Parent) do
begin
Cells[1,aRow]:=d.FileName;
end;
except
//
end;
FreeAndNil(d);
UnregisterDllHack(Cookie);
TfrmGameEditor(Self.Form).LoadParamSfo(True);
Hide;
end;
function TMyStringGrid.NewBtn:TButtonPath;
var
i:Integer;
btn:TButtonPath;
begin
btn:=nil;
if (ComponentCount<>0) then
for i:=0 to ComponentCount-1 do
begin
if Components[i] is TButtonPath then
begin
btn:=TButtonPath(Components[i]);
Break;
end;
end;
if (btn=nil) then
begin
btn:=TButtonPath.Create(Self);
btn.Form:=TWinControl(Self.Tag);
btn.AutoSize:=True;
btn.Caption:='...';
btn.Parent:=Self;
btn.BorderSpacing.Top :=-3;
btn.BorderSpacing.Right :=-3;
btn.BorderSpacing.Bottom:=-3;
end;
btn.aRow:=Self.Row;
btn.AnchorSide[akTop].Side:=asrTop;
btn.AnchorSide[akTop].Control:=Editor;
btn.AnchorSide[akRight].Side:=asrBottom;
btn.AnchorSide[akRight].Control:=Editor;
btn.AnchorSide[akBottom].Side:=asrBottom;
btn.AnchorSide[akBottom].Control:=Editor;
btn.Anchors:=[akTop,akRight,akBottom];
btn.Editor:=Editor;
Result:=btn;
end;
procedure TMyStringGrid.EditorDirEnter(Sender:TObject);
var
btn:TButtonPath;
begin
btn:=NewBtn;
btn.OnClick:=@btn.OpenDir;
Editor.OnExit:=@btn.EditorExit;
btn.Show;
end;
procedure TFieldInfoPath.SelectEditor(Grid:TStringGrid;aCol,aRow:Integer;var Editor:TWinControl);
begin
Editor.OnEnter:=@TMyStringGrid(Grid).EditorDirEnter;
end;
procedure AddRow(Grid:TStringGrid;const name,value:RawByteString;info:TFieldInfo);
var
i:Integer;
begin
i:=Grid.RowCount;
Grid.RowCount:=i+1;
Grid.Cells[0,i]:=name;
Grid.Cells[1,i]:=value;
Grid.Objects[0,i]:=info;
end;
procedure TfrmGameEditor.FormInit(UpdateTitle:Boolean);
var
fip:TFieldInfoPath;
i:TRttiPropertyIterator;
p:TRttiProperty;
begin
EditPages.ActivePageIndex:=0;
GridMain.Clear;
GridMounts.Clear;
//TypInfo.SetRawByteStrProp();
//AddRow(GridMain,'Name:',nil);
//
fip:=TFieldInfoPath.Create(Self);
//
i:=Item.FGameInfo.GetPropertyIterator;
try
while (i.GetProperty<>nil) do
begin
p:=i.GetProperty;
case p.Name of
'Name' :FName_row :=GridMain.RowCount;
'TitleId':FTitleId_row:=GridMain.RowCount;
'Version':FVersion_row:=GridMain.RowCount;
else;
end;
AddRow(GridMain,p.Name+':',p.GetValue(Item.FGameInfo).AsString,nil);
i.Next;
end;
finally
i.free;
end;
i:=Item.FMountList.GetPropertyIterator;
try
while (i.GetProperty<>nil) do
begin
p:=i.GetProperty;
case p.Name of
'app0':Fapp0_row:=GridMounts.RowCount;
else;
end;
AddRow(GridMounts,'/'+p.Name,p.GetValue(Item.FMountList).AsString,fip);
i.Next;
end;
finally
i.free;
end;
LoadParamSfo(UpdateTitle);
Show;
end;
procedure TfrmGameEditor.FormSave;
var
i:TRttiPropertyIterator;
p:TRttiProperty;
begin
i:=Item.FGameInfo.GetPropertyIterator;
try
while (i.GetProperty<>nil) do
begin
p:=i.GetProperty;
p.SetValue(Item.FGameInfo,GridMain.Cells[1,i.i]);
i.Next;
end;
finally
i.free;
end;
i:=Item.FMountList.GetPropertyIterator;
try
while (i.GetProperty<>nil) do
begin
p:=i.GetProperty;
p.SetValue(Item.FMountList,GridMounts.Cells[1,i.i]);
i.Next;
end;
finally
i.free;
end;
end;
function GetGridVal(Grid:TStringGrid;ARow:Integer):RawByteString;
begin
Result:='';
if (ARow<0) and (ARow>=Grid.RowCount) then Exit;
//
Result:=Grid.Cells[1,ARow];
end;
procedure SetGridVal(Grid:TStringGrid;ARow:Integer;const value:RawByteString);
begin
if (ARow<0) and (ARow>=Grid.RowCount) then Exit;
//
Grid.Cells[1,ARow]:=value;
end;
procedure TfrmGameEditor.LoadParamSfo(UpdateTitle:Boolean);
var
i:Integer;
V:RawByteString;
begin
V:=GetGridVal(GridMounts,Fapp0_row);
if (Fapp0p=V) then Exit;
FreeAndNil(ParamSfo);
ParamSfo:=LoadParamSfoFile(ExcludeTrailingPathDelimiter(V)+
DirectorySeparator+
'sce_sys'+
DirectorySeparator+
'param.sfo');
Fapp0p:=V;
GridParamSfo.Clear;
if (ParamSfo=nil) then
begin
SetGridVal(GridMain,FTitleId_row,'???');
SetGridVal(GridMain,FVersion_row,'???');
Exit;
end;
if (Length(ParamSfo.params)=0) then Exit;
For i:=0 to High(ParamSfo.params) do
begin
if (ParamSfo.params[i].format=SFO_FORMAT_UINT32) then
begin
V:='0x'+HexStr(ParamSfo.params[i].GetUInt,8);
end else
begin
V:=Trim(ParamSfo.params[i].GetString);
end;
AddRow(GridParamSfo,ParamSfo.params[i].name,V,nil);
end;
GridParamSfo.AutoSizeColumn(0);
//
if not UpdateTitle then Exit;
V:=ParamSfo.GetString('TITLE');
SetGridVal(GridMain,FName_row,V);
V:=ParamSfo.GetString('TITLE_ID');
SetGridVal(GridMain,FTitleId_row,V);
V:=ParamSfo.GetString('APP_VER');
SetGridVal(GridMain,FVersion_row,V);
end;
procedure TfrmGameEditor.GridSelectEditor(Sender:TObject;aCol,aRow:Integer;var Editor:TWinControl);
var
obj:TObject;
begin
obj:=TStringGrid(Sender).Objects[0,aRow];
if (obj=nil) then Exit;
if not obj.InheritsFrom(TFieldInfo) then Exit;
//
TStringGrid(Sender).Tag:=PtrInt(Self);
//
TFieldInfo(obj).SelectEditor(TStringGrid(Sender),aCol,aRow,Editor);
end;
procedure TfrmGameEditor.GridEditingDone(Sender: TObject);
begin
LoadParamSfo(True);
end;
procedure TfrmGameEditor.BtnOkClick(Sender: TObject);
begin
FormSave;
Hide;
if Assigned(OnSave) then
begin
OnSave(Self);
end;
Close;
end;
procedure TfrmGameEditor.BtnCancelClick(Sender: TObject);
begin
Close;
end;
procedure TfrmGameEditor.FormClose(Sender:TObject;var CloseAction:TCloseAction);
begin
if (Item<>nil) then
begin
if Item.FLock then
begin
Item.FLock:=False;
end else
begin
FreeAndNil(Item);
end;
end;
//
FreeAndNil(ParamSfo);
//
CloseAction:=caFree;
end;
end.