summaryrefslogtreecommitdiff
path: root/Lights.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Lights.cs')
-rw-r--r--Lights.cs993
1 files changed, 854 insertions, 139 deletions
diff --git a/Lights.cs b/Lights.cs
index 0eed477..cff48d2 100644
--- a/Lights.cs
+++ b/Lights.cs
@@ -13,184 +13,869 @@ namespace WorldTuningTool
{
public Lights() { }
- private class Light
+ private class uLight
{
- public nint Object;
- public int Type;
- public Parameter[] Parameters = {
- newParameter<int>("Group", 0x13C, ParameterType.INT, pMinMaxStep(1, 255, 1)), // 1 = World, (1 << 1) = Player/Palico, (1 << 2) = NPCs
- newFrameParameter<float>("Position", 0x5A0, ParameterType.VECTOR3, pStep(0.15f)),
- newFrameParameter<int>("Color", 0x140, ParameterType.COLOR),
- newFrameParameter<float>("Intensity", 0x8A8, ParameterType.FLOAT),
- newFrameParameter<float>("Radius", 0x6A0, ParameterType.FLOAT, pStep(0.25f)),
- newFrameParameter<float>("Effective Radius", 0x588, ParameterType.FLOAT, pStep(0.25f)),
- newFrameParameter<float>("Min Roughness", 0x58C, ParameterType.FLOAT, pStep(0.0025f)),
- newParameter<bool>("Do Volumetric", 0x590, ParameterType.BOOL),
- newFlag<bool>("Shadow Cast", 0x138, ParameterType.FLAG, (1 << 23)),
- newParameter<int>("Shadow Map Size", 0x1B8, ParameterType.ALIGNED_INT, pMinStep(0, 128)),
- newParameter<float>("Shadow Near Clip Distance", 0x1B4, ParameterType.FLOAT),
- newFrameParameter<float>("Shadow Depth Bias", 0x57C, ParameterType.FLOAT, pStep(0.00001f)),
- newFrameParameter<float>("Shadow Sloped Depth Bias", 0x580, ParameterType.FLOAT, pStep(0.00001f)),
- newFrameParameter<float>("Shadow Max Depth Bias", 0x584, ParameterType.FLOAT, pStep(0.00001f)),
- };
+ public nint Object = 0x0;
+ public virtual int Type => -1;
+ public virtual string Name => $"uLight";
+ public virtual string Info => $"0x{Object:X}";
+ public List<Parameter> Parameters = new List<Parameter>();
- public Light(nint lightObject, int type)
+ public void UpdateParams()
{
- Object = lightObject;
- Type = type;
+ Assert(Object != 0x0);
foreach (Parameter param in Parameters)
{
- param.Update(lightObject);
+ param.Update(Object);
}
}
- public Light(nint lightObject, int type, Vector3 pos)
+ public uLight(nint lightObject)
{
Object = lightObject;
- Type = type;
+ Parameters.AddRange(new Parameter[]{
+ M<int>("Group", 0x13C, ParameterType.INT, 0x7, pMinMaxStep(0, 7, 1)), // 1 = World, (1 << 1) = Player/Palico, (1 << 2) = NPCs
+ M<int>("Priority", 0x138, ParameterType.INT, (0xFF << 6), pMinMaxStep(0, 255, 1)),
+ P<int>("Color", 0x140, ParameterType.COLOR),
+ P<float>("Intensity", 0x144, ParameterType.FLOAT),
+ P<float>("Min Roughness", 0x58C, ParameterType.FLOAT, pStep(0.001f)),
+ M<bool>("Disp", 0x138, ParameterType.FLAG, (1 << 24)),
+ M<bool>("Primary", 0x138, ParameterType.FLAG, (1 << 26)),
+ M<bool>("Shadow Cast", 0x138, ParameterType.FLAG, (1 << 23)),
+ M<int>("Shadow Priority", 0x138, ParameterType.INT, (0xFF << 14), pMinMaxStep(0, 255, 1)),
+ P<int>("Shadow Map Size", 0x1B8, ParameterType.ALIGNED_INT, pMinStep(0, 128)), // Result of mShadowMapSize.
+ P<float>("Near Clip Distance", 0x1B4, ParameterType.FLOAT),
+ P<float>("Shadow Depth Bias", 0x57C, ParameterType.FLOAT, pStep(0.00001f)),
+ P<float>("Shadow Sloped Depth Bias", 0x580, ParameterType.FLOAT, pStep(0.00001f)),
+ P<float>("Shadow Max Depth Bias", 0x584, ParameterType.FLOAT, pStep(0.00001f)),
+ P<bool>("Use Umbra", 0x591, ParameterType.BOOL),
+ P<bool>("Enable Camera Lod", 0x592, ParameterType.BOOL),
+ P<bool>("Do Volumetric", 0x590, ParameterType.BOOL)
+ });
+ UpdateParams();
+ }
+ }
+
+ private class uInfiniteLight : uLight
+ {
+ public override int Type => 1;
+ public override string Name => $"uInfiniteLight";
+ // mpTexture unaccounted for.
+
+ public uInfiniteLight(nint lightObject) : base(lightObject)
+ {
+ Parameters.AddRange(new Parameter[]{
+ P<float>("Direction", 0x5A0, ParameterType.VECTOR3, pStep(0.00025f)),
+ P<float>("Shadow Distance", 0x5B0, ParameterType.FLOAT),
+ P<float>("Shadow Backforward Distance", 0x5B8, ParameterType.FLOAT),
+ P<float>("Shadow Distribution", 0x5B4, ParameterType.FLOAT),
+ P<float>("Shadow Radius Scale", 0x5BC, ParameterType.FLOAT),
+ P<bool>("Manual Split", 0x5C1, ParameterType.BOOL),
+ P<bool>("Individual Shadow Bias", 0x5D0, ParameterType.BOOL),
+ P<float>("Cascade Blend", 0x5C0, ParameterType.FLOAT),
+ P<float>("Fov", 0x630, ParameterType.FLOAT),
+ P<bool>("Is Fixed Fov Mode", 0x634, ParameterType.BOOL),
+ P<bool>("Is Discretized Fov Mode", 0x63C, ParameterType.BOOL),
+ P<float>("Discretization Angle", 0x638, ParameterType.FLOAT),
+ P<float>("Manual Split Distance[0]", 0x5C4, ParameterType.FLOAT),
+ P<float>("Cascade Depth Bias[0]", 0x5D4, ParameterType.FLOAT, pStep(0.00001f)),
+ P<float>("Cascade Sloped Depth Bias[0]", 0x5E0, ParameterType.FLOAT, pStep(0.00001f)),
+ P<float>("Cascade Max Depth Bias[0]", 0x5EC, ParameterType.FLOAT, pStep(0.00001f)),
+ P<float>("Manual Split Distance[1]", 0x5C8, ParameterType.FLOAT),
+ P<float>("Cascade Depth Bias[1]", 0x5D8, ParameterType.FLOAT, pStep(0.00001f)),
+ P<float>("Cascade Sloped Depth Bias[1]", 0x5E4, ParameterType.FLOAT, pStep(0.00001f)),
+ P<float>("Cascade Max Depth Bias[1]", 0x5F0, ParameterType.FLOAT, pStep(0.00001f)),
+ P<float>("Manual Split Distance[2]", 0x5CC, ParameterType.FLOAT),
+ P<float>("Cascade Depth Bias[2]", 0x5DC, ParameterType.FLOAT, pStep(0.00001f)),
+ P<float>("Cascade Sloped Depth Bias[2]", 0x5E8, ParameterType.FLOAT, pStep(0.00001f)),
+ P<float>("Cascade Max Depth Bias[2]", 0x5F4, ParameterType.FLOAT, pStep(0.00001f)),
+ P<float>("Projection Scale", 0x600, ParameterType.VECTOR2),
+ P<float>("Projection Offset", 0x60C, ParameterType.VECTOR2),
+ P<float>("Projection Up", 0x620, ParameterType.VECTOR3)
+ });
+ UpdateParams();
+ }
+ }
+
+ private class uMhInfiniteLight : uInfiniteLight
+ {
+ public override string Name => $"uMhInfiniteLight";
+
+ public uMhInfiniteLight(nint lightObject) : base(lightObject)
+ {
+ Parameters.AddRange(new Parameter[]{
+ P<float>("Projection Offset Speed", 0x6D0, ParameterType.VECTOR2),
+ P<float>("Projection Offset Current", 0x6D8, ParameterType.VECTOR2)
+ });
+ UpdateParams();
+ }
+ }
+
+ private class uMhActorInfiniteLight : uMhInfiniteLight
+ {
+ public override string Name => $"uMhActorInfiniteLight";
+
+ public uMhActorInfiniteLight(nint lightObject) : base(lightObject)
+ {
+ }
+ }
+
+ private class uLlkInfiniteLight : uInfiniteLight
+ {
+ public override string Name => $"uLlkInfiniteLight";
+ public nint CycleTimelineRes => MemoryUtil.Read<nint>(Object + 0x658);
+ public int CycleAnimNo => MemoryUtil.Read<int>(Object + 0x7A8);
+
+ public uLlkInfiniteLight(nint lightObject) : base(lightObject)
+ {
+ Parameters.AddRange(new Parameter[]{
+ P<int>("Llk Color", 0x640, ParameterType.COLOR),
+ P<float>("Llk Intensity", 0x644, ParameterType.FLOAT),
+ P<float>("Projection Offset Speed", 0x648, ParameterType.VECTOR2)
+ });
+ UpdateParams();
+ }
+ }
+
+ private class uLlkActorInfiniteLight : uLlkInfiniteLight
+ {
+ public override string Name => $"uLlkActorInfiniteLight";
+
+ public uLlkActorInfiniteLight(nint lightObject) : base(lightObject)
+ {
+ }
+ }
+
+ private class uLlkFollowCameraInfiniteLight : uLlkInfiniteLight
+ {
+ public override string Name => $"uLlkFollowCameraInfiniteLight";
+
+ public uLlkFollowCameraInfiniteLight(nint lightObject) : base(lightObject)
+ {
+ }
+ }
+
+ private class uPointLight : uLight
+ {
+ public override int Type => 2;
+ public override string Name => $"uPointLight";
+ public override string Info => $"0x{Object:X}" + (Parent != 0x0 ? $", Parent: 0x{Parent:X}" : "");
+ public nint Parent => MemoryUtil.Read<nint>(Object + 0x5C0);
+ public int ParentNo => MemoryUtil.Read<int>(Object + 0x5C8);
+ public Vector3 Position => MemoryUtil.Read<Vector3>(Object + 0x5A0);
+
+ public uPointLight(nint lightObject) : base(lightObject)
+ {
+ Parameters.AddRange(new Parameter[]{
+ P<float>("Position", 0x5A0, ParameterType.VECTOR3, pStep(0.15f)),
+ P<float>("Radius", 0x1B0, ParameterType.FLOAT),
+ P<float>("Effective Radius", 0x588, ParameterType.FLOAT)
+ });
+ UpdateParams();
+ }
+ }
+
+ private class uMhPointLight : uPointLight
+ {
+ public override string Name => $"uMhPointLight";
+
+ public uMhPointLight(nint lightObject) : base(lightObject)
+ {
+ Parameters.AddRange(new Parameter[]{
+ P<bool>("Multiply Radius Square", 0x5D0, ParameterType.BOOL)
+ });
+ UpdateParams();
+ }
+
+ public uMhPointLight(nint lightObject, Vector3 pos) : this(lightObject)
+ {
foreach (Parameter param in Parameters)
{
param.OverrideOn(false);
}
- Parameters[0].SetOverrideValue(default, 255);
- Parameters[1].SetOverrideValue(new Vector4(pos.X, pos.Y, pos.Z, 0.0f), 0);
+ Parameters[0].SetOverrideValue(default, 0x7);
Parameters[3].SetOverrideValue(new Vector4(10.0f, 0.0f, 0.0f, 0.0f), 0);
+ Parameters[17].SetOverrideValue(new Vector4(pos.X, pos.Y, pos.Z, 0.0f), 0);
+ }
+ }
+
+ private class uMhActorPointLight : uMhPointLight
+ {
+ public override string Name => $"uMhActorPointLight";
+
+ public uMhActorPointLight(nint lightObject) : base(lightObject)
+ {
+ }
+ }
+
+ private class uLlkPointLight : uPointLight
+ {
+ public override string Name => $"uLlkPointLight";
+ public nint TimelineRes => MemoryUtil.Read<nint>(Object + 0x8A4);
+ public int AnimNo => MemoryUtil.Read<int>(Object + 0x7A8);
+ public NativeAction<nint> PlayResource = new NativeAction<nint>(0x141F89CB0);
+ public NativeAction<nint> StopResource = new NativeAction<nint>(0x141F8A0C0);
+ public nint CycleTimelineRes => MemoryUtil.Read<nint>(Object + 0x750);
+ public int CycleAnimNo => MemoryUtil.Read<int>(Object + 0x8A0);
+
+ public uLlkPointLight(nint lightObject) : base(lightObject)
+ {
+ Parameters.AddRange(new Parameter[]{
+ P<int>("Llk Color", 0x970, ParameterType.COLOR),
+ P<float>("Llk Intensity", 0x974, ParameterType.FLOAT),
+ P<float>("Llk Radius", 0x978, ParameterType.FLOAT),
+ P<float>("Llk Effective Radius", 0x97C, ParameterType.FLOAT),
+ P<bool>("Multiply Radius Square", 0x980, ParameterType.BOOL),
+ P<int>("Random Param Bits", 0x6C8, ParameterType.HEX),
+ P<float>("Force Set Time", 0x8B4, ParameterType.FLOAT),
+ P<float>("Near Fade Out Start Distance", 0x8D4, ParameterType.FLOAT),
+ P<float>("Near Fade Out End Distance", 0x8D8, ParameterType.FLOAT),
+ P<float>("Fade Out Start Distance", 0x8DC, ParameterType.FLOAT),
+ P<float>("Fade Out End Distance", 0x8E0, ParameterType.FLOAT),
+ P<float>("Random Move Radius", 0x8E8, ParameterType.FLOAT),
+ P<float>("Random Move Friction", 0x900, ParameterType.VECTOR3),
+ P<float>("Random Move Force To Center", 0x8EC, ParameterType.FLOAT),
+ P<float>("Random Move Time Min", 0x8F8, ParameterType.FLOAT),
+ P<float>("Random Move Time Max", 0x8FC, ParameterType.FLOAT),
+ P<float>("Random Move Speed V Max", 0x940, ParameterType.VECTOR3),
+ P<float>("Random Move Force V Max", 0x960, ParameterType.VECTOR3)
+ });
+ UpdateParams();
+ }
+ }
+
+ private class uLlkActorPointLight : uLlkPointLight
+ {
+ public override string Name => $"uLlkActorPointLight";
+
+ public uLlkActorPointLight(nint lightObject) : base(lightObject)
+ {
+ }
+ }
+
+ private class uLlkFollowCameraPointLight : uLlkPointLight
+ {
+ public override string Name => $"uLlkFollowCameraPointLight";
+
+ public uLlkFollowCameraPointLight(nint lightObject) : base(lightObject)
+ {
+ }
+ }
+
+ private class uSpotLight : uLight
+ {
+ public override int Type => 3;
+ public override string Name => $"uSpotLight";
+ public override string Info => $"0x{Object:X}, Parent: 0x{Parent:X}";
+ public nint Parent => MemoryUtil.Read<nint>(Object + 0x600);
+ public int ParentNo => MemoryUtil.Read<int>(Object + 0x610);
+ public nint Target => MemoryUtil.Read<nint>(Object + 0x608);
+ public int TargetNo => MemoryUtil.Read<int>(Object + 0x614);
+ public nint Texture => MemoryUtil.Read<nint>(Object + 0x670);
+ public nint ShadowCacheResource => MemoryUtil.Read<nint>(Object + 0x698);
+
+ public uSpotLight(nint lightObject) : base(lightObject)
+ {
+ Parameters.AddRange(new Parameter[]{
+ P<float>("Position", 0x5A0, ParameterType.VECTOR3, pStep(0.15f)),
+ P<float>("Direction", 0x5B0, ParameterType.VECTOR3, pStep(0.0025f)),
+ P<float>("Target Position", 0x5C0, ParameterType.VECTOR3, pStep(0.15f)),
+ P<bool>("Target Mode", 0x5F8, ParameterType.BOOL),
+ P<float>("Radius", 0x1B0, ParameterType.FLOAT),
+ P<float>("Effective Radius", 0x588, ParameterType.FLOAT),
+ P<float>("Cone", 0x5F0, ParameterType.FLOAT, pStep(0.01f)),
+ P<float>("Spread", 0x5F0, ParameterType.FLOAT, pStep(0.01f)),
+ P<float>("Falloff", 0x618, ParameterType.FLOAT, pStep(0.01f)),
+ P<float>("Projection Scale", 0x67C, ParameterType.VECTOR2),
+ P<float>("Projection Offset", 0x684, ParameterType.VECTOR2),
+ P<float>("Projection Rotation Z", 0x68C, ParameterType.FLOAT),
+ P<int>("Texture Index", 0x678, ParameterType.INT, pStep(1)),
+ P<bool>("Use Shadow Cache", 0x690, ParameterType.BOOL)
+ });
+ UpdateParams();
+ }
+ }
+
+ private class uMhSpotLight : uSpotLight
+ {
+ public override string Name => $"uMhSpotLight";
+
+ public uMhSpotLight(nint lightObject) : base(lightObject)
+ {
+ Parameters.AddRange(new Parameter[]{
+ P<bool>("Multiply Radius Square", 0x6A0, ParameterType.BOOL),
+ });
+ UpdateParams();
+ }
+
+ public uMhSpotLight(nint lightObject, Vector3 pos) : this(lightObject)
+ {
+ foreach (Parameter param in Parameters)
+ {
+ param.OverrideOn(false);
+ }
+ Parameters[0].SetOverrideValue(default, 0x7);
+ Parameters[3].SetOverrideValue(new Vector4(350.0f, 0.0f, 0.0f, 0.0f), 0);
+ Parameters[17].SetOverrideValue(new Vector4(pos.X, pos.Y + 200.0f, pos.Z, 0.0f), 0);
+ Parameters[19].SetOverrideValue(new Vector4(pos.X, pos.Y, pos.Z, 0.0f), 0);
+ Parameters[20].SetOverrideValue(default, 1);
+ Parameters[23].SetOverrideValue(new Vector4(45.0f, 0.0f, 0.0f, 0.0f), 0);
+ }
+ }
+
+ private class uMhActorSpotLight : uMhSpotLight
+ {
+ public override string Name => $"uMhActorSpotLight";
+
+ public uMhActorSpotLight(nint lightObject) : base(lightObject)
+ {
+ }
+ }
+
+ private class uLlkSpotLight : uSpotLight
+ {
+ public override string Name => $"uLlkSpotLight";
+ public nint TimelineRes => MemoryUtil.Read<nint>(Object + 0x790);
+ public int AnimNo => MemoryUtil.Read<int>(Object + 0x974);
+ public NativeAction<nint> PlayResource = new NativeAction<nint>(0x141F8D550);
+ public NativeAction<nint> StopResource = new NativeAction<nint>(0x141F8D970);
+ public nint CycleTimelineRes => MemoryUtil.Read<nint>(Object + 0x820);
+ public int CycleAnimNo => MemoryUtil.Read<int>(Object + 0x970);
+
+ public uLlkSpotLight(nint lightObject) : base(lightObject)
+ {
+ Parameters.AddRange(new Parameter[]{
+ P<int>("Llk Color", 0xA40, ParameterType.COLOR),
+ P<float>("Llk Intensity", 0xA44, ParameterType.FLOAT),
+ P<float>("Llk Radius", 0xA48, ParameterType.FLOAT),
+ P<float>("Llk Effective Radius", 0xA4C, ParameterType.FLOAT),
+ P<float>("Llk Cone", 0xA50, ParameterType.FLOAT),
+ P<float>("Llk Spread", 0xA54, ParameterType.FLOAT),
+ P<float>("Llk Falloff", 0xA58, ParameterType.FLOAT),
+ P<bool>("Multiply Radius Square", 0xA68, ParameterType.BOOL),
+ P<int>("Random Param Bits", 0x798, ParameterType.HEX),
+ P<float>("Force Set Time", 0x984, ParameterType.FLOAT),
+ P<float>("Near Fade Out Start Distance", 0x9A4, ParameterType.FLOAT),
+ P<float>("Near Fade Out End Distance", 0x9A8, ParameterType.FLOAT),
+ P<float>("Fade Out Start Distance", 0x9AC, ParameterType.FLOAT),
+ P<float>("Fade Out End Distance", 0x9B0, ParameterType.FLOAT),
+ P<float>("Random Move Radius", 0x9B8, ParameterType.FLOAT),
+ P<float>("Random Move Friction", 0x9D0, ParameterType.VECTOR3),
+ P<float>("Random Move Force To Center", 0x9BC, ParameterType.FLOAT),
+ P<float>("Random Move Time Min", 0x9C8, ParameterType.FLOAT),
+ P<float>("Random Move Time Max", 0x9CC, ParameterType.FLOAT),
+ P<float>("Random Move Speed V Max", 0xA10, ParameterType.VECTOR3),
+ P<float>("Random Move Force V Max", 0xA30, ParameterType.VECTOR3),
+ P<float>("Projection Offset Speed", 0xA60, ParameterType.VECTOR2)
+ });
+ UpdateParams();
+ }
+ }
+
+ private class uLlkActorSpotLight : uLlkSpotLight
+ {
+ public override string Name => $"uLlkActorSpotLight";
+
+ public uLlkActorSpotLight(nint lightObject) : base(lightObject)
+ {
+ }
+ }
+
+ private class uLlkNullAngleSpotLight : uLlkSpotLight
+ {
+ public override string Name => $"uLlkNullAngleSpotLight";
+
+ public uLlkNullAngleSpotLight(nint lightObject) : base(lightObject)
+ {
+ }
+ }
+
+ private class uLlkFollowCameraSpotLight : uLlkSpotLight
+ {
+ public override string Name => $"uLlkFollowCameraSpotLight";
+
+ public uLlkFollowCameraSpotLight(nint lightObject) : base(lightObject)
+ {
+ }
+ }
+
+ private class uHemiSphereLight : uLight
+ {
+ public override int Type => 4;
+ public override string Name => $"uHemiSphereLight";
+
+ public uHemiSphereLight(nint lightObject) : base(lightObject)
+ {
+ Parameters.AddRange(new Parameter[]{
+ P<int>("Rev Color", 0x5A0, ParameterType.COLOR),
+ P<float>("Rev Intensity", 0x5A4, ParameterType.FLOAT),
+ P<float>("Direction", 0x5B0, ParameterType.VECTOR3, pStep(0.00025f))
+ });
+ UpdateParams();
+ }
+ }
+
+ private class uMhHemiSphereLight : uHemiSphereLight
+ {
+ public override string Name => $"uMhHemiSphereLight";
+
+ public uMhHemiSphereLight(nint lightObject) : base(lightObject)
+ {
+ }
+
+ public uMhHemiSphereLight(nint lightObject, Vector3 pos) : this(lightObject)
+ {
foreach (Parameter param in Parameters)
{
- param.Update(lightObject);
+ param.OverrideOn(false);
}
}
}
- // Point Light (2):
- // Create1: 0x141F875A0 ()
- // Create2: 0x141F87CD0 (nint)
- // Destroy: 0x141F87D90 (nint, int)
- //
- // Spot Light (3):
- // Create1: 0x141F8AE80 ()
- // Create2: 0x141F8B2D0 (nint)
- // Destroy: 0x141F8B390 (nint, int)
- //
- // Hemi Sphere Light (4):
- // Create1: 0x141F84840 ()
- // Create2: 0x141F84990 (nint)
- // Destroy: 0x141F84A40 (nint, int)
- //
- // Wrapper? (8):
- // Create1: 0x141F816C0 ()
- // Create2: 0x141F81800 ()
- // Destroy: 0x141F81940 (nint, int)
+ private class uLlkHemiSphereLight : uHemiSphereLight
+ {
+ public override string Name => $"uLlkHemiSphereLight";
+ public nint CycleTimelineRes => MemoryUtil.Read<nint>(Object + 0x5D0);
+ public int CycleAnimNo => MemoryUtil.Read<int>(Object + 0x720);
+
+ public uLlkHemiSphereLight(nint lightObject) : base(lightObject)
+ {
+ Parameters.AddRange(new Parameter[]{
+ P<int>("Llk Color", 0x5C0, ParameterType.COLOR),
+ P<float>("Llk Intensity", 0x5C8, ParameterType.FLOAT),
+ P<int>("Llk Rev Color", 0x5C4, ParameterType.COLOR),
+ P<float>("Llk Rev Intensity", 0x5CC, ParameterType.FLOAT)
+ });
+ UpdateParams();
+ }
+ }
+
+ private class uMhObjectLight : uLight
+ {
+ public override int Type => 5;
+ public override string Name => $"uMhObjectLight";
+
+ public uMhObjectLight(nint lightObject) : base(lightObject)
+ {
+ }
+ }
+
+ private class uLlkObjectLight : uLight
+ {
+ public override string Name => $"uLlkObjectLight";
+
+ public uLlkObjectLight(nint lightObject) : base(lightObject)
+ {
+ }
+ }
+
+ private delegate nint CreateLightObject(nint lightObject);
+ private delegate nint DestroyLightObject(nint lightObjectInternal, int unknownInt);
+ private Hook<CreateLightObject>? createLightObject;
+ private static Dictionary<nint, Func<nint, uLight>> lightTypes = new Dictionary<nint, Func<nint, uLight>>()
+ {
+ { lton(0x143514168), (x) => new uLight(x) },
+ { lton(0x143514288), (x) => new uInfiniteLight(x) },
+ { lton(0x1434994D0), (x) => new uMhInfiniteLight(x) },
+ { lton(0x1434954F0), (x) => new uMhActorInfiniteLight(x) },
+ { lton(0x143494150), (x) => new uLlkInfiniteLight(x) },
+ { lton(0x1434936A0), (x) => new uLlkActorInfiniteLight(x) },
+ { lton(0x143493E30), (x) => new uLlkFollowCameraInfiniteLight(x) },
+ { lton(0x1435143A8), (x) => new uPointLight(x) },
+ { lton(0x14349A6C8), (x) => new uMhPointLight(x) },
+ { lton(0x1434952B0), (x) => new uMhActorPointLight(x) },
+ { lton(0x1434944E8), (x) => new uLlkPointLight(x) },
+ { lton(0x143493460), (x) => new uLlkActorPointLight(x) },
+ { lton(0x143493BF0), (x) => new uLlkFollowCameraPointLight(x) },
+ { lton(0x1435144C8), (x) => new uSpotLight(x) },
+ { lton(0x14349E280), (x) => new uMhSpotLight(x) },
+ { lton(0x1434953D0), (x) => new uMhActorSpotLight(x) },
+ { lton(0x143494888), (x) => new uLlkSpotLight(x) },
+ { lton(0x143493580), (x) => new uLlkActorSpotLight(x) },
+ { lton(0x1434937C0), (x) => new uLlkNullAngleSpotLight(x) },
+ { lton(0x143493D10), (x) => new uLlkFollowCameraSpotLight(x) },
+ { lton(0x1435145E8), (x) => new uHemiSphereLight(x) },
+ { lton(0x143499378), (x) => new uMhHemiSphereLight(x) },
+ { lton(0x143493F98), (x) => new uLlkHemiSphereLight(x) },
+ { lton(0x14349A498), (x) => new uMhObjectLight(x) },
+ { lton(0x1434942A0), (x) => new uLlkObjectLight(x) },
+ { lton(0x143493918), (x) => new uLight(x) }, // @TODO: uLlkBaseModel is not implemented.
+ };
+ private static nint[] lightObjectDestructors = {
+ lton(0x142311FF0), // # uLight
+ lton(0x142311F40), // # uInfiniteLight
+ lton(0x141FB8F50), // # uMhInfiniteLight
+ lton(0x141F91DE0), // # uMhActorInfiniteLight
+ lton(0x141F855A0), // # uLlkInfiniteLight
+ lton(0x141F81940), // # uLlkActorInfiniteLight
+ lton(0x141F83B00), // # uLlkFollowCameraInfiniteLight
+ lton(0x142312070), // # uPointLight
+ lton(0x141FC0950), // # uMhPointLight
+ lton(0x141F91E80), // # uMhActorPointLight
+ lton(0x141F87D90), // # uLlkPointLight
+ lton(0x141F819B0), // # uLlkActorPointLight
+ lton(0x141F83B70), // # uLlkFollowCameraPointLight
+ lton(0x1423120F0), // # uSpotLight
+ lton(0x141FDE0D0), // # uMhSpotLight
+ lton(0x141F91F20), // # uMhActorSpotLight
+ lton(0x141F8B390), // # uLlkSpotLight
+ lton(0x141F81A20), // # uLlkActorSpotLight
+ lton(0x141F81A90), // # uLlkNullAngleSpotLight
+ lton(0x141F83BE0), // # uLlkFollowCameraSpotLight
+ lton(0x142311EC0), // # uHemiSphereLight
+ lton(0x141FB8C20), // # uMhHemiSphereLight
+ lton(0x141F84A40), // # uLlkHemiSphereLight
+ lton(0x141FBF6B0), // # uMhObjectLight
+ lton(0x141F86270), // # uLlkObjectLight
+ lton(0x141F83460), // # uLlkBaseModel
+ };
+ private Hook<DestroyLightObject>[] lightObjectDestructorHooks = new Hook<DestroyLightObject>[lightObjectDestructors.Length];
+
+ private List<uLight> newLights = new List<uLight>();
+ private List<uLight> sceneLights = new List<uLight>();
+ private bool sortByDistanceToPlayer = false;
- private int requestLightType = 2;
- private NativeFunction<int, nint> createLight;
- //private bool interceptCreateLight = false;
- private List<Light> ourLights = new List<Light>();
- //private List<Light> sceneLights = new List<Light>();
private NativeAction<nint, int, nint, int> addToScene;
private NativeAction<nint> removeFromScene;
- //private delegate nint CreateLightObject(int type);
- //private Hook<CreateLightObject>? createLightObject;
- private delegate void DestroyLightObject(nint lightObject, int unknownInt);
- private Hook<DestroyLightObject>? destroyLightObject;
- private delegate void UpdateLights(nint lightObject);
- private Hook<UpdateLights>? updateLights;
+ private bool interceptCreateLight = false;
+ private List<uLight> ourLights = new List<uLight>();
public void Initialize()
{
- createLight = new NativeFunction<int, nint>(0x1418A3EF0);
- //createLightObject = Hook.Create<CreateLightObject>(0x1418A3EF0, CreateLightObjectHook);
- destroyLightObject = Hook.Create<DestroyLightObject>(0x141F87D90, DestroyLightObjectHook);
+ createLightObject = Hook.Create<CreateLightObject>(0x142311420, CreateLightObjectHook);
+ DestroyLightObject[] destructorHookFuncs = {
+ DestroyLightObjectHook0,
+ DestroyLightObjectHook1,
+ DestroyLightObjectHook2,
+ DestroyLightObjectHook3,
+ DestroyLightObjectHook4,
+ DestroyLightObjectHook5,
+ DestroyLightObjectHook6,
+ DestroyLightObjectHook7,
+ DestroyLightObjectHook8,
+ DestroyLightObjectHook9,
+ DestroyLightObjectHook10,
+ DestroyLightObjectHook11,
+ DestroyLightObjectHook12,
+ DestroyLightObjectHook13,
+ DestroyLightObjectHook14,
+ DestroyLightObjectHook15,
+ DestroyLightObjectHook16,
+ DestroyLightObjectHook17,
+ DestroyLightObjectHook18,
+ DestroyLightObjectHook19,
+ DestroyLightObjectHook20,
+ DestroyLightObjectHook21,
+ DestroyLightObjectHook22,
+ DestroyLightObjectHook23,
+ DestroyLightObjectHook24,
+ DestroyLightObjectHook25
+ };
+ for (int i = 0; i < lightObjectDestructors.Length; i++)
+ {
+ lightObjectDestructorHooks[i] = Hook.Create<DestroyLightObject>(lightObjectDestructors[i], destructorHookFuncs[i]);
+ }
+
addToScene = new NativeAction<nint, int, nint, int>(0x142219070);
removeFromScene = new NativeAction<nint>(0x142228F10);
- updateLights = Hook.Create<UpdateLights>(0x141F88F30, UpdateLightsHook);
}
- /*
- private nint CreateLightObjectHook(int type)
+ public void PostUpdateUnits()
{
- nint lightObject = createLightObject!.Original(type);
- if (interceptCreateLight)
+ for (int i = 0; i < sceneLights.Count; i++)
{
- interceptCreateLight = false;
+ uLight light = sceneLights[i];
+ foreach (Parameter param in light.Parameters)
+ {
+ param.Update(light.Object);
+ }
}
- //else if (type == 2)
- else
+ }
+
+ public void OnUpdate()
+ {
+ for (int i = newLights.Count - 1; i >= 0; i--)
{
- sceneLights.Add(new Light(lightObject, type));
+ uLight light = newLights[i];
+ nint vTable = MemoryUtil.Read<nint>(light.Object);
+ newLights.RemoveAt(i);
+ if (lightTypes.ContainsKey(vTable))
+ {
+ sceneLights.Add(lightTypes[vTable](light.Object));
+ }
+ else
+ {
+ Log.Error($"Unknown Light Type: 0x{vTable:X}.");
+ }
}
- return lightObject;
}
- */
- private void UpdateLightsHook(nint lightObject)
+ private bool lightObjectIsTracked(nint lightObject)
{
- Light? light = null;
- /*
- for (int i = 0; i < sceneLights.Count; i++)
+ for (int i = 0; i < newLights.Count; i++)
{
- if (lightObject == sceneLights[i].Object)
+ if (lightObject == newLights[i].Object)
{
- light = sceneLights[i];
- break;
+ return true;
}
}
- */
- if (light == null)
+ for (int i = 0; i < sceneLights.Count; i++)
{
- for (int i = 0; i < ourLights.Count; i++)
+ if (lightObject == sceneLights[i].Object)
{
- if (lightObject == ourLights[i].Object)
- {
- light = ourLights[i];
- break;
- }
+ return true;
}
}
- updateLights!.Original(lightObject);
- if (light != null)
+ for (int i = 0; i < ourLights.Count; i++)
{
- foreach (Parameter param in light.Parameters)
+ if (lightObject == ourLights[i].Object)
{
- param.Update(lightObject);
+ return true;
}
}
+ return false;
+ }
+
+ private nint CreateLightObjectHook(nint lightObject)
+ {
+ lightObject = createLightObject!.Original(lightObject);
+ if (!interceptCreateLight)
+ {
+ Assert(!lightObjectIsTracked(lightObject));
+ newLights.Add(new uLight(lightObject));
+ }
+ return lightObject;
}
- private void DestroyLightObjectHook(nint lightObject, int unknownInt)
+ private void cleanupCommon(nint lightObject)
{
- /*
+ for (int i = 0; i < newLights.Count; i++)
+ {
+ uLight light = newLights[i];
+ if (lightObject == light.Object)
+ {
+ newLights.RemoveAt(i);
+ Assert(!lightObjectIsTracked(lightObject));
+ return;
+ }
+ }
for (int i = 0; i < sceneLights.Count; i++)
{
- if (lightObject == sceneLights[i].Object)
+ uLight light = sceneLights[i];
+ if (lightObject == light.Object)
{
sceneLights.RemoveAt(i);
- break;
+ Assert(!lightObjectIsTracked(lightObject));
+ return;
}
}
- */
for (int i = 0; i < ourLights.Count; i++)
{
- if (lightObject == ourLights[i].Object)
+ uLight light = ourLights[i];
+ if (lightObject == light.Object)
{
ourLights.RemoveAt(i);
- break;
+ Assert(!lightObjectIsTracked(lightObject));
+ return;
}
}
- destroyLightObject!.Original(lightObject, unknownInt);
+ }
+
+ private nint DestroyLightObjectHook0(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[0]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook1(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[1]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook2(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[2]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook3(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[3]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook4(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[4]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook5(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[5]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook6(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[6]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook7(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[7]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook8(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[8]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook9(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[9]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook10(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[10]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook11(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[11]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook12(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[12]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook13(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[13]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook14(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[14]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook15(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[15]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook16(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[16]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook17(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[17]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook18(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[18]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook19(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[19]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook20(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[20]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook21(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[21]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook22(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[22]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook23(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[23]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook24(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[24]!.Original(lightObject, unknownInt);
+ }
+ private nint DestroyLightObjectHook25(nint lightObject, int unknownInt)
+ {
+ Assert(unknownInt == 1); cleanupCommon(lightObject);
+ return lightObjectDestructorHooks[25]!.Original(lightObject, unknownInt);
+ }
+
+ private void DrawLights(IEnumerable<uLight> lights, float width)
+ {
+ bool disableAll = ImGui.Button("Disable All");
+ if (ImGui.BeginItemTooltip())
+ {
+ ImGui.Text("Set \"Group\" to 0, Disable \"Shadow Cast\" and \"Do Volumetric\".");
+ ImGui.EndTooltip();
+ }
+ ImGui.SameLine();
+ bool enableAll = ImGui.Button("Enable All");
+ foreach (uLight light in lights)
+ {
+ ImGui.PushID(light.Object);
+ if (disableAll)
+ {
+ light.Parameters[0].ForceOverrideOn();
+ light.Parameters[0].SetOverrideValue(default, 0);
+ light.Parameters[7].ForceOverrideOn();
+ light.Parameters[7].SetOverrideValue(default, 0);
+ light.Parameters[16].ForceOverrideOn();
+ light.Parameters[16].SetOverrideValue(default, 0);
+ }
+ if (enableAll)
+ {
+ light.Parameters[0].ForceOverrideOff();
+ light.Parameters[7].ForceOverrideOff();
+ light.Parameters[16].ForceOverrideOff();
+ }
+ if (ImGui.CollapsingHeader(($"{light.Name} ({light.Info})")))
+ {
+ foreach (Parameter param in light.Parameters)
+ {
+ param.Draw(width);
+ }
+ }
+ ImGui.PopID();
+ }
}
public unsafe void DrawUI(float width)
{
- /*
- ImGui.NextItemWidth(width * 0.25f);
- ImGui.InputInt("Type", ref requestLightType, 1);
+ interceptCreateLight = true;
+ int lightType = -1;
+ nint lightObject = 0x0;
+ if (ImGui.Button("New Point Light"))
+ {
+ lightType = 2;
+ lightObject = new NativeFunction<nint>(0x141FC0780).Invoke();
+ }
+ ImGui.SameLine();
+ if (ImGui.Button("New Spot Light"))
+ {
+ lightType = 3;
+ lightObject = new NativeFunction<nint>(0x141FDDF00).Invoke();
+ }
ImGui.SameLine();
- */
- if (ImGui.Button("New"))
+ if (ImGui.Button("New Hemi Sphere Light"))
+ {
+ lightType = 4;
+ lightObject = new NativeFunction<nint>(0x141FB8A50).Invoke();
+ }
+ interceptCreateLight = false;
+ if (lightObject != 0x0)
{
- //interceptCreateLight = true;
- nint lightObject = createLight.Invoke(requestLightType);
Vector3 pos = default;
Player? player = Player.MainPlayer;
if (player != null)
@@ -198,66 +883,96 @@ namespace WorldTuningTool
pos = player.Position;
pos.Y += 30.0f;
}
- ourLights.Add(new Light(lightObject, requestLightType, pos));
+ if (lightType == 2)
+ {
+ ourLights.Add(new uMhPointLight(lightObject, pos));
+ }
+ else if (lightType == 3)
+ {
+ ourLights.Add(new uMhSpotLight(lightObject, pos));
+ }
+ else if (lightType == 4)
+ {
+ ourLights.Add(new uMhHemiSphereLight(lightObject, pos));
+ }
// mov byte ptr[rsp+20],00 unaccounted for, hopefully it never matters.
addToScene.Invoke(MemoryUtil.Read<nint>(0x1451238C8), 0x16, lightObject, 0x0);
}
- ImGui.Separator();
ImGui.PushID("Ours");
for (int i = 0; i < ourLights.Count; i++)
{
- Light light = ourLights[i];
+ uLight light = ourLights[i];
ImGui.PushID(i);
- ImGui.Text($"Type: {light.Type}, Address: 0x{light.Object:X}");
- foreach (Parameter param in light.Parameters)
+ if (ImGui.Button("X"))
{
- param.Draw(width, true);
+ removeFromScene.Invoke(light.Object); // removeFromScene triggers destructor.
}
- /*
- if (ImGui.CollapsingHeader("Random Move"))
+ ImGui.SameLine();
+ if (ImGui.CollapsingHeader(($"{light.Name} (0x{light.Object:X})")))
{
- foreach (Parameter param in light.RandomMoveParameters)
+ foreach (Parameter param in light.Parameters)
{
param.Draw(width, true);
}
}
- */
- if (ImGui.Button("Remove"))
- {
- /*
- nint vTable = MemoryUtil.Read<nint>(lightObject);
- NativeAction<nint, int> freeLight = new NativeAction<nint, int>(MemoryUtil.Read<nint>(vTable));
- freeLight.Invoke(lightObject, 1);
- */
- // removeFromScene triggers destructor.
- removeFromScene.Invoke(light.Object);
- }
ImGui.PopID();
- ImGui.Separator();
}
ImGui.PopID();
+ ImGui.Separator();
ImGui.PushID("Scene");
- /*
- if (ImGui.CollapsingHeader("Scene Lights"))
+ ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags.Framed;
+ if (ImGui.TreeNodeEx("Scene Lights", flags))
{
- for (int i = 0; i < sceneLights.Count; i++)
+ if (ImGui.CollapsingHeader("Infinite"))
{
- Light light = sceneLights[i];
- ImGui.PushID(i);
- ImGui.Text($"Type: {light.Type}, Address: 0x{light.Object:X}");
- foreach (Parameter param in light.Parameters)
+ DrawLights(sceneLights.Where(x => (x.Type == 1)), width);
+ ImGui.Separator();
+ }
+ if (ImGui.CollapsingHeader("Point"))
+ {
+ ImGui.Checkbox("Sort By Distance To Player", ref sortByDistanceToPlayer);
+ ImGui.SameLine();
+ if (sortByDistanceToPlayer)
{
- param.Draw(width);
+ Vector3 pos = default;
+ Player? player = Player.MainPlayer;
+ if (player != null)
+ {
+ pos = player.Position;
+ }
+ uLight[] pointLights = sceneLights.Where(x => (x.Type == 2)).ToArray();
+ Array.Sort(pointLights, delegate(uLight x, uLight y)
+ {
+ float distX = Vector3.Distance(pos, ((uPointLight)x).Position);
+ float distY = Vector3.Distance(pos, ((uPointLight)y).Position);
+ if (distX < distY) return -1;
+ else if (distX > distY) return 1;
+ return 0;
+ });
+ DrawLights(pointLights, width);
}
- if (ImGui.Button("Remove"))
+ else
{
- removeFromScene.Invoke(light.Object);
+ DrawLights(sceneLights.Where(x => (x.Type == 2)), width);
}
- ImGui.PopID();
ImGui.Separator();
}
+ if (ImGui.CollapsingHeader("Spot"))
+ {
+ DrawLights(sceneLights.Where(x => (x.Type == 3)), width);
+ ImGui.Separator();
+ }
+ if (ImGui.CollapsingHeader("Hemi Sphere"))
+ {
+ DrawLights(sceneLights.Where(x => (x.Type == 4)), width);
+ ImGui.Separator();
+ }
+ if (ImGui.CollapsingHeader("Other"))
+ {
+ DrawLights(sceneLights.Where(x => (x.Type == -1 || x.Type == 5)), width);
+ }
+ ImGui.TreePop();
}
- */
ImGui.PopID();
}
}