123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803 |
- unit tilepaletteunit;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils, Forms, Controls, ComCtrls, ExtCtrls, fpjson,
- tilepalettedrawerunit, Graphics, StdCtrls, tilesetgraphicsunit,
- BGRABitmapTypes, BGRABitmap, tileselectionunit, palettehelper,
- LCLTranslator;
- type
- { TTilePaletteFrame }
- TTilePaletteType = (tptDrawing, tptEditing);
- TEditedTileSetting = (etsPassability, etsFourDir, etsSingleBit, etsTerrainTag);
- TTilePaletteFrame = class(TFrame)
- IdleTimerDrawPalette: TIdleTimer;
- UpdatingLabel: TLabel;
- TilePalettePaintBox: TPaintBox;
- TilePaletteScrollBox: TScrollBox;
- TilePaletteTabControl: TTabControl;
- procedure IdleTimerDrawPaletteTimer(Sender: TObject);
- procedure TilePalettePaintBoxMouseDown(Sender: TObject;
- Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- procedure TilePalettePaintBoxMouseMove(Sender: TObject; Shift: TShiftState;
- X, Y: Integer);
- procedure TilePalettePaintBoxMouseUp(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure TilePalettePaintBoxPaint(Sender: TObject);
- procedure TilePaletteScrollBoxResize(Sender: TObject);
- procedure TilePaletteTabControlChange(Sender: TObject);
- private
- Drawer: TTilePaletteDrawer;
- PaletteBitmap: TBGRABitmap;
- ResizedBitmap: TBGRACustomBitmap;
- TilesetGraphics: TTilesetGraphics;
- PaletteBeingDrawn: Boolean;
- NeedsResize: Boolean;
- FType: TTilePaletteType;
- {Only used when FType = tptEditing}
- TilesetData: TJSONArray;
- EditedTileSetting: TEditedTileSetting;
- EditedBit: Integer;
- {Only used when FType = tptDrawing}
- SelTab: Integer;
- SelRect: TRect;
- SelStartX, SelStartY: Integer;
- SelStarted: Boolean;
- IsSingleLayer: Boolean;
- IsWorldType: Boolean;
- procedure UpdateSelection(X, Y: Integer);
- function IsSelectionValid: Boolean;
- function MakeSelection: TTileSelection;
- function GetFlags(TileId: Integer): Dword;
- public
- UpdateCallback: SelectionUpdateCallback;
- constructor Create(TheOwner: TComponent); override;
- procedure SetType(AType: TTilePaletteType);
- procedure UpdatePaletteImage;
- procedure UpdatePaletteSize;
- procedure DoPaletteUpdate;
- procedure UpdateFromTileset(ATilesetGraphics: TTilesetGraphics; Tileset: TJSONObject);
- procedure SelectMapLayer(LayerId: Integer);
- procedure SetEditedData(ATilesetData: TJSONArray; AEditedTileSetting: TEditedTileSetting; AEditedBit: Integer = 0);
- //procedure SetEditedSetting();
- destructor Destroy; override;
- end;
- implementation
- uses
- globals, math, Dialogs, constants, Types, autotilehelper;
- {$R *.lfm}
- constructor TTilePaletteFrame.Create(TheOwner: TComponent);
- begin
- inherited;
- Drawer := TTilePaletteDrawer.Create;
- end;
- procedure TTilePaletteFrame.SetType(AType: TTilePaletteType);
- begin
- FType := AType;
- end;
- procedure TTilePaletteFrame.UpdateFromTileset(ATilesetGraphics: TTilesetGraphics; Tileset: TJSONObject);
- var
- Mode: Integer;
- ModeJson: TJSONNumber;
- begin
- Mode := 0;
- if Tileset.Find('mode', ModeJson) then
- Mode := ModeJson.AsInteger;
- TilesetGraphics := ATilesetGraphics;
- SelTab := -1;
- IsWorldType := Mode = 0;
- UpdatePaletteImage;
- TilePalettePaintBox.Visible := False;
- end;
- procedure TTilePaletteFrame.UpdatePaletteImage;
- begin
- if PaletteBitmap <> nil then begin
- PaletteBitmap.Free;
- PaletteBitmap := nil;
- end;
- if TilesetGraphics <> nil then begin
- PaletteBeingDrawn := True;
- UpdatingLabel.Visible := True;
- TilePalettePaintBox.Visible := False;
- IdleTimerDrawPalette.Enabled := True;
- end
- else begin
- if ResizedBitmap <> nil then begin
- ResizedBitmap.Free;
- ResizedBitmap := nil;
- end;
- TilePalettePaintBox.Visible := False;
- end;
- Refresh;
- end;
- procedure TTilePaletteFrame.UpdatePaletteSize;
- var
- NewHeight: Integer;
- begin
- if PaletteBitmap = nil then begin
- TilePalettePaintBox.Visible := False;
- Exit;
- end;
- TilePalettePaintBox.Visible := True;
- NewHeight := PaletteBitmap.Height * (TilePaletteScrollBox.ClientWidth - 20)
- div PaletteBitmap.Width;
- //TODO: remove this hack with 20, add some normal way to get scrollbar width
- //or some way to resize that without going into an endless loop
- TilePalettePaintBox.ClientHeight := NewHeight;
- TilePaletteScrollBox.ClientWidth := TilePaletteScrollBox.ClientWidth - 20;
- if ResizedBitmap <> nil then
- ResizedBitmap.Free;
- ResizedBitmap := PaletteBitmap.Resample(
- TilePalettePaintBox.ClientWidth,
- TilePalettePaintBox.ClientHeight,
- rmSimpleStretch
- );
- end;
- function TTilePaletteFrame.GetFlags(TileId: Integer): Dword;
- begin
- if (TileId >= 0) and (TileId < TilesetData.Count) and (TilesetData[TileId].JSONType = jtNumber) then
- GetFlags := DWord(TilesetData.Integers[TileId])
- else
- GetFlags := GetDefaultTileFlags(TileId);
- end;
- procedure TTilePaletteFrame.TilePalettePaintBoxPaint(Sender: TObject);
- var
- OriginalTileWidth, OriginalTileHeight: Integer;
- ResizedTileWidth, ResizedTileHeight: Double;
- procedure DrawSelection;
- begin
- TilePalettePaintBox.Canvas.Pen.Width := 3;
- TilePalettePaintBox.Canvas.Pen.Color := clWhite;
- TilePalettePaintBox.Canvas.Brush.Style := bsClear;
- TilePalettePaintBox.Canvas.Rectangle(
- Math.floor(SelRect.Left * ResizedTileWidth) + 1,
- Math.floor(SelRect.Top * ResizedTileHeight) + 1,
- Math.ceil(SelRect.Right * ResizedTileWidth) -2,
- Math.ceil(SelRect.Bottom * ResizedTileHeight) -2
- );
- TilePalettePaintBox.Canvas.Pen.Width := 1;
- TilePalettePaintBox.Canvas.Pen.Color := clBlack;
- TilePalettePaintBox.Canvas.Rectangle(
- Math.floor(SelRect.Left * ResizedTileWidth) + 1,
- Math.floor(SelRect.Top * ResizedTileHeight) + 1,
- Math.ceil(SelRect.Right * ResizedTileWidth) - 2,
- Math.ceil(SelRect.Bottom * ResizedTileHeight) - 2
- );
- end;
- procedure DrawFlags;
- var
- X, Y: Integer;
- procedure TextOnTile(Text: String);
- var
- Extent: TSize;
- TextX, TextY: Integer;
- begin
- with TilePalettePaintBox.Canvas do begin
- Extent := TextExtent(Text);
- TextX := Ceil(X * ResizedTileWidth) + (Ceil(ResizedTileWidth) - Extent.cx) div 2;
- TextY := Ceil(Y * ResizedTileHeight) + + (Ceil(ResizedTileHeight) - Extent.cy) div 2;
- Font.Color := clBlack;
- TextOut(TextX -1, TextY -1, Text);
- TextOut(TextX -1, TextY + 1, Text);
- TextOut(TextX +1, TextY -1, Text);
- TextOut(TextX +1, TextY +1, Text);
- TextOut(TextX -1, TextY, Text);
- TextOut(TextX -1, TextY, Text);
- TextOut(TextX, TextY -1, Text);
- TextOut(TextX, TextY +1, Text);
- Font.Color := clWhite;
- TextOut(TextX, TextY, Text);
- end;
- end;
- function GetBit(TileId, BitNumber: Integer): Boolean;
- begin
- GetBit := ((GetFlags(TileId) shr BitNumber) and 1) > 0
- end;
- procedure DrawSingleBitFlag;
- var
- Bit: Boolean;
- Item: String;
- Tile: TPaletteTile;
- begin
- Tile := GetPaletteTile(X, Y, TilePaletteTabControl.TabIndex, TilesetGraphics);
- Bit := GetBit(Tile.MainTileId, EditedBit);
- if Bit then begin
- case EditedBit of
- 5: Item := 'H';
- 6: Item := '≈';
- 7: Item := '◆';
- 8: Item := 'W';
- 9..11: Item := '#';
- else
- Item := '+';
- end;
- end
- else
- Item := '.';
- TextOnTile(Item);
- end;
- procedure DrawTriangle(X1, Y1, X2, Y2, X3, Y3: Integer); inline;
- var
- Points: array [1..3] of TPoint;
- begin
- with TilePalettePaintBox.Canvas do begin
- Brush.Style := bsSolid;
- Pen.Style := psSolid;
- Brush.Color := clWhite;
- Pen.Color := clBlack;
- Points[1] := Point(X1, Y1);
- Points[2] := Point(X2, Y2);
- Points[3] := Point(X3, Y3);
- Polygon(@Points[1], 3, True);
- end;
- end;
- procedure DrawDot(DotX, DotY: Integer); inline;
- begin
- with TilePalettePaintBox.Canvas do begin
- Brush.Style := bsSolid;
- Pen.Style := psSolid;
- Brush.Color := clWhite;
- Pen.Color := clBlack;
- Ellipse(DotX -2, DotY -2, DotX +2, DotY + 2);
- end;
- end;
- procedure DrawPassability;
- var
- Star, FullBlock: Boolean;
- Tile: TPaletteTile;
- begin
- Tile := GetPaletteTile(X, Y, TilePaletteTabControl.TabIndex, TilesetGraphics);
- Star := GetBit(Tile.MainTileId, 4);
- FullBlock := IsFullBlock(GetFlags(Tile.MainTileId));
- if Star then
- TextOnTile('★')
- else if FullBlock then
- TextOnTile('x')
- else
- TextOnTile('o');
- end;
- procedure DrawTerrainTag;
- var
- Tag: Dword;
- Tile: TPaletteTile;
- begin
- Tile := GetPaletteTile(X, Y, TilePaletteTabControl.TabIndex, TilesetGraphics);
- Tag := ((GetFlags(Tile.MainTileId) shr 12) and 7);
- TextOnTile(IntToStr(Tag));
- end;
- procedure DrawFourDir;
- var
- Tile: TPaletteTile;
- TopBlock, LeftBlock, RightBlock, BottomBlock: Boolean;
- begin
- Tile := GetPaletteTile(X, Y, TilePaletteTabControl.TabIndex, TilesetGraphics);
- if IsAutotile(Tile.MainTileId) then
- Exit;
- BottomBlock := GetBit(Tile.MainTileId, 0);
- LeftBlock := GetBit(Tile.MainTileId, 1);
- RightBlock := GetBit(Tile.MainTileId, 2);
- TopBlock := GetBit(Tile.MainTileId, 3);
- if TopBlock then
- DrawDot(
- Round((0.5 + X) * ResizedTileWidth),
- Round((0.25 + Y) * ResizedTileHeight)
- )
- else
- DrawTriangle(
- Round((0.5 + X) * ResizedTileWidth),
- Ceil(Y * ResizedTileHeight),
- Floor((0.4 + X) * ResizedTileWidth),
- Ceil((0.4 + Y) * ResizedTileHeight),
- Ceil((0.6 + X) * ResizedTileWidth),
- Ceil((0.4 + Y) * ResizedTileHeight)
- );
- if LeftBlock then
- DrawDot(
- Round((0.25 + X) * ResizedTileWidth),
- Round((0.5 + Y) * ResizedTileHeight)
- )
- else
- DrawTriangle(
- Floor(X * ResizedTileWidth),
- Round((0.5 + Y) * ResizedTileHeight),
- Ceil((0.4 + X) * ResizedTileWidth),
- Ceil((0.6 + Y) * ResizedTileHeight),
- Ceil((0.4 + X) * ResizedTileWidth),
- Floor((0.4 + Y) * ResizedTileHeight)
- );
- if RightBlock then
- DrawDot(
- Round((0.75 + X) * ResizedTileWidth),
- Round((0.5 + Y) * ResizedTileHeight)
- )
- else
- DrawTriangle(
- Ceil((1 + X) * ResizedTileWidth),
- Round((0.5 + Y) * ResizedTileHeight),
- Floor((0.6 + X) * ResizedTileWidth),
- Ceil((0.6 + Y) * ResizedTileHeight),
- Floor((0.6 + X) * ResizedTileWidth),
- Floor((0.4 + Y) * ResizedTileHeight)
- );
- if BottomBlock then
- DrawDot(
- Round((0.5 + X) * ResizedTileWidth),
- Round((0.75 + Y) * ResizedTileHeight)
- )
- else
- DrawTriangle(
- Round((0.5 + X) * ResizedTileWidth),
- Ceil((Y + 1) * ResizedTileHeight),
- Floor((0.4 + X) * ResizedTileWidth),
- Ceil((0.6 + Y) * ResizedTileHeight),
- Ceil((0.6 + X) * ResizedTileWidth),
- Ceil((0.6 + Y) * ResizedTileHeight)
- );
- end;
- procedure DrawFlagsForCell;
- begin
- case EditedTileSetting of
- etsPassability: DrawPassability;
- etsFourDir: DrawFourDir;
- etsSingleBit: DrawSingleBitFlag;
- etsTerrainTag: DrawTerrainTag;
- end;
- end;
- var
- XEnd, YEnd: Integer;
- begin
- TilePalettePaintBox.Canvas.Brush.Style := bsClear;
- {TODO: edit it to include only visible parts of the scrollbox}
- XEnd := (PaletteBitmap.Width div OriginalTileWidth) - 1;
- YEnd := (PaletteBitmap.Height div OriginalTileHeight) -1;
- for X := 0 to XEnd do
- for Y := 0 to YEnd do
- DrawFlagsForCell;
- end;
- begin
- if (ResizedBitmap <> nil) and (PaletteBitmap <> nil) then begin
- ResizedBitmap.Draw(TilePalettePaintBox.Canvas, 0, 0, True);
- OriginalTileWidth := 48; //TODO: adapt for tilewidth <> 48
- OriginalTileHeight := 48; //TODO: adapt for tileheight <> 48
- ResizedTileWidth := OriginalTileWidth * ResizedBitmap.Width / PaletteBitmap.Width;
- ResizedTileHeight := OriginalTileHeight * ResizedBitmap.Height / PaletteBitmap.Height;
- if (SelTab = TilePaletteTabControl.TabIndex) and IsSelectionValid then
- DrawSelection;
- if FType = tptEditing then
- DrawFlags;
- end;
- end;
- procedure TTilePaletteFrame.DoPaletteUpdate;
- var
- TileType: Integer;
- begin
- if TilesetGraphics <> nil then begin
- TileType := TilePaletteTabControl.TabIndex;
- PaletteBitmap := Drawer.MakePaletteBitmap(TileType, TilesetGraphics, True);
- UpdatingLabel.Visible := False;
- TilePalettePaintBox.Visible := True;
- PaletteBeingDrawn := False;
- IdleTimerDrawPalette.Enabled := False;
- UpdatePaletteSize;
- end;
- end;
- procedure TTilePaletteFrame.IdleTimerDrawPaletteTimer(Sender: TObject);
- begin
- if PaletteBeingDrawn then
- DoPaletteUpdate;
- if NeedsResize then begin
- UpdatePaletteSize;
- NeedsResize := False;
- end;
- end;
- procedure TTilePaletteFrame.TilePalettePaintBoxMouseDown(Sender: TObject;
- Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- begin
- if FType = tptDrawing then begin
- SelStartX := X;
- SelStartY := Y;
- SelStarted := True;
- end;
- end;
- procedure TTilePaletteFrame.TilePalettePaintBoxMouseMove(Sender: TObject;
- Shift: TShiftState; X, Y: Integer);
- begin
- if SelStarted then begin
- UpdateSelection(X, Y);
- Refresh
- end;
- end;
- procedure TTilePaletteFrame.TilePalettePaintBoxMouseUp(Sender: TObject;
- Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- procedure EditSelectedTile;
- var
- Tile: TPaletteTile;
- ResizedTileWidth, ResizedTileHeight: Double;
- TileX, TileY: Integer;
- Mask: Dword;
- procedure ToggleBit(BitNumber: Integer);
- var
- Bit, NewBit: Boolean;
- I: Integer;
- begin
- Bit := ((DWord(TilesetData.Integers[Tile.MainTileId]) shr BitNumber) and 1) > 0;
- NewBit := not Bit;
- Mask := 1 shl BitNumber;
- { TODO: handle nulls here }
- for I := Tile.StartTileId to Tile.EndTileId do
- if NewBit then
- TilesetData.Integers[I] := DWord(TilesetData.Integers[I]) or Mask
- else
- TilesetData.Integers[I] := DWord(TilesetData.Integers[I]) and not Mask
- end;
- procedure ToggleDirection;
- var
- PosX, PosY: Double;
- UnderLRDiagonal, UnderRLDiagonal: Boolean;
- {
- ^ / ^\
- | / | \
- | / | \
- |/ | \
- +-------> +----->
- LR diagonal RL diagonal
- \ over RL /
- \over LR/
- \ Top/
- \ /
- underRL\ / under LR
- Left X Right
- over LR/ \ over RL
- / \
- / \
- / Bottom\
- / underLR \
- / under RL \
- }
- begin
- if IsAutotile(Tile.MainTileId) then
- Exit;
- PosX := X / ResizedTileWidth - TileX;
- PosY := Y / ResizedTileHeight - TileY;
- UnderLRDiagonal := PosX < PosY;
- UnderRLDiagonal := (1.0 - PosX) < PosY;
- if UnderLRDiagonal and UnderRLDiagonal then
- ToggleBit(0) //bottom
- else if not UnderLRDiagonal and UnderRLDiagonal then
- ToggleBit(2) //right
- else if UnderLRDiagonal and not UnderRLDiagonal then
- ToggleBit(1) //left
- else
- ToggleBit(3) //top
- end;
- procedure ChangeTerrainTag;
- var
- Tag: Integer;
- RemoveMask, AddMask: Dword;
- I: Integer;
- begin
- RemoveMask := not (7 shl 12);
- { TODO: handle nulls here }
- Tag := ((DWord(TilesetData.Integers[Tile.MainTileId]) shr 12) and 7);
- if Button = mbRight then
- Dec(Tag)
- else if Button = mbLeft then
- Inc(Tag);
- if Tag < 0 then
- Tag := Tag + 7;
- if Tag > 7 then
- Tag := Tag - 7;
- AddMask := Tag shl 12;
- for I := Tile.StartTileId to Tile.EndTileId do
- TilesetData.Integers[I] := (DWord(TilesetData.Integers[I]) and RemoveMask)
- or AddMask;
- end;
- procedure TogglePassability;
- var
- Star, FullBlock: Boolean;
- TypeIndex: Integer; //1 is o, 2 is x, 3 is *
- RemoveMask, AddMask: DWord;
- I: Integer;
- begin
- Star := ((DWord(TilesetData.Integers[Tile.MainTileId]) shr 4) and 1) > 0;
- FullBlock := IsFullBlock(DWord(TilesetData.Integers[Tile.MainTileId]));
- if IsAutotile(Tile.MainTileId) then begin
- if FullBlock then
- AddMask := 0
- else
- AddMask := 15;
- end else begin
- if Star then
- TypeIndex := 3
- else if FullBlock then
- TypeIndex := 2
- else
- TypeIndex := 1;
- if Button = mbLeft then
- Inc(TypeIndex)
- else if Button = mbRight then
- Dec(TypeIndex);
- if TypeIndex = 0 then
- TypeIndex := 3;
- if TypeIndex = 4 then
- TypeIndex := 1;
- if TypeIndex = 1 then begin
- AddMask := 0;
- end else if TypeIndex = 2 then begin
- AddMask := 15;
- end else begin
- AddMask := 16;
- end;
- end;
- //left: ox*
- RemoveMask := not 31;
- { TODO: handle nulls here }
- for I := Tile.StartTileId to Tile.EndTileId do
- TilesetData.Integers[I] := (DWord(TilesetData.Integers[I]) and RemoveMask)
- or AddMask;
- end;
- begin
- ResizedTileWidth := 48 * ResizedBitmap.Width / PaletteBitmap.Width; //TODO: adapt for tilewidth <> 48
- ResizedTileHeight := 48 * ResizedBitmap.Height / PaletteBitmap.Height; //TODO: adapt for tilewidth <> 48
- TileX := Floor(X / ResizedTileWidth);
- TileY := Floor(Y / ResizedTileHeight);
- Tile := GetPaletteTile(TileX, TileY, TilePaletteTabControl.TabIndex, TilesetGraphics);
- while Tile.EndTileId >= TilesetData.Count do
- TilesetData.Add(0); { TODO: verify this is the correct default value }
- case EditedTileSetting of
- etsPassability: TogglePassability;
- etsFourDir: ToggleDirection;
- etsSingleBit: ToggleBit(EditedBit);
- etsTerrainTag: ChangeTerrainTag;
- end;
- end;
- begin
- if FType = tptDrawing then begin
- UpdateSelection(X, Y);
- SelStarted := False;
- if UpdateCallback <> nil then
- UpdateCallback(MakeSelection);
- end else if FType = tptEditing then
- EditSelectedTile;
- Refresh;
- end;
- procedure TTilePaletteFrame.UpdateSelection(X, Y: Integer);
- var
- ResizedTileWidth, ResizedTileHeight: Double;
- begin
- if (ResizedBitmap = nil) or (PaletteBitmap = nil) then
- Exit;
- ResizedTileWidth := 48 * ResizedBitmap.Width / PaletteBitmap.Width; //TODO: adapt for tilewidth <> 48
- ResizedTileHeight := 48 * ResizedBitmap.Height / PaletteBitmap.Height; //TODO: adapt for tilewidth <> 48
- SelTab := TilePaletteTabControl.TabIndex;
- if SelStartX < X then begin
- SelRect.Left := Floor(SelStartX / ResizedTileWidth);
- SelRect.Right := Min(
- Ceil(X / ResizedTileWidth),
- PaletteBitmap.Width div 48);
- end
- else begin
- SelRect.Left := Max(0, Floor(X / ResizedTileWidth));
- SelRect.Right := Ceil(SelStartX / ResizedTileWidth);
- end;
- if SelStartY < Y then begin
- SelRect.Top := Floor(SelStartY / ResizedTileHeight);
- SelRect.Bottom := Min(
- Ceil(Y / ResizedTileHeight),
- PaletteBitmap.Height div 48);
- end
- else begin
- SelRect.Top := Max(0, Floor(Y / ResizedTileHeight));
- SelRect.Bottom := Ceil(SelStartY / ResizedTileHeight);
- end;
- if SelRect.Right = SelRect.Left then
- Inc(SelRect.Right);
- if SelRect.Bottom = SelRect.Top then
- Inc(SelRect.Bottom);
- end;
- function TTilePaletteFrame.MakeSelection: TTileSelection;
- var
- Sel: TTileSelection;
- X, Y: Integer;
- ATileSelectFn: ATileSelectionCallback;
- ATileStartY: Integer;
- begin
- if SelTab < 0 then begin
- MakeSelection := nil;
- Exit;
- end;
- Sel := TTileSelection.Create;
- Sel.Init(
- SelRect.Right - SelRect.Left,
- SelRect.Bottom - SelRect.Top,
- IsSingleLayer
- );
- for Y := SelRect.Top to SelRect.Bottom do begin
- for X := SelRect.Left to SelRect.Right do begin
- if SelTab = 0 then begin
- ATileSelectFn := Sel.GetATileSelectFn(Y, TilesetGraphics, ATileStartY);
- ATileSelectFn(X - SelRect.Left, Y - SelRect.Top, ATileStartY, Y * 8 + X, IsWorldType)
- end
- else if SelTab > 0 then
- Sel.SelectUpperTile(X-SelRect.Left, Y-SelRect.Top, SelTab, Y * 8 + X);
- end;
- end;
- MakeSelection := Sel;
- end;
- function TTilePaletteFrame.IsSelectionValid: Boolean;
- begin
- IsSelectionValid := (SelTab > -1) and (SelRect.Left <> SelRect.Right)
- and (SelRect.Top <> SelRect.Bottom);
- end;
- procedure TTilePaletteFrame.TilePaletteScrollBoxResize(Sender: TObject);
- begin
- NeedsResize := True;
- IdleTimerDrawPalette.Enabled := True;
- end;
- procedure TTilePaletteFrame.TilePaletteTabControlChange(Sender: TObject);
- begin
- UpdatePaletteImage
- end;
- procedure TTilePaletteFrame.SelectMapLayer(LayerId: Integer);
- var
- NeedsSelectionReset: Boolean;
- begin
- NeedsSelectionReset := (LayerId <> LAYER_ALL) <> IsSingleLayer;
- IsSingleLayer := (LayerId <> LAYER_ALL);
- if NeedsSelectionReset then begin
- SelTab := -1;
- SelRect := Rect(0, 0, 0, 0);
- if UpdateCallback <> nil then
- UpdateCallback(MakeSelection);
- Refresh;
- end;
- end;
- procedure TTilePaletteFrame.SetEditedData(ATilesetData: TJSONArray;
- AEditedTileSetting: TEditedTileSetting; AEditedBit: Integer);
- begin
- TilesetData := ATilesetData;
- EditedTileSetting := AEditedTileSetting;
- EditedBit := AEditedBit;
- TilePalettePaintBox.Refresh;
- end;
- destructor TTilePaletteFrame.Destroy;
- begin
- if Drawer <> nil then
- Drawer.Free;
- if PaletteBitmap <> nil then
- PaletteBitmap.Free;
- inherited;
- end;
- end.
|