unit UnitMain;

interface

uses
  Windows, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DXDraws, DXClass, DXSprite, ActnList, ComCtrls,
  ExtCtrls, ImgList, StdCtrls, Buttons, Menus, DIB,
  MenuToolBar, Spin, ToolWin, ShellApi, ExtDlgs, IdBaseComponent,
  IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, IniFiles, ShlObj,
  Messages,
  { Selbst definiert }
  UnitGrid, UnitMapProp, Sprites, UnitList,
  WindowsUtils, GraphicUtils, DXMap;

type
  TMode = (mDesinging, mTesting);

  TCursorSprite = class(TImageSprite);

  TFormMain = class(TDXForm)
    Panel1: TPanel;
    StatusBar1: TStatusBar;
    ActionList1: TActionList;
    DXSpriteEngine1: TDXSpriteEngine;
    DXTimer1: TDXTimer;
    DXImageListLib: TDXImageList;
    OpenDialog1: TAction;
    SaveDialog1: TAction;
    ExitDialog1: TAction;
    OpenLibDialog1: TAction;
    Undo1: TAction;
    AboutDialog1: TAction;
    ImageList1: TImageList;
    Panel4: TPanel;
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    OpenMap1: TMenuItem;
    SaveDialog11: TMenuItem;
    AboutDialog11: TMenuItem;
    NewDialog1: TAction;
    SaveDialog12: TMenuItem;
    N1: TMenuItem;
    ExitDialog11: TMenuItem;
    Library1: TMenuItem;
    OpenImage1: TMenuItem;
    Map1: TMenuItem;
    Object1: TMenuItem;
    Help1: TMenuItem;
    Help2: TMenuItem;
    Undo2: TMenuItem;
    Run1: TAction;
    Stop1: TAction;
    Test1: TMenuItem;
    Run2: TMenuItem;
    Pause1: TMenuItem;
    OpenDialog2: TOpenDialog;
    DXImageListEditor: TDXImageList;
    Properties1: TAction;
    Properties2: TMenuItem;
    List1: TAction;
    N2: TMenuItem;
    List2: TMenuItem;
    Panel11: TPanel;
    Grids1: TAction;
    DXDraw1: TDXDraw;
    Preferences2: TAction;
    Options1: TMenuItem;
    Preferences1: TMenuItem;
    N3: TMenuItem;
    View1: TMenuItem;
    ViewGrid1: TMenuItem;
    GridsHelpLines1: TMenuItem;
    ViewHelpLines1: TMenuItem;
    Information1: TAction;
    Panel2: TPanel;
    GroupBox1: TGroupBox;
    BitBtnUp: TBitBtn;
    BitBtnLeft: TBitBtn;
    BitBtnDown: TBitBtn;
    BitBtnRight: TBitBtn;
    Panel10: TPanel;
    SpinEditScroll: TSpinEdit;
    Panel3: TPanel;
    PageControl2: TPageControl;
    TabSheet3: TTabSheet;
    Panel5: TPanel;
    CheckBoxStretch: TCheckBox;
    PanelX: TPanel;
    PanelY: TPanel;
    TabSheet4: TTabSheet;
    Panel6: TPanel;
    SpinEditZ: TSpinEdit;
    Panel9: TPanel;
    SpinEditType: TSpinEdit;
    Panel12: TPanel;
    EditName: TEdit;
    Panel13: TPanel;
    ListBoxLib: TListBox;
    Panel14: TPanel;
    OpenAppendLibDialog1: TAction;
    AppendLibrary1: TMenuItem;
    ColorPanel: TPanel;
    ImagePreview: TImage;
    Panel15: TPanel;
    ColorPreviewPanel: TPanel;
    SaveDialog2: TSaveDialog;
    PopupMenu1: TPopupMenu;
    Addbitmap1: TMenuItem;
    N4: TMenuItem;
    Savelibrary1: TMenuItem;
    OpenAppendBitmapDialog1: TAction;
    SaveLibDialog1: TAction;
    ToolBar1: TToolBar;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    ToolButton6: TToolButton;
    ToolButton8: TToolButton;
    ToolButton9: TToolButton;
    ToolButton10: TToolButton;
    ToolButton11: TToolButton;
    ToolButton12: TToolButton;
    ToolButton13: TToolButton;
    OpenPictureDialog1: TOpenPictureDialog;
    SpeedButtonTrans: TSpeedButton;
    ToolButton7: TToolButton;
    Update1: TAction;
    Checkupdate1: TMenuItem;
    N5: TMenuItem;
    Http: TIdHTTP;
    ToolButton14: TToolButton;
    ToolButton15: TToolButton;
    N6: TMenuItem;
    Appendlibrary2: TMenuItem;
    N7: TMenuItem;
    Savelibrary2: TMenuItem;
    Label1: TLabel;
    Label2: TLabel;
    BitBtnOrg: TBitBtn;
    BitBtnCenter: TBitBtn;
    TabSheet1: TTabSheet;
    TileSetup1: TAction;
    ToolButton16: TToolButton;
    ToolButton17: TToolButton;
    ToolButton18: TToolButton;
    Panel16: TPanel;
    PageControl1: TPageControl;
    SpriteSetup: TTabSheet;
    TileSetup: TTabSheet;
    ListBoxPats: TListBox;
    Panel20: TPanel;
    ComboBoxImages: TComboBox;
    GroupBox2: TGroupBox;
    Panel8: TPanel;
    SpinEditSkipHeight: TSpinEdit;
    Panel7: TPanel;
    SpinEditSkipWidth: TSpinEdit;
    GroupBox3: TGroupBox;
    Panel17: TPanel;
    SpinEditPatWidth: TSpinEdit;
    Panel18: TPanel;
    SpinEditPatHeight: TSpinEdit;
    Panel19: TPanel;
    LabelCount: TLabel;
    BitBtnUpdProps: TBitBtn;
    ileSetup1: TMenuItem;
    Panel21: TPanel;
    SpinEditSpeed1: TSpinEdit;
    SpinEditSpeed2: TSpinEdit;
    Label3: TLabel;
    Panel22: TPanel;
    SpinEditAnimStart: TSpinEdit;
    DXMap1: TDXMap;
    procedure ExitDialog1Execute(Sender: TObject);
    procedure OpenLibDialog1Execute(Sender: TObject);
    procedure ListBoxLibClick(Sender: TObject);
    procedure CheckBoxStretchClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure DXDraw1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure DXTimer1Timer(Sender: TObject; LagCount: Integer);
    procedure DXDraw1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure BitBtnMoveClick(Sender: TObject);
    procedure Undo1Execute(Sender: TObject);
    procedure FormKeyPress(Sender: TObject; var Key: Char);
    procedure SpinEditZChange(Sender: TObject);
    procedure Properties1Execute(Sender: TObject);
    procedure OpenAppendLibDialog1Execute(Sender: TObject);
    procedure NewDialog1Execute(Sender: TObject);
    procedure ImagePreviewMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure ImagePreviewClick(Sender: TObject);
    procedure SaveDialog1Execute(Sender: TObject);
    procedure List1Execute(Sender: TObject);
    procedure PopupMenu1Popup(Sender: TObject);
    procedure ListBoxLibDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure SaveLibDialog1Execute(Sender: TObject);
    procedure OpenAppendBitmapDialog1Execute(Sender: TObject);
    procedure SpeedButtonTransClick(Sender: TObject);
    procedure Update1Execute(Sender: TObject);
    procedure OpenDialog1Execute(Sender: TObject);
    procedure AboutDialog1Execute(Sender: TObject);
    procedure TileSetupShow(Sender: TObject);
    procedure ComboBoxImagesDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure ComboBoxImagesChange(Sender: TObject);
    procedure BitBtnUpdPropsClick(Sender: TObject);
    procedure SpinEditChange(Sender: TObject);
    procedure ListBoxPatsDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure TileSetup1Execute(Sender: TObject);
    procedure TileSetupHide(Sender: TObject);
    procedure DXDraw1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure DXMap1ImageLibraryNotFound(Sender: TObject;
      var Handled: Boolean);
  private
    FMapModified, FLibModified: Boolean;
    Abort, LeftMouseDown, RightMouseDown: Boolean;
    MapSprite: TMapSprite;
    GridX, GridY: Integer;
    LastX, LastY, LastIndex: Integer;
    procedure ClearAll;
    function OpenErrorDlg(s: String): TModalResult;
    function SaveErrorDlg(s: String; Confirmation: Boolean): TModalResult;
    procedure PaintPreview;
    procedure UpdateLibList (iml: TDXImageList);
    procedure UpdateStatusBar(MouseX, MouseY: Integer);
    procedure UpdateComboBox;
    procedure SetMapModified(Modified: Boolean);
    procedure SetLibModified(Modified: Boolean);
  protected
    procedure SpecialKey(var msg: TMessage); message WM_KEYDOWN;
  public
    MCursor: TCursorSprite;
    property MapModified: Boolean read FMapModified write SetMapModified;
    property LibModified: Boolean read FLibModified write SetLibModified;
  end;

