Subversion Repositories plumbers

Rev

Rev 8 | Rev 11 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit Unit1;
  2.  
  3. // TODO: the "folder open" icons look like you can CHOOSE a file, not open it!
  4. //       - change the icon to something else
  5. //       - add open-dialogs for choosing the bmp and wav files
  6. // TODO: Give controls better names
  7. // Idea: When actions are deleted, remove the colorful marking on the picture?
  8. // Idea: decision bitmap markings: anti moiree?
  9. // Idea: unused liste auch bei decision page anzeigen
  10. // Idea: hotspots: netz ziehen anstelle linke und rechts maustaste. netz in jede beliebige richtung ziehen und topleft/bottomright automatisch bestimmen
  11. // Idea: Automatic correct wrong Game.numScenes/numPics values? (especially since we rely on them when adding a scene)
  12. // Idea: "defragmentation": shift all pictures to the left if a scene has a higher "numPics" value than actual pictures
  13.  
  14. interface
  15.  
  16. uses
  17.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  18.   Dialogs, StdCtrls, Spin, Grids, GameBinStruct, ComCtrls, ExtCtrls, MPlayer,
  19.   Menus;
  20.  
  21. const
  22.   CUR_VER = '2017-10-04';
  23.  
  24. type
  25.   TForm1 = class(TForm)
  26.     ListBox1: TListBox;
  27.     Button1: TButton;
  28.     Button2: TButton;
  29.     Button3: TButton;
  30.     Button4: TButton;
  31.     Button5: TButton;
  32.     Button10: TButton;
  33.     PageControl2: TPageControl;
  34.     TabSheet4: TTabSheet;
  35.     Label1: TLabel;
  36.     Label2: TLabel;
  37.     SpinEdit1: TSpinEdit;
  38.     Edit1: TEdit;
  39.     Button6: TButton;
  40.     Button7: TButton;
  41.     Button8: TButton;
  42.     Button9: TButton;
  43.     ListBox2: TListBox;
  44.     TabSheet5: TTabSheet;
  45.     Label3: TLabel;
  46.     Image1: TImage;
  47.     Label10: TLabel;
  48.     Label11: TLabel;
  49.     Edit2: TEdit;
  50.     PageControl1: TPageControl;
  51.     TabSheet1: TTabSheet;
  52.     Label5: TLabel;
  53.     Label4: TLabel;
  54.     Label6: TLabel;
  55.     SpinEdit6: TSpinEdit;
  56.     SpinEdit2: TSpinEdit;
  57.     SpinEdit3: TSpinEdit;
  58.     SpinEdit4: TSpinEdit;
  59.     SpinEdit5: TSpinEdit;
  60.     ComboBox1: TComboBox;
  61.     TabSheet2: TTabSheet;
  62.     Label13: TLabel;
  63.     Label14: TLabel;
  64.     Label15: TLabel;
  65.     ComboBox2: TComboBox;
  66.     SpinEdit17: TSpinEdit;
  67.     SpinEdit18: TSpinEdit;
  68.     SpinEdit19: TSpinEdit;
  69.     SpinEdit20: TSpinEdit;
  70.     SpinEdit21: TSpinEdit;
  71.     TabSheet3: TTabSheet;
  72.     Label7: TLabel;
  73.     Label8: TLabel;
  74.     Label9: TLabel;
  75.     ComboBox3: TComboBox;
  76.     SpinEdit7: TSpinEdit;
  77.     SpinEdit8: TSpinEdit;
  78.     SpinEdit9: TSpinEdit;
  79.     SpinEdit10: TSpinEdit;
  80.     SpinEdit11: TSpinEdit;
  81.     SpinEdit12: TSpinEdit;
  82.     Image2: TImage;
  83.     Edit3: TEdit;
  84.     SpinEdit13: TSpinEdit;
  85.     Label12: TLabel;
  86.     Label16: TLabel;
  87.     Button13: TButton;
  88.     Button14: TButton;
  89.     MediaPlayer1: TMediaPlayer;
  90.     Timer1: TTimer;
  91.     GroupBox2: TGroupBox;
  92.     Button15: TButton;
  93.     Button17: TButton;
  94.     Button16: TButton;
  95.     Label18: TLabel;
  96.     Label17: TLabel;
  97.     ListBox3: TListBox;
  98.     Label19: TLabel;
  99.     Label24: TLabel;
  100.     Label25: TLabel;
  101.     Label26: TLabel;
  102.     Label27: TLabel;
  103.     Label28: TLabel;
  104.     Label29: TLabel;
  105.     Button11: TButton;
  106.     Button12: TButton;
  107.     Button18: TButton;
  108.     MainMenu1: TMainMenu;
  109.     File1: TMenuItem;
  110.     Close1: TMenuItem;
  111.     Newfile1: TMenuItem;
  112.     Savetogamebin1: TMenuItem;
  113.     Saveandtest1: TMenuItem;
  114.     N1: TMenuItem;
  115.     N2: TMenuItem;
  116.     Help1: TMenuItem;
  117.     About1: TMenuItem;
  118.     PopupMenu1: TPopupMenu;
  119.     Addtoscene1: TMenuItem;
  120.     Panel1: TPanel;
  121.     Panel2: TPanel;
  122.     Panel3: TPanel;
  123.     Image3: TImage;
  124.     Button19: TButton;
  125.     PageControl3: TPageControl;
  126.     TabSheet6: TTabSheet;
  127.     TabSheet7: TTabSheet;
  128.     Label20: TLabel;
  129.     Label21: TLabel;
  130.     Label22: TLabel;
  131.     Label23: TLabel;
  132.     Label34: TLabel;
  133.     Label35: TLabel;
  134.     Label32: TLabel;
  135.     Label33: TLabel;
  136.     Label30: TLabel;
  137.     Label31: TLabel;
  138.     Label36: TLabel;
  139.     Label37: TLabel;
  140.     procedure ListBox1Click(Sender: TObject);
  141.     procedure Edit1Change(Sender: TObject);
  142.     procedure Edit2Change(Sender: TObject);
  143.     procedure SpinEdit1Change(Sender: TObject);
  144.     procedure Button3Click(Sender: TObject);
  145.     procedure FormShow(Sender: TObject);
  146.     procedure SpinEdit12Change(Sender: TObject);
  147.     procedure ActionTargetChange(Sender: TObject);
  148.     procedure ActionSpinEditsChange(Sender: TObject);
  149.     procedure Button1Click(Sender: TObject);
  150.     procedure Button10Click(Sender: TObject);
  151.     procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  152.       Y: Integer);
  153.     procedure ListBox2Click(Sender: TObject);
  154.     procedure SpinEdit13Change(Sender: TObject);
  155.     procedure Edit3Change(Sender: TObject);
  156.     procedure FormCreate(Sender: TObject);
  157.     procedure Button13Click(Sender: TObject);
  158.     procedure Button14Click(Sender: TObject);
  159.     procedure Button2Click(Sender: TObject);
  160.     procedure Timer1Timer(Sender: TObject);
  161.     procedure Button17Click(Sender: TObject);
  162.     procedure Button15Click(Sender: TObject);
  163.     procedure Button16Click(Sender: TObject);
  164.     procedure ListBox1DblClick(Sender: TObject);
  165.     procedure ListBox2DblClick(Sender: TObject);
  166.     procedure Button4Click(Sender: TObject);
  167.     procedure Button5Click(Sender: TObject);
  168.     procedure Button6Click(Sender: TObject);
  169.     procedure Button7Click(Sender: TObject);
  170.     procedure Button8Click(Sender: TObject);
  171.     procedure Button9Click(Sender: TObject);
  172.     procedure Image1MouseLeave(Sender: TObject);
  173.     procedure ListBox3DblClick(Sender: TObject);
  174.     procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
  175.       Shift: TShiftState; X, Y: Integer);
  176.     procedure Button11Click(Sender: TObject);
  177.     procedure Button12Click(Sender: TObject);
  178.     procedure Button18Click(Sender: TObject);
  179.     procedure Image1MouseEnter(Sender: TObject);
  180.     procedure About1Click(Sender: TObject);
  181.     procedure Close1Click(Sender: TObject);
  182.     procedure Addtoscene1Click(Sender: TObject);
  183.     procedure ListBox3MouseDown(Sender: TObject; Button: TMouseButton;
  184.       Shift: TShiftState; X, Y: Integer);
  185.     procedure ListBox3Click(Sender: TObject);
  186.     procedure Button19Click(Sender: TObject);
  187.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  188.   private
  189.     Game: TGameBinFile;
  190.     GameBak: TGameBinFile;
  191.     PlayStart: Cardinal;
  192.     MediaplayerOpened: boolean;
  193.     StopPlayRequest: boolean;
  194.     FirstTickCount: Cardinal;
  195.     procedure ShowSceneBmp;
  196.     function CurScene: PSceneDef;
  197.     procedure LoadScene;
  198.     procedure Load;
  199.     procedure Save;
  200.     procedure ReloadActionSceneLists;
  201.     function FindSceneIndex(sceneID: integer): integer;
  202.     function GetGreatestSceneID: integer;
  203.     function SearchSceneIDGapFromTop: integer;
  204.     procedure RedrawDecisionBitmap;
  205.     function CurPicture: PPictureDef;
  206.     function CurPictureTimepos: Cardinal;
  207.     procedure New;
  208.     procedure NewScene;
  209.     procedure SetupGUIAfterLoad;
  210.     procedure RecalcSlideshowLength;
  211.     procedure RecalcSoundtrackLength;
  212.     procedure RecalcUnusedFiles;
  213.     procedure RecalcStats;
  214.     procedure HandlePossibleEmptySceneList;
  215.     procedure DisableEnableSceneControls(enable: boolean);
  216.     procedure DisableEnablePictureControls(enable: boolean);
  217.     procedure DisableEnableFileControls(enable: boolean);
  218.     class procedure AspectRatio(image: TImage; panel: TControl);
  219.   end;
  220.  
  221. var
  222.   Form1: TForm1;
  223.  
  224. implementation
  225.  
  226. {$R *.dfm}
  227.  
  228. uses
  229.   Math, MMSystem, ShellAPI;
  230.  
  231. const
  232.   DEFAULT_DURATION = 0;
  233.   DEFAULT_FILENAME = 'DUMMY.BMP';
  234.  
  235. function GetSceneIDFromName(sceneName: string): Integer;
  236. var
  237.   sSceneID: string;
  238. begin
  239.   if Copy(sceneName, 1, 2) <> 'SC' then raise Exception.Create('Scene name invalid');
  240.   sSceneID := Copy(sceneName, 3, 2);
  241.   if not TryStrToInt(sSceneID, result) then raise Exception.Create('Scene name invalid');
  242. end;
  243.  
  244. procedure SelectFilenameBase(Edit: TEdit);
  245. begin
  246.   if Edit.CanFocus then
  247.   begin
  248.     Edit.SetFocus;
  249.     Edit.SelStart := 0;
  250.     Edit.SelLength := Pos('.', Edit.Text)-1;
  251.   end;
  252. end;
  253.  
  254. function _DecisecondToTime(ds: integer): string;
  255. begin
  256.   result := FormatDatetime('hh:nn:ss', ds / 10 / (24*60*60))+','+IntToStr(ds mod 10);
  257. end;
  258.  
  259. { TForm1 }
  260.  
  261. function TForm1.GetGreatestSceneID: integer;
  262. var
  263.   i: integer;
  264. begin
  265.   result := -1;
  266.   for i := 0 to ListBox1.Items.Count - 1 do
  267.   begin
  268.     result := Max(result, GetSceneIDFromName(ListBox1.Items.Strings[i]));
  269.   end;
  270. end;
  271.  
  272. procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  273.   Shift: TShiftState; X, Y: Integer);
  274. var
  275.   sE1, sE2, sE3, sE4: TSpinEdit;
  276.  
  277.   procedure _Go;
  278.   begin
  279.     if Button = mbLeft then
  280.     begin
  281.       sE1.Value := Round(Image1.Picture.Width*(X/Image1.Width));
  282.       sE2.Value := Round(Image1.Picture.Height*(Y/Image1.Height));
  283.     end
  284.     else if Button = mbRight then
  285.     begin
  286.       sE3.Value := Round(Image1.Picture.Width*(X/Image1.Width));
  287.       sE4.Value := Round(Image1.Picture.Height*(Y/Image1.Height));
  288.     end;
  289.   end;
  290.  
  291. begin
  292.   if PageControl1.ActivePage = TabSheet1 then
  293.   begin
  294.     sE1 := SpinEdit3;
  295.     sE2 := SpinEdit2;
  296.     sE3 := SpinEdit4;
  297.     sE4 := SpinEdit5;
  298.     _Go;
  299.   end
  300.   else if PageControl1.ActivePage = TabSheet2 then
  301.   begin
  302.     sE1 := SpinEdit17;
  303.     sE2 := SpinEdit18;
  304.     sE3 := SpinEdit19;
  305.     sE4 := SpinEdit20;
  306.     _Go;
  307.   end
  308.   else if PageControl1.ActivePage = TabSheet3 then
  309.   begin
  310.     sE1 := SpinEdit7;
  311.     sE2 := SpinEdit8;
  312.     sE3 := SpinEdit10;
  313.     sE4 := SpinEdit9;
  314.     _Go;
  315.   end;
  316. end;
  317.  
  318. procedure TForm1.Image1MouseEnter(Sender: TObject);
  319. begin
  320.   Label28.Visible := true;
  321.   Label29.Visible := true;
  322. end;
  323.  
  324. procedure TForm1.Image1MouseLeave(Sender: TObject);
  325. begin
  326.   Label10.Caption := '';
  327.   Label28.Visible := false;
  328.   Label29.Visible := false;
  329. end;
  330.  
  331. procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  332.   Y: Integer);
  333. begin
  334.   label10.Caption := Format('Coords: [%d, %d]', [Round(Image1.Picture.Width*(X/Image1.Width)),
  335.                                                  Round(Image1.Picture.Height*(Y/Image1.Height))]);
  336. end;
  337.  
  338. function TForm1.SearchSceneIDGapFromTop: integer;
  339. var
  340.   i: integer;
  341. begin
  342.   result := -1;
  343.   for i := 99 downto 0 do
  344.   begin
  345.     if ListBox1.Items.IndexOf(Format('SC%.2d', [i])) = -1 then
  346.     begin
  347.       result := i;
  348.       exit;
  349.     end;
  350.   end;
  351. end;
  352.  
  353. procedure TForm1.Button10Click(Sender: TObject);
  354. begin
  355.   Save;
  356.   if not FileExists('ShowTime32.exe') then raise Exception.Create('GAME.BIN saved; ShowTime32.exe not found.');
  357.   ShellExecute(Application.Handle, 'open', 'ShowTime32.exe', '', '', SW_NORMAL);
  358. end;
  359.  
  360. procedure TForm1.Button11Click(Sender: TObject);
  361. var
  362.   fileName: string;
  363. begin
  364.   fileName := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + CurScene^.szDecisionBmp;
  365.   if not FileExists(fileName) then exit;
  366.   ShellExecute(Application.Handle, 'open', PChar(fileName), '', '', SW_NORMAL);
  367. end;
  368.  
  369. procedure TForm1.Button12Click(Sender: TObject);
  370. var
  371.   fileName: string;
  372. begin
  373.   fileName := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + CurPicture^.szBitmapFile;
  374.   if not FileExists(fileName) then exit;
  375.   ShellExecute(Application.Handle, 'open', Pchar(fileName), '', '', SW_NORMAL);
  376. end;
  377.  
  378. procedure TForm1.Button13Click(Sender: TObject);
  379. var
  380.   fileName: string;
  381. begin
  382.   fileName := CurScene^.szSceneFolder;
  383.   if not DirectoryExists(fileName) then MkDir(fileName);
  384.   ShellExecute(Application.Handle, 'open', 'explorer.exe', PChar(fileName), '', SW_NORMAL);
  385. end;
  386.  
  387. procedure TForm1.HandlePossibleEmptySceneList;
  388. begin
  389.   if Game.numScenes = 0 then
  390.   begin
  391.     PageControl2.ActivePage := nil;
  392.     PageControl2.Pages[0].TabVisible := false;
  393.     PageControl2.Pages[1].TabVisible := false;
  394.   end
  395.   else
  396.   begin
  397.     if PageControl2.ActivePage = nil then PageControl2.ActivePageIndex := 0;
  398.     PageControl2.Pages[0].TabVisible := true;
  399.     PageControl2.Pages[1].TabVisible := true;
  400.   end;
  401. end;
  402.  
  403. procedure TForm1.Button14Click(Sender: TObject);
  404. begin
  405.   New;
  406. end;
  407.  
  408. procedure TForm1.DisableEnableSceneControls(enable: boolean);
  409. begin
  410.   ListBox1.Enabled := enable;
  411.   Button1.Enabled := enable;
  412.   Button2.Enabled := enable;
  413.   Button4.Enabled := enable;
  414.   Button5.Enabled := enable;
  415. end;
  416.  
  417. procedure TForm1.DisableEnablePictureControls(enable: boolean);
  418. begin
  419.   Button8.Enabled := enable;
  420.   Button9.Enabled := enable;
  421.   Button6.Enabled := enable;
  422.   Button7.Enabled := enable;
  423. end;
  424.  
  425. procedure TForm1.DisableEnableFileControls(enable: boolean);
  426. begin
  427.   Button3.Enabled := enable;
  428.   Button10.Enabled := enable;
  429.   Button14.Enabled := enable;
  430. end;
  431.  
  432. var
  433.   AutomaticNextDia: boolean;
  434.  
  435. procedure TForm1.Button15Click(Sender: TObject);
  436. var
  437.   decisionBMP: string;
  438.   PictureLastFrame: Cardinal;
  439.   i: integer;
  440.   DecisionPicSet: boolean;
  441. begin
  442.   if PlayStart <> 0 then
  443.   begin
  444.     if MediaplayerOpened and not AutomaticNextDia then
  445.     begin
  446.       if MediaPlayer1.Mode = mpPlaying then MediaPlayer1.Stop;
  447.       Mediaplayer1.TimeFormat := tfMilliseconds;
  448.       if CurPictureTimepos*100 < Cardinal(MediaPlayer1.Length) then
  449.       begin
  450.         MediaPlayer1.Position := CurPictureTimepos * 100;
  451.         MediaPlayer1.Play;
  452.       end;
  453.     end;
  454.     AutomaticNextDia := false;
  455.     FirstTickCount := GetTickCount;
  456.     PlayStart := GetTickCount - CurPictureTimepos * 100;
  457.   end
  458.   else
  459.   begin
  460.     TabSheet5.TabVisible := false;
  461.     DisableEnablePictureControls(false);
  462.     DisableEnableSceneControls(false);
  463.     DisableEnableFileControls(false);
  464.     Edit1.Enabled := false;
  465.     Edit3.Enabled := false;
  466.     SpinEdit1.Enabled := false;
  467.     SpinEdit13.Enabled := false;
  468.     Label18.Font.Color := clGreen;
  469.     try
  470.       Timer1.Enabled := false;
  471.  
  472.       RecalcSoundtrackLength; // optional
  473.  
  474.       Mediaplayer1.FileName := Format('%s\%s', [CurScene^.szSceneFolder, CurScene^.szDialogWav]);
  475.       if FileExists(Mediaplayer1.FileName) then
  476.       begin
  477.         Mediaplayer1.TimeFormat := tfMilliseconds;
  478.         Mediaplayer1.Open;
  479.         MediaplayerOpened := true;
  480.         if CurPictureTimepos*100 < Cardinal(MediaPlayer1.Length) then
  481.         begin
  482.           MediaPlayer1.Position := CurPictureTimepos * 100;
  483.           MediaPlayer1.Play;
  484.         end;
  485.       end
  486.       else
  487.       begin
  488.         MediaplayerOpened := false;
  489.         MediaPlayer1.FileName := '';
  490.       end;
  491.       PlayStart := GetTickCount - CurPictureTimepos * 100;
  492.       Timer1.Enabled := true;
  493.  
  494.       {$REGION 'Calculate PictureLastFrame'}
  495.       PictureLastFrame := 0;
  496.       for i := 0 to CurScene^.numPics-1 do
  497.       begin
  498.         Inc(PictureLastFrame, Game.pictures[CurScene^.pictureIndex + i].duration);
  499.       end;
  500.       PictureLastFrame := PictureLastFrame * 100;
  501.       {$ENDREGION}
  502.  
  503.       DecisionPicSet := false;
  504.       while not Application.Terminated and
  505.             not StopPlayRequest and
  506.             (
  507.                   (MediaPlayer1.Mode = mpPlaying) or
  508.                   (GetTickCount - PlayStart <= PictureLastFrame)
  509.             ) do
  510.       begin
  511.         if GetTickCount - PlayStart <= PictureLastFrame then
  512.         begin
  513.           DecisionPicSet := false;
  514.           FirstTickCount := GetTickCount;
  515.           while not Application.Terminated and ((GetTickCount - FirstTickCount) < CurPicture^.duration * 100) and not StopPlayRequest do
  516.           begin
  517.             Application.ProcessMessages;
  518.             Sleep(0);
  519.           end;
  520.  
  521.           if not Application.Terminated and (ListBox2.ItemIndex < ListBox2.Count-1) and not StopPlayRequest then
  522.           begin
  523.             ListBox2.ItemIndex := ListBox2.ItemIndex + 1;
  524.             AutomaticNextDia := true;
  525.             ListBox2Click(ListBox2);
  526.           end;
  527.         end
  528.         else
  529.         begin
  530.           if not DecisionPicSet then
  531.           begin
  532.             decisionBMP := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + CurScene^.szDecisionBmp;
  533.             if (CurScene^.szDecisionBmp <> '') and FileExists(decisionBMP) then
  534.             begin
  535.               Image2.Picture.LoadFromFile(decisionBMP);
  536.               AspectRatio(Image2, Panel2);
  537.             end
  538.             else
  539.             begin
  540.               Image2.Picture := nil;
  541.             end;
  542.             DecisionPicSet := true;
  543.           end;
  544.           Application.ProcessMessages;
  545.           Sleep(0);
  546.         end;
  547.       end;
  548.     finally
  549.       PlayStart := 0;
  550.       if MediaPlayer1.Mode = mpPlaying then MediaPlayer1.Stop;
  551.       if MediaplayerOpened then MediaPlayer1.Close;
  552.       StopPlayRequest := false;
  553.       Label18.Font.Color := clWindowText;
  554.       Timer1.Enabled := false;
  555.       DisableEnableFileControls(true);
  556.       DisableEnableSceneControls(true);
  557.       DisableEnablePictureControls(true);
  558.       TabSheet5.TabVisible := true;
  559.       Edit1.Enabled := true;
  560.       SpinEdit1.Enabled := true;
  561.       Edit3.Enabled := true;
  562.       SpinEdit13.Enabled := true;
  563.       Label18.Caption := _DecisecondToTime(CurPictureTimepos);
  564.       ListBox2Click(ListBox2);
  565.     end;
  566.   end;
  567. end;
  568.  
  569. procedure TForm1.ShowSceneBmp;
  570. var
  571.   Filename: string;
  572. begin
  573.   Filename := string(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + CurPicture^.szBitmapFile);
  574.   if FileExists(Filename) then
  575.   begin
  576.     Image2.Picture.LoadFromFile(Filename);
  577.     AspectRatio(Image2, Panel2);
  578.   end
  579.   else
  580.   begin
  581.     Image2.Picture := nil;
  582.   end;
  583. end;
  584.  
  585. procedure TForm1.Button16Click(Sender: TObject);
  586. begin
  587.   ListBox2.ItemIndex := 0; // go to the beginning
  588.   ListBox2Click(ListBox2); // load picture data
  589.   Button15Click(Button15); // play
  590. end;
  591.  
  592. procedure TForm1.Button17Click(Sender: TObject);
  593. begin
  594.   if PlayStart <> 0 then
  595.   begin
  596.     Timer1.Enabled := false;
  597.     if MediaplayerOpened then MediaPlayer1.Stop;
  598.     StopPlayRequest := true;
  599.   end;
  600. end;
  601.  
  602. procedure TForm1.Button18Click(Sender: TObject);
  603. var
  604.   fileName: string;
  605. begin
  606.   fileName := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + CurScene^.szDialogWav;
  607.   if not FileExists(fileName) then exit;
  608.   ShellExecute(Application.Handle, 'open', PChar(fileName), '', '', SW_NORMAL);
  609. end;
  610.  
  611. procedure TForm1.Button19Click(Sender: TObject);
  612. begin
  613.   CopyMemory(@Game, @GameBak, SizeOf(Game));
  614.   SetupGUIAfterLoad;
  615. end;
  616.  
  617. procedure TForm1.NewScene;
  618. var
  619.   sceneID: integer;
  620.   newScene: PSceneDef;
  621. begin
  622.   if ListBox1.Items.Count = 100 then
  623.   begin
  624.     raise Exception.Create('No more space for another scene');
  625.   end;
  626.  
  627.   sceneID := GetGreatestSceneID+1;
  628.   if sceneID >= Length(Game.scenes) then sceneID := SearchSceneIDGapFromTop;
  629.  
  630.   newScene := Game.AddSceneAtEnd(sceneID);
  631.   newScene.actions[0].nextSceneID := SCENEID_ENDGAME;
  632.   newScene.pictureIndex := Game.numPics;
  633.   ListBox1.Items.Add(newScene.szSceneFolder);
  634.   ReloadActionSceneLists;
  635.   HandlePossibleEmptySceneList;
  636.   ListBox1.ItemIndex := ListBox1.Items.Count - 1;
  637.   ListBox1Click(ListBox1);
  638. end;
  639.  
  640. procedure TForm1.Button1Click(Sender: TObject);
  641. begin
  642.   NewScene;
  643. end;
  644.  
  645. procedure TForm1.Button2Click(Sender: TObject);
  646. var
  647.   iScene, iAction, sceneID: integer;
  648.   conflicts: TStringList;
  649.   sWarning: string;
  650.   bakItemindex: integer;
  651. begin
  652.   if ListBox1.Count = 0 then exit;
  653.  
  654.   (*
  655.   if ListBox1.Count = 1 then
  656.   begin
  657.     raise Exception.Create('Can''t delete the scene if there is only one.');
  658.   end;
  659.   *)
  660.  
  661.   conflicts := TStringList.Create;
  662.   try
  663.     sceneID := GetSceneIDFromName(CurScene^.szSceneFolder);
  664.     for iScene := 0 to Game.numScenes-1 do
  665.     begin
  666.       for iAction := 0 to Game.scenes[iScene].numActions-1 do
  667.       begin
  668.         if Game.scenes[iScene].actions[iAction].nextSceneID = sceneID then
  669.         begin
  670.           conflicts.Add(Format('Scene %s, action #%d', [Game.scenes[iScene].szSceneFolder, iAction+1]));
  671.         end;
  672.       end;
  673.     end;
  674.     if conflicts.Count > 0 then
  675.     begin
  676.       raise Exception.Create('Can''t delete this scene. There are following dependencies:'+#13#10#13#10+conflicts.Text);
  677.     end;
  678.   finally
  679.     FreeAndNil(conflicts);
  680.   end;
  681.  
  682.   sWarning := Format('Do you really want to delete scene %s?', [CurScene^.szSceneFolder]);
  683.   if (ListBox1.ItemIndex = 0) and (ListBox1.Count >= 2) then
  684.     sWarning := Format('Attention: This will make %s to your new intro sequence. Is that OK?', [ListBox1.Items[ListBox1.ItemIndex+1]]);
  685.   if (MessageDlg(sWarning, mtConfirmation, mbYesNoCancel, 0) <> mrYes) then
  686.   begin
  687.     Exit;
  688.   end;
  689.  
  690.   Game.DeleteScene(ListBox1.ItemIndex);
  691.  
  692.   bakItemindex := ListBox1.ItemIndex;
  693.   ListBox1.Items.Delete(bakItemindex);
  694.   ReloadActionSceneLists;
  695.   HandlePossibleEmptySceneList;
  696.   if ListBox1.Count > 0 then
  697.   begin
  698.     if bakItemindex = ListBox1.Count then Dec(bakItemindex);
  699.     Listbox1.ItemIndex := bakItemindex;
  700.     ListBox1Click(ListBox1);
  701.   end;
  702. end;
  703.  
  704. procedure TForm1.Button3Click(Sender: TObject);
  705. begin
  706.   Save;
  707. end;
  708.  
  709. procedure TForm1.Button4Click(Sender: TObject);
  710. begin
  711.   if ListBox1.ItemIndex <= 0 then exit;
  712.   Game.SwapScene(ListBox1.ItemIndex, ListBox1.ItemIndex-1);
  713.   ListBox1.Items.Exchange(ListBox1.ItemIndex, ListBox1.ItemIndex-1);
  714.   ReloadActionSceneLists;
  715. end;
  716.  
  717. procedure TForm1.Button5Click(Sender: TObject);
  718. begin
  719.   if ListBox1.ItemIndex = ListBox1.Count-1 then exit;
  720.   Game.SwapScene(ListBox1.ItemIndex, ListBox1.ItemIndex+1);
  721.   ListBox1.Items.Exchange(ListBox1.ItemIndex, ListBox1.ItemIndex+1);
  722.   ReloadActionSceneLists;
  723. end;
  724.  
  725. procedure TForm1.Button6Click(Sender: TObject);
  726. var
  727.   pic: PPictureDef;
  728. begin
  729.   if ListBox2.Items.Count > 0 then
  730.     pic := Game.AddPictureBetween(CurScene^.pictureIndex + Max(ListBox2.ItemIndex+1,0), false)
  731.   else
  732.     pic := Game.AddPictureBetween(CurScene^.pictureIndex + Max(ListBox2.ItemIndex,0), true);
  733.   pic.duration     := DEFAULT_DURATION;
  734.   pic.szBitmapFile := DEFAULT_FILENAME;
  735.   if ListBox2.ItemIndex = -1 then
  736.   begin
  737.     ListBox2.Items.Insert(ListBox2.Count, Format('(%d) %s', [DEFAULT_DURATION, DEFAULT_FILENAME]));
  738.     ListBox2.ItemIndex := ListBox2.Count - 1;
  739.   end
  740.   else
  741.   begin
  742.     ListBox2.Items.Insert(ListBox2.ItemIndex+1, Format('(%d) %s', [DEFAULT_DURATION, DEFAULT_FILENAME]));
  743.     ListBox2.ItemIndex := ListBox2.ItemIndex + 1;
  744.   end;
  745.   ListBox2Click(Listbox2);
  746.   SelectFilenameBase(Edit3);
  747.   RecalcStats;
  748. end;
  749.  
  750. procedure TForm1.Button7Click(Sender: TObject);
  751. var
  752.   bakIdx: integer;
  753. begin
  754.   if Listbox2.Count > 0 then
  755.   begin
  756.     bakIdx := ListBox2.ItemIndex;
  757.     Game.DeletePicture(CurScene^.pictureIndex + bakIdx);
  758.     ListBox2.Items.Delete(bakIdx);
  759.     if ListBox2.Count > 0 then
  760.     begin
  761.       if bakIdx = ListBox2.Count then Dec(bakIdx);
  762.       ListBox2.ItemIndex := bakIdx;
  763.       ListBox2Click(Listbox2);
  764.     end;
  765.     RecalcUnusedFiles;
  766.   end;
  767.   RecalcStats;
  768. end;
  769.  
  770. procedure TForm1.Button8Click(Sender: TObject);
  771. begin
  772.   if ListBox2.ItemIndex <= 0 then exit;
  773.   Game.SwapPicture(CurScene^.pictureIndex+ListBox2.ItemIndex, CurScene^.pictureIndex+ListBox2.ItemIndex-1);
  774.   ListBox2.Items.Exchange(ListBox2.ItemIndex, ListBox2.ItemIndex-1);
  775. end;
  776.  
  777. procedure TForm1.Button9Click(Sender: TObject);
  778. begin
  779.   if ListBox2.ItemIndex = ListBox2.Count-1 then exit;
  780.   Game.SwapPicture(CurScene^.pictureIndex+ListBox2.ItemIndex, CurScene^.pictureIndex+ListBox2.ItemIndex+1);
  781.   ListBox2.Items.Exchange(ListBox2.ItemIndex, ListBox2.ItemIndex+1);
  782. end;
  783.  
  784. procedure TForm1.Save;
  785. var
  786.   fs: TFileStream;
  787. begin
  788.   CopyMemory(@GameBak, @Game, SizeOf(Game));
  789.  
  790.   fs := TFileStream.Create('GAME.BIN', fmOpenWrite or fmCreate);
  791.   try
  792.     fs.WriteBuffer(Game, SizeOf(Game));
  793.   finally
  794.     FreeAndNil(fs);
  795.   end;
  796. end;
  797.  
  798. procedure TForm1.ActionTargetChange(Sender: TObject);
  799. var
  800.   actionIdx: integer;
  801.   itemIdx: Integer;
  802. begin
  803.        if Sender = ComboBox1 then actionIdx := 0
  804.   else if Sender = ComboBox2 then actionIdx := 1
  805.   else if Sender = ComboBox3 then actionIdx := 2
  806.   else raise Exception.Create('Unexpected sender for ActionTargetChange()');
  807.  
  808.   itemIdx := TComboBox(Sender).ItemIndex;
  809.   if itemIdx = 0 then
  810.     CurScene^.actions[actionIdx].nextSceneID := SCENEID_ENDGAME
  811.   else if itemIdx = 1 then
  812.     CurScene^.actions[actionIdx].nextSceneID := SCENEID_PREVDECISION
  813.   else
  814.     CurScene^.actions[actionIdx].nextSceneID := GetSceneIDFromName(ListBox1.Items[itemIdx - 2]);
  815. end;
  816.  
  817. procedure TForm1.Addtoscene1Click(Sender: TObject);
  818. var
  819.   fil: string;
  820. begin
  821.   if ListBox3.ItemIndex = -1 then exit;
  822.   fil := ListBox3.Items[ListBox3.ItemIndex];
  823.   Button6.Click;
  824.   Edit3.Text := fil;
  825. end;
  826.  
  827. procedure TForm1.Edit1Change(Sender: TObject);
  828. begin
  829.   _WriteStringToFilename(@CurScene^.szDialogWav, Edit1.Text);
  830.   RecalcSoundtrackLength;
  831.   RecalcUnusedFiles;
  832.  
  833.   Label24.Visible := not FileExists(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + Edit1.Text);
  834.   Label25.Visible := not FileExists(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + 'E' + Edit1.Text);
  835.  
  836.   Button18.Visible := CurScene^.szDialogWav <> '';
  837. end;
  838.  
  839. procedure TForm1.Edit2Change(Sender: TObject);
  840. begin
  841.   _WriteStringToFilename(@CurScene^.szDecisionBmp, Edit2.Text);
  842.   RecalcUnusedFiles;
  843.   RedrawDecisionBitmap;
  844.   Label27.Visible := not FileExists(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + Edit2.Text) and not (Edit2.Text = '');
  845.   Button11.Visible := CurScene^.szDecisionBmp <> '';
  846. end;
  847.  
  848. procedure TForm1.Edit3Change(Sender: TObject);
  849. begin
  850.   _WriteStringToFilename(@CurPicture^.szBitmapFile, Edit3.Text);
  851.   ListBox2.Items[ListBox2.ItemIndex] := Format('(%d) %s', [CurPicture^.duration, CurPicture^.szBitmapFile]);
  852.   RecalcUnusedFiles;
  853.   ShowSceneBmp;
  854.   Label26.Visible := not FileExists(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + Edit3.Text);
  855.   Button12.Visible := CurPicture^.szBitmapFile <> '';
  856. end;
  857.  
  858. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  859. begin
  860.   if not CompareMem(@Game, @GameBak, SizeOf(Game)) then
  861.   begin
  862.     case MessageDlg('Do you want to save the changes?', mtConfirmation, mbYesNoCancel, 0) of
  863.       ID_YES:
  864.       begin
  865.         Save;
  866.         CanClose := true;
  867.       end;
  868.       ID_NO:
  869.       begin
  870.         CanClose := true;
  871.       end;
  872.       ID_CANCEL:
  873.       begin
  874.         CanClose := false;
  875.       end;
  876.     end;
  877.   end;
  878. end;
  879.  
  880. procedure TForm1.FormCreate(Sender: TObject);
  881. begin
  882.   PageControl1.ActivePageIndex := 0;
  883.   PageControl2.ActivePageIndex := 0;
  884.   PageControl3.ActivePageIndex := 0;
  885.   Label10.Caption := '';
  886.   Label21.Caption := '';
  887.   Label23.Caption := '';
  888. end;
  889.  
  890. procedure TForm1.FormShow(Sender: TObject);
  891. begin
  892.   if FileExists('GAME.BIN') then
  893.     Load
  894.   else
  895.     New;
  896. end;
  897.  
  898. function TForm1.CurScene: PSceneDef;
  899. begin
  900.   if ListBox1.Count = 0 then raise Exception.Create('No scene available. Please create one.');
  901.   if ListBox1.ItemIndex = -1 then raise Exception.Create('No scene selected. Please select one.');
  902.   result := @Game.scenes[ListBox1.ItemIndex];
  903. end;
  904.  
  905. procedure TForm1.ListBox1Click(Sender: TObject);
  906. begin
  907.   LoadScene;
  908. end;
  909.  
  910. procedure TForm1.ListBox1DblClick(Sender: TObject);
  911. begin
  912.   Button16Click(Button16);
  913. end;
  914.  
  915. procedure TForm1.Close1Click(Sender: TObject);
  916. begin
  917.   Close;
  918. end;
  919.  
  920. function TForm1.CurPicture: PPictureDef;
  921. begin
  922.   if ListBox2.Count = 0 then raise Exception.Create('No pictures available. Please create one.');
  923.   if ListBox2.ItemIndex = -1 then raise Exception.Create('No pictures selected. Please select one.');
  924.   result := @Game.pictures[CurScene^.pictureIndex + ListBox2.ItemIndex]
  925. end;
  926.  
  927. function TForm1.CurPictureTimepos: Cardinal;
  928. var
  929.   i: integer;
  930. begin
  931.   result := 0;
  932.   for i := curScene^.pictureIndex to curScene^.pictureIndex + ListBox2.ItemIndex - 1 do
  933.   begin
  934.     Inc(result, Game.pictures[i].duration);
  935.   end;
  936. end;
  937.  
  938. class procedure TForm1.AspectRatio(image: TImage; panel: TControl);
  939. var
  940.   wi, hi, ws, hs: integer;
  941.   ri, rs: double;
  942. begin
  943.   wi := image.Picture.Width;
  944.   hi := image.Picture.Height;
  945.   ri := wi / hi;
  946.  
  947.   ws := panel.Width;
  948.   hs := panel.Height;
  949.   rs := ws / hs;
  950.  
  951.   if rs > ri then
  952.   begin
  953.     image.Width  := Round(wi * hs/hi);
  954.     image.Height := hs;
  955.   end
  956.   else
  957.   begin
  958.     image.Width  := ws;
  959.     image.Height := Round(hi * ws/wi);
  960.   end;
  961.  
  962.   image.Left := Round(panel.Width  / 2 - image.Width  / 2);
  963.   image.Top  := Round(panel.Height / 2 - image.Height / 2);
  964. end;
  965.  
  966. procedure TForm1.ListBox2Click(Sender: TObject);
  967. var
  968.   bakEvent: TNotifyEvent;
  969. begin
  970.   if CurScene^.numPics = 0 then
  971.   begin
  972.     SpinEdit13.Value := 0;
  973.  
  974.     bakEvent := Edit3.OnChange;
  975.     try
  976.       Edit3.OnChange := nil;
  977.       Edit3.Text := '';
  978.     finally
  979.       Edit3.OnChange := bakEvent;
  980.     end;
  981.  
  982.     Label18.Caption := '';
  983.     Image2.Picture := nil;
  984.     exit;
  985.   end;
  986.  
  987.   SpinEdit13.Value := CurPicture^.duration;
  988.   Edit3.Text := string(CurPicture^.szBitmapFile);
  989.  
  990.   ShowSceneBmp;
  991.  
  992.   Label18.Caption := _DecisecondToTime(CurPictureTimepos);
  993.  
  994.   if PlayStart <> 0 then
  995.   begin
  996.     Button15Click(Button15);
  997.   end;
  998.  
  999.   RecalcStats;
  1000. end;
  1001.  
  1002. procedure TForm1.ListBox2DblClick(Sender: TObject);
  1003. begin
  1004.   Button15Click(Button15);
  1005. end;
  1006.  
  1007. procedure TForm1.ListBox3Click(Sender: TObject);
  1008. var
  1009.   fileName: string;
  1010. begin
  1011.   if ListBox3.ItemIndex = -1 then exit;
  1012.   fileName := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + ListBox3.Items[ListBox3.ItemIndex];
  1013.   Image3.Visible := FileExists(FileName);
  1014.   if not FileExists(FileName) then exit;
  1015.   Image3.Picture.LoadFromFile(Filename);
  1016.   AspectRatio(Image3, Panel3);
  1017. end;
  1018.  
  1019. procedure TForm1.ListBox3DblClick(Sender: TObject);
  1020. var
  1021.   fileName: string;
  1022. begin
  1023.   if ListBox3.ItemIndex = -1 then exit;
  1024.   fileName := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + ListBox3.Items[ListBox3.ItemIndex];
  1025.   if not FileExists(FileName) then exit;
  1026.   ShellExecute(Application.Handle, 'open', PChar(fileName), '', '', SW_NORMAL);
  1027. end;
  1028.  
  1029. procedure TForm1.ListBox3MouseDown(Sender: TObject; Button: TMouseButton;
  1030.   Shift: TShiftState; X, Y: Integer);
  1031. var
  1032.   APoint: TPoint;
  1033.   Index: integer;
  1034. begin
  1035.   if Button = mbRight then
  1036.   begin
  1037.     APoint.X := X;
  1038.     APoint.Y := Y;
  1039.     Index := TListbox(Sender).ItemAtPos(APoint, True);
  1040.     if Index > -1 then TListbox(Sender).Selected[Index] := True;
  1041.   end;
  1042. end;
  1043.  
  1044. procedure TForm1.SetupGUIAfterLoad;
  1045. var
  1046.   i: integer;
  1047. begin
  1048.   ListBox1.Clear;
  1049.   for i := 0 to Game.numScenes - 1 do
  1050.   begin
  1051.     ListBox1.Items.Add(string(Game.scenes[i].szSceneFolder));
  1052.   end;
  1053.   (*
  1054.   if ListBox1.Items.Count = 0 then
  1055.   begin
  1056.     NewScene;
  1057.   end;
  1058.   *)
  1059.  
  1060.   ReloadActionSceneLists;
  1061.   HandlePossibleEmptySceneList;
  1062.  
  1063.   if ListBox1.Count > 0 then
  1064.   begin
  1065.     ListBox1.ItemIndex := 0;
  1066.     ListBox1Click(Listbox1);
  1067.   end;
  1068. end;
  1069.  
  1070. procedure TForm1.New;
  1071. begin
  1072.   ZeroMemory(@Game, SizeOf(Game));
  1073.   ZeroMemory(@GameBak, SizeOf(Game));
  1074.  
  1075.   SetupGUIAfterLoad;
  1076. end;
  1077.  
  1078. procedure TForm1.Load;
  1079. var
  1080.   fs: TFileStream;
  1081. begin
  1082.   fs := TFileStream.Create('GAME.BIN', fmOpenRead);
  1083.   try
  1084.     fs.ReadBuffer(Game, SizeOf(Game));
  1085.   finally
  1086.     FreeAndNil(fs);
  1087.   end;
  1088.  
  1089.   if Game.RealPictureCount <> Game.numPics then
  1090.   begin
  1091.     MessageDlg('Picture count was wrong. Value was corrected.', mtInformation, [mbOk], 0);
  1092.     Game.numPics := Game.RealPictureCount;
  1093.   end;
  1094.  
  1095.   CopyMemory(@GameBak, @Game, SizeOf(Game));
  1096.  
  1097.   SetupGUIAfterLoad;
  1098. end;
  1099.  
  1100. function TForm1.FindSceneIndex(sceneID: integer): integer;
  1101. var
  1102.   i: Integer;
  1103.   sSceneID: string;
  1104. begin
  1105.   sSceneID := Format('SC%.2d', [sceneID]);
  1106.   for i := 0 to ListBox1.Count - 1 do
  1107.   begin
  1108.     if ListBox1.Items.Strings[i] = sSceneID then
  1109.     begin
  1110.       result := i;
  1111.       exit;
  1112.     end;
  1113.   end;
  1114.   result := -1;
  1115. end;
  1116.  
  1117. procedure TForm1.RecalcSlideshowLength;
  1118. var
  1119.   i: integer;
  1120.   Sum: integer;
  1121. begin
  1122.   Sum := 0;
  1123.   for i := CurScene^.pictureIndex to CurScene^.pictureIndex + CurScene^.numPics - 1 do
  1124.   begin
  1125.     Inc(Sum, Game.pictures[i].duration);
  1126.   end;
  1127.   Label21.Caption := _DecisecondToTime(Sum);
  1128. end;
  1129.  
  1130. procedure TForm1.RecalcUnusedFiles;
  1131. var
  1132.   i, idx: integer;
  1133.   SR: TSearchRec;
  1134.   ext: string;
  1135. begin
  1136.   ListBox3.Items.BeginUpdate;
  1137.   try
  1138.     ListBox3.Clear;
  1139.  
  1140.     Image3.Visible := false;
  1141.  
  1142.     if FindFirst(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + '*.*', faArchive, SR) = 0 then
  1143.     begin
  1144.       repeat
  1145.         ext := UpperCase(ExtractFileExt(SR.Name));
  1146.         if ((ext <> '.PK' {Adobe Audition}) and (ext <> '.DB' {Windows Thumbnail})) then
  1147.         begin
  1148.           ListBox3.Items.Add(SR.Name); //Fill the list
  1149.         end;
  1150.       until FindNext(SR) <> 0;
  1151.       FindClose(SR);
  1152.     end;
  1153.  
  1154.     // Remove the entries which are present
  1155.     for i := CurScene^.pictureIndex to CurScene^.pictureIndex+CurScene^.numPics-1 do
  1156.     begin
  1157.       idx := ListBox3.Items.IndexOf(Game.pictures[i].szBitmapFile);
  1158.       if idx <> -1 then ListBox3.Items.Delete(idx);
  1159.     end;
  1160.  
  1161.     idx := ListBox3.Items.IndexOf(Edit1.Text);
  1162.     if idx <> -1 then ListBox3.Items.Delete(idx);
  1163.     idx := ListBox3.Items.IndexOf('E'+Edit1.Text);
  1164.     if idx <> -1 then ListBox3.Items.Delete(idx);
  1165.  
  1166.     idx := ListBox3.Items.IndexOf(Edit2.Text);
  1167.     if idx <> -1 then ListBox3.Items.Delete(idx);
  1168.  
  1169.     idx := ListBox3.Items.IndexOf(Edit3.Text);
  1170.     if idx <> -1 then ListBox3.Items.Delete(idx);
  1171.   finally
  1172.     ListBox3.Items.EndUpdate;
  1173.   end;
  1174. end;
  1175.  
  1176. procedure TForm1.RecalcSoundtrackLength;
  1177. var
  1178.   FileName: string;
  1179. begin
  1180.   if MediaPlayer1.Mode = mpPlaying then exit;
  1181.  
  1182.   FileName := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + CurScene^.szDialogWav;
  1183.   if not FileExists(FileName) then
  1184.   begin
  1185.     Label23.Caption := 'n/a';
  1186.     exit;
  1187.   end;
  1188.   MediaPlayer1.FileName := FileName;
  1189.   MediaPlayer1.TimeFormat := tfMilliseconds;
  1190.   MediaPlayer1.Open;
  1191.   Label23.Caption := _DecisecondToTime(MediaPlayer1.Length div 100);
  1192.   MediaPlayer1.Close;
  1193. end;
  1194.  
  1195. procedure TForm1.LoadScene;
  1196.  
  1197.   procedure _SelectActionComboBox(ComboBox: TComboBox; sceneID: SmallInt);
  1198.   var
  1199.     idx: Integer;
  1200.   begin
  1201.     if sceneID = SCENEID_ENDGAME then
  1202.       ComboBox.ItemIndex := 0
  1203.     else if sceneID = SCENEID_PREVDECISION then
  1204.       ComboBox.ItemIndex := 1
  1205.     else
  1206.     begin
  1207.       idx := FindSceneIndex(sceneID);
  1208.       if idx = -1 then
  1209.         ComboBox.ItemIndex := -1
  1210.       else
  1211.         ComboBox.ItemIndex := 2 + idx;
  1212.     end;
  1213.   end;
  1214.  
  1215.   procedure _PreparePictureList;
  1216.   var
  1217.     i: integer;
  1218.     //pic: PPictureDef;
  1219.   begin
  1220.     ListBox2.Clear;
  1221.  
  1222.     if CurScene^.numPics = 0 then
  1223.     begin
  1224.       (*
  1225.       pic := Game.AddPictureBetween(CurScene^.pictureIndex + Max(ListBox2.ItemIndex,0));
  1226.       pic.duration := DEFAULT_DURATION;
  1227.       pic.szBitmapFile := DEFAULT_FILENAME;
  1228.       *)
  1229.     end;
  1230.  
  1231.     for i := CurScene^.pictureIndex to CurScene^.pictureIndex + CurScene^.numPics - 1 do
  1232.     begin
  1233.       Listbox2.Items.Add(Format('(%d) %s', [Game.pictures[i].duration, Game.pictures[i].szBitmapFile]));
  1234.     end;
  1235.   end;
  1236.  
  1237. begin
  1238.   SpinEdit1.Value := GetSceneIDFromName(CurScene^.szSceneFolder);
  1239.   Edit1.Text := string(CurScene^.szDialogWav);
  1240.   Edit2.Text := string(CurScene^.szDecisionBmp);
  1241.  
  1242.   _PreparePictureList;
  1243.   ListBox2.ItemIndex := 0;
  1244.   ListBox2Click(Listbox2);
  1245.  
  1246.   _SelectActionComboBox(ComboBox1, CurScene^.actions[0].nextSceneID);
  1247.   _SelectActionComboBox(ComboBox2, CurScene^.actions[1].nextSceneID);
  1248.   _SelectActionComboBox(ComboBox3, CurScene^.actions[2].nextSceneID);
  1249.  
  1250.   SpinEdit12.Value := CurScene^.numActions;
  1251.   SpinEdit12Change(SpinEdit12);
  1252.   PageControl1.ActivePageIndex := 0;
  1253.  
  1254.   SpinEdit3.Value  := CurScene^.actions[0].cHotspotTopLeft.X;
  1255.   SpinEdit17.Value := CurScene^.actions[1].cHotspotTopLeft.X;
  1256.   SpinEdit7.Value  := CurScene^.actions[2].cHotspotTopLeft.X;
  1257.   SpinEdit2.Value  := CurScene^.actions[0].cHotspotTopLeft.Y;
  1258.   SpinEdit18.Value := CurScene^.actions[1].cHotspotTopLeft.Y;
  1259.   SpinEdit8.Value  := CurScene^.actions[2].cHotspotTopLeft.Y;
  1260.   SpinEdit4.Value  := CurScene^.actions[0].cHotspotBottomRight.X;
  1261.   SpinEdit19.Value := CurScene^.actions[1].cHotspotBottomRight.X;
  1262.   SpinEdit10.Value := CurScene^.actions[2].cHotspotBottomRight.X;
  1263.   SpinEdit5.Value  := CurScene^.actions[0].cHotspotBottomRight.Y;
  1264.   SpinEdit20.Value := CurScene^.actions[1].cHotspotBottomRight.Y;
  1265.   SpinEdit9.Value  := CurScene^.actions[2].cHotspotBottomRight.Y;
  1266.   SpinEdit6.Value  := CurScene^.actions[0].scoreDelta;
  1267.   SpinEdit21.Value := CurScene^.actions[1].scoreDelta;
  1268.   SpinEdit11.Value := CurScene^.actions[2].scoreDelta;
  1269.  
  1270.   RedrawDecisionBitmap;
  1271.  
  1272.   RecalcSlideshowLength;
  1273.   RecalcSoundtrackLength;
  1274.  
  1275.   RecalcUnusedFiles;
  1276.  
  1277.   RecalcStats;
  1278. end;
  1279.  
  1280. procedure TForm1.RecalcStats;
  1281. begin
  1282.   Label35.Caption := IntToStr(ListBox1.ItemIndex) + ' / ' + IntToStr(Game.numScenes);
  1283.  
  1284.   if ListBox2.ItemIndex >= 0 then
  1285.     Label31.Caption := IntToStr(CurScene^.pictureIndex) + ' + ' + IntToStr(ListBox2.ItemIndex) + ' = ' + IntToStr(CurScene^.pictureIndex+ListBox2.ItemIndex)
  1286.   else
  1287.     Label31.Caption := IntToStr(CurScene^.pictureIndex);
  1288.  
  1289.   Label33.Caption := IntToStr(CurScene^.numPics) + ' / ' + IntToStr(Game.numPics);
  1290.  
  1291.   Label37.Caption := IntToStr(CurScene^.numActions) + ' / ' + IntToStr(Game.RealActionCount);
  1292. end;
  1293.  
  1294. procedure TForm1.ReloadActionSceneLists;
  1295.  
  1296.   procedure _ReloadActionSceneLists(ComboBox: TComboBox);
  1297.   var
  1298.     prevSelection: string;
  1299.     i: Integer;
  1300.   begin
  1301.     prevSelection := ComboBox.Text;
  1302.     try
  1303.       ComboBox.Items.Clear;
  1304.       ComboBox.Items.Add('Terminate program');
  1305.       ComboBox.Items.Add('Previous decision');
  1306.       ComboBox.Items.AddStrings(ListBox1.Items);
  1307.     finally
  1308.       ComboBox.ItemIndex := 0;
  1309.       for i := ComboBox.Items.Count - 1 downto 0 do
  1310.       begin
  1311.         if ComboBox.Items.Strings[i] = prevSelection then
  1312.         begin
  1313.           ComboBox.ItemIndex := i;
  1314.         end;
  1315.       end;
  1316.     end;
  1317.   end;
  1318.  
  1319. begin
  1320.   _ReloadActionSceneLists(ComboBox1);
  1321.   _ReloadActionSceneLists(ComboBox2);
  1322.   _ReloadActionSceneLists(ComboBox3);
  1323. end;
  1324.  
  1325. procedure TForm1.SpinEdit12Change(Sender: TObject);
  1326. begin
  1327.   TabSheet3.TabVisible := SpinEdit12.Value >= 3;
  1328.   if PageControl1.ActivePage = TabSheet3 then PageControl1.ActivePage := TabSheet2;
  1329.  
  1330.   TabSheet2.TabVisible := SpinEdit12.Value >= 2;
  1331.   if PageControl1.ActivePage = TabSheet2 then PageControl1.ActivePage := TabSheet1;
  1332.  
  1333.   // TabSheet1.TabVisible := SpinEdit12.Value >= 1;
  1334.  
  1335.   CurScene^.numActions := SpinEdit12.Value;
  1336.  
  1337.   // QUE: zero data of actions which are inactive (numActions<action)?
  1338.  
  1339.   RecalcStats;
  1340. end;
  1341.  
  1342. procedure TForm1.SpinEdit13Change(Sender: TObject);
  1343. begin
  1344.   if SpinEdit13.Text = '' then exit;
  1345.   CurPicture^.duration := SpinEdit13.Value;
  1346.   ListBox2.Items[ListBox2.ItemIndex] := Format('(%d) %s', [CurPicture^.duration, CurPicture^.szBitmapFile]);
  1347.   RecalcSlideshowLength;
  1348. end;
  1349.  
  1350. procedure TForm1.SpinEdit1Change(Sender: TObject);
  1351.  
  1352.   function _CountNumScenes(str: string): integer;
  1353.   var
  1354.     i: integer;
  1355.   begin
  1356.     result := 0;
  1357.     for i := 0 to ListBox1.Count-1 do
  1358.     begin
  1359.       if ListBox1.Items[i] = str then Inc(result);
  1360.     end;
  1361.   end;
  1362.  
  1363. var
  1364.   sNew: string;
  1365. begin
  1366.   // TODO: warn if dependencies are broken
  1367.  
  1368.   if SpinEdit1.Text = '' then exit;
  1369.   CurScene; // verify that a scene exists and is selected
  1370.   sNew := Format('SC%.2d', [SpinEdit1.Value]);
  1371.   ListBox1.Items[ListBox1.ItemIndex] := sNew;
  1372.   Label17.Visible := _CountNumScenes(sNew) > 1;
  1373.   ReloadActionSceneLists;
  1374.   _WriteStringToFilename(@CurScene^.szSceneFolder, ListBox1.Items[ListBox1.ItemIndex]);
  1375. end;
  1376.  
  1377. procedure TForm1.Timer1Timer(Sender: TObject);
  1378. var
  1379.   ms: Cardinal;
  1380. begin
  1381.   ms := GetTickCount - PlayStart;
  1382.   Label18.Caption := FormatDatetime('hh:nn:ss', ms / 1000 / (24*60*60)) + ',' + IntToStr(ms mod 1000 div 100);
  1383. end;
  1384.  
  1385. procedure TForm1.About1Click(Sender: TObject);
  1386. begin
  1387.   ShowMessage('Plumbers Don''t Wear Ties - GAME.BIN editor (can be also used to create new games based on the "ShowTime" engine!)'+#13#10#13#10+'Written by Daniel Marschall (www.daniel-marschall.de)'+#13#10#13#10+'Published by ViaThinkSoft (www.viathinksoft.com)'+#13#10#13#10+'Current version: ' + CUR_VER);
  1388. end;
  1389.  
  1390. procedure TForm1.ActionSpinEditsChange(Sender: TObject);
  1391. begin
  1392.   if TSpinEdit(Sender).Text = '' then exit; // user is about to enter a negative value
  1393.   if TSpinEdit(Sender).Text = '-' then exit; // user is about to enter a negative value
  1394.  
  1395.        if Sender = SpinEdit3  then CurScene^.actions[0].cHotspotTopLeft.X := TSpinEdit(Sender).Value
  1396.   else if Sender = SpinEdit17 then CurScene^.actions[1].cHotspotTopLeft.X := TSpinEdit(Sender).Value
  1397.   else if Sender = SpinEdit7  then CurScene^.actions[2].cHotspotTopLeft.X := TSpinEdit(Sender).Value
  1398.   else if Sender = SpinEdit2  then CurScene^.actions[0].cHotspotTopLeft.Y := TSpinEdit(Sender).Value
  1399.   else if Sender = SpinEdit18 then CurScene^.actions[1].cHotspotTopLeft.Y := TSpinEdit(Sender).Value
  1400.   else if Sender = SpinEdit8  then CurScene^.actions[2].cHotspotTopLeft.Y := TSpinEdit(Sender).Value
  1401.   else if Sender = SpinEdit4  then CurScene^.actions[0].cHotspotBottomRight.X := TSpinEdit(Sender).Value
  1402.   else if Sender = SpinEdit19 then CurScene^.actions[1].cHotspotBottomRight.X := TSpinEdit(Sender).Value
  1403.   else if Sender = SpinEdit10 then CurScene^.actions[2].cHotspotBottomRight.X := TSpinEdit(Sender).Value
  1404.   else if Sender = SpinEdit5  then CurScene^.actions[0].cHotspotBottomRight.Y := TSpinEdit(Sender).Value
  1405.   else if Sender = SpinEdit20 then CurScene^.actions[1].cHotspotBottomRight.Y := TSpinEdit(Sender).Value
  1406.   else if Sender = SpinEdit9  then CurScene^.actions[2].cHotspotBottomRight.Y := TSpinEdit(Sender).Value
  1407.   else if Sender = SpinEdit6  then CurScene^.actions[0].scoreDelta := TSpinEdit(Sender).Value
  1408.   else if Sender = SpinEdit21 then CurScene^.actions[1].scoreDelta := TSpinEdit(Sender).Value
  1409.   else if Sender = SpinEdit11 then CurScene^.actions[2].scoreDelta := TSpinEdit(Sender).Value;
  1410.  
  1411.   RedrawDecisionBitmap;
  1412. end;
  1413.  
  1414. procedure TForm1.RedrawDecisionBitmap;
  1415. var
  1416.   Filename: string;
  1417. begin
  1418.   FileName := string(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + Edit2.Text);
  1419.  
  1420.   Image1.Visible := FileExists(FileName);
  1421.  
  1422.   if not FileExists(FileName) then exit;
  1423.  
  1424.   Image1.Picture.Bitmap.LoadFromFile(FileName);
  1425.   AspectRatio(Image1, Panel1);
  1426.  
  1427.   Image1.Picture.Bitmap.PixelFormat := pf24bit; // Extend the palette, so we have red, green and blue guaranteed.
  1428.  
  1429.   Image1.Canvas.Brush.Style := bsDiagCross;
  1430.  
  1431.   if (SpinEdit3.Value < SpinEdit4.Value) and (SpinEdit2.Value < SpinEdit5.Value) then
  1432.   begin
  1433.     Image1.Canvas.Pen.Color := clRed;
  1434.     Image1.Canvas.Brush.Color := clRed;
  1435.     Image1.Canvas.Rectangle(SpinEdit3.Value,  SpinEdit2.Value,  SpinEdit4.Value,  SpinEdit5.Value);
  1436.   end;
  1437.  
  1438.   if (SpinEdit17.Value < SpinEdit19.Value) and (SpinEdit18.Value < SpinEdit20.Value) then
  1439.   begin
  1440.     Image1.Canvas.Pen.Color := clLime;
  1441.     Image1.Canvas.Brush.Color := clLime;
  1442.     Image1.Canvas.Rectangle(SpinEdit17.Value, SpinEdit18.Value, SpinEdit19.Value, SpinEdit20.Value);
  1443.   end;
  1444.  
  1445.   if (SpinEdit7.Value < SpinEdit10.Value) and (SpinEdit8.Value < SpinEdit9.Value) then
  1446.   begin
  1447.     Image1.Canvas.Pen.Color := clBlue;
  1448.     Image1.Canvas.Brush.Color := clBlue;
  1449.     Image1.Canvas.Rectangle(SpinEdit7.Value,  SpinEdit8.Value,  SpinEdit10.Value, SpinEdit9.Value);
  1450.   end;
  1451. end;
  1452.  
  1453. end.
  1454.