<commit_before>unit KM_GUIMapEdTerrainObjects;
{$I KaM_Remake.inc}
interface
uses
  {$IFDEF MSWindows} Windows, {$ENDIF}
  {$IFDEF Unix} LCLIntf, LCLType, {$ENDIF}
  Classes, Math, SysUtils,
  KM_InterfaceDefaults,
  KM_Controls, KM_ControlsBase, KM_ControlsPopUp, KM_ControlsScroll, KM_ControlsSwitch, KM_ControlsTrackBar,
  KM_TerrainTypes,
  KM_Defaults, KM_Pics, KM_Cursor, KM_Points, KM_CommonTypes;

type
  TKMTerrainObjectAttribute = (toaBlockDiagonal, toaBlockAllExceptBuild, toaBlockBuild, toaChoppableTree);

  TKMTerrainObjectAttributeSet = set of TKMTerrainObjectAttribute;

  TKMMapEdTerrainObjects = class(TKMMapEdSubMenuPage)
  private
    fHideAllPages: TEvent;
    //Objects in MapElem are placed sparsely, so we need to compact them
    //to use in MapEd palette
    fLastObjectIndex: Integer;
    fCountCompact: Integer;
    fCompactToMapElem: array [Byte] of Byte; //Pointers to valid MapElem's
    fMapElemToCompact: array [Byte] of Byte; //Pointers of valid MapElem's back to map objects. (reverse lookup to one above) 256 is no object.

    fObjPaletteTableSize: TKMPoint;
    fObjPaletteAttr: array of TKMTerrainObjectAttributeSet;

    function GetObjPaletteTableHeight: Integer;
    function GetObjPaletteTableWidth: Integer;

    procedure UpdatePaletteButton(aBtnID: Integer);
    function UpdateObjAttributesAndDesc(aBtn: TKMButtonFlat; aObjID: Integer): TKMTerrainObjectAttributeSet;
    procedure CompactMapElements;
    procedure ObjectsUpdate(aObjIndex: Integer);
    procedure UpdateObjectsScrollPosToIndex(aObjIndex: Integer);
    procedure ObjectsChange(Sender: TObject);
    procedure ObjectsBrushChange(Sender: TObject);
    procedure ObjectsRefresh(Sender: TObject);

    procedure ObjectsPalette_Refresh(Sender: TObject);
    procedure ObjPalette_UpdateControlsPosition;
    procedure ObjectsPalette_OnShow(Sender: TObject; aVisible: Boolean);
    procedure ObjPalette_ClickShift(Sender: TObject; Shift: TShiftState);

    procedure ObjectsPaletteButton_Click(Sender: TObject);
    procedure ObjectsPaletteClose_Click(Sender: TObject);
  protected
    Panel_Objects: TKMScrollPanel;
      ObjectErase: TKMButtonFlat;
      ObjectBlock: TKMButtonFlat;
      ObjectsPalette_Button: TKMButtonFlat;
      ObjectsTable: array [0..8] of TKMButtonFlat;
      ObjectsScroll: TKMScrollBar;
    PopUp_ObjectsPalette: TKMPopUpMenu;
      Bevel_ObjectsPalette: TKMBevel;
      Image_ObjectsPalette: TKMImage;
      Label_ObjectsPalette: TKMLabel;
      Button_ClosePalette: TKMButton;
      Button_ObjPaletteErase: TKMButtonFlat;
      Button_ObjPaletteBlock: TKMButtonFlat;
      ObjectsPaletteTable: array of TKMButtonFlat;
      Image_ObjectAttributes: array[0..2] of array of TKMImage;

      //Objects brush
      BrushSize, ForestDensity, ForestAge: TKMTrackBar;
      ObjectTypeSet: array [TKMTerrainObjectType] of TKMButtonFlat;
      BrushCircle, BrushSquare: TKMButtonFlat;
      CleanBrush: TKMButtonFlat;
      Label_ForestAge: TKMLabel;
      OverrideObjects: TKMCheckBox;

      Scroll_ObjectsPalette: TKMScrollBar;
  public
    constructor Create(aParent: TKMPanel; aHideAllPages: TEvent);

    procedure KeyDown(Key: Word; Shift: TShiftState; var aHandled: Boolean);
    procedure KeyUp(Key: Word; Shift: TShiftState; var aHandled: Boolean);
    procedure MouseWheel(Shift: TShiftState; WheelSteps: Integer; X,Y: Integer; var aHandled: Boolean);

    procedure Show;
    function Visible: Boolean; override;
    procedure Hide;
    procedure Resize;
    procedure Cancel_Clicked(var aHandled: Boolean);
    procedure UpdateHotkeys;
    procedure UpdateState;
  end;