const
  CrLf = #10#13;
  LocalUpdateFile = 'dxdevs.ini';
  UpdateUrl = 'http://localhost/files/' +  LocalUpdateFile;
  AppTitle = 'DXMapEdit 1.0';
  CursorName = 'cursor';
  Spacer: Integer = 2;

var
  FormMain: TFormMain;
  CursorImage: TPictureCollectionItem;
  Separator: String = '#';
  Header: String[6] = 'DXMap1';
  MoveCount: Integer = 20;
  Intervall: Integer = 100;

implementation

{$R *.dfm}

procedure TFormMain.ExitDialog1Execute(Sender: TObject);
begin
  if MapModified then
    case MessageDlg('Map has been modified. Save Changes?', mtConfirmation, mbYesNoCancel, 0) of
      mrYes: begin
               SaveDialog1.Execute;
             end;
      mrCancel: Exit;
    end;
  if LibModified then
    case MessageDlg('Library has been modified. Save Changes?', mtConfirmation, mbYesNoCancel, 0) of
      mrYes: begin
               SaveLibDialog1.Execute;
             end;
      mrCancel: Exit;
    end;
  Close;
end;

procedure TFormMain.OpenLibDialog1Execute(Sender: TObject);
begin
  with OpenDialog2 do begin
    Filter := 'DelphiX Image Library (*.dxg)|*.dxg|All Files (*.*)|*.*';
    FilterIndex := 1;
    if not Execute then exit;
    if Filename <> EmptyStr then begin
      DXImageListLib.Items.Clear;
      try
        DXImageListLib.Items.LoadFromFile(FileName);
      except
        OpenErrorDlg(Filename);
        Exit;
      end;
      UpdateLibList(DXImageListLib);
      StatusBar1.Panels[4].Text := 'Library: '+Filename;
      OpenLibDialog1.Enabled := false;
      SpriteSetup.Show;
      PaintPreview;
    end;
  end;
end;

procedure TFormMain.UpdateLibList(iml: TDXImageList);
var i: integer;
begin
  ListBoxLib.Clear;
  for i := 0 to iml.Items.Count - 1 do begin
    ListBoxLib.AddItem(iml.Items[i].Name, iml.Items[i].Picture);
  end;
end;

procedure TFormMain.ListBoxLibClick(Sender: TObject);
var Image: TPictureCollectionItem;
    i: Integer;
begin
  i := ListBoxLib.ItemIndex;
  if i >= 0 then begin
    Image := DXImageListLib.Items[i];
    PaintPreview;
    ListBoxLib.Hint := ListBoxLib.Items[i];
    ColorPanel.Color := Image.TransparentColor;
    PanelX.Caption := 'X: '+IntToStr(Image.Width);
    PanelY.Caption := 'Y: '+IntToStr(Image.Height);
    EditName.Text := ListBoxLib.Items[i];
    MCursor.Z := SpinEditZ.Value;
    MCursor.Image := DXImageListLib.Items[i];
    MCursor.Width := Image.Width;
    MCursor.Height := Image.Height;
  end;
end;

procedure TFormMain.CheckBoxStretchClick(Sender: TObject);
begin
  PaintPreview;
end;

procedure TFormMain.FormCreate(Sender: TObject);
begin
  DXDraw1.Cursor := crNone;
  MCursor := TCursorSprite.Create(DXSpriteEngine1.Engine);
  CursorImage := DXImageListEditor.Items.Find(CursorName);
  MCursor.Image := CursorImage;
  MCursor.Z := 10000;
  MapSprite := TMapSprite.Create(DXSpriteEngine1.Engine);
  MapSprite.Name := 'BackgroundMap';
  MapSprite.Z := -1;
  MapSprite.Image := nil;
  MapSprite.SetMapSize(1, 1);
  MapModified := false;
  LibModified := false;
  DXMap1.MapName := EmptyStr;
  DXMap1.LibName := EmptyStr;
  Caption := AppTitle;
  Application.Title := Caption;
  StatusBar1.Panels[2].Text := 'Not modified';
  StatusBar1.Panels[4].Text := 'Library: ';
  EditName.Text := EmptyStr;
  ImageList1.GetBitmap(93, SpeedButtonTrans.Glyph);
  with ImagePreview.Canvas do begin
    Brush.Color := clWhite;
    FillRect(ClientRect);
  end;
end;

