Compare commits

..

4 Commits

Author SHA1 Message Date
Jarrod Doyle 8bd2e53d7e
Update to Godot 4.4.1 2025-04-11 16:31:14 +01:00
Jarrod Doyle 1177474fd6
Apply subobj hierarchy to model 2024-12-23 11:44:13 +00:00
Jarrod Doyle 202edd424b
Fix extraction issue 2024-12-23 11:43:33 +00:00
Jarrod Doyle f924470e8d
Port LGS changes from lightmapper 2024-12-22 08:50:45 +00:00
48 changed files with 159 additions and 66 deletions

View File

@ -1,4 +1,4 @@
<Project Sdk="Godot.NET.Sdk/4.3.0"> <Project Sdk="Godot.NET.Sdk/4.4.1">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading> <EnableDynamicLoading>true</EnableDynamicLoading>

View File

@ -12,7 +12,7 @@ config_version=5
config/name="Thief Mission Viewer" config/name="Thief Mission Viewer"
run/main_scene="res://project/scenes/main.tscn" run/main_scene="res://project/scenes/main.tscn"
config/features=PackedStringArray("4.3", "C#", "Forward Plus") config/features=PackedStringArray("4.4", "C#", "Forward Plus")
config/icon="res://icon.svg" config/icon="res://icon.svg"
[autoload] [autoload]

View File

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

View File

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

View File

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

View File

@ -0,0 +1 @@
uid://64d8uwu3n6hq

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -17,7 +17,7 @@ public class RendParams : IChunk
public string palette; public string palette;
public Vector3 ambientLight; public Vector3 ambientLight;
public int useSunlight; public bool useSunlight;
public SunlightMode sunlightMode; public SunlightMode sunlightMode;
public Vector3 sunlightDirection; public Vector3 sunlightDirection;
public float sunlightHue; public float sunlightHue;
@ -32,7 +32,8 @@ public class RendParams : IChunk
{ {
palette = reader.ReadNullString(16); palette = reader.ReadNullString(16);
ambientLight = reader.ReadVec3(); ambientLight = reader.ReadVec3();
useSunlight = reader.ReadInt32(); useSunlight = reader.ReadBoolean();
reader.ReadBytes(3);
sunlightMode = (SunlightMode)reader.ReadUInt32(); sunlightMode = (SunlightMode)reader.ReadUInt32();
sunlightDirection = reader.ReadVec3(); sunlightDirection = reader.ReadVec3();
sunlightHue = reader.ReadSingle(); sunlightHue = reader.ReadSingle();
@ -59,6 +60,7 @@ public class RendParams : IChunk
writer.WriteNullString(palette, 16); writer.WriteNullString(palette, 16);
writer.WriteVec3(ambientLight); writer.WriteVec3(ambientLight);
writer.Write(useSunlight); writer.Write(useSunlight);
writer.Write(new byte[3]);
writer.Write((uint)sunlightMode); writer.Write((uint)sunlightMode);
writer.WriteVec3(sunlightDirection); writer.WriteVec3(sunlightDirection);
writer.Write(sunlightHue); writer.Write(sunlightHue);

View File

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

View File

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

View File

@ -246,12 +246,30 @@ public class WorldRep : IChunk
// TODO: This ONLY works for rgba (bpp = 4)!!! // TODO: This ONLY works for rgba (bpp = 4)!!!
public void AddLight(int layer, int x, int y, float r, float g, float b) public void AddLight(int layer, int x, int y, float r, float g, float b)
{ {
ArgumentOutOfRangeException.ThrowIfLessThan(layer, 0, nameof(layer));
ArgumentOutOfRangeException.ThrowIfGreaterThan(layer, Layers, nameof(layer));
var idx = (x + y * Width) * Bpp; var idx = (x + y * Width) * Bpp;
var pLayer = Pixels[layer]; var pLayer = Pixels[layer];
pLayer[idx] = (byte)Math.Clamp(pLayer[idx] + r, 0, 255); switch (Bpp)
{
// 1bpp isn't really supported (does nd dromed even produce it?)
case 2:
var raw2 = pLayer[idx] + (pLayer[idx + 1] << 8);
var newR = (int)Math.Clamp((raw2 & 31) + r * 32f / 255f, 0, 31);
var newG = (int)Math.Clamp(((raw2 >> 5) & 31) + g * 32f / 255f, 0, 31);
var newB = (int)Math.Clamp(((raw2 >> 10) & 31) + b * 32f / 255f, 0, 31);
raw2 = newR + (newG << 5) + (newB << 10);
pLayer[idx] = (byte)(raw2 & 0xff);
pLayer[idx + 1] = (byte)((raw2 >> 8) & 0xff);
break;
case 4:
pLayer[idx] = (byte)Math.Clamp(pLayer[idx] + b, 0, 255);
pLayer[idx + 1] = (byte)Math.Clamp(pLayer[idx + 1] + g, 0, 255); pLayer[idx + 1] = (byte)Math.Clamp(pLayer[idx + 1] + g, 0, 255);
pLayer[idx + 2] = (byte)Math.Clamp(pLayer[idx + 2] + b, 0, 255); pLayer[idx + 2] = (byte)Math.Clamp(pLayer[idx + 2] + r, 0, 255);
pLayer[idx + 3] = 255; pLayer[idx + 3] = 255;
break;
}
_litLayers[layer] = true; _litLayers[layer] = true;
} }
@ -274,7 +292,7 @@ public class WorldRep : IChunk
c /= ratio; c /= ratio;
} }
AddLight(layer, x, y, c.Z, c.Y, c.X); AddLight(layer, x, y, c.X, c.Y, c.Z);
} }
public void Reset(Vector3 ambientLight, bool hdr) public void Reset(Vector3 ambientLight, bool hdr)

