/trunk/FileFormat/Delphi/GameBinStruct.pas |
---|
55,6 → 55,9 |
scenes: array[0..99] of TSceneDef; // Scenes start at 0x0016 |
pictures: array[0..1999] of TPictureDef; // Pictures start at 0x2596 |
class function MaxSceneCount: integer; static; |
class function MaxPictureCount: integer; static; |
function AddSceneAtEnd(SceneID: integer): PSceneDef; |
procedure DeleteScene(SceneIndex: integer); |
procedure SwapScene(IndexA, IndexB: integer); |
63,6 → 66,8 |
function AddPictureBetween(Index: integer; assignToUpperScene: boolean=true): PPictureDef; |
function RealPictureCount: integer; |
function RealActionCount: integer; |
function Defrag(OnlyCheck: boolean=false): boolean; |
function BiggestUsedPictureIndex: integer; |
end; |
procedure _WriteStringToFilename(x: PAnsiFileName; s: AnsiString); |
78,10 → 83,23 |
StrPLCopy(x^, s, Length(x^)); |
end; |
function TGameBinFile.BiggestUsedPictureIndex: integer; |
var |
iScene, candidate: integer; |
begin |
result := -1; |
for iScene := 0 to Self.numScenes - 1 do |
begin |
candidate := Self.scenes[iScene].pictureIndex + Self.scenes[iScene].numPics - 1; |
if candidate > result then result := candidate; |
end; |
end; |
function TGameBinFile.AddSceneAtEnd(SceneID: integer): PSceneDef; |
begin |
if Self.numScenes >= Length(Self.scenes) then raise Exception.Create('No more space for another scene'); |
if sceneID >= Length(Self.scenes) then raise Exception.Create('SceneID is too large.'); |
if Self.numScenes >= Length(Self.scenes) then raise Exception.Create('Not enough space for another scene'); |
if SceneID < 0 then raise Exception.Create('Invalid scene ID'); |
if sceneID >= Length(Self.scenes) then raise Exception.Create('SceneID is too large.'); // TODO: I think this is not correct. This is the scene *ID* |
result := @Self.scenes[Self.numScenes]; |
ZeroMemory(result, SizeOf(TSceneDef)); |
_WriteStringToFilename(@result.szSceneFolder, AnsiString(Format('SC%.2d', [sceneID]))); |
99,6 → 117,22 |
Dec(Self.numScenes); |
end; |
class function TGameBinFile.MaxPictureCount: integer; |
var |
dummy: TGameBinFile; |
begin |
dummy.numScenes := 1; // avoid compiler give a warning |
result := Length(dummy.pictures); |
end; |
class function TGameBinFile.MaxSceneCount: integer; |
var |
dummy: TGameBinFile; |
begin |
dummy.numScenes := 1; // avoid compiler give a warning |
result := Length(dummy.scenes); |
end; |
function TGameBinFile.RealActionCount: integer; |
var |
iScene: integer; |
132,6 → 166,45 |
CopyMemory(@Self.scenes[IndexB], @bakScene, SizeOf(TSceneDef)); |
end; |
function TGameBinFile.Defrag(OnlyCheck: boolean=false): boolean; |
var |
iPicture, iScene, iScene2: integer; |
isGap: boolean; |
begin |
result := false; |
for iPicture := MaxPictureCount - 1 downto 0 do |
begin |
isGap := true; |
for iScene := 0 to Self.numScenes - 1 do |
begin |
if (iPicture >= Self.scenes[iScene].pictureIndex) and |
(iPicture <= Self.scenes[iScene].pictureIndex + Self.scenes[iScene].numPics - 1) then |
begin |
isGap := false; |
break; |
end; |
end; |
if isGap then |
begin |
result := true; |
if not OnlyCheck then |
begin |
{$REGION 'Close the gap'} |
for iScene2 := 0 to Self.numScenes - 1 do |
begin |
if (iPicture < Self.scenes[iScene2].pictureIndex) then |
begin |
Dec(Self.scenes[iScene2].pictureIndex); |
end; |
end; |
CopyMemory(@Self.pictures[iPicture], @Self.pictures[iPicture+1], (Length(Self.pictures)-iPicture-1)*SizeOf(TPictureDef)); |
ZeroMemory(@Self.pictures[Length(Self.pictures)-1], SizeOf(TPictureDef)); |
{$ENDREGION} |
end; |
end; |
end; |
end; |
procedure TGameBinFile.DeletePicture(PictureIndex: integer); |
var |
iScene, iScene2: integer; |
164,11 → 237,11 |
end; |
end; |
If (PictureIndex+protection < Length(Self.pictures)-1) and (protection = 0) then |
If (PictureIndex < Length(Self.pictures)-1) and (protection = 0) then |
begin |
CopyMemory(@Self.pictures[PictureIndex+protection], @Self.pictures[PictureIndex+protection+1], (Length(Self.pictures)-PictureIndex+protection-1)*SizeOf(TPictureDef)); |
CopyMemory(@Self.pictures[PictureIndex], @Self.pictures[PictureIndex+1], (Length(Self.pictures)-PictureIndex-1)*SizeOf(TPictureDef)); |
ZeroMemory(@Self.pictures[Length(Self.pictures)-1], SizeOf(TPictureDef)); |
end; |
ZeroMemory(@Self.pictures[Length(Self.pictures)-1], SizeOf(TPictureDef)); |
Dec(Self.numPics); |
end; |
207,9 → 280,14 |
var |
iScene: integer; |
begin |
if Self.numPics >= Length(Self.pictures) then raise Exception.Create('No more space for another picture'); |
if ((Index < 0) or (Index >= Length(Self.pictures))) then raise Exception.Create('Invalid picture index'); |
if (BiggestUsedPictureIndex = MaxPictureCount-1) and Defrag(true) then |
raise Exception.Create('Not enough space for another picture. Please defrag to fill the gaps first.'); |
if Self.numPics >= MaxPictureCount then |
raise Exception.Create('Not enough space for another picture. Maximum limit reached.'); |
if assignToUpperScene then |
begin |
// Sc1 Sc2 Sc1 Sc2 |
/trunk/SceneEditor/Unit1.dfm |
---|
454,8 → 454,6 |
TabOrder = 17 |
object TabSheet6: TTabSheet |
Caption = 'Scene length' |
ExplicitWidth = 281 |
ExplicitHeight = 165 |
object Label20: TLabel |
Left = 16 |
Top = 15 |
488,8 → 486,6 |
object TabSheet7: TTabSheet |
Caption = 'Stats' |
ImageIndex = 1 |
ExplicitWidth = 281 |
ExplicitHeight = 165 |
object Label34: TLabel |
Left = 16 |
Top = 16 |
547,11 → 543,27 |
Caption = '---' |
end |
end |
object TabSheet8: TTabSheet |
Caption = 'Misc' |
ImageIndex = 2 |
object Button20: TButton |
Left = 11 |
Top = 19 |
Width = 75 |
Height = 25 |
Caption = 'Defrag' |
TabOrder = 0 |
OnClick = Button20Click |
end |
end |
end |
end |
object TabSheet5: TTabSheet |
Caption = 'Decision' |
ImageIndex = 1 |
DesignSize = ( |
791 |
575) |
object Label3: TLabel |
Left = 16 |
Top = 16 |
617,7 → 629,7 |
Top = 64 |
Width = 365 |
Height = 185 |
ActivePage = TabSheet3 |
ActivePage = TabSheet1 |
TabOrder = 3 |
object TabSheet1: TTabSheet |
Caption = 'Action 1 (Red)' |
925,7 → 937,7 |
Width = 409 |
Height = 291 |
BevelOuter = bvNone |
TabOrder = 4 |
TabOrder = 5 |
object Image1: TImage |
Left = 0 |
Top = 1 |
939,8 → 951,18 |
OnMouseMove = Image1MouseMove |
end |
end |
object CheckBox1: TCheckBox |
Left = 651 |
Top = 547 |
Width = 137 |
Height = 17 |
Anchors = [akRight, akBottom] |
Caption = 'Show disabled hotspots' |
TabOrder = 4 |
OnClick = CheckBox1Click |
end |
end |
end |
object Button14: TButton |
Left = 8 |
Top = 534 |
952,11 → 974,11 |
OnClick = Button14Click |
end |
object Button19: TButton |
Left = 136 |
Left = 119 |
Top = 534 |
Width = 81 |
Width = 98 |
Height = 25 |
Caption = 'Undo all' |
Caption = 'Discard changes' |
TabOrder = 6 |
OnClick = Button19Click |
end |
/trunk/SceneEditor/Unit1.pas |
---|
4,12 → 4,13 |
// - change the icon to something else |
// - add open-dialogs for choosing the bmp and wav files |
// TODO: Give controls better names |
// Idea: When actions are deleted, remove the colorful marking on the picture? |
// Idea: decision bitmap markings: anti moiree? |
// TODO: When loading the file, check if dependencies are broken and output a warning |
// Idea: About the hotspot / action markings: |
// - anti moiree? |
// - allow user to draw a rectangle with drag'n'drop instead of left and right mouse button. |
// also, automatically determine the left/top and right/bottom border, so the user can draw the rectange in every direction |
// Idea: unused liste auch bei decision page anzeigen |
// Idea: hotspots: netz ziehen anstelle linke und rechts maustaste. netz in jede beliebige richtung ziehen und topleft/bottomright automatisch bestimmen |
// Idea: Automatic correct wrong Game.numScenes/numPics values? (especially since we rely on them when adding a scene) |
// Idea: "defragmentation": shift all pictures to the left if a scene has a higher "numPics" value than actual pictures |
// Idea: Function to re-order stuff? |
interface |
137,6 → 138,9 |
Label31: TLabel; |
Label36: TLabel; |
Label37: TLabel; |
CheckBox1: TCheckBox; |
TabSheet8: TTabSheet; |
Button20: TButton; |
procedure ListBox1Click(Sender: TObject); |
procedure Edit1Change(Sender: TObject); |
procedure Edit2Change(Sender: TObject); |
185,6 → 189,8 |
procedure ListBox3Click(Sender: TObject); |
procedure Button19Click(Sender: TObject); |
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); |
procedure Button20Click(Sender: TObject); |
procedure CheckBox1Click(Sender: TObject); |
private |
Game: TGameBinFile; |
GameBak: TGameBinFile; |
610,9 → 616,12 |
procedure TForm1.Button19Click(Sender: TObject); |
begin |
if MessageDlg('Are you sure you want to discard all changes?', mtConfirmation, mbYesNoCancel, 0) = mrYes then |
begin |
CopyMemory(@Game, @GameBak, SizeOf(Game)); |
SetupGUIAfterLoad; |
end; |
end; |
procedure TForm1.NewScene; |
var |
642,6 → 651,12 |
NewScene; |
end; |
procedure TForm1.Button20Click(Sender: TObject); |
begin |
Game.Defrag; |
RecalcStats; |
end; |
procedure TForm1.Button2Click(Sender: TObject); |
var |
iScene, iAction, sceneID: integer; |
860,16 → 875,16 |
if not CompareMem(@Game, @GameBak, SizeOf(Game)) then |
begin |
case MessageDlg('Do you want to save the changes?', mtConfirmation, mbYesNoCancel, 0) of |
ID_YES: |
mrYes: |
begin |
Save; |
CanClose := true; |
end; |
ID_NO: |
mrNo: |
begin |
CanClose := true; |
end; |
ID_CANCEL: |
mrCancel: |
begin |
CanClose := false; |
end; |
912,6 → 927,11 |
Button16Click(Button16); |
end; |
procedure TForm1.CheckBox1Click(Sender: TObject); |
begin |
RedrawDecisionBitmap; |
end; |
procedure TForm1.Close1Click(Sender: TObject); |
begin |
Close; |
1069,6 → 1089,13 |
procedure TForm1.New; |
begin |
PageControl1.ActivePageIndex := 0; |
PageControl2.ActivePageIndex := 0; |
PageControl3.ActivePageIndex := 0; |
Label10.Caption := ''; |
Label21.Caption := ''; |
Label23.Caption := ''; |
ZeroMemory(@Game, SizeOf(Game)); |
ZeroMemory(@GameBak, SizeOf(Game)); |
1086,6 → 1113,8 |
FreeAndNil(fs); |
end; |
CopyMemory(@GameBak, @Game, SizeOf(Game)); |
if Game.RealPictureCount <> Game.numPics then |
begin |
MessageDlg('Picture count was wrong. Value was corrected.', mtInformation, [mbOk], 0); |
1092,8 → 1121,6 |
Game.numPics := Game.RealPictureCount; |
end; |
CopyMemory(@GameBak, @Game, SizeOf(Game)); |
SetupGUIAfterLoad; |
end; |
1337,6 → 1364,7 |
// QUE: zero data of actions which are inactive (numActions<action)? |
RecalcStats; |
RedrawDecisionBitmap; |
end; |
procedure TForm1.SpinEdit13Change(Sender: TObject); |
1428,7 → 1456,8 |
Image1.Canvas.Brush.Style := bsDiagCross; |
if (SpinEdit3.Value < SpinEdit4.Value) and (SpinEdit2.Value < SpinEdit5.Value) then |
if (CheckBox1.Checked or (CurScene^.numActions >= 1)) and |
(SpinEdit3.Value < SpinEdit4.Value) and (SpinEdit2.Value < SpinEdit5.Value) then |
begin |
Image1.Canvas.Pen.Color := clRed; |
Image1.Canvas.Brush.Color := clRed; |
1435,7 → 1464,8 |
Image1.Canvas.Rectangle(SpinEdit3.Value, SpinEdit2.Value, SpinEdit4.Value, SpinEdit5.Value); |
end; |
if (SpinEdit17.Value < SpinEdit19.Value) and (SpinEdit18.Value < SpinEdit20.Value) then |
if (CheckBox1.Checked or (CurScene^.numActions >= 2)) and |
(SpinEdit17.Value < SpinEdit19.Value) and (SpinEdit18.Value < SpinEdit20.Value) then |
begin |
Image1.Canvas.Pen.Color := clLime; |
Image1.Canvas.Brush.Color := clLime; |
1442,7 → 1472,8 |
Image1.Canvas.Rectangle(SpinEdit17.Value, SpinEdit18.Value, SpinEdit19.Value, SpinEdit20.Value); |
end; |
if (SpinEdit7.Value < SpinEdit10.Value) and (SpinEdit8.Value < SpinEdit9.Value) then |
if (CheckBox1.Checked or (CurScene^.numActions >= 3)) and |
(SpinEdit7.Value < SpinEdit10.Value) and (SpinEdit8.Value < SpinEdit9.Value) then |
begin |
Image1.Canvas.Pen.Color := clBlue; |
Image1.Canvas.Brush.Color := clBlue; |