procedure TFormMain.DXDraw1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var CellX, CellY: Integer;
begin
  MCursor.X := x - DXSpriteEngine1.Engine.x;
  MCursor.Y := y - DXSpriteEngine1.Engine.y;
  MCursor.Z := SpinEditZ.Value;
  UpdateStatusBar(x, y);
  if MCursor.Image = CursorImage then
    MCursor.Z := 10000;

  if (ListBoxPats.ItemIndex < 0) or (ListBoxPats.Count = 0) then Exit;
  if (MapSprite.Width <= 0) or (MapSprite.Height <= 0) then Exit;

  if PageControl1.ActivePage = TileSetup then begin
    CellX := Round(MCursor.X) DIV MapSprite.Width;
    CellY := Round(MCursor.Y) DIV MapSprite.Height;
    if RightMouseDown then begin
      MapSprite.Chips[CellX, CellY] := -1; 
      Exit;
    end;
    if not LeftMouseDown then MapSprite.Chips[LastX, LastY] := LastIndex;
    if (CellX = LastX) and (CellY = LastY) and (ListBoxPats.ItemIndex = LastIndex) then Exit;
    LastIndex := MapSprite.Chips[CellX, CellY];
    MapSprite.Chips[CellX, CellY] := ListBoxPats.ItemIndex;
    LastX := CellX;
    LastY := CellY;
  end;
end;

procedure TFormMain.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
  if not DXDraw1.CanDraw then Exit;
  DXDraw1.Surface.Fill(clBlack);
  DXSpriteEngine1.Draw;
  DXSpriteEngine1.Move(MoveCount);
  DXSpriteEngine1.Dead;
 DXDRaw1.Flip;
end;

procedure TFormMain.DXDraw1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var Image: TPictureCollectionItem;
    NewSprite: TObjectSprite;
    Rect: TRect;
    Point: TPoint;
    Sprite: TSprite;
    CellX, CellY, i: Integer;
begin

  if DXImageListLib.Items.Count = 0 then Exit;

  { Sprite handling }

  if PageControl1.ActivePage = SpriteSetup then begin
    if (Button = mbLeft) and (ssCtrl in Shift) then begin
      if MCursor.Image <> CursorImage then exit;
      for i := DXSpriteEngine1.Engine.AllCount - 1 downto 0 do begin
        Sprite := DXSpriteEngine1.Engine.Items[i];
        if not (Sprite is TObjectSprite) then Continue;
        Rect := Sprite.BoundsRect;
        Point.X := x;
        Point.Y := y;
        if PointInRect(Point, Rect) then begin
          MCursor.Image := TObjectSprite(Sprite).Image;
          with ImagePreview.Canvas do begin
            Brush.Color := clWhite;
            FillRect(ClientRect);
            Draw(0, 0, MCursor.Image.Picture.Graphic);
          end;
          MCursor.Width := TObjectSprite(Sprite).Width;
          MCursor.Height := TObjectSprite(Sprite).Height;
          MCursor.Z := TObjectSprite(Sprite).Z;
          ListBoxLib.ItemIndex := TObjectSprite(Sprite).ImageIndex;
          SpinEditZ.Value := TObjectSprite(Sprite).Z;
          SpinEditType.Value := TObjectSprite(Sprite).Id;
         EditName.Text := TObjectSprite(Sprite).Name;
          Sprite.Dead;
          Break;
        end;
      end;
    end;

    if (Button = mbLeft) and not (ssAlt in Shift) and not (ssCtrl in Shift) then begin
      if MCursor.Image = CursorImage then exit;
      NewSprite := TObjectSprite.Create(DXSpriteEngine1.Engine);
      NewSprite.Image := MCursor.Image;
      NewSprite.Height := MCursor.Height;
      NewSprite.Width := MCursor.Width;
      i := ListBoxLib.ItemIndex;
      if i > 0 then EditName.Text := ListBoxLib.Items[i] + '-' + IntToStr(DXSpriteEngine1.Engine.AllCount);
      NewSprite.Id := SpinEditType.Value;
      NewSprite.Z := SpinEditZ.Value;
      NewSprite.x := x - DXSpriteEngine1.Engine.x;
      NewSprite.y := y - DXSpriteEngine1.Engine.y;
      NewSprite.ImageIndex := ListBoxLib.ItemIndex;
      if not (ssShift in Shift) then begin
        Image := CursorImage;
        MCursor.Image := Image;
        MCursor.Height := Image.Height;
        MCursor.Width := Image.Width;
        ListBoxLib.ItemIndex := -1;
      end;
      EditName.Text := EditName.Text + Separator + IntToStr(DXSpriteEngine1.Engine.AllCount);
      NewSprite.Name := EditName.Text;
      NewSprite.ImageName := ListBoxLib.Items[i];
      MapModified := true;
    end;
    if (Button = mbRight) and not (ssAlt in Shift) and not (ssCtrl in Shift) then begin
      Image := CursorImage;
      MCursor.Image := Image;
      MCursor.Height := Image.Height;
      MCursor.Width := Image.Width;
      ListBoxLib.ItemIndex := -1;
    end;

    if DXSpriteEngine1.Engine.AllCount >= 2 then
      Undo1.Enabled := true
    else
      Undo1.Enabled := false;
  end;

  { Tiles handlig }

  if PageControl1.ActivePage = TileSetup then begin
    if (Button = mbLeft) then begin
      CellX := Round(MCursor.X) DIV MapSprite.Width;
      CellY := Round(MCursor.Y) DIV MapSprite.Height;
      MapSprite.Chips[CellX, CellY] := ListBoxPats.ItemIndex;
      LastIndex := ListBoxPats.ItemIndex;
      LeftMouseDown := true;
    end;
    if Button = mbRight then begin
      if not RightMouseDown then begin
        ListBoxPats.ItemIndex := -1;
        MapSprite.Chips[LastX, LastY] := LastIndex;
        RightMouseDown := true;
      end;
    end;
  end;

  StatusBar1.Panels[3].Text := '# of objects: ' + IntToStr(DXSpriteEngine1.Engine.AllCount - 2);
  DXSpriteEngine1.Dead;
end;