View File

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

View File

@ -159,6 +159,8 @@ public class DbFile
"P$Scale" => new PropertyChunk<PropVector>(), "P$Scale" => new PropertyChunk<PropVector>(),
"P$RenderTyp" => new PropertyChunk<PropRenderType>(), "P$RenderTyp" => new PropertyChunk<PropRenderType>(),
"P$JointPos" => new PropertyChunk<PropJointPos>(), "P$JointPos" => new PropertyChunk<PropJointPos>(),
"P$Immobile" => new PropertyChunk<PropBool>(),
"P$StatShad" => new PropertyChunk<PropBool>(),
"P$OTxtRepr0" => new PropertyChunk<PropString>(), "P$OTxtRepr0" => new PropertyChunk<PropString>(),
"P$OTxtRepr1" => new PropertyChunk<PropString>(), "P$OTxtRepr1" => new PropertyChunk<PropString>(),
"P$OTxtRepr2" => new PropertyChunk<PropString>(), "P$OTxtRepr2" => new PropertyChunk<PropString>(),

View File

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

View File

@ -94,6 +94,8 @@ public class ObjectHierarchy
AddProp<PropVector>("P$Scale"); AddProp<PropVector>("P$Scale");
AddProp<PropRenderType>("P$RenderTyp"); AddProp<PropRenderType>("P$RenderTyp");
AddProp<PropJointPos>("P$JointPos"); AddProp<PropJointPos>("P$JointPos");
AddProp<PropBool>("P$Immobile");
AddProp<PropBool>("P$StatShad");
AddProp<PropString>("P$OTxtRepr0"); AddProp<PropString>("P$OTxtRepr0");
AddProp<PropString>("P$OTxtRepr1"); AddProp<PropString>("P$OTxtRepr1");
AddProp<PropString>("P$OTxtRepr2"); AddProp<PropString>("P$OTxtRepr2");

View File

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

View File

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

View File

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

View File

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

View File

