diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index a3e3d4b4..d91b97a6 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -196,6 +196,22 @@ namespace NewHorizons.Builder.Props } } + if (detail.isRelativeToParent) + { + prop.transform.localPosition = detail.position == null ? Vector3.zero : detail.position; + if (detail.alignToNormal) + { + // Apply the rotation after aligning it with normal + var up = (prop.transform.position - go.transform.position).normalized; + prop.transform.rotation = Quaternion.FromToRotation(Vector3.up, up); + prop.transform.rotation *= rot; + } + else + { + prop.transform.localRotation = rot; + } + } + if (isItem) { // Else when you put them down you can't pick them back up diff --git a/NewHorizons/Builder/Props/DialogueBuilder.cs b/NewHorizons/Builder/Props/DialogueBuilder.cs index 8c6b1489..738f9da8 100644 --- a/NewHorizons/Builder/Props/DialogueBuilder.cs +++ b/NewHorizons/Builder/Props/DialogueBuilder.cs @@ -128,12 +128,19 @@ namespace NewHorizons.Builder.Props conversationZone.transform.parent = sector?.transform ?? planetGO.transform; - if (!string.IsNullOrEmpty(info.pathToAnimController)) + if (!string.IsNullOrEmpty(info.parentPath)) + { + conversationZone.transform.parent = planetGO.transform.Find(info.parentPath); + } + else if (!string.IsNullOrEmpty(info.pathToAnimController)) { conversationZone.transform.parent = planetGO.transform.Find(info.pathToAnimController); } - - conversationZone.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); + + var pos = (Vector3)(info.position ?? Vector3.zero); + if (info.isRelativeToParent) conversationZone.transform.localPosition = pos; + else conversationZone.transform.position = planetGO.transform.TransformPoint(pos); + conversationZone.SetActive(true); return dialogueTree; diff --git a/NewHorizons/Builder/Props/NomaiTextBuilder.cs b/NewHorizons/Builder/Props/NomaiTextBuilder.cs index 8a472ea0..f108edaa 100644 --- a/NewHorizons/Builder/Props/NomaiTextBuilder.cs +++ b/NewHorizons/Builder/Props/NomaiTextBuilder.cs @@ -163,19 +163,40 @@ namespace NewHorizons.Builder.Props } } - nomaiWallTextObj.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); - if (info.normal != null) + var pos = (Vector3)(info.position ?? Vector3.zero); + if (info.isRelativeToParent) { - // In global coordinates (normal was in local coordinates) - var up = (nomaiWallTextObj.transform.position - planetGO.transform.position).normalized; - var forward = planetGO.transform.TransformDirection(info.normal).normalized; + nomaiWallTextObj.transform.localPosition = pos; + if (info.normal != null) + { + // In global coordinates (normal was in local coordinates) + var up = (nomaiWallTextObj.transform.position - planetGO.transform.position).normalized; + var forward = planetGO.transform.TransformDirection(info.normal).normalized; - nomaiWallTextObj.transform.up = up; - nomaiWallTextObj.transform.forward = forward; + nomaiWallTextObj.transform.up = up; + nomaiWallTextObj.transform.forward = forward; + } + if (info.rotation != null) + { + nomaiWallTextObj.transform.localRotation = Quaternion.Euler(info.rotation); + } } - if (info.rotation != null) + else { - nomaiWallTextObj.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); + nomaiWallTextObj.transform.position = planetGO.transform.TransformPoint(pos); + if (info.normal != null) + { + // In global coordinates (normal was in local coordinates) + var up = (nomaiWallTextObj.transform.position - planetGO.transform.position).normalized; + var forward = planetGO.transform.TransformDirection(info.normal).normalized; + + nomaiWallTextObj.transform.up = up; + nomaiWallTextObj.transform.forward = forward; + } + if (info.rotation != null) + { + nomaiWallTextObj.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); + } } nomaiWallTextObj.SetActive(true); @@ -238,7 +259,9 @@ namespace NewHorizons.Builder.Props } } - customScroll.transform.position = planetGO.transform.TransformPoint(info.position ?? Vector3.zero); + var pos = (Vector3)(info.position ?? Vector3.zero); + if (info.isRelativeToParent) customScroll.transform.localPosition = pos; + else customScroll.transform.position = planetGO.transform.TransformPoint(pos); var up = planetGO.transform.InverseTransformPoint(customScroll.transform.position).normalized; customScroll.transform.rotation = Quaternion.FromToRotation(customScroll.transform.up, up) * customScroll.transform.rotation; @@ -291,7 +314,9 @@ namespace NewHorizons.Builder.Props } } - computerObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); + var pos = (Vector3)(info.position ?? Vector3.zero); + if (info.isRelativeToParent) computerObject.transform.localPosition = pos; + else computerObject.transform.position = planetGO.transform.TransformPoint(pos); var up = computerObject.transform.position - planetGO.transform.position; if (info.normal != null) up = planetGO.transform.TransformDirection(info.normal); @@ -318,29 +343,14 @@ namespace NewHorizons.Builder.Props { var detailInfo = new PropModule.DetailInfo() { - position = info.position + position = info.position, + parentPath = info.parentPath, + isRelativeToParent = info.isRelativeToParent, + rename = info.rename }; var computerObject = DetailBuilder.Make(planetGO, sector, _preCrashComputerPrefab, detailInfo); computerObject.SetActive(false); - if (!string.IsNullOrEmpty(info.rename)) - { - computerObject.name = info.rename; - } - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - computerObject.transform.SetParent(newParent, true); - } - else - { - Logger.LogWarning($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - var up = computerObject.transform.position - planetGO.transform.position; if (info.normal != null) up = planetGO.transform.TransformDirection(info.normal); computerObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * computerObject.transform.rotation; @@ -407,11 +417,15 @@ namespace NewHorizons.Builder.Props } } - cairnObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); + var pos = (Vector3)(info.position ?? Vector3.zero); + if (info.isRelativeToParent) cairnObject.transform.localPosition = pos; + else cairnObject.transform.position = planetGO.transform.TransformPoint(pos); if (info.rotation != null) { - cairnObject.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); + var rot = Quaternion.Euler(info.rotation); + if (info.isRelativeToParent) cairnObject.transform.localRotation = rot; + else cairnObject.transform.rotation = planetGO.transform.TransformRotation(rot); } else { @@ -456,18 +470,13 @@ namespace NewHorizons.Builder.Props var detailInfo = new PropModule.DetailInfo { parentPath = info.parentPath, rotation = info.rotation, - position = info.position + position = info.position, + isRelativeToParent = info.isRelativeToParent, + rename = info.rename }; var recorderObject = DetailBuilder.Make(planetGO, sector, prefab, detailInfo); recorderObject.SetActive(false); - if (!string.IsNullOrEmpty(info.rename)) - { - recorderObject.name = info.rename; - } - - recorderObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); - if (info.rotation == null) { var up = recorderObject.transform.position - planetGO.transform.position; @@ -517,14 +526,18 @@ namespace NewHorizons.Builder.Props } } - trailmarkerObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); + var pos = (Vector3)(info.position ?? Vector3.zero); + if (info.isRelativeToParent) trailmarkerObject.transform.localPosition = pos; + else trailmarkerObject.transform.position = planetGO.transform.TransformPoint(pos); // shrink because that is what mobius does on all trailmarkers or else they are the size of the player trailmarkerObject.transform.localScale = Vector3.one * 0.75f; if (info.rotation != null) { - trailmarkerObject.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); + var rot = Quaternion.Euler(info.rotation); + if (info.isRelativeToParent) trailmarkerObject.transform.localRotation = rot; + else trailmarkerObject.transform.rotation = planetGO.transform.TransformRotation(rot); } else { diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index 1b91bb67..09e086c4 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -122,8 +122,18 @@ namespace NewHorizons.Builder.Props } } - slideReelObj.transform.position = planetGO.transform.TransformPoint((Vector3)(info.position ?? Vector3.zero)); - slideReelObj.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler((Vector3)(info.rotation ?? Vector3.zero))); + var pos = (Vector3)(info.position ?? Vector3.zero); + var rot = Quaternion.Euler((Vector3)(info.rotation ?? Vector3.zero)); + if (info.isRelativeToParent) + { + slideReelObj.transform.localPosition = pos; + slideReelObj.transform.localRotation = rot; + } + else + { + slideReelObj.transform.position = planetGO.transform.TransformPoint(pos); + slideReelObj.transform.rotation = planetGO.transform.TransformRotation(rot); + } // Now we replace the slides int slidesCount = info.slides.Length; @@ -208,8 +218,18 @@ namespace NewHorizons.Builder.Props } } - autoProjector.transform.position = planetGO.transform.TransformPoint((Vector3)(info.position ?? Vector3.zero)); - autoProjector.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler((Vector3)(info.rotation ?? Vector3.zero))); + var pos = (Vector3)(info.position ?? Vector3.zero); + var rot = Quaternion.Euler((Vector3)(info.rotation ?? Vector3.zero)); + if (info.isRelativeToParent) + { + autoProjector.transform.localPosition = pos; + autoProjector.transform.localRotation = rot; + } + else + { + autoProjector.transform.position = planetGO.transform.TransformPoint(pos); + autoProjector.transform.rotation = planetGO.transform.TransformRotation(rot); + } // Now we replace the slides int slidesCount = info.slides.Length; @@ -243,23 +263,13 @@ namespace NewHorizons.Builder.Props var detailInfo = new PropModule.DetailInfo() { position = info.position, + rotation = info.rotation, + parentPath = info.parentPath, + isRelativeToParent = info.isRelativeToParent, scale = 2 }; var g = DetailBuilder.Make(planetGO, sector, _visionTorchDetectorPrefab, detailInfo); - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - g.transform.SetParent(newParent, true); - } - else - { - Logger.LogWarning($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - if (g == null) { Logger.LogWarning($"Tried to make a vision torch target but couldn't. Do you have the DLC installed?"); @@ -300,23 +310,12 @@ namespace NewHorizons.Builder.Props var detailInfo = new PropModule.DetailInfo() { position = info.position, - rotation = info.rotation + rotation = info.rotation, + parentPath = info.parentPath, + isRelativeToParent = info.isRelativeToParent }; var standingTorch = DetailBuilder.Make(planetGO, sector, _standingVisionTorchPrefab, detailInfo); - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = planetGO.transform.Find(info.parentPath); - if (newParent != null) - { - standingTorch.transform.SetParent(newParent, true); - } - else - { - Logger.LogWarning($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}"); - } - } - if (standingTorch == null) { Logger.LogWarning($"Tried to make a vision torch target but couldn't. Do you have the DLC installed?"); diff --git a/NewHorizons/Builder/Props/RemoteBuilder.cs b/NewHorizons/Builder/Props/RemoteBuilder.cs index 2d90e8f5..83c66158 100644 --- a/NewHorizons/Builder/Props/RemoteBuilder.cs +++ b/NewHorizons/Builder/Props/RemoteBuilder.cs @@ -171,31 +171,14 @@ namespace NewHorizons.Builder.Props var detailInfo = new PropModule.DetailInfo() { position = info.position, - rotation = info.rotation + rotation = info.rotation, + parentPath = info.parentPath, + isRelativeToParent = info.isRelativeToParent, + rename = info.rename }; var whiteboard = DetailBuilder.Make(go, sector, _whiteboardPrefab, detailInfo); whiteboard.SetActive(false); - if (!string.IsNullOrEmpty(info.rename)) - { - whiteboard.name = info.rename; - } - - whiteboard.transform.parent = sector?.transform ?? go.transform; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = go.transform.Find(info.parentPath); - if (newParent != null) - { - whiteboard.transform.parent = newParent; - } - else - { - Logger.LogWarning($"Cannot find parent object at path: {go.name}/{info.parentPath}"); - } - } - var decalMat = new Material(_decalMaterial); decalMat.SetTexture("_MainTex", decal); decalMat.SetTexture("_EmissionMap", decal); @@ -236,31 +219,14 @@ namespace NewHorizons.Builder.Props var detailInfo = new PropModule.DetailInfo() { position = info.position, - rotation = info.rotation + rotation = info.rotation, + parentPath = info.parentPath, + isRelativeToParent = info.isRelativeToParent, + rename = info.rename }; var platform = DetailBuilder.Make(go, sector, _remoteCameraPlatformPrefab, detailInfo); platform.SetActive(false); - if (!string.IsNullOrEmpty(info.rename)) - { - platform.name = info.rename; - } - - platform.transform.parent = sector?.transform ?? go.transform; - - if (!string.IsNullOrEmpty(info.parentPath)) - { - var newParent = go.transform.Find(info.parentPath); - if (newParent != null) - { - platform.transform.parent = newParent; - } - else - { - Logger.LogWarning($"Cannot find parent object at path: {go.name}/{info.parentPath}"); - } - } - var decalMat = new Material(_decalMaterial); decalMat.SetTexture("_MainTex", decal); decalMat.SetTexture("_EmissionMap", decal); @@ -310,8 +276,18 @@ namespace NewHorizons.Builder.Props } } - shareStone.transform.position = go.transform.TransformPoint((Vector3)(info.position ?? Vector3.zero)); - shareStone.transform.rotation = go.transform.TransformRotation(Quaternion.Euler((Vector3)(info.rotation ?? Vector3.zero))); + var pos = (Vector3)(info.position ?? Vector3.zero); + var rot = Quaternion.Euler((Vector3)(info.rotation ?? Vector3.zero)); + if (info.isRelativeToParent) + { + shareStone.transform.localPosition = pos; + shareStone.transform.localRotation = rot; + } + else + { + shareStone.transform.position = go.transform.TransformPoint(pos); + shareStone.transform.rotation = go.transform.TransformRotation(rot); + } shareStone.GetComponent()._connectedPlatform = id; diff --git a/NewHorizons/Builder/Props/SignalBuilder.cs b/NewHorizons/Builder/Props/SignalBuilder.cs index 13ea9409..3072bb45 100644 --- a/NewHorizons/Builder/Props/SignalBuilder.cs +++ b/NewHorizons/Builder/Props/SignalBuilder.cs @@ -129,7 +129,9 @@ namespace NewHorizons.Builder.Props } } - signalGO.transform.position = planetGO.transform.TransformPoint(info.position != null ? (Vector3)info.position : Vector3.zero); + var pos = (Vector3)(info.position ?? Vector3.zero); + if (info.isRelativeToParent) signalGO.transform.localPosition = pos; + else signalGO.transform.position = planetGO.transform.TransformPoint(pos); signalGO.layer = LayerMask.NameToLayer("AdvancedEffectVolume"); var source = signalGO.AddComponent(); diff --git a/NewHorizons/External/Modules/PropModule.cs b/NewHorizons/External/Modules/PropModule.cs index cdd7dc54..839f75b6 100644 --- a/NewHorizons/External/Modules/PropModule.cs +++ b/NewHorizons/External/Modules/PropModule.cs @@ -220,6 +220,11 @@ namespace NewHorizons.External.Modules /// public string parentPath; + /// + /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. + /// + public bool isRelativeToParent; + /// /// Should this detail stay loaded even if you're outside the sector (good for very large props) /// @@ -451,6 +456,11 @@ namespace NewHorizons.External.Modules /// public string xmlFile; + /// + /// Whether the positional and rotational coordinates are relative to the animation controller instead of the root planet object. + /// + public bool isRelativeToParent; + /// /// Optionally rename the dialogue object. The remote trigger volume will be renamed to have this as a prefix. /// @@ -560,6 +570,11 @@ namespace NewHorizons.External.Modules /// public string parentPath; + /// + /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. + /// + public bool isRelativeToParent; + /// /// An optional rename of this object /// @@ -658,6 +673,11 @@ namespace NewHorizons.External.Modules /// The relative path from the planet to the parent of this slideshow. Optional (will default to the root sector). /// public string parentPath; + + /// + /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. + /// + public bool isRelativeToParent; } [JsonObject] @@ -857,6 +877,11 @@ namespace NewHorizons.External.Modules /// public string parentPath; + /// + /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. + /// + public bool isRelativeToParent; + /// /// An optional rename of this object /// @@ -920,6 +945,11 @@ namespace NewHorizons.External.Modules /// public string parentPath; + /// + /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. + /// + public bool isRelativeToParent; + /// /// An optional rename of this object /// @@ -959,6 +989,11 @@ namespace NewHorizons.External.Modules /// public string parentPath; + /// + /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. + /// + public bool isRelativeToParent; + /// /// An optional rename of this object /// diff --git a/NewHorizons/External/Modules/SignalModule.cs b/NewHorizons/External/Modules/SignalModule.cs index 3397df9a..255ebc9b 100644 --- a/NewHorizons/External/Modules/SignalModule.cs +++ b/NewHorizons/External/Modules/SignalModule.cs @@ -80,6 +80,11 @@ namespace NewHorizons.External.Modules /// The relative path from the planet to the parent of this signal. Optional (will default to the root sector). /// public string parentPath; + + /// + /// Whether the positional and rotational coordinates are relative to parent instead of the root planet object. + /// + public bool isRelativeToParent; } } } \ No newline at end of file diff --git a/NewHorizons/Schemas/body_schema.json b/NewHorizons/Schemas/body_schema.json index 8fde872b..53171b59 100644 --- a/NewHorizons/Schemas/body_schema.json +++ b/NewHorizons/Schemas/body_schema.json @@ -1055,6 +1055,10 @@ "type": "string", "description": "The path (not including the root planet object) of the parent of this game object. Optional (will default to the root sector)." }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, "keepLoaded": { "type": "boolean", "description": "Should this detail stay loaded even if you're outside the sector (good for very large props)" @@ -1106,6 +1110,10 @@ "type": "string", "description": "Relative path to the xml file defining the dialogue." }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to the animation controller instead of the root planet object." + }, "rename": { "type": "string", "description": "Optionally rename the dialogue object. The remote trigger volume will be renamed to have this as a prefix." @@ -1236,6 +1244,10 @@ "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, "rename": { "type": "string", "description": "An optional rename of this object" @@ -1464,6 +1476,10 @@ "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this slideshow. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." } } }, @@ -1858,6 +1874,10 @@ "parentPath": { "type": "string", "description": "The relative path from the planet to the parent of this signal. Optional (will default to the root sector)." + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." } } }, @@ -1913,6 +1933,10 @@ "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, "rename": { "type": "string", "description": "An optional rename of this object" @@ -1974,6 +1998,10 @@ "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, "rename": { "type": "string", "description": "An optional rename of this object" @@ -2009,6 +2037,10 @@ "type": "string", "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, "rename": { "type": "string", "description": "An optional rename of this object"