procedure TFormMain.BitBtnMoveClick(Sender: TObject);
begin
  if TBitBtn(Sender).Name = 'BitBtnLeft' then begin
    DXSpriteEngine1.Engine.X := DXSpriteEngine1.Engine.X + SpinEditScroll.Value;
    MCursor.X := MCursor.X - SpinEditScroll.Value;
  end;
  if TBitBtn(Sender).Name = 'BitBtnRight' then begin
    DXSpriteEngine1.Engine.X := DXSpriteEngine1.Engine.X - SpinEditScroll.Value;
    MCursor.X := MCursor.X + SpinEditScroll.Value;
  end;
  if TBitBtn(Sender).Name = 'BitBtnUp' then begin
    DXSpriteEngine1.Engine.Y := DXSpriteEngine1.Engine.Y + SpinEditScroll.Value;
    MCursor.Y := MCursor.Y - SpinEditScroll.Value;
  end;
  if TBitBtn(Sender).Name = 'BitBtnDown' then begin
    DXSpriteEngine1.Engine.Y := DXSpriteEngine1.Engine.Y - SpinEditScroll.Value;
    MCursor.Y := MCursor.Y + SpinEditScroll.Value;
  end;
  if TBitBtn(Sender).Name = 'BitBtnOrg' then begin
    DXSpriteEngine1.Engine.X := 0;
    DXSpriteEngine1.Engine.Y := 0;
  end;
  if TBitBtn(Sender).Name = 'BitBtnCenter' then begin
    DXSpriteEngine1.Engine.X := DXSpriteEngine1.Engine.Items[DXSpriteEngine1.Engine.AllCount - 1].x / 2;
    DXSpriteEngine1.Engine.X := DXSpriteEngine1.Engine.Items[DXSpriteEngine1.Engine.AllCount - 1].y / 2;
  end;
  StatusBar1.Panels[2].Text := 'X: ' +
    FloatToStr(DXSpriteEngine1.Engine.x) + ', Y: ' +
    FloatToStr(DXSpriteEngine1.Engine.y);
end;

procedure TFormMain.Undo1Execute(Sender: TObject);
begin
  if DXSpriteEngine1.Engine.AllCount >= 3 then begin
    DXSpriteEngine1.Engine.Items[DXSpriteEngine1.Engine.AllCount - 1].Dead;
    DXSpriteEngine1.Dead;
    MapModified := true;
  end;
  Undo1.Enabled := DXSpriteEngine1.Engine.AllCount >= 3;
  StatusBar1.Panels[3].Text := '# of objects: ' + IntToStr(DXSpriteEngine1.Engine.AllCount - 2)
end;

procedure TFormMain.FormKeyPress(Sender: TObject; var Key: Char);
begin
  case Key of
    '+': SpinEditZ.Value := SpinEditZ.Value + 1;
    '-': SpinEditZ.Value := SpinEditZ.Value - 1;
    'w': BitBtnMoveClick(BitBtnUp);
    's': BitBtnMoveClick(BitBtnDown);
    'a': BitBtnMoveClick(BitBtnLeft);
    'd': BitBtnMoveClick(BitBtnRight);
    'W': DXSpriteEngine1.Engine.Y := DXSpriteEngine1.Engine.Y + 1;
    'S': DXSpriteEngine1.Engine.Y := DXSpriteEngine1.Engine.Y - 1;
    'A': DXSpriteEngine1.Engine.X := DXSpriteEngine1.Engine.X + 1;
    'D': DXSpriteEngine1.Engine.X := DXSpriteEngine1.Engine.X - 1;
  end;
  StatusBar1.Panels[2].Text := 'X: ' +
    FloatToStr(DXSpriteEngine1.Engine.x) + ', Y: ' +
    FloatToStr(DXSpriteEngine1.Engine.y);
end;

procedure TFormMain.SpinEditZChange(Sender: TObject);
begin
  MCursor.Z := SpinEditZ.Value;
end;

procedure TFormMain.Properties1Execute(Sender: TObject);
begin
  if not Assigned(FormMapProp) then begin
    FormMapProp := TFormMapProp.Create(Self);
    with FormMapProp.ImagePreview.Canvas do begin
      Brush.Color := clWhite;
      FillRect(ClientRect);
    end;
  end;
  with FormMapProp do begin
    DXImageList := Self.DXImageListLib;
    MapSprite := Self.MapSprite;
    FormMapProp.Visible := not FormMapProp.Visible;
  end;
end;

procedure TFormMain.OpenAppendLibDialog1Execute(Sender: TObject);
var i, j: Integer;
    Temp: TDXImageList;
    AlreadyExists: TStringList;
begin
  if ListBoxLib.Count = 0 then begin
    OpenLibDialog1.Execute;
    Exit;
  end;

  with OpenDialog2 do begin
    Filter := 'DelphiX Image Library (*.dxg)|*.dxg|All Files (*.*)|*.*';
    FilterIndex := 1;
    if not Execute then Exit;
  end;

  Temp := TDXImageList.Create(Self);
  try
    Temp.Items.LoadFromFile(OpenDialog2.FileName);
  except
    OpenErrorDlg(OpenDialog2.Filename);
    Exit;
  end;

  AlreadyExists := TStringList.Create;

  for j := 0 to Temp.Items.Count - 1 do begin
    i := DXImageListLib.Items.Add.Index;

    try
      if Assigned(DXImageListLib.Items.Find(Temp.Items[j].Name)) then AlreadyExists.AddObject(IntToStr(i), DXImageListLib.Items[i]);
    except end;
    DXImageListLib.Items[i].Picture := Temp.Items[j].Picture;
    DXImageListLib.Items[i].Name := Temp.Items[j].Name;    DXImageListLib.Items[i].PatternWidth := Temp.Items[j].PatternWidth;
    DXImageListLib.Items[i].PatternHeight := Temp.Items[j].PatternHeight;
    DXImageListLib.Items[i].SkipWidth := Temp.Items[j].SkipWidth;
    DXImageListLib.Items[i].SkipHeight := Temp.Items[j].SkipHeight;
    DXImageListLib.Items[i].SystemMemory := Temp.Items[j].SystemMemory;
    DXImageListLib.Items[i].Transparent := Temp.Items[j].Transparent;
    DXImageListLib.Items[i].TransparentColor := Temp.Items[j].TransparentColor;
  end;

  if AlreadyExists.Count > 0 then
    if MessageDlg(Format('%d name(s) already exists. Automatically rename them to [Name]' + Separator + '[Index]?', [AlreadyExists.Count]),
      mtInformation, [mbYes, mbNo], 0) = mrYes then
        for i := 0 to AlreadyExists.Count - 1 do
          TPictureCollectionItem(AlreadyExists.Objects[i]).Name := TPictureCollectionItem(AlreadyExists.Objects[i]).Name + Separator + AlreadyExists[i];

  UpdateLibList (DXImageListLib);
  AlreadyExists.Free;
  Temp.Free;
  LibModified := true;
end;

procedure TFormMain.NewDialog1Execute(Sender: TObject);
begin
//  if (DXSpriteEngine1.Engine.AllCount < 3) and (ListBoxLib.Count = 0) and then Exit;

  if MapModified then
    case MessageDlg('Map has been modified. Save Changes?', mtConfirmation, mbYesNoCancel, 0) of
      mrYes: begin
               SaveDialog1.Execute;
             end;
      mrCancel: Exit;
    end;
  if LibModified then
    case MessageDlg('Library has been modified. Save Changes?', mtConfirmation, mbYesNoCancel, 0) of
      mrYes: begin
               SaveLibDialog1.Execute;
             end;
      mrCancel: Exit;
    end;

  ClearAll;
  OpenLibDialog1.Enabled := true;
end;

procedure TFormMain.ImagePreviewMouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
begin
  ColorPreviewPanel.Color := ImagePreview.Canvas.Pixels[x, y];