@ -151,38 +151,44 @@ public class ResourcePathManager
throw new InvalidOperationException("Failed to find all installation config paths."); throw new InvalidOperationException("Failed to find all installation config paths.");
} }
// Get the paths of the base Fam and Obj resources so we can extract them. // We need to know where all the texture and object resources are
var installCfgLines = File.ReadAllLines(configPaths[(int)ConfigFile.Install]); var installCfgLines = File.ReadAllLines(configPaths[(int)ConfigFile.Install]);
FindConfigVar(installCfgLines, "resname_base", out var resPaths); if (!FindConfigVar(installCfgLines, "resname_base", out var resPaths))
var baseFamPath = ""; {
var baseObjPath = ""; throw new InvalidOperationException("Failed to find resnames in install config");
}
var zipPaths = new List<string>();
foreach (var resPath in resPaths.Split('+')) foreach (var resPath in resPaths.Split('+'))
{ {
var dir = Path.Join(installPath, ConvertSeparator(resPath)); var dir = Path.Join(installPath, ConvertSeparator(resPath));
if (!Directory.Exists(dir))
{
continue;
}
foreach (var path in Directory.GetFiles(dir)) foreach (var path in Directory.GetFiles(dir))
{ {
var name = Path.GetFileName(path).ToLower(); var name = Path.GetFileName(path).ToLower();
if (name == "fam.crf" && baseFamPath == "") if (name is "fam.crf" or "obj.crf")
{ {
baseFamPath = path; zipPaths.Add(path);
}
else if (name == "obj.crf" && baseObjPath == "")
{
baseObjPath = path;
} }
} }
} }
// Do the extraction bro // Do the extraction bro
(string, string)[] resources = [("fam", baseFamPath), ("obj", baseObjPath)]; // The path order is a priority order, so we don't want to overwrite any files when extracting
foreach (var (extractName, zipPath) in resources) // TODO: Check if there's any problems caused by case sensitivity
if (Directory.Exists(_extractionPath))
{ {
var extractPath = Path.Join(_extractionPath, extractName); Directory.Delete(_extractionPath, true);
if (Directory.Exists(extractPath))
{
Directory.Delete(extractPath, true);
} }
ZipFile.OpenRead(zipPath).ExtractToDirectory(extractPath); foreach (var zipPath in zipPaths)
{
var resType = Path.GetFileNameWithoutExtension(zipPath);
var extractPath = Path.Join(_extractionPath, resType);
ZipFile.OpenRead(zipPath).ExtractToDirectory(extractPath, false);
} }
FindConfigVar(installCfgLines, "load_path", out var omsPath); FindConfigVar(installCfgLines, "load_path", out var omsPath);

View File

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

View File

@ -0,0 +1 @@
uid://8slua3vhscjw

View File

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

View File

@ -265,14 +265,12 @@ public partial class Mission : Node3D
var meshDetails = Timing.TimeStage("Get Models", () => Context.Instance.ModelLoader.Load(modelName)); var meshDetails = Timing.TimeStage("Get Models", () => Context.Instance.ModelLoader.Load(modelName));
if (meshDetails.Length != 0) if (meshDetails.Length != 0)
{ {
var model = new Node3D(); var joints = jointPosProp != null ? jointPosProp.Positions : [0, 0, 0, 0, 0, 0];
var model = ModelLoader.TransformMeshes(joints, meshDetails);
model.Position = pos; model.Position = pos;
model.RotationDegrees = rot; model.RotationDegrees = rot;
model.Scale = scale; model.Scale = scale;
var joints = jointPosProp != null ? jointPosProp.Positions : [0, 0, 0, 0, 0, 0];
var meshes = ModelLoader.TransformMeshes(joints, meshDetails);
bool GetTextReplPath(PropString prop, out string path) bool GetTextReplPath(PropString prop, out string path)
{ {
path = ""; path = "";
@ -301,12 +299,16 @@ public partial class Mission : Node3D
} }
var repls = new PropString[] { txtRepl0, txtRepl1, txtRepl2, txtRepl3 }; var repls = new PropString[] { txtRepl0, txtRepl1, txtRepl2, txtRepl3 };
foreach (var meshInstance in meshes) foreach (var child in model.FindChildren("*", "MeshInstance3D", true, false))
{ {
var meshInstance = child as MeshInstance3D;
for (var i = 0; i < 4; i++) for (var i = 0; i < 4; i++)
{ {
if (GetTextReplPath(repls[i], out var path)) if (!GetTextReplPath(repls[i], out var path))
{ {
continue;
}
var overrideMat = new StandardMaterial3D var overrideMat = new StandardMaterial3D
{ {
AlbedoTexture = TextureLoader.LoadTexture(path), AlbedoTexture = TextureLoader.LoadTexture(path),
@ -323,14 +325,11 @@ public partial class Mission : Node3D
} }
} }
} }
}
if (renderAlpha != null) if (renderAlpha != null)
{ {
meshInstance.Transparency = 1.0f - renderAlpha.value; meshInstance.Transparency = 1.0f - renderAlpha.value;
} }
model.AddChild(meshInstance);
} }
model.AddToGroup(OBJECT_MODELS_GROUP); model.AddToGroup(OBJECT_MODELS_GROUP);

