Integrate Godot cutout art

This commit is contained in:
2026-05-12 22:36:13 +02:00
parent 3224f3768b
commit 390a09015b
26 changed files with 466 additions and 26 deletions

View File

@@ -111,3 +111,18 @@ no photorealism, no noisy texture, no high-frequency detail, no dense grime, no
## Existing Asset Note ## Existing Asset Note
The current Win2D PNGs are useful subject references for the required asset categories, but they are not the target style. Future assets should be simpler, cleaner, more silhouette-driven, and more readable when scaled down. The current Win2D PNGs are useful subject references for the required asset categories, but they are not the target style. Future assets should be simpler, cleaner, more silhouette-driven, and more readable when scaled down.
## Generated Godot Cutouts
The first transparent Godot cutouts live under `src/ReactorMaintenance.Godot/Assets`. They were generated with `gpt-image-1.5` using the mood sheets in `output/imagegen/godot-mood` as references:
- `Assets/Characters/maintenance_robot.png`
- `Assets/Ui/primary_button_accent.png`
- `Assets/Ui/state_badge_frame.png`
- `Assets/Ui/fuel_icon.png`
- `Assets/Ui/coolant_icon.png`
- `Assets/Ui/electric_icon.png`
- `Assets/Ui/heat_shield_icon.png`
- `Assets/Ui/scanner_eye_icon.png`
The exact generation prompts are recorded in `src/ReactorMaintenance.Godot/Assets/generated_cutouts_prompts.jsonl`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://g8njonkahvns"
path="res://.godot/imported/maintenance_robot.png-77cbb0f8610a91dc82df7b4565ee0a3a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Characters/maintenance_robot.png"
dest_files=["res://.godot/imported/maintenance_robot.png-77cbb0f8610a91dc82df7b4565ee0a3a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c460u833mc8wd"
path="res://.godot/imported/coolant_icon.png-5f62705f72d18fbac1995d1563570521.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Ui/coolant_icon.png"
dest_files=["res://.godot/imported/coolant_icon.png-5f62705f72d18fbac1995d1563570521.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c15hva5fpyqb0"
path="res://.godot/imported/electric_icon.png-f93d44cfb4888519024e3d64de9dbe62.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Ui/electric_icon.png"
dest_files=["res://.godot/imported/electric_icon.png-f93d44cfb4888519024e3d64de9dbe62.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://2v0gglovpy7t"
path="res://.godot/imported/fuel_icon.png-8e723683b233f30e6235d28f228f5d83.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Ui/fuel_icon.png"
dest_files=["res://.godot/imported/fuel_icon.png-8e723683b233f30e6235d28f228f5d83.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://6lpfwf7pkx0c"
path="res://.godot/imported/heat_shield_icon.png-80a3ecc066be8caa1d77f8459e73bf57.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Ui/heat_shield_icon.png"
dest_files=["res://.godot/imported/heat_shield_icon.png-80a3ecc066be8caa1d77f8459e73bf57.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bj45xeusdpf2g"
path="res://.godot/imported/primary_button_accent.png-99d4e7a7f8a491f0ae2203e71d886e65.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Ui/primary_button_accent.png"
dest_files=["res://.godot/imported/primary_button_accent.png-99d4e7a7f8a491f0ae2203e71d886e65.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c3v3xokega3lk"
path="res://.godot/imported/scanner_eye_icon.png-003ae6769bc5ea847f0ea3422bbd05b3.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Ui/scanner_eye_icon.png"
dest_files=["res://.godot/imported/scanner_eye_icon.png-003ae6769bc5ea847f0ea3422bbd05b3.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bmpb1t3muf78i"
path="res://.godot/imported/state_badge_frame.png-391c9f73136d3046614e3bac00f56da2.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Ui/state_badge_frame.png"
dest_files=["res://.godot/imported/state_badge_frame.png-391c9f73136d3046614e3bac00f56da2.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@@ -0,0 +1,8 @@
{"out":"res://Assets/Characters/maintenance_robot.png","model":"gpt-image-1.5","source":"output/imagegen/godot-mood/20-robot-design-sheet.png","prompt":"Create one transparent PNG cutout of the compact Reactor Maintenance player robot from the reference sheet. Keep the same modern elegant stylized playful sci-fi art direction: readable top-down 2D game asset, compact practical likable maintenance robot, cool graphite and blue-gray steel body, one cyan status light, selective dark outline, broad hue-varied wear instead of noisy luminance scratches. Center a single robot with generous transparent padding, no floor, no shadow, no text, no watermark, no UI frame. The robot must read clearly at 128px, 64px, and 32px."}
{"out":"res://Assets/Ui/primary_button_accent.png","model":"gpt-image-1.5","source":"output/imagegen/godot-mood/11-reusable-controls-kit.png","prompt":"Create one transparent PNG cutout for a Reactor Maintenance primary command button accent plate from the reusable controls reference. It should be a compact sci-fi UI button ornament or left icon plate, not a full button with text. Style: modern elegant stylized playful sci-fi, scrappy industrial, cool graphite and blue-gray steel, cyan edge light, selective dark outline, broad hue-varied wear, readable at 44px height. Center it with transparent padding. No text, no watermark, no background, no shadow."}
{"out":"res://Assets/Ui/state_badge_frame.png","model":"gpt-image-1.5","source":"output/imagegen/godot-mood/11-reusable-controls-kit.png","prompt":"Create one transparent PNG cutout for a Reactor Maintenance state badge frame from the reusable controls reference. It should be a small rounded industrial sci-fi badge backing with selective dark outline, cool graphite steel, subtle cyan rim detail, quiet center area for overlaid state text, broad hue variation not noisy scratches. Center with transparent padding. No text, no watermark, no background, no shadow."}
{"out":"res://Assets/Ui/fuel_icon.png","model":"gpt-image-1.5","source":"output/imagegen/godot-mood/11-reusable-controls-kit.png","prompt":"Create one transparent PNG cutout UI inventory icon for fuel neutralizer in Reactor Maintenance. Use the reusable controls reference style and art bible: flat-cleaner UI art, red fuel droplet/container pictogram, compact industrial badge silhouette, selective outline, readable at 24px. Center with transparent padding. No text, no watermark, no background, no shadow."}
{"out":"res://Assets/Ui/coolant_icon.png","model":"gpt-image-1.5","source":"output/imagegen/godot-mood/11-reusable-controls-kit.png","prompt":"Create one transparent PNG cutout UI inventory icon for coolant neutralizer in Reactor Maintenance. Use the reusable controls reference style and art bible: flat-cleaner UI art, cyan-blue droplet/canister pictogram, compact industrial badge silhouette, selective outline, readable at 24px. Center with transparent padding. No text, no watermark, no background, no shadow."}
{"out":"res://Assets/Ui/electric_icon.png","model":"gpt-image-1.5","source":"output/imagegen/godot-mood/11-reusable-controls-kit.png","prompt":"Create one transparent PNG cutout UI inventory icon for electricity neutralizer in Reactor Maintenance. Use the reusable controls reference style and art bible: flat-cleaner UI art, yellow lightning/insulated cell pictogram, compact industrial badge silhouette, selective outline, readable at 24px. Center with transparent padding. No text, no watermark, no background, no shadow."}
{"out":"res://Assets/Ui/heat_shield_icon.png","model":"gpt-image-1.5","source":"output/imagegen/godot-mood/11-reusable-controls-kit.png","prompt":"Create one transparent PNG cutout UI inventory icon for heat shield in Reactor Maintenance. Use the reusable controls reference style and art bible: flat-cleaner UI art, green-white shield with restrained orange heat edge, compact industrial badge silhouette, selective outline, readable at 24px. Center with transparent padding. No text, no watermark, no background, no shadow."}
{"out":"res://Assets/Ui/scanner_eye_icon.png","model":"gpt-image-1.5","source":"output/imagegen/godot-mood/11-reusable-controls-kit.png","prompt":"Create one transparent PNG cutout UI icon for the all-seeing-eye diagnostic scanner in Reactor Maintenance. Use the reusable controls reference style and art bible: flat-cleaner UI art, practical industrial eye/scanner symbol, teal/cyan diagnostic glow with muted graphite casing, selective outline, readable at 24px and 48px. Center with transparent padding. No text, no watermark, no background, no shadow."}

View File

@@ -1,4 +1,4 @@
using Godot; using Godot;
namespace ReactorMaintenance.Godot.Controls; namespace ReactorMaintenance.Godot.Controls;
@@ -6,10 +6,21 @@ public partial class CellInspector : PanelContainer
{ {
public override void _Ready() public override void _Ready()
{ {
AddChild(m_Text); var body = new VBoxContainer();
AddChild(body);
var header = new HBoxContainer();
header.AddChild(FrontendAssets.CreateIcon(FrontendAssets.ScannerEyeIcon, new(34, 34)));
header.AddChild(new Label {
Text = "Inspector",
VerticalAlignment = VerticalAlignment.Center
});
body.AddChild(header);
body.AddChild(m_Text);
m_Text.Text = "Selected Cell: 0,0\nTerrain: service floor\nProp: none\nHazards: none\nUnderground: hidden"; m_Text.Text = "Selected Cell: 0,0\nTerrain: service floor\nProp: none\nHazards: none\nUnderground: hidden";
m_Text.AutowrapMode = TextServer.AutowrapMode.WordSmart; m_Text.AutowrapMode = TextServer.AutowrapMode.WordSmart;
} }
private readonly Label m_Text = new(); private readonly Label m_Text = new();
} }

View File

@@ -0,0 +1,31 @@
using Godot;
namespace ReactorMaintenance.Godot.Controls;
internal static class FrontendAssets
{
public const string CoolantIcon = "res://Assets/Ui/coolant_icon.png";
public const string ElectricIcon = "res://Assets/Ui/electric_icon.png";
public const string FuelIcon = "res://Assets/Ui/fuel_icon.png";
public const string HeatShieldIcon = "res://Assets/Ui/heat_shield_icon.png";
public const string MaintenanceRobot = "res://Assets/Characters/maintenance_robot.png";
public const string PrimaryButtonAccent = "res://Assets/Ui/primary_button_accent.png";
public const string ScannerEyeIcon = "res://Assets/Ui/scanner_eye_icon.png";
public const string StateBadgeFrame = "res://Assets/Ui/state_badge_frame.png";
public static Texture2D? LoadTexture(string path)
{
return ResourceLoader.Exists(path) ? ResourceLoader.Load<Texture2D>(path) : null;
}
public static TextureRect CreateIcon(string path, Vector2 size)
{
return new() {
Texture = LoadTexture(path),
CustomMinimumSize = size,
ExpandMode = TextureRect.ExpandModeEnum.FitWidthProportional,
StretchMode = TextureRect.StretchModeEnum.KeepAspectCentered,
MouseFilter = Control.MouseFilterEnum.Ignore
};
}
}

View File

@@ -0,0 +1 @@
uid://bfvrecxfcutol

View File

@@ -1,4 +1,4 @@
using Godot; using Godot;
namespace ReactorMaintenance.Godot.Controls; namespace ReactorMaintenance.Godot.Controls;
@@ -6,18 +6,23 @@ public partial class InventoryStrip : HBoxContainer
{ {
public override void _Ready() public override void _Ready()
{ {
AddChild(CreateItem("Fuel Neutralizer", 2)); AddChild(CreateItem("Fuel Neutralizer", 2, FrontendAssets.FuelIcon));
AddChild(CreateItem("Coolant Neutralizer", 2)); AddChild(CreateItem("Coolant Neutralizer", 2, FrontendAssets.CoolantIcon));
AddChild(CreateItem("Electric Neutralizer", 1)); AddChild(CreateItem("Electric Neutralizer", 1, FrontendAssets.ElectricIcon));
AddChild(CreateItem("Heat Shield", 1)); AddChild(CreateItem("Heat Shield", 1, FrontendAssets.HeatShieldIcon));
} }
private static Label CreateItem(string name, int count) private static HBoxContainer CreateItem(string name, int count, string iconPath)
{ {
return new() { var item = new HBoxContainer {
SizeFlagsHorizontal = SizeFlags.ExpandFill
};
item.AddChild(FrontendAssets.CreateIcon(iconPath, new(30, 30)));
item.AddChild(new Label {
Text = $"{name}: {count}", Text = $"{name}: {count}",
HorizontalAlignment = HorizontalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center,
SizeFlagsHorizontal = SizeFlags.ExpandFill SizeFlagsHorizontal = SizeFlags.ExpandFill
}; });
return item;
} }
} }

View File

@@ -1,4 +1,4 @@
using Godot; using Godot;
namespace ReactorMaintenance.Godot.Controls; namespace ReactorMaintenance.Godot.Controls;
@@ -9,6 +9,10 @@ public partial class PrimaryButton : Button
FocusMode = FocusModeEnum.All; FocusMode = FocusModeEnum.All;
CustomMinimumSize = new(220, 44); CustomMinimumSize = new(220, 44);
SizeFlagsHorizontal = SizeFlags.ExpandFill; SizeFlagsHorizontal = SizeFlags.ExpandFill;
Icon = FrontendAssets.LoadTexture(FrontendAssets.PrimaryButtonAccent);
ExpandIcon = true;
IconAlignment = HorizontalAlignment.Left;
} }
public void Configure(string text, string tooltip = "", bool disabled = false) public void Configure(string text, string tooltip = "", bool disabled = false)
@@ -17,4 +21,4 @@ public partial class PrimaryButton : Button
TooltipText = tooltip; TooltipText = tooltip;
Disabled = disabled; Disabled = disabled;
} }
} }

View File

@@ -1,20 +1,39 @@
using Godot; using Godot;
namespace ReactorMaintenance.Godot.Controls; namespace ReactorMaintenance.Godot.Controls;
public partial class StateBadge : Label public partial class StateBadge : PanelContainer
{ {
public override void _Ready() public override void _Ready()
{ {
HorizontalAlignment = HorizontalAlignment.Center;
VerticalAlignment = VerticalAlignment.Center;
CustomMinimumSize = new(96, 28); CustomMinimumSize = new(96, 28);
var stack = new Control {
CustomMinimumSize = CustomMinimumSize,
SizeFlagsHorizontal = SizeFlags.ExpandFill
};
AddChild(stack);
var frame = new TextureRect {
Texture = FrontendAssets.LoadTexture(FrontendAssets.StateBadgeFrame),
AnchorRight = 1,
AnchorBottom = 1,
ExpandMode = TextureRect.ExpandModeEnum.FitWidthProportional,
StretchMode = TextureRect.StretchModeEnum.Scale,
MouseFilter = MouseFilterEnum.Ignore
};
stack.AddChild(frame);
m_Text.SetAnchorsPreset(LayoutPreset.FullRect);
m_Text.HorizontalAlignment = HorizontalAlignment.Center;
m_Text.VerticalAlignment = VerticalAlignment.Center;
stack.AddChild(m_Text);
} }
public void SetState(string state) public void SetState(string state)
{ {
Text = state; m_Text.Text = state;
AddThemeColorOverride("font_color", GetColor(state)); m_Text.AddThemeColorOverride("font_color", GetColor(state));
} }
private static Color GetColor(string state) private static Color GetColor(string state)
@@ -27,4 +46,6 @@ public partial class StateBadge : Label
_ => Colors.White _ => Colors.White
}; };
} }
}
private readonly Label m_Text = new();
}