implementation
uses
  KM_Main, KM_Resource, KM_ResFonts, KM_ResMapElements, KM_ResTexts, KM_ResKeys, KM_Terrain,
  KM_HandsCollection, KM_RenderUI, KM_InterfaceGame, KM_Utils,
  KM_ResTypes;

type
  TKMObjBrushForestAge = (faAll, faAllButStomps, faYoung, faMedium, faBig, faChop, faStomp);

const
  OBJECTS_PALETTE_MAX_COLS_CNT = 17;
  OBJ_CELL_W = 68;
  OBJ_CELL_H = 84;

  OBJ_CELL_PALETTE_W = 68;
  OBJ_CELL_PALETTE_H = 84;

  OBJ_NONE_TAG = -100;
  OBJ_BLOCK_TAG = -200;
  //Objects brush bins
  BTN_BRUSH_TYPE_S = 30;
  BTN_BRUSH_SIZE = 36;

  OBJECT_MAX_DENSITY = 30;


  FOREST_AGE_THUMB_TX: array[TKMObjBrushForestAge] of Integer = (TX_MAPED_OBJECTS_BRUSH_TREES_AGE_ALL,
                                                                 TX_MAPED_OBJECTS_BRUSH_TREES_AGE_ALL_BUT_STOMP,
                                                                 TX_MAPED_OBJECTS_BRUSH_TREES_AGE_YOUNG,
                                                                 TX_MAPED_OBJECTS_BRUSH_TREES_AGE_MEDIUM,
                                                                 TX_MAPED_OBJECTS_BRUSH_TREES_AGE_BIG,
                                                                 TX_MAPED_OBJECTS_BRUSH_TREES_AGE_RDY_2CHOP,
                                                                 TX_MAPED_OBJECTS_BRUSH_TREES_AGE_STOMP);

  FOREST_AGE_HINT_TX: array[TKMObjBrushForestAge] of Integer = (TX_MAPED_OBJECTS_BRUSH_TREES_AGE_ALL_HINT,
                                                                TX_MAPED_OBJECTS_BRUSH_TREES_AGE_ALL_BUT_STOMP_HINT,
                                                                TX_MAPED_OBJECTS_BRUSH_TREES_AGE_YOUNG_HINT,
                                                                TX_MAPED_OBJECTS_BRUSH_TREES_AGE_MEDIUM_HINT,
                                                                TX_MAPED_OBJECTS_BRUSH_TREES_AGE_BIG_HINT,
                                                                TX_MAPED_OBJECTS_BRUSH_TREES_AGE_RDY_2CHOP_HINT,
                                                                TX_MAPED_OBJECTS_BRUSH_TREES_AGE_STOMP_HINT);

  OBJECT_TYPE_BTN: array [TKMTerrainObjectType] of record
    TexID: Integer;
    HintTX: Integer;
  end = (
    (TexID: 226;  HintTX: TX_MAPED_OBJECTS_BRUSH_TREES;),
    (TexID: 34;   HintTX: TX_MAPED_OBJECTS_BRUSH_ALL;),
    (TexID: 14;   HintTX: TX_MAPED_OBJECTS_BRUSH_FLOWERS;),
    (TexID: 4;    HintTX: TX_MAPED_OBJECTS_BRUSH_MUSHROOMS;),
    (TexID: 26;   HintTX: TX_MAPED_OBJECTS_BRUSH_TRUNKS;),
    (TexID: 39;   HintTX: TX_MAPED_OBJECTS_BRUSH_DEAD;),
    (TexID: 21;   HintTX: TX_MAPED_OBJECTS_BRUSH_STONES;),
    (TexID: 143;  HintTX: TX_MAPED_OBJECTS_BRUSH_BUSH;),
    (TexID: 173;  HintTX: TX_MAPED_OBJECTS_BRUSH_CACTUS;),
    (TexID: 245;  HintTX: TX_MAPED_OBJECTS_BRUSH_RUINS;)
  );