View File

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

View File

@ -19,13 +19,8 @@ public partial class Model : Node3D
} }
Context.Instance.SetCampaign(campaignName); Context.Instance.SetCampaign(campaignName);
var model = new Node3D();
var meshDetails = Context.Instance.ModelLoader.Load(modelPath); var meshDetails = Context.Instance.ModelLoader.Load(modelPath);
var meshes = ModelLoader.TransformMeshes([0, 0, 0, 0, 0, 0], meshDetails); var model = ModelLoader.TransformMeshes([0, 0, 0, 0, 0, 0], meshDetails);
foreach (var meshInstance in meshes)
{
model.AddChild(meshInstance);
}
AddChild(model); AddChild(model);
} }
} }

View File

@ -0,0 +1 @@
uid://6v4368eednxc

View File

@ -8,11 +8,12 @@ namespace KeepersCompound.TMV;
// TODO: Work out a way to share base game models again in the cache // TODO: Work out a way to share base game models again in the cache
public class ModelLoader public class ModelLoader
{ {
public struct MeshDetails(int jointIdx, Transform3D transform, MeshInstance3D mesh) public struct MeshDetails(int jointIdx, Transform3D transform, MeshInstance3D mesh, int parentIdx)
{ {
public readonly int JointIdx = jointIdx; public readonly int JointIdx = jointIdx;
public readonly Transform3D Transform = transform; public readonly Transform3D Transform = transform;
public readonly MeshInstance3D Mesh = mesh; public readonly MeshInstance3D Mesh = mesh;
public int ParentIdx = parentIdx;
} }
private readonly Dictionary<(string, string), MeshDetails[]> _cache = new(); private readonly Dictionary<(string, string), MeshDetails[]> _cache = new();
@ -40,15 +41,20 @@ public class ModelLoader
return details; return details;
} }
public static MeshInstance3D[] TransformMeshes(float[] joints, MeshDetails[] meshDetails) public static Node3D TransformMeshes(float[] joints, MeshDetails[] meshDetails)
{ {
for (var i = 0; i < joints.Length; i++)
{
joints[i] = float.DegreesToRadians(joints[i]);
}
var meshes = new List<MeshInstance3D>(); var meshes = new List<MeshInstance3D>();
foreach (var details in meshDetails) foreach (var details in meshDetails)
{ {
var mesh = details.Mesh.Duplicate() as MeshInstance3D; var mesh = details.Mesh.Duplicate() as MeshInstance3D;
if (details.JointIdx != -1) if (details.JointIdx != -1)
{ {
var ang = float.DegreesToRadians(joints[details.JointIdx]); var ang = joints[details.JointIdx];
var r1 = new Quaternion(new Vector3(0, 0, 1), ang); var r1 = new Quaternion(new Vector3(0, 0, 1), ang);
var r2 = details.Transform.Basis.GetRotationQuaternion(); var r2 = details.Transform.Basis.GetRotationQuaternion();
var basis = new Basis(r2 * r1); var basis = new Basis(r2 * r1);
@ -62,7 +68,22 @@ public class ModelLoader
meshes.Add(mesh); meshes.Add(mesh);
} }
return [..meshes]; var root = new Node3D();
for (var i = 0; i < meshes.Count; i++)
{
var details = meshDetails[i];
var parentId = details.ParentIdx;
if (parentId == -1)
{
root.AddChild(meshes[i]);
}
else
{
meshes[parentId].AddChild(meshes[i]);
}
}
return root;
} }
public static MeshDetails[] LoadModel(string modelName) public static MeshDetails[] LoadModel(string modelName)
@ -186,7 +207,19 @@ public class ModelLoader
var pos = -modelFile.Header.Center.ToGodotVec3(); var pos = -modelFile.Header.Center.ToGodotVec3();
var meshInstance = new MeshInstance3D { Mesh = mesh, Position = pos }; var meshInstance = new MeshInstance3D { Mesh = mesh, Position = pos };
meshDetails[i] = new MeshDetails(jointIdx, transform, meshInstance); meshDetails[i] = new MeshDetails(jointIdx, transform, meshInstance, -1);
}
// Build parentage
for (var i = 0; i < objCount; i++)
{
var subObj = modelFile.Objects[i];
var childIdx = subObj.Child;
while (childIdx != -1)
{
meshDetails[childIdx].ParentIdx = i;
childIdx = modelFile.Objects[childIdx].Next;
}
} }
return meshDetails; return meshDetails;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,8 @@
[gd_scene load_steps=9 format=3 uid="uid://byknmqac1a5vn"] [gd_scene load_steps=9 format=3 uid="uid://byknmqac1a5vn"]
[ext_resource type="Texture2D" uid="uid://b208ufsau5jhb" path="res://project/jorge.png" id="1_1vlw2"] [ext_resource type="Texture2D" uid="uid://b208ufsau5jhb" path="res://project/jorge.png" id="1_1vlw2"]
[ext_resource type="Script" path="res://project/code/TMV/UI/AssetBrowser.cs" id="1_5rr8c"] [ext_resource type="Script" uid="uid://beoujsbxyth70" path="res://project/code/TMV/UI/AssetBrowser.cs" id="1_5rr8c"]
[ext_resource type="Script" path="res://project/code/TMV/UI/TextureBrowser.cs" id="1_72xft"] [ext_resource type="Script" uid="uid://dy6yk7onoihyd" path="res://project/code/TMV/UI/TextureBrowser.cs" id="1_72xft"]
[ext_resource type="Texture2D" uid="uid://beb4tj06ivjae" path="res://project/assets/icons/Search.svg" id="1_ityvd"] [ext_resource type="Texture2D" uid="uid://beb4tj06ivjae" path="res://project/assets/icons/Search.svg" id="1_ityvd"]
[ext_resource type="Texture2D" uid="uid://dx8paqeom7dtb" path="res://project/assets/icons/Sort.svg" id="3_0k1fm"] [ext_resource type="Texture2D" uid="uid://dx8paqeom7dtb" path="res://project/assets/icons/Sort.svg" id="3_0k1fm"]
[ext_resource type="Texture2D" uid="uid://dqefy830o4foj" path="res://project/assets/icons/Folder.svg" id="3_xdjfn"] [ext_resource type="Texture2D" uid="uid://dqefy830o4foj" path="res://project/assets/icons/Folder.svg" id="3_xdjfn"]
@ -82,6 +82,7 @@ item_count = 4
popup/item_0/text = "Name" popup/item_0/text = "Name"
popup/item_0/checkable = 2 popup/item_0/checkable = 2
popup/item_0/checked = true popup/item_0/checked = true
popup/item_0/id = 0
popup/item_1/text = "Family" popup/item_1/text = "Family"
popup/item_1/checkable = 2 popup/item_1/checkable = 2
popup/item_1/id = 1 popup/item_1/id = 1
@ -228,6 +229,7 @@ size_flags_horizontal = 3
selected = 0 selected = 0
item_count = 2 item_count = 2
popup/item_0/text = "Linear" popup/item_0/text = "Linear"
popup/item_0/id = 0
popup/item_1/text = "Nearest" popup/item_1/text = "Nearest"
popup/item_1/id = 1 popup/item_1/id = 1
@ -241,6 +243,7 @@ size_flags_horizontal = 3
selected = 0 selected = 0
item_count = 2 item_count = 2
popup/item_0/text = "Scaled" popup/item_0/text = "Scaled"
popup/item_0/id = 0
popup/item_1/text = "Tiled" popup/item_1/text = "Tiled"
popup/item_1/id = 1 popup/item_1/id = 1

