Login | ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/plumbers/trunk/SceneEditor/Unit1.pas
Revision: 14
Committed: Sun Oct 8 09:49:24 2017 UTC (4 years ago) by daniel-marschall
Content type: text/x-pascal
File size: 44959 byte(s)

File Contents

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