end;

procedure TFormMain.ImagePreviewClick(Sender: TObject);
begin
  ColorPanel.Color := ColorPreviewPanel.Color;
  if MCursor.Image = CursorImage then Exit;
  MCursor.Image.TransparentColor := ColorPanel.Color;
  MCursor.Image.Restore;
  ListBoxLib.Refresh;
end;

procedure TFormMain.UpdateStatusBar(MouseX, MouseY: Integer);
begin
  StatusBar1.Panels[1].Text := 'X: ' +
    IntToStr(MouseX) + ', Y: ' +
    IntToStr(MouseY) + ', AbsX: ' +
    FloatToStr(DXSpriteEngine1.Engine.x + MouseX) + ', AbsY: ' +
    FloatToStr(DXSpriteEngine1.Engine.y + MouseY);
  StatusBar1.Panels[2].Text := 'X: ' +
    FloatToStr(DXSpriteEngine1.Engine.x) + ', Y: ' +
    FloatToStr(DXSpriteEngine1.Engine.y);
end;

procedure TFormMain.SaveDialog1Execute(Sender: TObject);
var i: Integer;
    Sprite: TSprite;
begin
  SaveLibDialog1.Execute;
  if Abort then Exit;
  with SaveDialog2 do begin
    Filename := DXMap1.MapName;
    Filter := 'DX Map Edit (*.dxm)|*.dxm|All Files (*.*)|*.*';
    DefaultExt := '.dxm';
    if not Execute then exit;
      if Filename <> EmptyStr then begin
        DXMap1.MapSprite := nil;
        for i := 0 to DXSpriteEngine1.Engine.AllCount - 1 do begin
          Sprite := DXSpriteEngine1.Engine.Items[i];
          if Sprite is TMapSprite then begin
            if TMapSprite(Sprite).Image = nil then Break;
            DXMap1.MapSprite := Sprite as TMapSprite;
            Break;
          end;
        end;
        DXMap1.SaveMap(Filename);
{  Stream := TFileStream.Create(Filename, fmCreate);
   Stream.Write(Header, Length(Header) + 1);
   c := DXSpriteEngine1.Engine.AllCount - 2;
    Stream.Write(c, SizeOf(c));
   HasMap := false;
   for i := 0 to DXSpriteEngine1.Engine.AllCount - 1 do begin
     Sprite := DXSpriteEngine1.Engine.Items[i];
    if Sprite is TMapSprite then begin
      if TMapSprite(Sprite).Image = nil then break;
      HasMap := true;
      MapSprite := Sprite as TMapSprite;
     break;
    end;
  end;
   HasMap := Assigned(MapSprite) and Assigned(MapSprite.Image);
  Stream.Write(HasMap, SizeOf(HasMap));
  lf := ExtractFilename(LibFileName);
  Stream.Write(lf, Length(lf) + 1);
  for i := 0 to DXSpriteEngine1.Engine.AllCount - 1 do begin
    Sprite := DXSpriteEngine1.Engine.Items[i];
    if Sprite is TObjectSprite then
      with Sprite as TObjectSprite do
        TObjectSprite(Sprite).StoreData(Stream);
      end;
     if HasMap then
      with MapSprite do
        MapSprite.StoreData(Stream);
  Stream.Free;
 end; }
       MapModified := false;
       LibModified := false;
       Caption := AppTitle + ' - ' + ExtractFilename(Filename);
       Application.Title := Caption;
      end;
  end;
end;


procedure TFormMain.List1Execute(Sender: TObject);
begin
  if not Assigned(FormList) then FormList := TFormList.Create(Self);
  FormList.Visible := not FormList.Visible;
end;

procedure TFormMain.PopupMenu1Popup(Sender: TObject);
begin
  if DXMap1.LibName = EmptyStr then begin
    OpenAppendLibDialog1.Enabled := false;
    OpenAppendBitmapDialog1.Enabled := false;
    SaveLibDialog1.Enabled := false;
  end else begin
    OpenAppendLibDialog1.Enabled := true;
    OpenAppendBitmapDialog1.Enabled := true;
    SaveLibDialog1.Enabled := true;
  end;

end;

procedure TFormMain.PaintPreview;
var Rec: TRect;
    Image: TPictureCollectionItem;
    i: Integer;
begin
  i := ListBoxLib.ItemIndex;
  if i < 0 then Exit;
  Image := DXImageListLib.Items[i];
  if not CheckBoxStretch.Checked then
    with ImagePreview.Canvas do begin
      Brush.Color := clWhite;
      FillRect(ImagePreview.ClientRect);
      Draw(0, 0, Image.Picture.Graphic);
    end else begin
      Rec := ClientRect;
      ScalePic(Image.Picture.Graphic.Width, Image.Picture.Graphic.Height, ImagePreview.Width, ImagePreview.Height, Rec.Right, Rec.Bottom);
      with ImagePreview.Canvas do begin
        Brush.Color := clWhite;
        FillRect(ImagePreview.ClientRect);
        StretchDraw(Rec, Image.Picture.Graphic);
      end
    end;
end;

procedure TFormMain.ListBoxLibDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
  Graphic: TGraphic;
  NewRect: TRect;
begin
  if DXImageListLib.Items.Count = 0 then Exit;
  Graphic := DXImageListLib.Items[Index].Picture.Graphic;
  if not Assigned(Graphic) then Exit;
  with (Control as TListBox).Canvas do begin
    FillRect(Rect);
    ScalePic(Graphic.Width, Graphic.Height, ListBoxLib.ItemHeight, ListBoxLib.ItemHeight, Rect.Right, Rect.Bottom);
    NewRect.Left := Rect.Left + (ListBoxLib.ItemHeight - Rect.Right) DIV 2;
    NewRect.Top := Rect.Top + (ListBoxLib.ItemHeight - Rect.Bottom) DIV 2;
    NewRect.Right := NewRect.Left + Rect.Right;
    NewRect.Bottom := NewRect.Top + Rect.Bottom;
    StretchDraw(NewRect, Graphic);
    Rect.Left := Rect.Left + ListBoxLib.ItemHeight + Spacer;
    Font.Style := [fsBold];
    TextOut(Rect.Left, Rect.Top, (Control as TListBox).Items[Index]);
    Font.Style := [];
    TextOut(Rect.Left, Rect.Top + 16, 'W: ' + IntToStr(Graphic.Width) +
      ' - H: ' + IntToStr(Graphic.Height) + ' - Key: ' + ColorToString(DXImageListLib.Items[Index].TransparentColor));
  end;
end;

function TFormMain.SaveErrorDlg(s: String;
  Confirmation: Boolean): TModalResult;