View File

@ -1,7 +1,7 @@
[gd_scene load_steps=6 format=3 uid="uid://boxi211q3kx6c"] [gd_scene load_steps=6 format=3 uid="uid://boxi211q3kx6c"]
[ext_resource type="Script" path="res://project/code/TMV/Mission.cs" id="1_3gnqe"] [ext_resource type="Script" uid="uid://ci24h68n7606n" path="res://project/code/TMV/Mission.cs" id="1_3gnqe"]
[ext_resource type="Script" path="res://project/code/camera.gd" id="2_w5otl"] [ext_resource type="Script" uid="uid://c032d00skt5fu" path="res://project/code/camera.gd" id="2_w5otl"]
[ext_resource type="PackedScene" uid="uid://bfxdpxkcgwlkx" path="res://project/scenes/ui/resource_selector.tscn" id="3_kdn7u"] [ext_resource type="PackedScene" uid="uid://bfxdpxkcgwlkx" path="res://project/scenes/ui/resource_selector.tscn" id="3_kdn7u"]
[ext_resource type="PackedScene" uid="uid://0h2w7w84vbea" path="res://project/scenes/ui/lightmap_layer_toggler.tscn" id="4_naip8"] [ext_resource type="PackedScene" uid="uid://0h2w7w84vbea" path="res://project/scenes/ui/lightmap_layer_toggler.tscn" id="4_naip8"]
@ -13,7 +13,6 @@ ssao_enabled = true
[node name="Main" type="Node3D"] [node name="Main" type="Node3D"]
[node name="Mission" type="Node3D" parent="."] [node name="Mission" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.110309, 0.187101, -0.461656)
script = ExtResource("1_3gnqe") script = ExtResource("1_3gnqe")
[node name="Camera3D" type="Camera3D" parent="."] [node name="Camera3D" type="Camera3D" parent="."]