View File

@@ -2,5 +2,5 @@
[ext_resource type="Script" path="res://Controls/StateBadge.cs" id="1"] [ext_resource type="Script" path="res://Controls/StateBadge.cs" id="1"]
[node name="StateBadge" type="Label"] [node name="StateBadge" type="PanelContainer"]
script = ExtResource("1") script = ExtResource("1")

View File

@@ -1,4 +1,4 @@
using Godot; using Godot;
using ReactorMaintenance.Godot.Controls; using ReactorMaintenance.Godot.Controls;
using ReactorMaintenance.Godot.Data; using ReactorMaintenance.Godot.Data;
@@ -36,20 +36,44 @@ public partial class LevelScreen : ScreenBase
private static PanelContainer CreateGridPlaceholder() private static PanelContainer CreateGridPlaceholder()
{ {
var panel = new PanelContainer { CustomMinimumSize = new(560, 360), SizeFlagsHorizontal = SizeFlags.ExpandFill, SizeFlagsVertical = SizeFlags.ExpandFill }; var panel = new PanelContainer { CustomMinimumSize = new(560, 360), SizeFlagsHorizontal = SizeFlags.ExpandFill, SizeFlagsVertical = SizeFlags.ExpandFill };
var viewport = new Control {
SizeFlagsHorizontal = SizeFlags.ExpandFill,
SizeFlagsVertical = SizeFlags.ExpandFill
};
panel.AddChild(viewport);
var label = new Label { var label = new Label {
Text = "Level Grid Placeholder\nRobot marker, terrain, props, hazards, and underground overlays will render here.", Text = "Level Grid Placeholder\nRobot marker, terrain, props, hazards, and underground overlays will render here.",
AnchorRight = 1,
AnchorBottom = 1,
HorizontalAlignment = HorizontalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center, VerticalAlignment = VerticalAlignment.Center,
AutowrapMode = TextServer.AutowrapMode.WordSmart AutowrapMode = TextServer.AutowrapMode.WordSmart
}; };
panel.AddChild(label); viewport.AddChild(label);
var robot = new TextureRect {
Texture = FrontendAssets.LoadTexture(FrontendAssets.MaintenanceRobot),
AnchorLeft = 0.5f,
AnchorTop = 0.5f,
AnchorRight = 0.5f,
AnchorBottom = 0.5f,
OffsetLeft = -48,
OffsetTop = -32,
OffsetRight = 48,
OffsetBottom = 64,
ExpandMode = TextureRect.ExpandModeEnum.FitWidthProportional,
StretchMode = TextureRect.StretchModeEnum.KeepAspectCentered,
MouseFilter = Control.MouseFilterEnum.Ignore
};
viewport.AddChild(robot);
return panel; return panel;
} }
private static VBoxContainer CreateSidePanel(CampaignLevel level) private static VBoxContainer CreateSidePanel(CampaignLevel level)
{ {
var sidePanel = new VBoxContainer { CustomMinimumSize = new(300, 0) }; var sidePanel = new VBoxContainer { CustomMinimumSize = new(300, 0) };
sidePanel.AddChild(new Label { Text = "Inspector" });
sidePanel.AddChild(new CellInspector()); sidePanel.AddChild(new CellInspector());
sidePanel.AddChild(new ForecastList()); sidePanel.AddChild(new ForecastList());
sidePanel.AddChild(new Label { Text = $"Level JSON: {level.LevelPath}", AutowrapMode = TextServer.AutowrapMode.WordSmart }); sidePanel.AddChild(new Label { Text = $"Level JSON: {level.LevelPath}", AutowrapMode = TextServer.AutowrapMode.WordSmart });
@@ -104,4 +128,4 @@ public partial class LevelScreen : ScreenBase
private CampaignLevel? m_Level; private CampaignLevel? m_Level;
private bool m_OutcomeVisible; private bool m_OutcomeVisible;
private CanvasLayer? m_OverlayLayer; private CanvasLayer? m_OverlayLayer;
} }