{ TKMMapEdTerrainObjects }
constructor TKMMapEdTerrainObjects.Create(aParent: TKMPanel; aHideAllPages: TEvent);

  function GetForestAgeThumbWidth(aFont: TKMFont): Integer;
  var
    BFA: TKMObjBrushForestAge;
  begin
    Result := 0;
    for BFA := Low(FOREST_AGE_THUMB_TX) to High(FOREST_AGE_THUMB_TX) do
      Result := Max(Result, gRes.Fonts[aFont].GetTextSize(gResTexts[FOREST_AGE_THUMB_TX[BFA]]).X);

    Inc(Result, TKMTrackBar.THUMB_WIDTH_ADD);
  end;

var
  top: Integer;

  function NextTop(aInc: Integer): Integer;
  begin
    Result := top;
    top := top + aInc;
  end;

var
  I, J: Integer;
//  TOA: TKMTerrainObjectAttribute;
  //For brushes
   K: Integer;
  OT: TKMTerrainObjectType;

begin
  inherited Create;

  fHideAllPages := aHideAllPages;
  fLastObjectIndex := -1;

  CompactMapElements;

  Panel_Objects := TKMScrollPanel.Create(aParent, 0, 28, aParent.Width, aParent.Height - 28, [saVertical], bsMenu, ssCommon);
  Panel_Objects.Padding.SetBottom(10);
  Panel_Objects.ScrollV_PadTop := 10;
  Panel_Objects.ScrollV_PadBottom := 10;
  Panel_Objects.AnchorsStretch;

  with TKMLabel.Create(Panel_Objects, 0, TERRAIN_PAGE_TITLE_Y, Panel_Objects.Width, 0, gResTexts[TX_MAPED_OBJECTS], fntOutline, taCenter) do
    Anchors := [anLeft, anTop, anRight];

  ObjectsScroll := TKMScrollBar.Create(Panel_Objects, 9, 295, Panel_Objects.Width - 9, 20, saHorizontal, bsGame);
  ObjectsScroll.Anchors := [anLeft, anTop, anRight];<commit_msg>Minor UI fix on MapEd object tab<commit_after>unit KM_GUIMapEdTerrainObjects;
{$I KaM_Remake.inc}
interface
uses
  {$IFDEF MSWindows} Windows, {$ENDIF}
  {$IFDEF Unix} LCLIntf, LCLType, {$ENDIF}
  Classes, Math, SysUtils,
  KM_InterfaceDefaults,
  KM_Controls, KM_ControlsBase, KM_ControlsPopUp, KM_ControlsScroll, KM_ControlsSwitch, KM_ControlsTrackBar,
  KM_TerrainTypes,
  KM_Defaults, KM_Pics, KM_Cursor, KM_Points, KM_CommonTypes;