begin
  result := mrNone;
  case Confirmation of
    false: Result := MessageDlg('Unable to save file "%s"!', mtInformation, [mbOk], 0);
    true: Result := MessageDlg(Format('Unable to save image "%s"!' + CrLf + 'Do you want to continue?',
           [s]), mtConfirmation, [mbYes, mbNo], 0);
  end;
end;

function TFormMain.OpenErrorDlg(s: String): TModalResult;
begin
  Result := MessageDlg(Format('Unable to open file "%s"!', [s]), mtInformation, [mbOk], 0);
end;

procedure TFormMain.SaveLibDialog1Execute(Sender: TObject);
begin
  if ListBoxLib.Count = 0 then begin
    ShowMessage('Nothing to save!');
    Abort := true;
    Exit;
  end;
  with SaveDialog2 do begin
    Filename := DXMap1.LibName;
    Filter := 'DelphiX ImageList Files (*.dxg)|*.dxg|All Files (*.*)|*.*';
    FilterIndex := 1;
    DefaultExt := '.dxg';
     if Execute then
       begin
          try
          DXImageListLib.Items.SaveToFile(SaveDialog2.Filename);
        except
          SaveErrorDlg(SaveDialog2.Filename, false);
          Exit;
        end;
        DXMap1.LibName := Filename;
        StatusBar1.Panels[4].Text := 'Library: ' + DXMap1.LibName;
        LibModified := false;
        Abort := false;
      end
    else Abort := true;
  end;
end;

procedure TFormMain.OpenAppendBitmapDialog1Execute(Sender: TObject);
var i, j: integer;
    s: String;
    AlreadyExists: TStringList;
begin
  if OpenPictureDialog1.Execute then begin
    AlreadyExists := TStringList.Create;
    for j := 0 to OpenPictureDialog1.Files.Count - 1 do begin
      i := DXImageListLib.Items.Add.Index;
      try
        DXImageListLib.Items[i].Picture.LoadFromFile(OpenPictureDialog1.Files[j]);
      except;
        OpenErrorDlg(OpenPictureDialog1.Files[j]);
        Exit;
      end;

      s := ExtractFileName(ChangeFileExt(OpenPictureDialog1.Files[j], EmptyStr));
      try
        if Assigned(DXImageListLib.Items.Find(s)) then AlreadyExists.AddObject(IntToStr(i), DXImageListLib.Items[i]);
      except end;
      DXImageListLib.Items[i].Name := s;
      DXImageListLib.Items[i].Transparent := SpeedButtonTrans.Down;
      DXImageListLib.Items[i].TransparentColor := ColorPanel.Color;
      DXImageLIstLib.Items[i].SystemMemory := true;
      DXImageListLib.Items[i].Restore;
    end;
    if AlreadyExists.Count > 0 then
      if MessageDlg(Format('%d name(s) already exists. Automatically rename them to [Name]' + Separator + '[Index]?', [AlreadyExists.Count]),
        mtInformation, [mbYes, mbNo], 0) = mrYes then
          for i := 0 to AlreadyExists.Count - 1 do
            TPictureCollectionItem(AlreadyExists.Objects[i]).Name := TPictureCollectionItem(AlreadyExists.Objects[i]).Name + Separator + AlreadyExists[i];
    UpdateLibList(DXImageListLib);
    AlreadyExists.Free;
    LibModified := true;
  end;
end;

procedure TFormMain.SpeedButtonTransClick(Sender: TObject);
begin
  SpeedButtonTrans.Down := not SpeedButtonTrans.Down;
end;

procedure TFormMain.ClearAll;
var i: Integer;
begin
  for i := DXSpriteEngine1.Engine.AllCount - 1 downto 2 do DXSpriteEngine1.Engine.Items[i].Dead;
  DXSpriteEngine1.Dead;
  DXImageListLib.Items.Clear;

  ListBoxLib.Items.Clear;
  ComboBoxImages.Clear;
  ListBoxPats.Clear;
  SpinEditSkipWidth.Value := 0;
  SpinEditSkipHeight.Value := 0;
  SpinEditPatWidth.Value := 0;
  SpinEditPatHeight.Value := 0;
  LabelCount.Caption := '0';

  MCursor.Image := CursorImage;
  MapSprite.SetMapSize(1,1);
  MapSprite.Z := -1;
  MapSprite.Image := nil;
  MapSprite.ImageIndex := -1;

  MapModified := false;
  LibModified := false;
  DXMap1.LibName := EmptyStr;
  DXMap1.MapName := EmptyStr;

  Caption := AppTitle;
  Application.Title := Caption;

  StatusBar1.Panels[4].Text := 'Library: ';
  EditName.Text := EmptyStr;

  with ImagePreview.Canvas do begin
    Brush.Color := clWhite;
    FillRect(ClientRect);
  end;

  if Assigned(FormMapProp) then
    with FormMapProp.ImagePreview.Canvas do begin
      Brush.Color := clWhite;
      FillRect(ClientRect);
    end;
  Undo1.Enabled := false;
end;

procedure TFormMain.Update1Execute(Sender: TObject);
var s: TFileStream;
    Ini: TIniFile;
    OldVer, NewVer, Pathname, Filename, Information: String;
begin
  s := TFileStream.Create(IncludeTrailingPathDelimiter(ExtractFileDir(Application.ExeName)) + LocalUpdateFile, fmCreate);
  try
    Http.Get(UpdateUrl, s);
  except
    MessageDlg('Could not start internet update. Make sure that you are connected' + CrLf +
               'to the internet and the proxy settings are correct. If problem persists' + CrLf +
               'try again later or contact the author.', mtInformation, [mbOk], 0);
    s.Free;
    Exit;
  end;
  s.Free;
  Ini := TIniFile.Create(IncludeTrailingPathDelimiter(ExtractFileDir(Application.ExeName)) + LocalUpdateFile);
  OldVer := GetFileVersion(Application.ExeName);
  NewVer := Ini.ReadString('DxmEdit', 'Version', EmptyStr);
  if NewerVersion(OldVer, NewVer) then begin
    if MessageDlg('Newer version found. Download now?', mtConfirmation, [mbYes, mbNo], 0) = mrNo then Exit
  end else begin
    MessageDlg('No update available!', mtInformation, [mbOk], 0);
    Exit;
  end;
  Pathname := IncludeTrailingPathDelimiter(Ini.ReadString('DxmEdit', 'UpdatePath', 'htp://www.wummy-online.de'));
  Filename := Ini.ReadString('DxmEdit', 'UpdateFile', 'dxmedit.exe');
  ShellExecute(0, nil, PChar(Pathname + Filename), nil, nil, SW_HIDE);
  Information := Ini.ReadString('DxmEdit', 'Information', EmptyStr);
  if Length(Information) > 0 then MessageDlg(Information, mtInformation, [mbOk], 0);
  Ini.Free;
end;