View File

@ -1,7 +1,7 @@
[gd_scene load_steps=5 format=3 uid="uid://iegbijrr5amb"] [gd_scene load_steps=5 format=3 uid="uid://iegbijrr5amb"]
[ext_resource type="Script" path="res://project/code/TMV/Model.cs" id="1_dax7s"] [ext_resource type="Script" uid="uid://6v4368eednxc" path="res://project/code/TMV/Model.cs" id="1_dax7s"]
[ext_resource type="Script" path="res://project/code/camera.gd" id="2_ov7rc"] [ext_resource type="Script" uid="uid://c032d00skt5fu" path="res://project/code/camera.gd" id="2_ov7rc"]
[ext_resource type="PackedScene" uid="uid://bfxdpxkcgwlkx" path="res://project/scenes/ui/resource_selector.tscn" id="3_yp5sl"] [ext_resource type="PackedScene" uid="uid://bfxdpxkcgwlkx" path="res://project/scenes/ui/resource_selector.tscn" id="3_yp5sl"]
[sub_resource type="Environment" id="Environment_e4172"] [sub_resource type="Environment" id="Environment_e4172"]

View File

@ -1,6 +1,6 @@
[gd_scene load_steps=3 format=3 uid="uid://bfxdpxkcgwlkx"] [gd_scene load_steps=3 format=3 uid="uid://bfxdpxkcgwlkx"]
[ext_resource type="Script" path="res://project/code/TMV/UI/ResourceSelector.cs" id="1_4lx6q"] [ext_resource type="Script" uid="uid://c8c7y5qlasj1x" path="res://project/code/TMV/UI/ResourceSelector.cs" id="1_4lx6q"]
[sub_resource type="LabelSettings" id="LabelSettings_4v24o"] [sub_resource type="LabelSettings" id="LabelSettings_4v24o"]
font_size = 20 font_size = 20