type
  TKMTerrainObjectAttribute = (toaBlockDiagonal, toaBlockAllExceptBuild, toaBlockBuild, toaChoppableTree);

  TKMTerrainObjectAttributeSet = set of TKMTerrainObjectAttribute;

  TKMMapEdTerrainObjects = class(TKMMapEdSubMenuPage)
  private
    fHideAllPages: TEvent;
    //Objects in MapElem are placed sparsely, so we need to compact them
    //to use in MapEd palette
    fLastObjectIndex: Integer;
    fCountCompact: Integer;
    fCompactToMapElem: array [Byte] of Byte; //Pointers to valid MapElem's
    fMapElemToCompact: array [Byte] of Byte; //Pointers of valid MapElem's back to map objects. (reverse lookup to one above) 256 is no object.

    fObjPaletteTableSize: TKMPoint;
    fObjPaletteAttr: array of TKMTerrainObjectAttributeSet;

    function GetObjPaletteTableHeight: Integer;
    function GetObjPaletteTableWidth: Integer;

    procedure UpdatePaletteButton(aBtnID: Integer);
    function UpdateObjAttributesAndDesc(aBtn: TKMButtonFlat; aObjID: Integer): TKMTerrainObjectAttributeSet;
    procedure CompactMapElements;
    procedure ObjectsUpdate(aObjIndex: Integer);
    procedure UpdateObjectsScrollPosToIndex(aObjIndex: Integer);
    procedure ObjectsChange(Sender: TObject);
    procedure ObjectsBrushChange(Sender: TObject);
    procedure ObjectsRefresh(Sender: TObject);

    procedure ObjectsPalette_Refresh(Sender: TObject);
    procedure ObjPalette_UpdateControlsPosition;
    procedure ObjectsPalette_OnShow(Sender: TObject; aVisible: Boolean);
    procedure ObjPalette_ClickShift(Sender: TObject; Shift: TShiftState);

    procedure ObjectsPaletteButton_Click(Sender: TObject);
    procedure ObjectsPaletteClose_Click(Sender: TObject);
  protected
    Panel_Objects: TKMScrollPanel;
      ObjectErase: TKMButtonFlat;
      ObjectBlock: TKMButtonFlat;
      ObjectsPalette_Button: TKMButtonFlat;
      ObjectsTable: array [0..8] of TKMButtonFlat;
      ObjectsScroll: TKMScrollBar;
    PopUp_ObjectsPalette: TKMPopUpMenu;
      Bevel_ObjectsPalette: TKMBevel;
      Image_ObjectsPalette: TKMImage;
      Label_ObjectsPalette: TKMLabel;
      Button_ClosePalette: TKMButton;
      Button_ObjPaletteErase: TKMButtonFlat;
      Button_ObjPaletteBlock: TKMButtonFlat;
      ObjectsPaletteTable: array of TKMButtonFlat;
      Image_ObjectAttributes: array[0..2] of array of TKMImage;

      //Objects brush
      BrushSize, ForestDensity, ForestAge: TKMTrackBar;
      ObjectTypeSet: array [TKMTerrainObjectType] of TKMButtonFlat;
      BrushCircle, BrushSquare: TKMButtonFlat;
      CleanBrush: TKMButtonFlat;
      Label_ForestAge: TKMLabel;
      OverrideObjects: TKMCheckBox;

      Scroll_ObjectsPalette: TKMScrollBar;
  public
    constructor Create(aParent: TKMPanel; aHideAllPages: TEvent);

    procedure KeyDown(Key: Word; Shift: TShiftState; var aHandled: Boolean);
    procedure KeyUp(Key: Word; Shift: TShiftState; var aHandled: Boolean);
    procedure MouseWheel(Shift: TShiftState; WheelSteps: Integer; X,Y: Integer; var aHandled: Boolean);

    procedure Show;
    function Visible: Boolean; override;
    procedure Hide;
    procedure Resize;
    procedure Cancel_Clicked(var aHandled: Boolean);
    procedure UpdateHotkeys;
    procedure UpdateState;
  end;


implementation
uses
  KM_Main, KM_Resource, KM_ResFonts, KM_ResMapElements, KM_ResTexts, KM_ResKeys, KM_Terrain,
  KM_HandsCollection, KM_RenderUI, KM_InterfaceGame, KM_Utils,
  KM_ResTypes;

type
  TKMObjBrushForestAge = (faAll, faAllButStomps, faYoung, faMedium, faBig, faChop, faStomp);