procedure TFormMain.OpenDialog1Execute(Sender: TObject);
begin
  with OpenDialog2 do begin
    Filename := DXMap1.MapName;
    Filter := 'DX Map Edit (*.dxm)|*.dxm|All Files (*.*)|*.*';
    DefaultExt := '.dxm';
    if not Execute then exit;
    if Filename <> EmptyStr then begin
      ClearAll;
      DXMap1.MapSprite := MapSprite;
      DXMap1.LoadMap(Filename);

     { MapFilename := Filename;
      Stream := TFileStream.Create(Filename, fmOpenRead);
      Stream.Read(h, Length(Header) + 1);
      if h <> Header then begin
        MessageDlg('Unknown filetype!', mtInformation, [mbOk], 0);
        Stream.Free;
        Exit;
      end;
      Stream.Read(c, SizeOf(c));
      Stream.Read(HasMap, SizeOf(HasMap));
      LibFilename := EmptyStr;
      Stream.Read(LibFilename[0], 1);
      Stream.Read(LibFilename[1], Byte(LibFilename[0]));
      Folder := ExtractFileDir(MapFilename);
      LibFilename := IncludeTrailingPathDelimiter(Folder) + ExtractFilename(LibFilename);
      if not FileExists(LibFilename) then begin
        Folder := GetFolder(CSIDL_DESKTOP, Format('Browse for image library "%s" ...', [ExtractFilename(LibFilename)]),  BIF_NEWDIALOGSTYLE or BIF_RETURNONLYFSDIRS);
        if Folder = EmptyStr then begin
          LibFilename := EmptyStr;
          Stream.Free;
          Exit;
        end;
        if not FileExists(IncludeTrailingPathDelimiter(Folder) + ExtractFilename(LibFilename)) then begin
          MessageDlg(Format('Image library "%s" not found in "%s"!', [ExtractFilename(LibFilename), Folder]), mtInformation, [mbOk], 0);
          LibFileName := EmptyStr;
          Stream.Free;
          Exit;
        end;
      end;
      try
        DXImageListLib.Items.LoadFromFile(LibFilename);
      except
        OpenErrorDlg(LibFilename);
        Stream.Free;
        Exit;
      end;
      try
        for i := 1 to c do begin
          SpriteObj := TObjectSprite.Create(DXSpriteEngine1.Engine);
          SpriteObj.GetByName := true;
          SpriteObj.LoadData(DXImageListLib, Stream);
        end;
        if HasMap then begin
          MapSprite.LoadData(DXImageListLib, Stream)
        end;
      except
        if MessageDlg(Format('Error reading "%s"!' + CrLf + 'Keep data already loaded?', [MapFilename]), mtInformation, [mbYes, mbNo], 0) = mrNo then ClearAll;
        Stream.Free;
        Exit;
      end; }
      UpdateLibList(DXIMageListLib);
      MapModified := false;
      LibModified := false;
      BitBtnMoveClick(BitBtnOrg);
      SpriteSetup.Show;
    end;
    if DXSpriteEngine1.Engine.AllCount >= 3 then Undo1.Enabled := true;
    StatusBar1.Panels[3].Text := '# of objects: ' + IntToStr(DXSpriteEngine1.Engine.AllCount - 2);
  end;
end;

procedure TFormMain.AboutDialog1Execute(Sender: TObject);
var Form: TForm;
    UrlLabel: TLabel;

  procedure UrlLabelClick (Sender: TObject);
    begin
      ShellExecute(0, 'OPEN', 'http://www.wummy-online.de', nil, nil, SW_NORMAL);
    end;
  procedure UrlLabelEnter (Sender: TObject);
    begin
      UrlLabel.Font.Style := [fsUnderline];
    end;
  procedure UrlLabelLeave (Sender: TObject);
    begin
      UrlLabel.Font.Style := [];
    end;

begin
  Form := CreateMessageDialog('DXMapEdit (DelphiX Map Editor) Version ' + GetFileVersion(Application.ExeName) + CrLf + CrLf + 
             'Copyright (C) Dominik Schindler (http://www.wummy-online.de)' + CrLf + CrLf +
             'To get latest version use the auto update function or use one of the above URLs.' + CrLf + CrLf +
             'This program is part of the DelphiX 2D Developer Suite and FREEWARE!', mtInformation, [mbOk]);
  Form.BorderIcons := [];
  UrlLabel := TLabel.Create(Form);
  UrlLabel.Font.Color := clNavy;
  // UrlLabel.OnClick := TNotifyEvent(@UrlLabelClick);
  Form.ShowModal;
  UrlLabel.Free;
  Form.Free;
end;

procedure TFormMain.TileSetupShow(Sender: TObject);
var x, y: Integer;
    Item: TPictureCollectionItem;
begin
  if DXImageListLib.Items.Count = 0 then Exit;

  UpdateComboBox;
  ComboBoxImages.ItemIndex := MapSprite.ImageIndex;
  ComboBoxImagesChange(nil);

  Item := MapSprite.Image;

  try
    SpinEditSkipWidth.Value := Item.SkipWidth;
    SpinEditSkipHeight.Value := Item.SkipHeight;
    SpinEditPatWidth.Value := Item.PatternWidth;
    SpinEditPatHeight.Value := Item.PatternHeight;
  except
    SpinEditSkipWidth.Value := 0;
    SpinEditSkipHeight.Value := 0;
    SpinEditPatWidth.Value := 0;
    SpinEditPatHeight.Value := 0;
  end;

  MCursor.Image := CursorImage;

  ToolButton17.Down := true;
end;

procedure TFormMain.UpdateComboBox;
var i: Integer;
begin
  ComboBoxImages.Clear;
  for i := 0 to DXImageListLib.Items.Count - 1 do
    ComboBoxImages.AddItem (DXImageListLib.Items[i].Name, DXImageListLib.Items[i]);
end;

procedure TFormMain.ComboBoxImagesDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
  Graphic: TGraphic;
  NewRect: TRect;
begin
  if DXImageListLib.Items.Count = 0 then Exit;
  Graphic := DXImageListLib.Items[Index].Picture.Graphic;
  if not Assigned(Graphic) then Exit;
  with (Control as TComboBox).Canvas do begin
    FillRect(Rect);
    ScalePic(Graphic.Width, Graphic.Height, ComboBoxImages.ItemHeight, ComboBoxImages.ItemHeight, Rect.Right, Rect.Bottom);
    NewRect.Left := Rect.Left + (ComboBoxImages.ItemHeight - Rect.Right) DIV 2;
    NewRect.Top := Rect.Top + (ComboBoxImages.ItemHeight - Rect.Bottom) DIV 2;
    NewRect.Right := NewRect.Left + Rect.Right;
    NewRect.Bottom := NewRect.Top + Rect.Bottom;
    NewRect := Rect;
    NewRect.Right := NewRect.Left + ComboBoxImages.ItemHeight;
    NewRect.Bottom := NewREct.Top + ComboBoxImages.ItemHeight;
    StretchDraw(NewRect, Graphic);
    Rect.Left := Rect.Left + ComboBoxImages.ItemHeight + Spacer;
    Font.Style := [fsBold];
    TextOut(Rect.Left, Rect.Top, (Control as TComboBox).Items[Index]);
    Font.Style := [];
    TextOut(Rect.Left, Rect.Top + 16, 'W: ' + IntToStr(Graphic.Width) +
      ' - H: ' + IntToStr(Graphic.Height) + ' - Key: ' + ColorToString(DXImageListLib.Items[Index].TransparentColor));
  end;
