Event light, map ambient, DSL highlighting, autotile palette, action buttons on top

This commit is contained in:
cthangover committed 2026-10-24 12:56:09 +02:00
1 parent ac5b21e4c3
commit dbe46a05bf
12 files changed
+146 -19

No files matched your search

+8
View File
@@ -102,3 +102,11 @@ tools/rpg_editor/item_found_line = Found: {0} ×{1}
tools/rpg_editor/placed_item = “{0}” lies on the map: event {1} tools/rpg_editor/placed_item = “{0}” lies on the map: event {1}
tools/rpg_editor/picker_no_look = No map picture found, a marker is shown tools/rpg_editor/picker_no_look = No map picture found, a marker is shown
tools/rpg_editor/problem_event_locked = Event id {0} is taken by an event of another file or mod — pick another one tools/rpg_editor/problem_event_locked = Event id {0} is taken by an event of another file or mod — pick another one
tools/rpg_editor/section_light = Light
tools/rpg_editor/light_radius = Light radius
tools/rpg_editor/light_radius_tip = In cells; 0 means the event gives no light. Light shows at dusk and at night
tools/rpg_editor/light_color = Light colour
tools/rpg_editor/light_color_tip = #rrggbb or #rrggbbaa (alpha is the strength); empty keeps the warm default
tools/rpg_editor/ambient = Fixed ambient
tools/rpg_editor/ambient_tip = #rrggbb: the map is always lit like this (a room with a lamp); empty: by the time of day
tools/rpg_editor/autotile = autotile
+8
View File
@@ -102,3 +102,11 @@ tools/rpg_editor/item_found_line = Encontrado: {0} ×{1}
tools/rpg_editor/placed_item = «{0}» está en el mapa: evento {1} tools/rpg_editor/placed_item = «{0}» está en el mapa: evento {1}
tools/rpg_editor/picker_no_look = No se encontró imagen para el mapa, se muestra un marcador tools/rpg_editor/picker_no_look = No se encontró imagen para el mapa, se muestra un marcador
tools/rpg_editor/problem_event_locked = El id de evento {0} ya lo usa un evento de otro archivo o mod: elige otro tools/rpg_editor/problem_event_locked = El id de evento {0} ya lo usa un evento de otro archivo o mod: elige otro
tools/rpg_editor/section_light = Luz
tools/rpg_editor/light_radius = Radio de luz
tools/rpg_editor/light_radius_tip = En casillas; 0: el evento no da luz. La luz se ve al anochecer y de noche
tools/rpg_editor/light_color = Color de la luz
tools/rpg_editor/light_color_tip = #rrggbb o #rrggbbaa (alfa = intensidad); vacío: el cálido por defecto
tools/rpg_editor/ambient = Luz ambiental fija
tools/rpg_editor/ambient_tip = #rrggbb: el mapa siempre tiene esta luz (una sala con lámpara); vacío: según la hora del día
tools/rpg_editor/autotile = autotile
+8
View File
@@ -102,3 +102,11 @@ tools/rpg_editor/item_found_line = 見つけた:{0} ×{1}
tools/rpg_editor/placed_item = 「{0}」をマップに置いた:イベント {1} tools/rpg_editor/placed_item = 「{0}」をマップに置いた:イベント {1}
tools/rpg_editor/picker_no_look = マップ用の画像が見つからないため、マーカーを表示します tools/rpg_editor/picker_no_look = マップ用の画像が見つからないため、マーカーを表示します
tools/rpg_editor/problem_event_locked = イベント id {0} は別のファイルか MOD のイベントが使っています——別の id にしてください tools/rpg_editor/problem_event_locked = イベント id {0} は別のファイルか MOD のイベントが使っています——別の id にしてください
tools/rpg_editor/section_light = 光
tools/rpg_editor/light_radius = 光の半径
tools/rpg_editor/light_radius_tip = マス単位。0 ならイベントは光らない。光は夕方と夜に見える
tools/rpg_editor/light_color = 光の色
tools/rpg_editor/light_color_tip = #rrggbb か #rrggbbaa(アルファが強さ)。空なら既定の暖色
tools/rpg_editor/ambient = 固定の環境光
tools/rpg_editor/ambient_tip = #rrggbb:マップは常にこの明るさ(ランプのある部屋)。空なら時刻に従う
tools/rpg_editor/autotile = オートタイル
+8
View File
@@ -102,3 +102,11 @@ tools/rpg_editor/item_found_line = 발견: {0} ×{1}
tools/rpg_editor/placed_item = "{0}"이(가) 맵에 놓였습니다: 이벤트 {1} tools/rpg_editor/placed_item = "{0}"이(가) 맵에 놓였습니다: 이벤트 {1}
tools/rpg_editor/picker_no_look = 맵용 그림을 찾지 못해 표식을 표시합니다 tools/rpg_editor/picker_no_look = 맵용 그림을 찾지 못해 표식을 표시합니다
tools/rpg_editor/problem_event_locked = 이벤트 id {0}은(는) 다른 파일이나 모드의 이벤트가 쓰고 있습니다 — 다른 것을 고르세요 tools/rpg_editor/problem_event_locked = 이벤트 id {0}은(는) 다른 파일이나 모드의 이벤트가 쓰고 있습니다 — 다른 것을 고르세요
tools/rpg_editor/section_light = 빛
tools/rpg_editor/light_radius = 빛 반경
tools/rpg_editor/light_radius_tip = 칸 단위, 0이면 이벤트가 빛나지 않음. 빛은 해질녘과 밤에 보임
tools/rpg_editor/light_color = 빛 색
tools/rpg_editor/light_color_tip = #rrggbb 또는 #rrggbbaa(알파가 세기), 비우면 기본 따뜻한 색
tools/rpg_editor/ambient = 고정 환경광
tools/rpg_editor/ambient_tip = #rrggbb: 맵이 항상 이 빛으로 비침(램프가 있는 방), 비우면 시간대에 따름
tools/rpg_editor/autotile = 오토타일
+8
View File
@@ -102,3 +102,11 @@ tools/rpg_editor/item_found_line = Найдено: {0} ×{1}
tools/rpg_editor/placed_item = «{0}» лежит на карте: событие {1} tools/rpg_editor/placed_item = «{0}» лежит на карте: событие {1}
tools/rpg_editor/picker_no_look = Картинка для карты не найдена, будет маркер tools/rpg_editor/picker_no_look = Картинка для карты не найдена, будет маркер
tools/rpg_editor/problem_event_locked = Id события {0} уже занят событием из другого файла или мода — выберите другой tools/rpg_editor/problem_event_locked = Id события {0} уже занят событием из другого файла или мода — выберите другой
tools/rpg_editor/section_light = Свет
tools/rpg_editor/light_radius = Радиус света
tools/rpg_editor/light_radius_tip = В клетках; 0 — событие не светит. Свет виден в сумерках и ночью
tools/rpg_editor/light_color = Цвет света
tools/rpg_editor/light_color_tip = #rrggbb или #rrggbbaa (альфа — сила); пусто — тёплый по умолчанию
tools/rpg_editor/ambient = Своё освещение
tools/rpg_editor/ambient_tip = #rrggbb: карта всегда освещена так (комната с лампой); пусто — по времени суток
tools/rpg_editor/autotile = автотайл
+8
View File
@@ -102,3 +102,11 @@ tools/rpg_editor/item_found_line = Tìm thấy: {0} ×{1}
tools/rpg_editor/placed_item = "{0}" nằm trên bản đồ: sự kiện {1} tools/rpg_editor/placed_item = "{0}" nằm trên bản đồ: sự kiện {1}
tools/rpg_editor/picker_no_look = Không tìm thấy hình cho bản đồ, hiển thị một điểm đánh dấu tools/rpg_editor/picker_no_look = Không tìm thấy hình cho bản đồ, hiển thị một điểm đánh dấu
tools/rpg_editor/problem_event_locked = Id sự kiện {0} đã được một sự kiện ở tệp hoặc mod khác dùng — hãy chọn id khác tools/rpg_editor/problem_event_locked = Id sự kiện {0} đã được một sự kiện ở tệp hoặc mod khác dùng — hãy chọn id khác
tools/rpg_editor/section_light = Ánh sáng
tools/rpg_editor/light_radius = Bán kính sáng
tools/rpg_editor/light_radius_tip = Tính theo ô; 0 là sự kiện không phát sáng. Ánh sáng hiện lúc chạng vạng và ban đêm
tools/rpg_editor/light_color = Màu ánh sáng
tools/rpg_editor/light_color_tip = #rrggbb hoặc #rrggbbaa (alpha là cường độ); để trống dùng màu ấm mặc định
tools/rpg_editor/ambient = Ánh sáng nền cố định
tools/rpg_editor/ambient_tip = #rrggbb: bản đồ luôn sáng như vậy (phòng có đèn); để trống thì theo giờ trong ngày
tools/rpg_editor/autotile = ô tự động
+8
View File
@@ -102,3 +102,11 @@ tools/rpg_editor/item_found_line = 找到:{0} ×{1}
tools/rpg_editor/placed_item = "{0}"放在地图上:事件 {1} tools/rpg_editor/placed_item = "{0}"放在地图上:事件 {1}
tools/rpg_editor/picker_no_look = 没有找到地图用的图片,显示为标记 tools/rpg_editor/picker_no_look = 没有找到地图用的图片,显示为标记
tools/rpg_editor/problem_event_locked = 事件 id {0} 已被其他文件或模组的事件占用——请换一个 tools/rpg_editor/problem_event_locked = 事件 id {0} 已被其他文件或模组的事件占用——请换一个
tools/rpg_editor/section_light = 光照
tools/rpg_editor/light_radius = 光照半径
tools/rpg_editor/light_radius_tip = 以格为单位;0 表示事件不发光。光在黄昏和夜晚可见
tools/rpg_editor/light_color = 光的颜色
tools/rpg_editor/light_color_tip = #rrggbb 或 #rrggbbaa(alpha 为强度);留空为默认暖色
tools/rpg_editor/ambient = 固定环境光
tools/rpg_editor/ambient_tip = #rrggbb:地图始终以此光照(点灯的房间);留空则随时间变化
tools/rpg_editor/autotile = 自动图块
+11 -7
View File
@@ -28,9 +28,19 @@ namespace Cthangover.Tools.RpgEditor
private readonly HBoxContainer buttons; private readonly HBoxContainer buttons;
private List<RpgPickerEntry> all = new(); private List<RpgPickerEntry> all = new();
/// <summary>Builds the search field, the list, the option and button rows and the hint.</summary> /// <summary>
/// Builds the option and button rows with their hint on top — the list grows with the
/// entries (<c>AutoHeight</c>), so buttons below it would scroll out of sight — then the
/// search field and the list.
/// </summary>
public RpgEntityPicker(string searchKey, string hintKey) public RpgEntityPicker(string searchKey, string hintKey)
{ {
options = new HBoxContainer();
AddChild(options);
buttons = new HBoxContainer();
AddChild(buttons);
AddChild(ToolUi.Hint(ToolUi.Tr(hintKey)));
search = ToolUi.Text(ToolUi.Tr(searchKey), OnSearchChanged); search = ToolUi.Text(ToolUi.Tr(searchKey), OnSearchChanged);
AddChild(search); AddChild(search);
@@ -43,12 +53,6 @@ namespace Cthangover.Tools.RpgEditor
}; };
list.ItemSelected += OnItemSelected; list.ItemSelected += OnItemSelected;
AddChild(list); AddChild(list);
options = new HBoxContainer();
AddChild(options);
buttons = new HBoxContainer();
AddChild(buttons);
AddChild(ToolUi.Hint(ToolUi.Tr(hintKey)));
} }
/// <summary>Reads the entries; called by <see cref="Reload"/>.</summary> /// <summary>Reads the entries; called by <see cref="Reload"/>.</summary>
+17 -1
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Cthangover.Mods.Rpg; using Cthangover.Mods.Rpg;
using Cthangover.Tools.Common; using Cthangover.Tools.Common;
using Cthangover.Tools.Services;
using Godot; using Godot;
namespace Cthangover.Tools.RpgEditor namespace Cthangover.Tools.RpgEditor
@@ -10,7 +11,8 @@ namespace Cthangover.Tools.RpgEditor
/// <summary> /// <summary>
/// Properties of the selected map event: id, cell, look (charset path, tileset index /// Properties of the selected map event: id, cell, look (charset path, tileset index
/// or item picture), facing, trigger, solidity, what it runs (scenario path, /// or item picture), facing, trigger, solidity, what it runs (scenario path,
/// inline DSL lines, or a teleport) and the condition that shows it. /// inline DSL lines with highlighting, or a teleport), the light it gives off (radius 0 = none)
/// and the condition that shows it.
/// <para/> /// <para/>
/// A teleport is on when its map or cell is filled in; clearing the teleport /// A teleport is on when its map or cell is filled in; clearing the teleport
/// map and both coordinates turns it off again. Solidity has a third state, /// map and both coordinates turns it off again. Solidity has a third state,
@@ -40,6 +42,8 @@ namespace Cthangover.Tools.RpgEditor
private readonly SpinBox teleportX; private readonly SpinBox teleportX;
private readonly SpinBox teleportY; private readonly SpinBox teleportY;
private readonly OptionButton teleportDir; private readonly OptionButton teleportDir;
private readonly SpinBox lightRadius;
private readonly LineEdit lightColor;
private RpgMapEvent mapEvent; private RpgMapEvent mapEvent;
private bool suppress; private bool suppress;
private bool editing; private bool editing;
@@ -78,10 +82,15 @@ namespace Cthangover.Tools.RpgEditor
body.AddChild(ToolUi.Hint(ToolUi.Tr("tools/rpg_editor/commands"))); body.AddChild(ToolUi.Hint(ToolUi.Tr("tools/rpg_editor/commands")));
commandsEdit = ToolUi.Code(); commandsEdit = ToolUi.Code();
commandsEdit.CustomMinimumSize = new Vector2(0, 90); commandsEdit.CustomMinimumSize = new Vector2(0, 90);
commandsEdit.SyntaxHighlighter = ScenarioSyntaxService.CreateHighlighter();
commandsEdit.SizeFlagsVertical = SizeFlags.Fill; commandsEdit.SizeFlagsVertical = SizeFlags.Fill;
commandsEdit.TextChanged += OnCommandsChanged; commandsEdit.TextChanged += OnCommandsChanged;
body.AddChild(commandsEdit); body.AddChild(commandsEdit);
body.AddChild(ToolUi.Section("tools/rpg_editor/section_light"));
lightRadius = ToolUi.Field(body, "tools/rpg_editor/light_radius", ToolUi.Number(0, 16, 0.5, OnNumberChanged), "tools/rpg_editor/light_radius_tip");
lightColor = ToolUi.Field(body, "tools/rpg_editor/light_color", ToolUi.Text("#ffd8a0", OnTextChanged), "tools/rpg_editor/light_color_tip");
body.AddChild(ToolUi.Section("tools/rpg_editor/section_teleport")); body.AddChild(ToolUi.Section("tools/rpg_editor/section_teleport"));
teleportMap = ToolUi.Field(body, "tools/rpg_editor/teleport_map", ToolUi.Text("", OnTextChanged), "tools/rpg_editor/teleport_map_tip"); teleportMap = ToolUi.Field(body, "tools/rpg_editor/teleport_map", ToolUi.Text("", OnTextChanged), "tools/rpg_editor/teleport_map_tip");
teleportX = ToolUi.Field(body, "tools/rpg_editor/x", ToolUi.Number(-1, 255, 1, OnNumberChanged)); teleportX = ToolUi.Field(body, "tools/rpg_editor/x", ToolUi.Number(-1, 255, 1, OnNumberChanged));
@@ -119,6 +128,8 @@ namespace Cthangover.Tools.RpgEditor
teleportX.Value = value.Teleport?.X ?? -1; teleportX.Value = value.Teleport?.X ?? -1;
teleportY.Value = value.Teleport?.Y ?? -1; teleportY.Value = value.Teleport?.Y ?? -1;
teleportDir.Select((int)(value.Teleport?.Dir ?? RpgDirection.Down)); teleportDir.Select((int)(value.Teleport?.Dir ?? RpgDirection.Down));
lightRadius.Value = value.Light?.Radius ?? 0;
lightColor.Text = value.Light?.Color ?? string.Empty;
suppress = false; suppress = false;
} }
@@ -183,6 +194,11 @@ namespace Cthangover.Tools.RpgEditor
Dir = (RpgDirection)teleportDir.Selected, Dir = (RpgDirection)teleportDir.Selected,
} }
: null; : null;
// A radius of 0 means no light; an empty colour keeps the warm default.
mapEvent.Light = lightRadius.Value > 0
? new RpgLight { Radius = (float)lightRadius.Value, Color = NullIfEmpty(lightColor.Text) ?? new RpgLight().Color }
: null;
Changed?.Invoke(); Changed?.Invoke();
} }
+7 -1
View File
@@ -157,8 +157,14 @@ namespace Cthangover.Tools.RpgEditor
for (var x = 0; x < grid.Width; x++) for (var x = 0; x < grid.Width; x++)
{ {
var index = grid.GetTile(layer, x, y); var index = grid.GetTile(layer, x, y);
if (index >= 0) if (index < 0)
continue;
// Autotiles are assembled from their neighbours exactly like in the game.
var autotile = Tileset.AutotileOf(index);
if (autotile == null)
DrawTextureRectRegion(Atlas, CellRect(x, y), TileRegion(index), modulate); DrawTextureRectRegion(Atlas, CellRect(x, y), TileRegion(index), modulate);
else if (textures.Tileset(autotile.Autotile) is { } block)
RpgAutotiles.Draw(this, block, CellRect(x, y), RpgAutotiles.QuartersAt(grid, layer, x, y, index), Tileset.TileSize, modulate);
} }
} }
} }
+13 -1
View File
@@ -10,7 +10,8 @@ namespace Cthangover.Tools.RpgEditor
{ {
/// <summary> /// <summary>
/// The map's own properties in the right column: id (the scene name, read /// The map's own properties in the right column: id (the scene name, read
/// only — it is the file name), display name key, tileset, size, zoom, spawn /// only — it is the file name), display name key, tileset, size, zoom, fixed
/// ambient light (empty: the time of day lights the map), spawn
/// and random encounters. The size is applied with a button, because a /// and random encounters. The size is applied with a button, because a
/// smaller size cuts cells off. Encounter groups are written as /// smaller size cuts cells off. Encounter groups are written as
/// <c>slime; wolf,slime</c> — groups split by semicolons. /// <c>slime; wolf,slime</c> — groups split by semicolons.
@@ -27,6 +28,7 @@ namespace Cthangover.Tools.RpgEditor
private readonly SpinBox widthSpin; private readonly SpinBox widthSpin;
private readonly SpinBox heightSpin; private readonly SpinBox heightSpin;
private readonly SpinBox zoomSpin; private readonly SpinBox zoomSpin;
private readonly LineEdit ambientEdit;
private readonly SpinBox spawnX; private readonly SpinBox spawnX;
private readonly SpinBox spawnY; private readonly SpinBox spawnY;
private readonly OptionButton spawnDir; private readonly OptionButton spawnDir;
@@ -61,6 +63,7 @@ namespace Cthangover.Tools.RpgEditor
heightSpin = ToolUi.Field(this, "tools/rpg_editor/height", ToolUi.Number(1, 256, 1, null)); heightSpin = ToolUi.Field(this, "tools/rpg_editor/height", ToolUi.Number(1, 256, 1, null));
AddChild(ToolUi.Button("tools/rpg_editor/resize", OnResizePressed)); AddChild(ToolUi.Button("tools/rpg_editor/resize", OnResizePressed));
zoomSpin = ToolUi.Field(this, "tools/rpg_editor/zoom", ToolUi.Number(1, 4, 1, OnZoomChanged), "tools/rpg_editor/zoom_tip"); zoomSpin = ToolUi.Field(this, "tools/rpg_editor/zoom", ToolUi.Number(1, 4, 1, OnZoomChanged), "tools/rpg_editor/zoom_tip");
ambientEdit = ToolUi.Field(this, "tools/rpg_editor/ambient", ToolUi.Text("#e0d2b8", OnAmbientChanged), "tools/rpg_editor/ambient_tip");
AddChild(ToolUi.Section("tools/rpg_editor/section_spawn")); AddChild(ToolUi.Section("tools/rpg_editor/section_spawn"));
spawnX = ToolUi.Field(this, "tools/rpg_editor/x", ToolUi.Number(0, 255, 1, OnSpawnChanged)); spawnX = ToolUi.Field(this, "tools/rpg_editor/x", ToolUi.Number(0, 255, 1, OnSpawnChanged));
@@ -94,6 +97,7 @@ namespace Cthangover.Tools.RpgEditor
widthSpin.Value = value.Grid.Width; widthSpin.Value = value.Grid.Width;
heightSpin.Value = value.Grid.Height; heightSpin.Value = value.Grid.Height;
zoomSpin.Value = map.Zoom; zoomSpin.Value = map.Zoom;
ambientEdit.Text = map.Ambient ?? string.Empty;
spawnX.Value = map.Spawn.X; spawnX.Value = map.Spawn.X;
spawnY.Value = map.Spawn.Y; spawnY.Value = map.Spawn.Y;
spawnDir.Select((int)map.Spawn.Dir); spawnDir.Select((int)map.Spawn.Dir);
@@ -123,6 +127,14 @@ namespace Cthangover.Tools.RpgEditor
Changed?.Invoke(); Changed?.Invoke();
} }
private void OnAmbientChanged(string text)
{
if (!Begin())
return;
document.Map.Ambient = string.IsNullOrWhiteSpace(text) ? null : text.Trim();
Changed?.Invoke();
}
private void OnTilesetPicked(long index) private void OnTilesetPicked(long index)
{ {
if (!Begin() || index < 0 || index >= tilesets.Count) if (!Begin() || index < 0 || index >= tilesets.Count)
+42 -9
View File
@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Cthangover.Core.UI.Theming; using Cthangover.Core.UI.Theming;
using Cthangover.Mods.Rpg; using Cthangover.Mods.Rpg;
@@ -10,16 +11,20 @@ namespace Cthangover.Tools.RpgEditor
/// Brush picker of the editor's left column. For a tile layer it shows the /// Brush picker of the editor's left column. For a tile layer it shows the
/// tileset atlas at one and a half times the tile size with the selected tile framed and the /// tileset atlas at one and a half times the tile size with the selected tile framed and the
/// solid tiles marked by a red corner; a click picks a tile, the tooltip /// solid tiles marked by a red corner; a click picks a tile, the tooltip
/// names it (index, tag, solid). For the collision layer it shows the three /// names it (index, tag, solid). The tileset's autotiles follow in a row under the
/// collision codes instead. /// atlas, each shown by its block's preview tile (<see cref="RpgAutotiles"/>). For the
/// collision layer it shows the three collision codes instead.
/// </summary> /// </summary>
public partial class RpgTilePalette : Control public partial class RpgTilePalette : Control
{ {
private const float Scale = 1.5f; private const float Scale = 1.5f;
private const float CodeHeight = 44f; private const float CodeHeight = 44f;
private const float AutotileGap = 8f;
private static readonly char[] Codes = { RpgCollision.Block, RpgCollision.Open, RpgCollision.Auto }; private static readonly char[] Codes = { RpgCollision.Block, RpgCollision.Open, RpgCollision.Auto };
private readonly RpgTextures textures = new();
private readonly List<RpgTileInfo> autotiles = new();
private RpgTileset tileset; private RpgTileset tileset;
private Texture2D atlas; private Texture2D atlas;
private bool collisionMode; private bool collisionMode;
@@ -49,6 +54,9 @@ namespace Cthangover.Tools.RpgEditor
{ {
tileset = value; tileset = value;
atlas = image; atlas = image;
autotiles.Clear();
if (value != null)
autotiles.AddRange(value.Tiles.Where(t => !string.IsNullOrEmpty(t.Autotile)));
Relayout(); Relayout();
} }
@@ -80,15 +88,23 @@ namespace Cthangover.Tools.RpgEditor
var cell = tileset.TileSize * Scale; var cell = tileset.TileSize * Scale;
DrawTextureRect(atlas, new Rect2(Vector2.Zero, atlas.GetSize() * Scale), false); DrawTextureRect(atlas, new Rect2(Vector2.Zero, atlas.GetSize() * Scale), false);
foreach (var tile in tileset.Tiles.Where(t => t.Solid)) foreach (var tile in tileset.Tiles.Where(t => t.Solid && string.IsNullOrEmpty(t.Autotile)))
DrawSolidMark((Vector2)RpgTileSetBuilder.AtlasCoords(tileset, tile.Index) * cell, cell);
for (var i = 0; i < autotiles.Count; i++)
{ {
var position = (Vector2)RpgTileSetBuilder.AtlasCoords(tileset, tile.Index) * cell; if (textures.Tileset(autotiles[i].Autotile) is { } block)
DrawColoredPolygon(new[] { position, position + new Vector2(cell * 0.25f, 0f), position + new Vector2(0f, cell * 0.25f) }, new Color(0.9f, 0.2f, 0.2f, 0.9f)); DrawTextureRectRegion(block, new Rect2(Slot(i), new Vector2(cell, cell)), RpgAutotiles.PreviewRect(tileset.TileSize));
if (autotiles[i].Solid)
DrawSolidMark(Slot(i), cell);
} }
var selected = (Vector2)RpgTileSetBuilder.AtlasCoords(tileset, SelectedTile) * cell; var slot = autotiles.FindIndex(t => t.Index == SelectedTile);
var selected = slot >= 0 ? Slot(slot) : (Vector2)RpgTileSetBuilder.AtlasCoords(tileset, SelectedTile) * cell;
DrawRect(new Rect2(selected, new Vector2(cell, cell)), UiTokens.AccentBright, false, 3f); DrawRect(new Rect2(selected, new Vector2(cell, cell)), UiTokens.AccentBright, false, 3f);
} }
private void DrawSolidMark(Vector2 position, float cell)
=> DrawColoredPolygon(new[] { position, position + new Vector2(cell * 0.25f, 0f), position + new Vector2(0f, cell * 0.25f) }, new Color(0.9f, 0.2f, 0.2f, 0.9f));
private void DrawCode(int i) private void DrawCode(int i)
{ {
var rect = new Rect2(0f, i * (CodeHeight + 6f), Size.X, CodeHeight); var rect = new Rect2(0f, i * (CodeHeight + 6f), Size.X, CodeHeight);
@@ -110,7 +126,7 @@ namespace Cthangover.Tools.RpgEditor
if (collisionMode) if (collisionMode)
CustomMinimumSize = new Vector2(200f, Codes.Length * (CodeHeight + 6f)); CustomMinimumSize = new Vector2(200f, Codes.Length * (CodeHeight + 6f));
else else
CustomMinimumSize = atlas != null ? atlas.GetSize() * Scale : Vector2.Zero; CustomMinimumSize = atlas != null && tileset != null ? new Vector2(atlas.GetWidth() * Scale, AutotileTop + AutotileRows * tileset.TileSize * Scale) : Vector2.Zero;
TooltipText = string.Empty; TooltipText = string.Empty;
QueueRedraw(); QueueRedraw();
} }
@@ -137,7 +153,7 @@ namespace Cthangover.Tools.RpgEditor
else if (tileset != null && atlas != null) else if (tileset != null && atlas != null)
{ {
var index = IndexAt(button.Position); var index = IndexAt(button.Position);
if (index >= 0 && index < RpgTileSetBuilder.TileCount(tileset, atlas)) if (index >= 0 && (index < RpgTileSetBuilder.TileCount(tileset, atlas) || tileset.AutotileOf(index) != null))
{ {
SelectedTile = index; SelectedTile = index;
TileSelected?.Invoke(index); TileSelected?.Invoke(index);
@@ -147,9 +163,25 @@ namespace Cthangover.Tools.RpgEditor
AcceptEvent(); AcceptEvent();
} }
private float AutotileTop => atlas == null ? 0f : atlas.GetHeight() * Scale + (autotiles.Count > 0 ? AutotileGap : 0f);
private int AutotileRows => (autotiles.Count + Math.Max(1, tileset.Columns) - 1) / Math.Max(1, tileset.Columns);
private Vector2 Slot(int i)
{
var cell = tileset.TileSize * Scale;
var columns = Math.Max(1, tileset.Columns);
return new Vector2(i % columns * cell, AutotileTop + i / columns * cell);
}
private int IndexAt(Vector2 position) private int IndexAt(Vector2 position)
{ {
var cell = tileset.TileSize * Scale; var cell = tileset.TileSize * Scale;
if (autotiles.Count > 0 && position.Y >= AutotileTop)
{
var slot = (int)((position.Y - AutotileTop) / cell) * Math.Max(1, tileset.Columns) + (int)(position.X / cell);
return slot >= 0 && slot < autotiles.Count && position.X < tileset.Columns * cell ? autotiles[slot].Index : -1;
}
var column = (int)(position.X / cell); var column = (int)(position.X / cell);
var row = (int)(position.Y / cell); var row = (int)(position.Y / cell);
return column < 0 || column >= tileset.Columns || row < 0 ? -1 : row * tileset.Columns + column; return column < 0 || column >= tileset.Columns || row < 0 ? -1 : row * tileset.Columns + column;
@@ -159,7 +191,8 @@ namespace Cthangover.Tools.RpgEditor
{ {
var info = tileset.Tiles.FirstOrDefault(t => t.Index == index); var info = tileset.Tiles.FirstOrDefault(t => t.Index == index);
var solid = info?.Solid == true ? " · " + TranslationServer.Translate("tools/rpg_editor/solid_tile") : string.Empty; var solid = info?.Solid == true ? " · " + TranslationServer.Translate("tools/rpg_editor/solid_tile") : string.Empty;
return $"#{index} {info?.Tag}{solid}"; var auto = string.IsNullOrEmpty(info?.Autotile) ? string.Empty : " · " + TranslationServer.Translate("tools/rpg_editor/autotile");
return $"#{index} {info?.Tag}{solid}{auto}";
} }
} }
} }