const
  OBJECTS_PALETTE_MAX_COLS_CNT = 17;
  OBJ_CELL_W = 68;
  OBJ_CELL_H = 84;

  OBJ_CELL_PALETTE_W = 68;
  OBJ_CELL_PALETTE_H = 84;

  OBJ_NONE_TAG = -100;
  OBJ_BLOCK_TAG = -200;
  //Objects brush bins
  BTN_BRUSH_TYPE_S = 30;
  BTN_BRUSH_SIZE = 36;

  OBJECT_MAX_DENSITY = 30;


  FOREST_AGE_THUMB_TX: array[TKMObjBrushForestAge] of Integer = (TX_MAPED_OBJECTS_BRUSH_TREES_AGE_ALL,
                                                                 TX_MAPED_OBJECTS_BRUSH_TREES_AGE_ALL_BUT_STOMP,
                                                                 TX_MAPED_OBJECTS_BRUSH_TREES_AGE_YOUNG,
                                                                 TX_MAPED_OBJECTS_BRUSH_TREES_AGE_MEDIUM,
                                                                 TX_MAPED_OBJECTS_BRUSH_TREES_AGE_BIG,
                                                                 TX_MAPED_OBJECTS_BRUSH_TREES_AGE_RDY_2CHOP,
                                                                 TX_MAPED_OBJECTS_BRUSH_TREES_AGE_STOMP);

  FOREST_AGE_HINT_TX: array[TKMObjBrushForestAge] of Integer = (TX_MAPED_OBJECTS_BRUSH_TREES_AGE_ALL_HINT,
                                                                TX_MAPED_OBJECTS_BRUSH_TREES_AGE_ALL_BUT_STOMP_HINT,
                                                                TX_MAPED_OBJECTS_BRUSH_TREES_AGE_YOUNG_HINT,
                                                                TX_MAPED_OBJECTS_BRUSH_TREES_AGE_MEDIUM_HINT,
                                                                TX_MAPED_OBJECTS_BRUSH_TREES_AGE_BIG_HINT,
                                                                TX_MAPED_OBJECTS_BRUSH_TREES_AGE_RDY_2CHOP_HINT,
                                                                TX_MAPED_OBJECTS_BRUSH_TREES_AGE_STOMP_HINT);

  OBJECT_TYPE_BTN: array [TKMTerrainObjectType] of record
    TexID: Integer;
    HintTX: Integer;
  end = (
    (TexID: 226;  HintTX: TX_MAPED_OBJECTS_BRUSH_TREES;),
    (TexID: 34;   HintTX: TX_MAPED_OBJECTS_BRUSH_ALL;),
    (TexID: 14;   HintTX: TX_MAPED_OBJECTS_BRUSH_FLOWERS;),
    (TexID: 4;    HintTX: TX_MAPED_OBJECTS_BRUSH_MUSHROOMS;),
    (TexID: 26;   HintTX: TX_MAPED_OBJECTS_BRUSH_TRUNKS;),
    (TexID: 39;   HintTX: TX_MAPED_OBJECTS_BRUSH_DEAD;),
    (TexID: 21;   HintTX: TX_MAPED_OBJECTS_BRUSH_STONES;),
    (TexID: 143;  HintTX: TX_MAPED_OBJECTS_BRUSH_BUSH;),
    (TexID: 173;  HintTX: TX_MAPED_OBJECTS_BRUSH_CACTUS;),
    (TexID: 245;  HintTX: TX_MAPED_OBJECTS_BRUSH_RUINS;)
  );


{ TKMMapEdTerrainObjects }
constructor TKMMapEdTerrainObjects.Create(aParent: TKMPanel; aHideAllPages: TEvent);

  function GetForestAgeThumbWidth(aFont: TKMFont): Integer;
  var
    BFA: TKMObjBrushForestAge;
  begin
    Result := 0;
    for BFA := Low(FOREST_AGE_THUMB_TX) to High(FOREST_AGE_THUMB_TX) do
      Result := Max(Result, gRes.Fonts[aFont].GetTextSize(gResTexts[FOREST_AGE_THUMB_TX[BFA]]).X);

    Inc(Result, TKMTrackBar.THUMB_WIDTH_ADD);
  end;

var
  top: Integer;

  function NextTop(aInc: Integer): Integer;
  begin
    Result := top;
    top := top + aInc;
  end;

var
  I, J: Integer;
//  TOA: TKMTerrainObjectAttribute;
  //For brushes
   K: Integer;
  OT: TKMTerrainObjectType;

begin
  inherited Create;

  fHideAllPages := aHideAllPages;
  fLastObjectIndex := -1;

  CompactMapElements;

  Panel_Objects := TKMScrollPanel.Create(aParent, 0, 28, aParent.Width, aParent.Height - 28, [saVertical], bsMenu, ssCommon);
  Panel_Objects.Padding.SetBottom(10);
  Panel_Objects.ScrollV_PadTop := 10;
  Panel_Objects.AnchorsStretch;

  with TKMLabel.Create(Panel_Objects, 0, TERRAIN_PAGE_TITLE_Y, Panel_Objects.Width, 0, gResTexts[TX_MAPED_OBJECTS], fntOutline, taCenter) do
    Anchors := [anLeft, anTop, anRight];

  ObjectsScroll := TKMScrollBar.Create(Panel_Objects, 9, 295, Panel_Objects.Width - 9, 20, saHorizontal, bsGame);
  ObjectsScroll.Anchors := [anLeft, anTop, anRight];
{'fraction_non_alphanumeric': 0.07136485280999108, 'fraction_numerical': 0.009557792787052377, 'mean_word_length': 3.1686586985391765, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 48, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '253850', 'n_tokens_mistral': 5729, 'n_tokens_neox': 5224, 'n_words': 991}