end;

procedure TFormMain.ComboBoxImagesChange(Sender: TObject);
var Item: TPictureCollectionItem;
    i, j: Integer;
begin
  i := ComboBoxImages.ItemIndex;
  if i < 0 then Exit;
  Item := DXImageListLib.Items[i];
  SpinEditSkipWidth.Value := Item.SkipWidth;
  SpinEditSkipHeight.Value := Item.SkipHeight;
  SpinEditPatWidth.Value := Item.PatternWidth;
  SpinEditPatHeight.Value := Item.PatternHeight;
  LabelCount.Caption := IntToStr(Item.PatternCount);
  ListBoxPats.Clear;
  for j := 0 to Item.PatternCount - 1 do
    ListBoxPats.Items.Add(IntToStr(j));
end;

procedure TFormMain.BitBtnUpdPropsClick(Sender: TObject);
var Image: TPictureCollectionItem;
    i: Integer;
begin
  i := ComboBoxImages.ItemIndex;
  if i < 0 then Exit;
  Image := DXImageListLib.Items[i];
  Image.SkipWidth := SpinEditSkipWidth.Value;
  Image.SkipHeight := SpinEditSkipHeight.Value;
  Image.PatternWidth := SpinEditPatWidth.Value;
  Image.PatternHeight := SpinEditPatHeight.Value;
  Image.Restore;
  LabelCount.Caption := IntToStr(Image.PatternCount);
  MapSprite.Image := Image;
end;

procedure TFormMain.SpinEditChange(Sender: TObject);
begin
  if SpinEditPatWidth.Value < 0 then SpinEditPatWidth.Value := 0;
  if SpinEditPatHeight.Value < 0 then SpinEditPatHeight.Value := 0;
  if SpinEditSkipWidth.Value < 0 then SpinEditSkipWidth.Value := 0;
  if SpinEditSkipHeight.Value < 0 then SpinEditSkipHeight.Value := 0;
end;

procedure TFormMain.ListBoxPatsDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var i: Integer;
    Pic: TPicture;
    NewRect: TRect;
    Item: TPictureCollectionItem;
begin
  if DXImageListLib.Items.Count = 0 then Exit;
  i := ComboBoxImages.ItemIndex;
  Item := DXImageListLib.Items[i];
  if not Assigned(Item) then Exit;
  Pic := TPicture.Create;
  Pic.Bitmap.Width := Item.Picture.Width;
  Pic.Bitmap.Height := Item.Picture.Height;
//  Pic.Bitmap.Canvas.Brush.Color := clBlack;
//    Pic.Bitmap.Assign(Item.Picture.Bitmap);
  Pic.Bitmap.PixelFormat := Item.Picture.Bitmap.PixelFormat;
  Pic.Bitmap.Canvas.FillRect(Pic.Bitmap.Canvas.ClipRect);
  Pic.Bitmap.Canvas.Draw(0,0, Item.Picture.Graphic);
 // Pic.Assign (Item.Picture);
  with (Control as TListBox).Canvas do begin
    FillRect(Rect);
    NewRect := Rect;
    NewRect.Right := Rect.Left + ListBoxPats.ItemHeight;
    NewRect.Bottom := Rect.Top + ListBoxPats.ItemHeight;
    // CopyMode := cmSrcCopy;
    //CopyRect(NewRect, Pic.Bitmap.Canvas, Item.PatternRects[Index]);
    BrushCopy(NewRect, Pic.Bitmap, Item.PatternRects[Index], Item.TransparentColor);  
    // StretchDraw(NewRect, DXIMageList.Items[i].Picture.Graphic);
    Rect.Left := Rect.Left + ListBoxPats.ItemHeight + Spacer;
    Font.Style := [fsBold];
    TextOut(Rect.Left, Rect.Top, (Control as TListBox).Items[Index]);
    Font.Style := [];
    TextOut(Rect.Left, Rect.Top + 16, 'W: ' + IntToStr(DXImageListLib.Items[i].PatternWidth) +
      ' - H: ' + IntToStr(DXImageListLib.Items[i].PatternHeight));
  end;
  Pic.Free;
end;

procedure TFormMain.TileSetup1Execute(Sender: TObject);
begin
  if ToolButton17.Down then
    PageControl1.ActivePage := TileSetup
  else
    PageControl1.ActivePage := SpriteSetup;
end;

procedure TFormMain.TileSetupHide(Sender: TObject);
begin
  ToolButton17.Down := false;
  MapSprite.Chips[LastX, LastY] := LastIndex;
end;

procedure TFormMain.SetLibModified(Modified: Boolean);
begin
  FLibModified := Modified;
  if Modified then
    StatusBar1.Panels[2].Text := 'Library modified'
  else
    StatusBar1.Panels[2].Text := 'Library not modified';
end;

procedure TFormMain.SetMapModified(Modified: Boolean);
begin
  FMapModified := Modified;
  if Modified then
    StatusBar1.Panels[2].Text := 'Map modified'
  else
    StatusBar1.Panels[2].Text := 'Map not modified';
end;

procedure TFormMain.DXDraw1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbLeft then LeftMouseDown := false;
  if Button = mbRight then RightMouseDown := false;
end;

procedure TFormMain.DXMap1ImageLibraryNotFound(Sender: TObject;
  var Handled: Boolean);
var Folder: String;
begin
  Folder := GetFolder(CSIDL_DESKTOP, Format('Browse for image library "%s" ...', [ExtractFilename((Sender as TDXMap).LibName)]),  BIF_NEWDIALOGSTYLE or BIF_RETURNONLYFSDIRS);

  if Folder = EmptyStr then begin
    Handled := false;
    Exit;
  end;

  Folder := IncludeTrailingPathDelimiter(Folder) + ExtractFileName(DXMap1.LibName);

  if not FileExists(Folder) then begin
    MessageDlg(Format('Image library "%s" not found in "%s"!', [ExtractFilename(Folder), ExtractFileDir(Folder)]), mtInformation, [mbOk], 0);
    Handled := false;
    Exit;
  end;

  DXMap1.LibName := Folder;
  Handled := true;
end;

procedure TFormMain.SpecialKey(var msg: TMessage);
begin
  //
  case msg.WParam of
    VK_UP: ShowMessage('ööö');
  end;
end;

end.

