diff --git a/docs/ART.md b/docs/ART.md index 7da0f27..3e33e11 100644 --- a/docs/ART.md +++ b/docs/ART.md @@ -111,3 +111,18 @@ no photorealism, no noisy texture, no high-frequency detail, no dense grime, no ## 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. + +## 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`. diff --git a/src/ReactorMaintenance.Godot/Assets/Characters/maintenance_robot.png b/src/ReactorMaintenance.Godot/Assets/Characters/maintenance_robot.png new file mode 100644 index 0000000..ffdc123 Binary files /dev/null and b/src/ReactorMaintenance.Godot/Assets/Characters/maintenance_robot.png differ diff --git a/src/ReactorMaintenance.Godot/Assets/Characters/maintenance_robot.png.import b/src/ReactorMaintenance.Godot/Assets/Characters/maintenance_robot.png.import new file mode 100644 index 0000000..56c8020 --- /dev/null +++ b/src/ReactorMaintenance.Godot/Assets/Characters/maintenance_robot.png.import @@ -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 diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/coolant_icon.png b/src/ReactorMaintenance.Godot/Assets/Ui/coolant_icon.png new file mode 100644 index 0000000..7024812 Binary files /dev/null and b/src/ReactorMaintenance.Godot/Assets/Ui/coolant_icon.png differ diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/coolant_icon.png.import b/src/ReactorMaintenance.Godot/Assets/Ui/coolant_icon.png.import new file mode 100644 index 0000000..fd69981 --- /dev/null +++ b/src/ReactorMaintenance.Godot/Assets/Ui/coolant_icon.png.import @@ -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 diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/electric_icon.png b/src/ReactorMaintenance.Godot/Assets/Ui/electric_icon.png new file mode 100644 index 0000000..71fb091 Binary files /dev/null and b/src/ReactorMaintenance.Godot/Assets/Ui/electric_icon.png differ diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/electric_icon.png.import b/src/ReactorMaintenance.Godot/Assets/Ui/electric_icon.png.import new file mode 100644 index 0000000..d943f82 --- /dev/null +++ b/src/ReactorMaintenance.Godot/Assets/Ui/electric_icon.png.import @@ -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 diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/fuel_icon.png b/src/ReactorMaintenance.Godot/Assets/Ui/fuel_icon.png new file mode 100644 index 0000000..c32938f Binary files /dev/null and b/src/ReactorMaintenance.Godot/Assets/Ui/fuel_icon.png differ diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/fuel_icon.png.import b/src/ReactorMaintenance.Godot/Assets/Ui/fuel_icon.png.import new file mode 100644 index 0000000..ba6aeea --- /dev/null +++ b/src/ReactorMaintenance.Godot/Assets/Ui/fuel_icon.png.import @@ -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 diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/heat_shield_icon.png b/src/ReactorMaintenance.Godot/Assets/Ui/heat_shield_icon.png new file mode 100644 index 0000000..89bba51 Binary files /dev/null and b/src/ReactorMaintenance.Godot/Assets/Ui/heat_shield_icon.png differ diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/heat_shield_icon.png.import b/src/ReactorMaintenance.Godot/Assets/Ui/heat_shield_icon.png.import new file mode 100644 index 0000000..c60b7c2 --- /dev/null +++ b/src/ReactorMaintenance.Godot/Assets/Ui/heat_shield_icon.png.import @@ -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 diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/primary_button_accent.png b/src/ReactorMaintenance.Godot/Assets/Ui/primary_button_accent.png new file mode 100644 index 0000000..4e9cd16 Binary files /dev/null and b/src/ReactorMaintenance.Godot/Assets/Ui/primary_button_accent.png differ diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/primary_button_accent.png.import b/src/ReactorMaintenance.Godot/Assets/Ui/primary_button_accent.png.import new file mode 100644 index 0000000..c1c8f32 --- /dev/null +++ b/src/ReactorMaintenance.Godot/Assets/Ui/primary_button_accent.png.import @@ -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 diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/scanner_eye_icon.png b/src/ReactorMaintenance.Godot/Assets/Ui/scanner_eye_icon.png new file mode 100644 index 0000000..a97fedd Binary files /dev/null and b/src/ReactorMaintenance.Godot/Assets/Ui/scanner_eye_icon.png differ diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/scanner_eye_icon.png.import b/src/ReactorMaintenance.Godot/Assets/Ui/scanner_eye_icon.png.import new file mode 100644 index 0000000..0113d07 --- /dev/null +++ b/src/ReactorMaintenance.Godot/Assets/Ui/scanner_eye_icon.png.import @@ -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 diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/state_badge_frame.png b/src/ReactorMaintenance.Godot/Assets/Ui/state_badge_frame.png new file mode 100644 index 0000000..389cad8 Binary files /dev/null and b/src/ReactorMaintenance.Godot/Assets/Ui/state_badge_frame.png differ diff --git a/src/ReactorMaintenance.Godot/Assets/Ui/state_badge_frame.png.import b/src/ReactorMaintenance.Godot/Assets/Ui/state_badge_frame.png.import new file mode 100644 index 0000000..9396704 --- /dev/null +++ b/src/ReactorMaintenance.Godot/Assets/Ui/state_badge_frame.png.import @@ -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 diff --git a/src/ReactorMaintenance.Godot/Assets/generated_cutouts_prompts.jsonl b/src/ReactorMaintenance.Godot/Assets/generated_cutouts_prompts.jsonl new file mode 100644 index 0000000..61b4448 --- /dev/null +++ b/src/ReactorMaintenance.Godot/Assets/generated_cutouts_prompts.jsonl @@ -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."} diff --git a/src/ReactorMaintenance.Godot/Controls/CellInspector.cs b/src/ReactorMaintenance.Godot/Controls/CellInspector.cs index 5b9e53b..663917d 100644 --- a/src/ReactorMaintenance.Godot/Controls/CellInspector.cs +++ b/src/ReactorMaintenance.Godot/Controls/CellInspector.cs @@ -1,4 +1,4 @@ -using Godot; +using Godot; namespace ReactorMaintenance.Godot.Controls; @@ -6,10 +6,21 @@ public partial class CellInspector : PanelContainer { 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.AutowrapMode = TextServer.AutowrapMode.WordSmart; } private readonly Label m_Text = new(); -} \ No newline at end of file +} diff --git a/src/ReactorMaintenance.Godot/Controls/FrontendAssets.cs b/src/ReactorMaintenance.Godot/Controls/FrontendAssets.cs new file mode 100644 index 0000000..f0d2567 --- /dev/null +++ b/src/ReactorMaintenance.Godot/Controls/FrontendAssets.cs @@ -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(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 + }; + } +} diff --git a/src/ReactorMaintenance.Godot/Controls/FrontendAssets.cs.uid b/src/ReactorMaintenance.Godot/Controls/FrontendAssets.cs.uid new file mode 100644 index 0000000..f05edf4 --- /dev/null +++ b/src/ReactorMaintenance.Godot/Controls/FrontendAssets.cs.uid @@ -0,0 +1 @@ +uid://bfvrecxfcutol diff --git a/src/ReactorMaintenance.Godot/Controls/InventoryStrip.cs b/src/ReactorMaintenance.Godot/Controls/InventoryStrip.cs index a4e422a..43030f5 100644 --- a/src/ReactorMaintenance.Godot/Controls/InventoryStrip.cs +++ b/src/ReactorMaintenance.Godot/Controls/InventoryStrip.cs @@ -1,4 +1,4 @@ -using Godot; +using Godot; namespace ReactorMaintenance.Godot.Controls; @@ -6,18 +6,23 @@ public partial class InventoryStrip : HBoxContainer { public override void _Ready() { - AddChild(CreateItem("Fuel Neutralizer", 2)); - AddChild(CreateItem("Coolant Neutralizer", 2)); - AddChild(CreateItem("Electric Neutralizer", 1)); - AddChild(CreateItem("Heat Shield", 1)); + AddChild(CreateItem("Fuel Neutralizer", 2, FrontendAssets.FuelIcon)); + AddChild(CreateItem("Coolant Neutralizer", 2, FrontendAssets.CoolantIcon)); + AddChild(CreateItem("Electric Neutralizer", 1, FrontendAssets.ElectricIcon)); + 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}", HorizontalAlignment = HorizontalAlignment.Center, SizeFlagsHorizontal = SizeFlags.ExpandFill - }; + }); + return item; } -} \ No newline at end of file +} diff --git a/src/ReactorMaintenance.Godot/Controls/PrimaryButton.cs b/src/ReactorMaintenance.Godot/Controls/PrimaryButton.cs index 8cd9d7c..887ac1d 100644 --- a/src/ReactorMaintenance.Godot/Controls/PrimaryButton.cs +++ b/src/ReactorMaintenance.Godot/Controls/PrimaryButton.cs @@ -1,4 +1,4 @@ -using Godot; +using Godot; namespace ReactorMaintenance.Godot.Controls; @@ -9,6 +9,10 @@ public partial class PrimaryButton : Button FocusMode = FocusModeEnum.All; CustomMinimumSize = new(220, 44); SizeFlagsHorizontal = SizeFlags.ExpandFill; + + Icon = FrontendAssets.LoadTexture(FrontendAssets.PrimaryButtonAccent); + ExpandIcon = true; + IconAlignment = HorizontalAlignment.Left; } public void Configure(string text, string tooltip = "", bool disabled = false) @@ -17,4 +21,4 @@ public partial class PrimaryButton : Button TooltipText = tooltip; Disabled = disabled; } -} \ No newline at end of file +} diff --git a/src/ReactorMaintenance.Godot/Controls/StateBadge.cs b/src/ReactorMaintenance.Godot/Controls/StateBadge.cs index 5539aa0..9d96e67 100644 --- a/src/ReactorMaintenance.Godot/Controls/StateBadge.cs +++ b/src/ReactorMaintenance.Godot/Controls/StateBadge.cs @@ -1,20 +1,39 @@ -using Godot; +using Godot; namespace ReactorMaintenance.Godot.Controls; -public partial class StateBadge : Label +public partial class StateBadge : PanelContainer { public override void _Ready() { - HorizontalAlignment = HorizontalAlignment.Center; - VerticalAlignment = VerticalAlignment.Center; 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) { - Text = state; - AddThemeColorOverride("font_color", GetColor(state)); + m_Text.Text = state; + m_Text.AddThemeColorOverride("font_color", GetColor(state)); } private static Color GetColor(string state) @@ -27,4 +46,6 @@ public partial class StateBadge : Label _ => Colors.White }; } -} \ No newline at end of file + + private readonly Label m_Text = new(); +} diff --git a/src/ReactorMaintenance.Godot/Scenes/Controls/StateBadge.tscn b/src/ReactorMaintenance.Godot/Scenes/Controls/StateBadge.tscn index e142c46..62f6e3b 100644 --- a/src/ReactorMaintenance.Godot/Scenes/Controls/StateBadge.tscn +++ b/src/ReactorMaintenance.Godot/Scenes/Controls/StateBadge.tscn @@ -2,5 +2,5 @@ [ext_resource type="Script" path="res://Controls/StateBadge.cs" id="1"] -[node name="StateBadge" type="Label"] +[node name="StateBadge" type="PanelContainer"] script = ExtResource("1") diff --git a/src/ReactorMaintenance.Godot/Screens/LevelScreen.cs b/src/ReactorMaintenance.Godot/Screens/LevelScreen.cs index e251b93..d52ac23 100644 --- a/src/ReactorMaintenance.Godot/Screens/LevelScreen.cs +++ b/src/ReactorMaintenance.Godot/Screens/LevelScreen.cs @@ -1,4 +1,4 @@ -using Godot; +using Godot; using ReactorMaintenance.Godot.Controls; using ReactorMaintenance.Godot.Data; @@ -36,20 +36,44 @@ public partial class LevelScreen : ScreenBase private static PanelContainer CreateGridPlaceholder() { 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 { Text = "Level Grid Placeholder\nRobot marker, terrain, props, hazards, and underground overlays will render here.", + AnchorRight = 1, + AnchorBottom = 1, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, 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; } private static VBoxContainer CreateSidePanel(CampaignLevel level) { var sidePanel = new VBoxContainer { CustomMinimumSize = new(300, 0) }; - sidePanel.AddChild(new Label { Text = "Inspector" }); sidePanel.AddChild(new CellInspector()); sidePanel.AddChild(new ForecastList()); 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 bool m_OutcomeVisible; private CanvasLayer? m_OverlayLayer; -} \ No newline at end of file +}