unit Main; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, StrUtils, Clipbrd, ExtCtrls, ComCtrls, Menus, Grids, MPHexEditor, ToolWin, ImgList, Tabs, MDITab, TB2Item, TB2Dock, TB2Toolbar, TB2MDI, OneInst, Data, Functions, DataStructures, OniDataClass, Exporters, Helper_LevelDB, Settings, Template, BinEdit, Extractor, Preview, RawEdit, TxmpReplace; type TForm_Main = class(TForm) saved: TSaveDialog; opend: TOpenDialog; statbar: TStatusBar; MenuImages: TImageList; DockTop: TTBDock; MainMenu: TTBToolbar; menu_main: TTBSubmenuItem; menu_loadfile: TTBItem; menu_sep1: TTBSeparatorItem; menu_settings: TTBItem; menu_sep4: TTBSeparatorItem; menu_exit: TTBItem; menu_convert: TTBSubmenuItem; menu_createdb: TTBItem; menu_createlvl: TTBItem; menu_tools: TTBSubmenuItem; menu_preview: TTBItem; menu_binedit: TTBItem; menu_rawedit: TTBItem; menu_txmpreplace: TTBItem; menu_extractor: TTBItem; menu_filecompare: TTBItem; menu_levelstructedit: TTBItem; menu_windows: TTBSubmenuItem; menu_windows_cascade: TTBItem; menu_windows_tile: TTBItem; menu_windows_closeall: TTBItem; menu_sep3: TTBSeparatorItem; menu_windows_next: TTBItem; menu_windows_previous: TTBItem; menu_sep2: TTBSeparatorItem; menu_About: TTBItem; Toolbar: TTBToolbar; tbOpen: TTBItem; DockLeft: TTBDock; DockRight: TTBDock; DockBottom: TTBDock; MDIToolbar: TTBToolbar; TBControlItem1: TTBControlItem; MDITab: TMDITab; menu_view: TTBSubmenuItem; menu_view_mdibar: TTBItem; menu_view_statusbar: TTBItem; menu_view_toolbar: TTBItem; tb_separator1: TTBSeparatorItem; tb_preview: TTBItem; tb_structure: TTBItem; tb_compare: TTBItem; tb_extractor: TTBItem; tb_txmpreplacer: TTBItem; tb_rawedit: TTBItem; tb_datedit: TTBItem; menu_windows_tilevert: TTBItem; tb_meta: TTBItem; menu_meta: TTBItem; TBSeparatorItem1: TTBSeparatorItem; tb_db2dat: TTBItem; tb_dat2db: TTBItem; menu_loaddb: TTBItem; tb_opendb: TTBItem; Images_Close: TImageList; menu_conns: TTBSubmenuItem; procedure UpdateConLists; procedure LoadFile(typedb: Boolean); function TryCloseAll: Boolean; procedure menu_AboutClick(Sender: TObject); procedure menu_settingsClick(Sender: TObject); procedure menu_filecompareClick(Sender: TObject); procedure menu_raweditClick(Sender: TObject); procedure menu_createlvlClick(Sender: TObject); procedure menu_extractorClick(Sender: TObject); procedure menu_createdbClick(Sender: TObject); procedure menu_windows_previousClick(Sender: TObject); procedure menu_windows_nextClick(Sender: TObject); procedure menu_windows_tileClick(Sender: TObject); function open_child(window_context: String; connection: TOniData; fileid: Integer): TForm_ToolTemplate; procedure menu_windows_closeallClick(Sender: TObject); procedure menu_windows_cascadeClick(Sender: TObject); procedure menu_bineditClick(Sender: TObject); procedure menu_loadfileClick(Sender: TObject); procedure menu_txmpreplaceClick(Sender: TObject); procedure menu_exitClick(Sender: TObject); procedure menu_previewClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormResize(Sender: TObject); procedure FormCreate(Sender: TObject); procedure UpdateStatBar; procedure menu_view_mdibarClick(Sender: TObject); procedure menu_view_statusbarClick(Sender: TObject); procedure menu_view_toolbarClick(Sender: TObject); procedure menu_conns_itemClick(Sender: TObject); procedure MDITabDrawTab(Control: TCustomTabControl; TabIndex: Integer; const Rect: TRect; Active: Boolean); procedure ActivateTools(active: Boolean); procedure MDITabMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure menu_windows_tilevertClick(Sender: TObject); procedure menu_metaClick(Sender: TObject); procedure ToolbarDockChanged(Sender: TObject); procedure menu_loaddbClick(Sender: TObject); procedure MDITabMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA; public procedure DefaultHandler(var Message); override; public end; var Form_Main: TForm_Main; implementation {$R *.dfm} { Eine zweite Instanz hat uns ihre Kommandozeilenparameter geschickt } procedure TForm_Main.WMCopyData(var Msg: TWMCopyData); var strings: TStringList; begin if (Msg.CopyDataStruct.dwData = SecondInstMsgId) and (SecondInstMsgId <> 0) then begin Application.BringToFront; strings := TStringList.Create; strings.Text := ParamBlobToStr(Msg.CopyDataStruct.lpData); if strings.Count = 2 then begin if strings.Strings[0] = 'opf' then begin ShowMessage('Load OPF-File: ' + ParamStr(2)); end else if strings.Strings[0] = 'oldb' then begin if CreateDataConnection(strings.Strings[1], ODB_ADB) = nil then ShowMessage('Error while loading the file:' + CrLf + strings.Strings[1] + CrLf + 'Perhaps not an OniUnPacker-LevelDatabase-file?'); end else if strings.Strings[0] = 'dat' then begin if CreateDataConnection(strings.Strings[1], ODB_Dat) = nil then ShowMessage('Error while loading the file:' + CrLf + strings.Strings[1] + CrLf + 'Perhaps not an Oni-.dat-file?'); end; UpdateStatBar; UpdateConLists; end; end else inherited; end; {----------------------------------------------------------------------------} { Wir überschreiben den DefaultHandler, der alle Nachrichten zuerst bekommt, } { damit wir auf die Nachricht mit der ID SecondInstMsgId reagieren können. } { (Dies ist notwendig, da wir jetzt noch nicht wissen welchen Wert } { die ID haben wird, weswegen wir keine statische Message-Prozedure, } { so wie bei WM_COPYDATA, schreiben können.) } {----------------------------------------------------------------------------} procedure TForm_Main.DefaultHandler(var Message); begin if TMessage(Message).Msg = SecondInstMsgId then { Eine zweite Instanz hat uns nach dem Handle gefragt } { Es wird in die Message-Queue des Threads gepostet. } PostThreadMessage(TMessage(Message).WParam, SecondInstMsgId, Handle, 0) else inherited; end; procedure TForm_Main.FormCreate(Sender: TObject); begin Self.Caption := 'Oni Un/Packer ' + version; Self.FormResize(Self); if FileExists(ExtractFilepath(Application.EXEname) + '\oniunpacker.ini') then begin AssignFile(AppSettingsFile, ExtractFilepath(Application.EXEname) + '\oniunpacker.ini'); Reset(AppSettingsFile); Read(AppSettingsFile, AppSettings); CloseFile(AppSettingsFile); end else begin AppSettings.DatPath := 'D:\Spiele\Oni\GameDataFolder'; AppSettings.ExtractPath := 'C:\Dokumente und Einstellungen\Administrator\Desktop'; AppSettings.FilenumbersAsHex := False; AppSettings.CharSet := DEFAULT_CHARSET; AppSettings.HideUnusedData := False; end; if MidStr(ParamStr(1), 1, 3) = 'opf' then begin ShowMessage('Load OPF-File: ' + ParamStr(2)); end else if MidStr(ParamStr(1), 1, 4) = 'oldb' then begin if CreateDataConnection(ParamStr(2), ODB_ADB) = nil then ShowMessage('Error while loading the file:' + CrLf + ParamStr( 2) + CrLf + 'Perhaps not an OniUnPacker-LevelDatabase-file?'); end else if MidStr(ParamStr(1), 1, 3) = 'dat' then begin if CreateDataConnection(ParamStr(2), ODB_Dat) = nil then ShowMessage('Error while loading the file:' + CrLf + ParamStr( 2) + CrLf + 'Perhaps not an Oni-.dat-file?'); end; UpdateStatBar; UpdateConLists; end; procedure TForm_Main.FormResize(Sender: TObject); const MinWidth: Integer = 750; MinHeight: Integer = 500; begin if Self.Width < MinWidth then Self.Width := MinWidth; if Self.Height < MinHeight then Self.Height := MinHeight; statbar.Panels.Items[0].Width := Self.Width - 200; MDITab.Width := Self.Width - 20; end; procedure TForm_Main.MDITabDrawTab(Control: TCustomTabControl; TabIndex: Integer; const Rect: TRect; Active: Boolean); var x, y: Integer; iconindex: Integer; caption: String; begin iconindex := TMDITab(Control).Glyphs[TabIndex]; caption := TMDITab(Control).Captions[TabIndex]; if active then begin Control.Canvas.Font.Style := Control.Canvas.Font.Style + [fsItalic]; y := Rect.Top + 1; end else y := Rect.Top; if iconindex >= 0 then begin TMDITab(Control).Images.Draw(Control.Canvas, Rect.Left + 4, y, iconindex); x := Rect.Left + 26; end else x := Rect.Left + 4; Control.Canvas.TextOut(x, y + 2, caption); if active then Images_Close.Draw(Control.Canvas, Rect.Right - 18, y, 0) else Images_Close.Draw(Control.Canvas, Rect.Right - 18, y, 1); end; procedure TForm_Main.MDITabMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var pt: TPoint; tabIndex: Integer; hint: String; begin pt.X := X; pt.Y := Y; tabIndex := MDITab.GetTabAtPos(pt); hint := ''; if tabIndex >= 0 then begin if MDITab.MDIChildren[tabIndex] is TForm_ToolTemplate then begin if TForm_ToolTemplate(MDITab.MDIChildren[tabIndex]).Connection <> nil then hint := 'Connection: ' + ExtractFileName(TForm_ToolTemplate(MDITab.MDIChildren[tabIndex]).Connection.FileName) + #13+#10 else hint := 'Connection: none' + #13+#10; if TForm_ToolTemplate(MDITab.MDIChildren[tabIndex]).SelectedFile.ID >= 0 then hint := hint + 'Selected File: ' + TForm_ToolTemplate(MDITab.MDIChildren[tabIndex]).SelectedFile.FileName else hint := hint + 'Selected File: none'; end else hint := 'Window: ' + MDITab.MDIChildren[tabIndex].Caption; if hint <> MDITab.Hint then begin MDITab.Hint := hint; MDITab.ShowHint := True; end; end else begin MDITab.ShowHint := False; MDITab.Hint := ''; end; end; procedure TForm_Main.MDITabMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var pt: TPoint; tabIndex: Integer; tabRect: TRect; tabX, tabY, tabWidth: Integer; begin pt.X := X; pt.Y := Y; tabIndex := MDITab.GetTabAtPos(pt); // if (Button = mbRight) and (tabIndex >= 0) then // MDITab.MDIChildren[tabIndex].Close; if (Button = mbLeft) and (tabIndex >= 0) then begin tabrect := MDITab.TabRect(tabIndex); tabX := X - tabrect.Left; tabY := Y - tabrect.Top; tabwidth := tabrect.Right - tabrect.Left; if (tabY >= 4) and (tabY <= 17) then if (tabX >= tabwidth - 19) and (tabX <= tabwidth - 7) then MDITab.MDIChildren[tabIndex].Close; end; end; procedure TForm_Main.FormClose(Sender: TObject; var Action: TCloseAction); begin AssignFile(AppSettingsFile, ExtractFilepath(Application.EXEname) + '\oniunpacker.ini'); if FileExists(ExtractFilepath(Application.EXEname) + '\oniunpacker.ini') then Reset(AppSettingsFile) else Rewrite(AppSettingsFile); Write(AppSettingsFile, AppSettings); CloseFile(AppSettingsFile); Action := caFree; end; procedure TForm_Main.ActivateTools(active: Boolean); begin menu_tools.Enabled := active; tb_preview.Enabled := active; tb_datedit.Enabled := active; tb_rawedit.Enabled := active; tb_txmpreplacer.Enabled := active; tb_extractor.Enabled := active; // tb_compare.Enabled := active; // tb_structure.Enabled := active; end; procedure TForm_Main.UpdateStatBar; begin if Length(DataConnections) > 0 then begin Self.Caption := 'Oni Un/Packer ' + version; ActivateTools(True); statbar.Panels.Items[1].Text := 'Connections: ' + IntToStr(Length(DataConnections)); end else begin Self.Caption := 'Oni Un/Packer ' + version; statbar.Panels.Items[0].Text := ''; statbar.Panels.Items[1].Text := 'Connections: -'; statbar.Panels.Items[2].Text := ''; ActivateTools(False); end; menu_conns.Enabled := Length(DataConnections) > 0; end; procedure TForm_Main.ToolbarDockChanged(Sender: TObject); var toolbar: TTBToolbar; position: TTBDockPosition; mode: TTBItemDisplayMode; i: Integer; isEnabled: Boolean; begin toolbar := TTBToolbar(Sender); if toolbar.Floating then mode := nbdmImageAndText else begin position := toolbar.CurrentDock.Position; if position in [dpLeft, dpRight] then mode := nbdmDefault else mode := nbdmImageAndText; end; for i := 0 to toolbar.Items.Count - 1 do toolbar.Items.Items[i].DisplayMode := mode; end; function TForm_Main.TryCloseAll: Boolean; begin menu_windows_closeallClick(Self); Application.ProcessMessages; if MDITab.MDIChildCount = 0 then Result := True else Result := False; end; procedure TForm_Main.menu_conns_itemClick(Sender: TObject); var name: String; i: Integer; begin name := TTBItem(Sender).Caption; if MessageBox(Handle, PChar('Do you really want to close data-connection to' +#13+#10+ name + '?'), PChar('Close?'), MB_YESNO + MB_ICONQUESTION) = ID_YES then begin for i := 0 to High(DataConnections) do if ExtractFileName(DataConnections[i].FileName) = name then begin CloseDataConnection(DataConnections[i]); Break; end; end; UpdateStatBar; UpdateConLists; end; procedure TForm_Main.UpdateConLists; var i: Integer; entry: TTBItem; begin if MDITab.MDIChildCount > 0 then for i := 0 to MDITab.MDIChildCount - 1 do if MDITab.MDIChildren[i] is TForm_ToolTemplate then TForm_ToolTemplate(MDITab.MDIChildren[i]).UpdateList; menu_conns.Clear; if Length(DataConnections) > 0 then begin for i := 0 to High(DataConnections) do begin entry := TTBItem.Create(menu_conns); entry.Caption := ExtractFileName(DataConnections[i].FileName); entry.Name := 'menu_conn_' + IntToStr(i); entry.OnClick := menu_conns_itemClick; menu_conns.Add(entry); entry := nil; end; end; end; procedure TForm_Main.LoadFile(typedb: Boolean); var ext: String; begin opend.InitialDir := AppSettings.DatPath; opend.Filter := 'Compatible level files|*.dat;*.oldb|Oni level (*.dat)|*.dat|OUP level database (*.oldb)|*.oldb|Any (*.*)|*'; if typedb then opend.FilterIndex := 3 else opend.FilterIndex := 2; if opend.Execute then begin ext := ExtractFileExt(opend.FileName); if ext = '.dat' then begin if CreateDataConnection(opend.FileName, ODB_Dat) <> nil then UpdateConLists; end else if ext = '.oldb' then begin if CreateDataConnection(opend.FileName, ODB_ADB) <> nil then UpdateConLists; end else ShowMessage('Incompatible file'); AppSettings.DatPath := ExtractFilepath(opend.FileName); end; UpdateStatBar; end; {#################################} {##### Main-Menu-Handlers #####} {#################################} procedure TForm_Main.menu_loaddbClick(Sender: TObject); begin LoadFile(True); end; procedure TForm_Main.menu_loadfileClick(Sender: TObject); begin LoadFile(False); end; procedure TForm_Main.menu_settingsClick(Sender: TObject); begin Form_Settings.Visible := True; Self.Enabled := False; end; procedure TForm_Main.menu_exitClick(Sender: TObject); begin Self.Close; end; {####################################} {##### Converters-Menu-Handlers #####} {####################################} procedure TForm_Main.menu_createdbClick(Sender: TObject); begin ShowMessage('Not yet usable'); { opend.Filter := 'Oni-Dat-Files|*.dat'; saved.Filter := 'OUP-Level-DB (*.oldb)|*.oldb'; saved.DefaultExt := 'oldb'; if opend.Execute then if saved.Execute then Form_LevelDB.CreateDatabase(opend.FileName, saved.FileName); } end; procedure TForm_Main.menu_createlvlClick(Sender: TObject); begin ShowMessage('Not yet usable'); { opend.Filter := 'OUP-Level-DB (*.oldb)|*.oldb'; saved.Filter := 'Oni-Dat-Files|*.dat'; saved.DefaultExt := 'dat'; if opend.Execute then if saved.Execute then Form_LevelDB.CreateLevel(opend.FileName, saved.FileName); } end; {#################################} {##### Tools-Menu-Handlers #####} {#################################} procedure TForm_Main.menu_previewClick(Sender: TObject); begin open_child('preview', nil, -1); end; procedure TForm_Main.menu_txmpreplaceClick(Sender: TObject); begin open_child('txmpreplace', nil, -1); end; procedure TForm_Main.menu_bineditClick(Sender: TObject); begin open_child('binedit', nil, -1); end; procedure TForm_Main.menu_raweditClick(Sender: TObject); begin open_child('rawedit', nil, -1); end; procedure TForm_Main.menu_extractorClick(Sender: TObject); begin open_child('extractor', nil, -1); end; procedure TForm_Main.menu_metaClick(Sender: TObject); begin ShowMessage('TBD'); end; procedure TForm_Main.menu_filecompareClick(Sender: TObject); begin open_child('compare', nil, -1); end; {#################################} {##### View-Menu-Handlers #####} {#################################} procedure TForm_Main.menu_view_mdibarClick(Sender: TObject); begin menu_view_mdibar.Checked := not menu_view_mdibar.Checked; mditoolbar.Visible := menu_view_mdibar.Checked; end; procedure TForm_Main.menu_view_statusbarClick(Sender: TObject); begin menu_view_statusbar.Checked := not menu_view_statusbar.Checked; statbar.Visible := menu_view_statusbar.Checked; end; procedure TForm_Main.menu_view_toolbarClick(Sender: TObject); begin menu_view_toolbar.Checked := not menu_view_toolbar.Checked; Toolbar.Visible := menu_view_toolbar.Checked; end; {#################################} {##### Window-Menu-Handlers #####} {#################################} procedure TForm_Main.menu_windows_cascadeClick(Sender: TObject); begin Self.Cascade; end; procedure TForm_Main.menu_windows_tileClick(Sender: TObject); begin Self.TileMode := tbHorizontal; Self.Tile; end; procedure TForm_Main.menu_windows_tilevertClick(Sender: TObject); begin Self.TileMode := tbVertical; Self.Tile; end; procedure TForm_Main.menu_windows_closeallClick(Sender: TObject); begin MDITab.CloseAll; end; procedure TForm_Main.menu_windows_nextClick(Sender: TObject); begin if MDIChildCount > 1 then if MDITab.TabIndex = MDITab.MDIChildCount - 1 then MDITab.MDIChildren[0].BringToFront else MDITab.MDIChildren[MDITab.TabIndex + 1].BringToFront; end; procedure TForm_Main.menu_windows_previousClick(Sender: TObject); begin if MDIChildCount > 1 then if MDITab.TabIndex = 0 then MDITab.MDIChildren[MDITab.MDIChildCount - 1].BringToFront else MDITab.MDIChildren[MDITab.TabIndex - 1].BringToFront; end; procedure TForm_Main.menu_AboutClick(Sender: TObject); begin ShowMessage('Will be implemented later ;)'); end; function TForm_Main.open_child(window_context: String; connection: TOniData; fileid: Integer): TForm_ToolTemplate; var toolform: TForm_ToolTemplate; i: Integer; tag: Integer; caption_end: String; iconindex: Integer; begin Result := nil; tag := 1; if MDIChildCount > 0 then for i := 0 to MDIChildCount - 1 do if MDIChildren[i].Tag >= tag then tag := MDIChildren[i].Tag + 1; iconindex := -1; caption_end := IntToStr(tag) + ' '; if window_context = 'binedit' then begin toolform := TForm_BinEdit.Create(Self); toolform.Caption := 'Binary .dat-Editor ' + caption_end; iconindex := 5; end; if window_context = 'extractor' then begin toolform := TForm_Extractor.Create(Self); toolform.Caption := 'Extractor ' + caption_end; iconindex := 8; end; if window_context = 'preview' then begin toolform := TForm_Preview.Create(Self); toolform.Caption := 'Preview-Window ' + caption_end; iconindex := 4; end; if window_context = 'rawedit' then begin toolform := TForm_RawEdit.Create(Self); toolform.Caption := 'Binary .raw-Editor ' + caption_end; iconindex := 6; end; if window_context = 'txmpreplace' then begin toolform := TForm_TxmpReplace.Create(Application); toolform.Caption := 'TXMP Replacer ' + caption_end; iconindex := 7; end; if Assigned(toolform) then begin toolform.Name := window_context + IntToStr(tag); toolform.Tag := tag; MDITab.AddTab(TForm(toolform), iconindex); toolform.Caption := AnsiReplaceStr(toolform.Caption, ' ', ''); if (fileid > -1) and (connection <> nil) then begin toolform.SelectFileID(connection, fileid); end; Result := toolform; end; end; end.