alignRadial migration plus cleanup of translator text normal handling

This commit is contained in:
Joshua Thome 2023-03-20 22:31:21 -05:00
parent 3c691d3511
commit 80c576bd01
14 changed files with 204 additions and 142 deletions

View File

@ -1,3 +1,4 @@
using Epic.OnlineServices.Presence;
using NewHorizons.Builder.Props; using NewHorizons.Builder.Props;
using NewHorizons.External.Modules; using NewHorizons.External.Modules;
using NewHorizons.Utility; using NewHorizons.Utility;
@ -18,8 +19,7 @@ namespace NewHorizons.Builder.General
if (!Main.Instance.IsWarpingFromVessel && !Main.Instance.IsWarpingFromShip && module.playerSpawn != null) if (!Main.Instance.IsWarpingFromVessel && !Main.Instance.IsWarpingFromShip && module.playerSpawn != null)
{ {
bool alignToBody = module.playerSpawn.rotation == null; GameObject spawnGO = GeneralPropBuilder.MakeNew("PlayerSpawnPoint", planetGO, null, module.playerSpawn);
GameObject spawnGO = GeneralPropBuilder.MakeNew("PlayerSpawnPoint", planetGO, null, module.playerSpawn, alignToBody: alignToBody);
spawnGO.layer = LayerUtilities.PlayerSafetyCollider; spawnGO.layer = LayerUtilities.PlayerSafetyCollider;
playerSpawn = spawnGO.AddComponent<SpawnPoint>(); playerSpawn = spawnGO.AddComponent<SpawnPoint>();
@ -29,8 +29,7 @@ namespace NewHorizons.Builder.General
} }
if (module.shipSpawn != null) if (module.shipSpawn != null)
{ {
bool alignToBody = module.shipSpawn.rotation == null; GameObject spawnGO = GeneralPropBuilder.MakeNew("ShipSpawnPoint", planetGO, null, module.shipSpawn);
GameObject spawnGO = GeneralPropBuilder.MakeNew("ShipSpawnPoint", planetGO, null, module.shipSpawn, alignToBody: alignToBody);
spawnGO.layer = LayerUtilities.PlayerSafetyCollider; spawnGO.layer = LayerUtilities.PlayerSafetyCollider;
var spawnPoint = spawnGO.AddComponent<SpawnPoint>(); var spawnPoint = spawnGO.AddComponent<SpawnPoint>();
@ -44,7 +43,7 @@ namespace NewHorizons.Builder.General
ship.transform.rotation = spawnGO.transform.rotation; ship.transform.rotation = spawnGO.transform.rotation;
// Move it up a bit more when aligning to surface // Move it up a bit more when aligning to surface
if (alignToBody) if (module.shipSpawn.alignRadial.GetValueOrDefault())
{ {
ship.transform.position += ship.transform.up * 4f; ship.transform.position += ship.transform.up * 4f;
} }

View File

@ -90,12 +90,12 @@ namespace NewHorizons.Builder.Props
// We save copies with all their components fixed, good if the user is placing the same detail more than once // We save copies with all their components fixed, good if the user is placing the same detail more than once
if (detail?.path != null && _fixedPrefabCache.TryGetValue((sector, detail.path), out var storedPrefab)) if (detail?.path != null && _fixedPrefabCache.TryGetValue((sector, detail.path), out var storedPrefab))
{ {
prop = GeneralPropBuilder.MakeFromPrefab(storedPrefab.prefab, prefab.name, go, sector, detail, alignToBody: detail.alignToNormal); prop = GeneralPropBuilder.MakeFromPrefab(storedPrefab.prefab, prefab.name, go, sector, detail);
isItem = storedPrefab.isItem; isItem = storedPrefab.isItem;
} }
else else
{ {
prop = GeneralPropBuilder.MakeFromPrefab(prefab, prefab.name, go, sector, detail, alignToBody: detail.alignToNormal); prop = GeneralPropBuilder.MakeFromPrefab(prefab, prefab.name, go, sector, detail);
StreamingHandler.SetUpStreaming(prop, sector); StreamingHandler.SetUpStreaming(prop, sector);

View File

@ -15,7 +15,6 @@ namespace NewHorizons.Builder.Props
{ {
public static GameObject MakeFromExisting(GameObject go, public static GameObject MakeFromExisting(GameObject go,
GameObject planetGO, Sector sector, GeneralPointPropInfo info, GameObject planetGO, Sector sector, GeneralPointPropInfo info,
bool alignToBody = false, MVector3 normal = null,
MVector3 defaultPosition = null, string defaultParentPath = null, Transform parentOverride = null) MVector3 defaultPosition = null, string defaultParentPath = null, Transform parentOverride = null)
{ {
if (info == null) return go; if (info == null) return go;
@ -61,9 +60,11 @@ namespace NewHorizons.Builder.Props
var pos = (Vector3)(info.position ?? defaultPosition ?? Vector3.zero); var pos = (Vector3)(info.position ?? defaultPosition ?? Vector3.zero);
var rot = Quaternion.identity; var rot = Quaternion.identity;
var alignRadial = false;
if (info is GeneralPropInfo rotInfo) if (info is GeneralPropInfo rotInfo)
{ {
rot = rotInfo.rotation != null ? Quaternion.Euler(rotInfo.rotation) : Quaternion.identity; rot = rotInfo.rotation != null ? Quaternion.Euler(rotInfo.rotation) : Quaternion.identity;
alignRadial = rotInfo.alignRadial.HasValue && rotInfo.alignRadial.Value;
} }
if (info.isRelativeToParent) if (info.isRelativeToParent)
{ {
@ -80,43 +81,30 @@ namespace NewHorizons.Builder.Props
go.transform.position = pos; go.transform.position = pos;
go.transform.rotation = rot; go.transform.rotation = rot;
} }
if (alignToBody) if (alignRadial)
{ {
var up = (go.transform.position - planetGO.transform.position).normalized; var up = (go.transform.position - planetGO.transform.position).normalized;
if (normal != null) go.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * rot;
{
if (info.isRelativeToParent)
{
up = go.transform.parent.TransformDirection(normal);
}
else
{
up = planetGO.transform.TransformDirection(normal);
}
}
go.transform.rotation = Quaternion.FromToRotation(go.transform.up, up) * rot;
} }
return go; return go;
} }
public static GameObject MakeNew(string defaultName, public static GameObject MakeNew(string defaultName,
GameObject planetGO, Sector sector, GeneralPointPropInfo info, GameObject planetGO, Sector sector, GeneralPointPropInfo info,
bool alignToBody = false, MVector3 normal = null,
MVector3 defaultPosition = null, string defaultParentPath = null, Transform parentOverride = null) MVector3 defaultPosition = null, string defaultParentPath = null, Transform parentOverride = null)
{ {
var go = new GameObject(defaultName); var go = new GameObject(defaultName);
go.SetActive(false); go.SetActive(false);
return MakeFromExisting(go, planetGO, sector, info, alignToBody, normal, defaultPosition, defaultParentPath, parentOverride); return MakeFromExisting(go, planetGO, sector, info, defaultPosition, defaultParentPath, parentOverride);
} }
public static GameObject MakeFromPrefab(GameObject prefab, string defaultName, public static GameObject MakeFromPrefab(GameObject prefab, string defaultName,
GameObject planetGO, Sector sector, GeneralPointPropInfo info, GameObject planetGO, Sector sector, GeneralPointPropInfo info,
bool alignToBody = false, MVector3 normal = null,
MVector3 defaultPosition = null, string defaultParentPath = null, Transform parentOverride = null) MVector3 defaultPosition = null, string defaultParentPath = null, Transform parentOverride = null)
{ {
var go = prefab.InstantiateInactive(); var go = prefab.InstantiateInactive();
go.name = defaultName; go.name = defaultName;
return MakeFromExisting(go, planetGO, sector, info, alignToBody, normal, defaultPosition, defaultParentPath, parentOverride); return MakeFromExisting(go, planetGO, sector, info, defaultPosition, defaultParentPath, parentOverride);
} }
} }
} }

View File

@ -21,21 +21,10 @@ namespace NewHorizons.Builder.Props
var geyserGO = GeneralPropBuilder.MakeFromPrefab(_geyserPrefab, "Geyser", planetGO, sector, info); var geyserGO = GeneralPropBuilder.MakeFromPrefab(_geyserPrefab, "Geyser", planetGO, sector, info);
var pos = planetGO.transform.InverseTransformPoint(geyserGO.transform.position); geyserGO.transform.position += geyserGO.transform.up * info.offset;
// Offset height, default -97.5 pushes it underground so the spout is at the surface
var length = pos.magnitude + info.offset;
// About 130 high, bubbles start at 10, shaft starts at 67, spout starts at 97.5
geyserGO.transform.position = planetGO.transform.TransformPoint(pos.normalized * length);
geyserGO.transform.localScale = Vector3.one; geyserGO.transform.localScale = Vector3.one;
// Geyser alignment is technically incorrect due to inheriting the prefab's rotation but we need backwards compat so explicitly applying it here
geyserGO.transform.rotation = _geyserPrefab.transform.rotation;
var up = planetGO.transform.TransformPoint(pos) - planetGO.transform.position;
geyserGO.transform.rotation = Quaternion.FromToRotation(geyserGO.transform.up, up) * _geyserPrefab.transform.rotation;
var bubbles = geyserGO.FindChild("GeyserParticles/GeyserBubbles"); var bubbles = geyserGO.FindChild("GeyserParticles/GeyserBubbles");
var shaft = geyserGO.FindChild("GeyserParticles/GeyserShaft"); var shaft = geyserGO.FindChild("GeyserParticles/GeyserShaft");
var spout = geyserGO.FindChild("GeyserParticles/GeyserSpout"); var spout = geyserGO.FindChild("GeyserParticles/GeyserSpout");

View File

@ -151,7 +151,7 @@ namespace NewHorizons.Builder.Props
switch (info.type) switch (info.type)
{ {
case PropModule.NomaiTextInfo.NomaiTextType.Wall: case PropModule.NomaiTextType.Wall:
{ {
var nomaiWallTextObj = MakeWallText(planetGO, sector, info, xmlPath).gameObject; var nomaiWallTextObj = MakeWallText(planetGO, sector, info, xmlPath).gameObject;
@ -216,7 +216,7 @@ namespace NewHorizons.Builder.Props
return nomaiWallTextObj; return nomaiWallTextObj;
} }
case PropModule.NomaiTextInfo.NomaiTextType.Scroll: case PropModule.NomaiTextType.Scroll:
{ {
var customScroll = _scrollPrefab.InstantiateInactive(); var customScroll = _scrollPrefab.InstantiateInactive();
@ -305,7 +305,7 @@ namespace NewHorizons.Builder.Props
return customScroll; return customScroll;
} }
case PropModule.NomaiTextInfo.NomaiTextType.Computer: case PropModule.NomaiTextType.Computer:
{ {
var computerObject = _computerPrefab.InstantiateInactive(); var computerObject = _computerPrefab.InstantiateInactive();
@ -358,7 +358,7 @@ namespace NewHorizons.Builder.Props
return computerObject; return computerObject;
} }
case PropModule.NomaiTextInfo.NomaiTextType.PreCrashComputer: case PropModule.NomaiTextType.PreCrashComputer:
{ {
var detailInfo = new PropModule.DetailInfo() var detailInfo = new PropModule.DetailInfo()
{ {
@ -408,10 +408,10 @@ namespace NewHorizons.Builder.Props
return computerObject; return computerObject;
} }
case PropModule.NomaiTextInfo.NomaiTextType.Cairn: case PropModule.NomaiTextType.Cairn:
case PropModule.NomaiTextInfo.NomaiTextType.CairnVariant: case PropModule.NomaiTextType.CairnVariant:
{ {
var cairnObject = (info.type == PropModule.NomaiTextInfo.NomaiTextType.CairnVariant ? _cairnVariantPrefab : _cairnPrefab).InstantiateInactive(); var cairnObject = (info.type == PropModule.NomaiTextType.CairnVariant ? _cairnVariantPrefab : _cairnPrefab).InstantiateInactive();
if (!string.IsNullOrEmpty(info.rename)) if (!string.IsNullOrEmpty(info.rename))
{ {
@ -483,10 +483,10 @@ namespace NewHorizons.Builder.Props
return cairnObject; return cairnObject;
} }
case PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder: case PropModule.NomaiTextType.PreCrashRecorder:
case PropModule.NomaiTextInfo.NomaiTextType.Recorder: case PropModule.NomaiTextType.Recorder:
{ {
var prefab = (info.type == PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder ? _preCrashRecorderPrefab : _recorderPrefab); var prefab = (info.type == PropModule.NomaiTextType.PreCrashRecorder ? _preCrashRecorderPrefab : _recorderPrefab);
var detailInfo = new PropModule.DetailInfo { var detailInfo = new PropModule.DetailInfo {
parentPath = info.parentPath, parentPath = info.parentPath,
rotation = info.rotation, rotation = info.rotation,
@ -518,7 +518,7 @@ namespace NewHorizons.Builder.Props
conversationInfoToCorrespondingSpawnedGameObject[info] = recorderObject; conversationInfoToCorrespondingSpawnedGameObject[info] = recorderObject;
return recorderObject; return recorderObject;
} }
case PropModule.NomaiTextInfo.NomaiTextType.Trailmarker: case PropModule.NomaiTextType.Trailmarker:
{ {
var trailmarkerObject = _trailmarkerPrefab.InstantiateInactive(); var trailmarkerObject = _trailmarkerPrefab.InstantiateInactive();

View File

@ -195,7 +195,7 @@ namespace NewHorizons.Builder.Props
{ {
var textInfo = info.nomaiText[i]; var textInfo = info.nomaiText[i];
component._remoteIDs[i] = RemoteHandler.GetPlatformID(textInfo.id); component._remoteIDs[i] = RemoteHandler.GetPlatformID(textInfo.id);
var wallText = TranslatorTextBuilder.Make(whiteboard, sector, new PropModule.NomaiTextInfo var wallText = TranslatorTextBuilder.Make(whiteboard, sector, new PropModule.TranslatorTextInfo
{ {
arcInfo = textInfo.arcInfo, arcInfo = textInfo.arcInfo,
location = textInfo.location, location = textInfo.location,
@ -204,7 +204,7 @@ namespace NewHorizons.Builder.Props
rename = textInfo.rename, rename = textInfo.rename,
rotation = Vector3.zero, rotation = Vector3.zero,
seed = textInfo.seed, seed = textInfo.seed,
type = PropModule.NomaiTextInfo.NomaiTextType.Wall, type = PropModule.NomaiTextType.Wall,
xmlFile = textInfo.xmlFile xmlFile = textInfo.xmlFile
}, nhBody).GetComponent<NomaiWallText>(); }, nhBody).GetComponent<NomaiWallText>();
wallText._showTextOnStart = false; wallText._showTextOnStart = false;

View File

@ -100,7 +100,7 @@ namespace NewHorizons.Builder.Props
private static void MakeTornado(GameObject planetGO, Sector sector, PropModule.TornadoInfo info, Vector3 position, bool downwards) private static void MakeTornado(GameObject planetGO, Sector sector, PropModule.TornadoInfo info, Vector3 position, bool downwards)
{ {
var prefab = downwards ? _downPrefab.InstantiateInactive() : _upPrefab.InstantiateInactive(); var prefab = downwards ? _downPrefab.InstantiateInactive() : _upPrefab.InstantiateInactive();
var tornadoGO = GeneralPropBuilder.MakeFromPrefab(prefab, downwards ? "Tornado_Down" : "Tornado_Up", planetGO, sector, info, true, defaultPosition: position); var tornadoGO = GeneralPropBuilder.MakeFromPrefab(prefab, downwards ? "Tornado_Down" : "Tornado_Up", planetGO, sector, info, defaultPosition: position);
// Add the sound thing before changing the scale // Add the sound thing before changing the scale
var soundGO = _soundPrefab.InstantiateInactive(); var soundGO = _soundPrefab.InstantiateInactive();

View File

@ -37,9 +37,9 @@ namespace NewHorizons.Builder.Props
return arcInfoToCorrespondingSpawnedGameObject[arc]; return arcInfoToCorrespondingSpawnedGameObject[arc];
} }
private static Dictionary<PropModule.NomaiTextInfo, GameObject> conversationInfoToCorrespondingSpawnedGameObject = new Dictionary<PropModule.NomaiTextInfo, GameObject>(); private static Dictionary<PropModule.TranslatorTextInfo, GameObject> conversationInfoToCorrespondingSpawnedGameObject = new Dictionary<PropModule.TranslatorTextInfo, GameObject>();
public static GameObject GetSpawnedGameObjectByNomaiTextInfo(PropModule.NomaiTextInfo convo) public static GameObject GetSpawnedGameObjectByTranslatorTextInfo(PropModule.TranslatorTextInfo convo)
{ {
Logger.LogVerbose("Retrieving wall text obj for " + convo); Logger.LogVerbose("Retrieving wall text obj for " + convo);
if (!conversationInfoToCorrespondingSpawnedGameObject.ContainsKey(convo)) return null; if (!conversationInfoToCorrespondingSpawnedGameObject.ContainsKey(convo)) return null;
@ -120,7 +120,7 @@ namespace NewHorizons.Builder.Props
} }
} }
public static GameObject Make(GameObject planetGO, Sector sector, PropModule.NomaiTextInfo info, NewHorizonsBody nhBody) public static GameObject Make(GameObject planetGO, Sector sector, PropModule.TranslatorTextInfo info, NewHorizonsBody nhBody)
{ {
InitPrefabs(); InitPrefabs();
@ -128,31 +128,22 @@ namespace NewHorizons.Builder.Props
switch (info.type) switch (info.type)
{ {
case PropModule.NomaiTextInfo.NomaiTextType.Wall: case PropModule.NomaiTextType.Wall:
{ {
var nomaiWallTextObj = MakeWallText(planetGO, sector, info, xmlPath, nhBody).gameObject; var nomaiWallTextObj = MakeWallText(planetGO, sector, info, xmlPath, nhBody).gameObject;
nomaiWallTextObj = GeneralPropBuilder.MakeFromExisting(nomaiWallTextObj, planetGO, sector, info); nomaiWallTextObj = GeneralPropBuilder.MakeFromExisting(nomaiWallTextObj, planetGO, sector, info);
// using GeneralPropBuilder normal here does not work so have to do it manually
if (info.normal != null) if (info.normal != null)
{ {
// In global coordinates (normal was in local coordinates)
var up = (nomaiWallTextObj.transform.position - planetGO.transform.position).normalized; var up = (nomaiWallTextObj.transform.position - planetGO.transform.position).normalized;
var forward = planetGO.transform.TransformDirection(info.normal).normalized; var forward = planetGO.transform.TransformDirection(info.normal).normalized;
if (info.isRelativeToParent)
{
nomaiWallTextObj.transform.up = up;
nomaiWallTextObj.transform.forward = forward;
} else
{
nomaiWallTextObj.transform.forward = forward; nomaiWallTextObj.transform.forward = forward;
var desiredUp = Vector3.ProjectOnPlane(up, forward); var desiredUp = Vector3.ProjectOnPlane(up, forward);
var zRotation = Vector3.SignedAngle(nomaiWallTextObj.transform.up, desiredUp, forward); var zRotation = Vector3.SignedAngle(nomaiWallTextObj.transform.up, desiredUp, forward);
nomaiWallTextObj.transform.RotateAround(nomaiWallTextObj.transform.position, forward, zRotation); nomaiWallTextObj.transform.RotateAround(nomaiWallTextObj.transform.position, forward, zRotation);
} }
}
// nomaiWallTextObj.GetComponent<NomaiTextArcArranger>().DrawBoundsWithDebugSpheres(); // nomaiWallTextObj.GetComponent<NomaiTextArcArranger>().DrawBoundsWithDebugSpheres();
@ -161,9 +152,9 @@ namespace NewHorizons.Builder.Props
return nomaiWallTextObj; return nomaiWallTextObj;
} }
case PropModule.NomaiTextInfo.NomaiTextType.Scroll: case PropModule.NomaiTextType.Scroll:
{ {
var customScroll = GeneralPropBuilder.MakeFromPrefab(_scrollPrefab, _scrollPrefab.name, planetGO, sector, info, alignToBody: info.rotation == null); var customScroll = GeneralPropBuilder.MakeFromPrefab(_scrollPrefab, _scrollPrefab.name, planetGO, sector, info);
var nomaiWallText = MakeWallText(planetGO, sector, info, xmlPath, nhBody); var nomaiWallText = MakeWallText(planetGO, sector, info, xmlPath, nhBody);
nomaiWallText.transform.parent = customScroll.transform; nomaiWallText.transform.parent = customScroll.transform;
@ -213,9 +204,9 @@ namespace NewHorizons.Builder.Props
return customScroll; return customScroll;
} }
case PropModule.NomaiTextInfo.NomaiTextType.Computer: case PropModule.NomaiTextType.Computer:
{ {
var computerObject = GeneralPropBuilder.MakeFromPrefab(_computerPrefab, _computerPrefab.name, planetGO, sector, info, alignToBody: true, normal: info.normal); var computerObject = GeneralPropBuilder.MakeFromPrefab(_computerPrefab, _computerPrefab.name, planetGO, sector, info);
var computer = computerObject.GetComponent<NomaiComputer>(); var computer = computerObject.GetComponent<NomaiComputer>();
computer.SetSector(sector); computer.SetSector(sector);
@ -234,22 +225,20 @@ namespace NewHorizons.Builder.Props
return computerObject; return computerObject;
} }
case PropModule.NomaiTextInfo.NomaiTextType.PreCrashComputer: case PropModule.NomaiTextType.PreCrashComputer:
{ {
var detailInfo = new PropModule.DetailInfo() var detailInfo = new PropModule.DetailInfo()
{ {
position = info.position, position = info.position,
rotation = info.rotation,
parentPath = info.parentPath, parentPath = info.parentPath,
isRelativeToParent = info.isRelativeToParent, isRelativeToParent = info.isRelativeToParent,
alignRadial = info.alignRadial,
rename = info.rename rename = info.rename
}; };
var computerObject = DetailBuilder.Make(planetGO, sector, _preCrashComputerPrefab, detailInfo); var computerObject = DetailBuilder.Make(planetGO, sector, _preCrashComputerPrefab, detailInfo);
computerObject.SetActive(false); computerObject.SetActive(false);
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;
var computer = computerObject.GetComponent<NomaiVesselComputer>(); var computer = computerObject.GetComponent<NomaiVesselComputer>();
computer.SetSector(sector); computer.SetSector(sector);
@ -284,11 +273,11 @@ namespace NewHorizons.Builder.Props
return computerObject; return computerObject;
} }
case PropModule.NomaiTextInfo.NomaiTextType.Cairn: case PropModule.NomaiTextType.Cairn:
case PropModule.NomaiTextInfo.NomaiTextType.CairnVariant: case PropModule.NomaiTextType.CairnVariant:
{ {
var cairnPrefab = info.type == PropModule.NomaiTextInfo.NomaiTextType.CairnVariant ? _cairnVariantPrefab : _cairnPrefab; var cairnPrefab = info.type == PropModule.NomaiTextType.CairnVariant ? _cairnVariantPrefab : _cairnPrefab;
var cairnObject = GeneralPropBuilder.MakeFromPrefab(cairnPrefab, _cairnPrefab.name, planetGO, sector, info, alignToBody: info.rotation == null); var cairnObject = GeneralPropBuilder.MakeFromPrefab(cairnPrefab, _cairnPrefab.name, planetGO, sector, info);
// Idk do we have to set it active before finding things? // Idk do we have to set it active before finding things?
cairnObject.SetActive(true); cairnObject.SetActive(true);
@ -319,17 +308,17 @@ namespace NewHorizons.Builder.Props
return cairnObject; return cairnObject;
} }
case PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder: case PropModule.NomaiTextType.PreCrashRecorder:
case PropModule.NomaiTextInfo.NomaiTextType.Recorder: case PropModule.NomaiTextType.Recorder:
{ {
var prefab = (info.type == PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder ? _preCrashRecorderPrefab : _recorderPrefab); var prefab = (info.type == PropModule.NomaiTextType.PreCrashRecorder ? _preCrashRecorderPrefab : _recorderPrefab);
var detailInfo = new PropModule.DetailInfo { var detailInfo = new PropModule.DetailInfo {
parentPath = info.parentPath, parentPath = info.parentPath,
rotation = info.rotation, rotation = info.rotation,
position = info.position, position = info.position,
isRelativeToParent = info.isRelativeToParent, isRelativeToParent = info.isRelativeToParent,
rename = info.rename, rename = info.rename,
alignToNormal = info.rotation == null, alignRadial = info.alignRadial,
}; };
var recorderObject = DetailBuilder.Make(planetGO, sector, prefab, detailInfo); var recorderObject = DetailBuilder.Make(planetGO, sector, prefab, detailInfo);
recorderObject.SetActive(false); recorderObject.SetActive(false);
@ -349,9 +338,9 @@ namespace NewHorizons.Builder.Props
conversationInfoToCorrespondingSpawnedGameObject[info] = recorderObject; conversationInfoToCorrespondingSpawnedGameObject[info] = recorderObject;
return recorderObject; return recorderObject;
} }
case PropModule.NomaiTextInfo.NomaiTextType.Trailmarker: case PropModule.NomaiTextType.Trailmarker:
{ {
var trailmarkerObject = GeneralPropBuilder.MakeFromPrefab(_trailmarkerPrefab, _trailmarkerPrefab.name, planetGO, sector, info, alignToBody: info.rotation == null); var trailmarkerObject = GeneralPropBuilder.MakeFromPrefab(_trailmarkerPrefab, _trailmarkerPrefab.name, planetGO, sector, info);
// shrink because that is what mobius does on all trailmarkers or else they are the size of the player // 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; trailmarkerObject.transform.localScale = Vector3.one * 0.75f;
@ -380,7 +369,7 @@ namespace NewHorizons.Builder.Props
} }
} }
private static NomaiWallText MakeWallText(GameObject go, Sector sector, PropModule.NomaiTextInfo info, string xmlPath, NewHorizonsBody nhBody) private static NomaiWallText MakeWallText(GameObject go, Sector sector, PropModule.TranslatorTextInfo info, string xmlPath, NewHorizonsBody nhBody)
{ {
GameObject nomaiWallTextObj = new GameObject("NomaiWallText"); GameObject nomaiWallTextObj = new GameObject("NomaiWallText");
nomaiWallTextObj.SetActive(false); nomaiWallTextObj.SetActive(false);
@ -417,7 +406,7 @@ namespace NewHorizons.Builder.Props
return nomaiWallText; return nomaiWallText;
} }
internal static void BuildArcs(string xml, NomaiWallText nomaiWallText, GameObject conversationZone, PropModule.NomaiTextInfo info, NewHorizonsBody nhBody) internal static void BuildArcs(string xml, NomaiWallText nomaiWallText, GameObject conversationZone, PropModule.TranslatorTextInfo info, NewHorizonsBody nhBody)
{ {
var dict = MakeNomaiTextDict(xml); var dict = MakeNomaiTextDict(xml);
@ -437,7 +426,7 @@ namespace NewHorizons.Builder.Props
public bool mirrored; public bool mirrored;
} }
internal static void RefreshArcs(NomaiWallText nomaiWallText, GameObject conversationZone, PropModule.NomaiTextInfo info, NewHorizonsBody nhBody, string cacheKey) internal static void RefreshArcs(NomaiWallText nomaiWallText, GameObject conversationZone, PropModule.TranslatorTextInfo info, NewHorizonsBody nhBody, string cacheKey)
{ {
var dict = nomaiWallText._dictNomaiTextData; var dict = nomaiWallText._dictNomaiTextData;
Random.InitState(info.seed == 0 ? info.xmlFile.GetHashCode() : info.seed); Random.InitState(info.seed == 0 ? info.xmlFile.GetHashCode() : info.seed);
@ -451,8 +440,8 @@ namespace NewHorizons.Builder.Props
} }
ArcCacheData[] cachedData = null; ArcCacheData[] cachedData = null;
if (nhBody.Cache?.ContainsKey(cacheKey) ?? false) //if (nhBody.Cache?.ContainsKey(cacheKey) ?? false)
cachedData = nhBody.Cache.Get<ArcCacheData[]>(cacheKey); // cachedData = nhBody.Cache.Get<ArcCacheData[]>(cacheKey);
var arranger = nomaiWallText.gameObject.AddComponent<NomaiTextArcArranger>(); var arranger = nomaiWallText.gameObject.AddComponent<NomaiTextArcArranger>();

View File

@ -46,7 +46,7 @@ namespace NewHorizons.Builder.Props
{ {
InitPrefab(); InitPrefab();
var launcherGO = GeneralPropBuilder.MakeFromPrefab(_meteorLauncherPrefab, "MeteorLauncher", planetGO, sector, info, alignToBody: true); var launcherGO = GeneralPropBuilder.MakeFromPrefab(_meteorLauncherPrefab, "MeteorLauncher", planetGO, sector, info);
var meteorLauncher = launcherGO.GetComponent<MeteorLauncher>(); var meteorLauncher = launcherGO.GetComponent<MeteorLauncher>();
meteorLauncher._audioSector = sector; meteorLauncher._audioSector = sector;

View File

@ -487,7 +487,7 @@ namespace NewHorizons.External.Configs
} }
// Remote dialogue trigger reorganized to use GeneralPointPropInfo // Remote dialogue trigger reorganized to use GeneralPointPropInfo
if (Props != null && Props.dialogue != null) if (Props?.dialogue != null)
{ {
foreach (var dialogue in Props.dialogue) foreach (var dialogue in Props.dialogue)
{ {
@ -502,6 +502,66 @@ namespace NewHorizons.External.Configs
} }
} }
} }
// alignRadial added to all props with rotation; default behavior varies
if (Spawn?.playerSpawn != null && Spawn.playerSpawn.rotation == null && !Spawn.playerSpawn.alignRadial.HasValue)
{
Spawn.playerSpawn.alignRadial = true;
}
if (Spawn?.shipSpawn != null && Spawn.shipSpawn.rotation == null && !Spawn.shipSpawn.alignRadial.HasValue)
{
Spawn.playerSpawn.alignRadial = true;
}
if (Props?.details != null)
{
foreach (var detail in Props.details)
{
if (!detail.alignRadial.HasValue)
{
detail.alignRadial = detail.alignToNormal;
}
}
}
if (Props?.proxyDetails != null)
{
foreach (var detail in Props.proxyDetails)
{
if (!detail.alignRadial.HasValue)
{
detail.alignRadial = detail.alignToNormal;
}
}
}
if (Props?.geysers != null)
{
foreach (var geyser in Props.geysers)
{
if (!geyser.alignRadial.HasValue && geyser.rotation == null)
{
geyser.alignRadial = true;
}
}
}
if (Props?.tornados != null)
{
foreach (var tornado in Props.tornados)
{
if (!tornado.alignRadial.HasValue && tornado.rotation == null)
{
tornado.alignRadial = true;
}
}
}
if (Props?.volcanoes != null)
{
foreach (var volcano in Props.volcanoes)
{
if (!volcano.alignRadial.HasValue && volcano.rotation == null)
{
volcano.alignRadial = true;
}
}
}
} }
} }
} }

View File

@ -35,6 +35,12 @@ namespace NewHorizons.External.Modules
/// Rotation of the object /// Rotation of the object
/// </summary> /// </summary>
public MVector3 rotation; public MVector3 rotation;
/// <summary>
/// Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.
/// Defaults to true for geysers, tornados, and volcanoes, and false for everything else.
/// </summary>
public bool? alignRadial;
} }
[JsonObject] [JsonObject]

View File

@ -42,7 +42,7 @@ namespace NewHorizons.External.Modules
/// <summary> /// <summary>
/// Add translatable text to this planet /// Add translatable text to this planet
/// </summary> /// </summary>
public NomaiTextInfo[] translatorText; public TranslatorTextInfo[] translatorText;
/// <summary> /// <summary>
/// Details which will be shown from 50km away. Meant to be lower resolution. /// Details which will be shown from 50km away. Meant to be lower resolution.
@ -165,12 +165,6 @@ namespace NewHorizons.External.Modules
[JsonObject] [JsonObject]
public class DetailInfo : GeneralPropInfo public class DetailInfo : GeneralPropInfo
{ {
/// <summary>
/// Do we override rotation and try to automatically align this object to stand upright on the body's surface?
/// </summary>
public bool alignToNormal;
/// <summary> /// <summary>
/// Relative filepath to an asset-bundle to load the prefab defined in `path` from /// Relative filepath to an asset-bundle to load the prefab defined in `path` from
/// </summary> /// </summary>
@ -229,10 +223,12 @@ namespace NewHorizons.External.Modules
/// If there's already good colliders on the detail, you can make this 0. /// If there's already good colliders on the detail, you can make this 0.
/// </summary> /// </summary>
[DefaultValue(1f)] public float physicsRadius = 1f; [DefaultValue(1f)] public float physicsRadius = 1f;
[Obsolete("alignToNormal is deprecated. Use alignRadial instead")] public bool alignToNormal;
} }
[JsonObject] [JsonObject]
public class RaftInfo : GeneralPointPropInfo public class RaftInfo : GeneralPropInfo
{ {
/// <summary> /// <summary>
/// Acceleration of the raft. Default acceleration is 5. /// Acceleration of the raft. Default acceleration is 5.
@ -241,7 +237,7 @@ namespace NewHorizons.External.Modules
} }
[JsonObject] [JsonObject]
public class GeyserInfo : GeneralPointPropInfo public class GeyserInfo : GeneralPropInfo
{ {
/// <summary> /// <summary>
/// Vertical offset of the geyser. From 0, the bubbles start at a height of 10, the shaft at 67, and the spout at 97.5. /// Vertical offset of the geyser. From 0, the bubbles start at a height of 10, the shaft at 67, and the spout at 97.5.
@ -280,7 +276,7 @@ namespace NewHorizons.External.Modules
} }
[JsonObject] [JsonObject]
public class TornadoInfo : GeneralPointPropInfo public class TornadoInfo : GeneralPropInfo
{ {
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
public enum TornadoType public enum TornadoType
@ -342,7 +338,7 @@ namespace NewHorizons.External.Modules
} }
[JsonObject] [JsonObject]
public class VolcanoInfo : GeneralPointPropInfo public class VolcanoInfo : GeneralPropInfo
{ {
/// <summary> /// <summary>
/// The colour of the meteor's lava. /// The colour of the meteor's lava.
@ -474,8 +470,39 @@ namespace NewHorizons.External.Modules
} }
[JsonObject] [JsonObject]
public class NomaiTextInfo : GeneralPointPropInfo public class TranslatorTextInfo : GeneralPropInfo
{ {
/// <summary>
/// Additional information about each arc in the text
/// </summary>
public NomaiTextArcInfo[] arcInfo;
/// <summary>
/// The random seed used to pick what the text arcs will look like.
/// </summary>
public int seed;
/// <summary>
/// Only for wall text. Aligns wall text to face towards the given direction, with 'up' oriented relative to its current rotation or alignment.
/// </summary>
public MVector3 normal;
/// <summary>
/// The type of object this is.
/// </summary>
[DefaultValue("wall")] public NomaiTextType type = NomaiTextType.Wall;
/// <summary>
/// The location of this object. Arcs will be blue if their locations match the wall, else orange.
/// </summary>
[DefaultValue("unspecified")] public NomaiTextLocation location = NomaiTextLocation.UNSPECIFIED;
/// <summary>
/// The relative path to the xml file for this object.
/// </summary>
public string xmlFile;
}
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
public enum NomaiTextType public enum NomaiTextType
{ {
@ -508,6 +535,10 @@ namespace NewHorizons.External.Modules
[EnumMember(Value = @"b")] B = 2 [EnumMember(Value = @"b")] B = 2
} }
[JsonObject]
public class NomaiTextInfo : GeneralPointPropInfo
{
/// <summary> /// <summary>
/// Additional information about each arc in the text /// Additional information about each arc in the text
/// </summary> /// </summary>
@ -827,7 +858,7 @@ namespace NewHorizons.External.Modules
/// <summary> /// <summary>
/// The location of this object. Arcs will be blue if their locations match the wall, else orange. /// The location of this object. Arcs will be blue if their locations match the wall, else orange.
/// </summary> /// </summary>
[DefaultValue("unspecified")] public NomaiTextInfo.NomaiTextLocation location = NomaiTextInfo.NomaiTextLocation.UNSPECIFIED; [DefaultValue("unspecified")] public NomaiTextLocation location = NomaiTextLocation.UNSPECIFIED;
/// <summary> /// <summary>
/// The relative path to the xml file for this object. /// The relative path to the xml file for this object.

View File

@ -155,14 +155,14 @@ namespace NewHorizons
} }
public GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles, public GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles,
float scale, bool alignWithNormal) float scale, bool alignRadial)
{ {
var prefab = SearchUtilities.Find(propToCopyPath); var prefab = SearchUtilities.Find(propToCopyPath);
var detailInfo = new PropModule.DetailInfo() { var detailInfo = new PropModule.DetailInfo() {
position = position, position = position,
rotation = eulerAngles, rotation = eulerAngles,
scale = scale, scale = scale,
alignToNormal = alignWithNormal alignRadial = alignRadial
}; };
return DetailBuilder.Make(planet, sector, prefab, detailInfo); return DetailBuilder.Make(planet, sector, prefab, detailInfo);
} }

View File

@ -273,7 +273,7 @@ namespace NewHorizons.Utility.DebugUtilities
// So we can't use local position/rotation here, we have to inverse transform the global position/rotation relative to root object // So we can't use local position/rotation here, we have to inverse transform the global position/rotation relative to root object
prop.detailInfo.position = rootTransform.InverseTransformPoint(prop.gameObject.transform.position); prop.detailInfo.position = rootTransform.InverseTransformPoint(prop.gameObject.transform.position);
prop.detailInfo.scale = prop.gameObject.transform.localScale.x; prop.detailInfo.scale = prop.gameObject.transform.localScale.x;
if (!prop.detailInfo.alignToNormal) prop.detailInfo.rotation = rootTransform.InverseTransformRotation(prop.gameObject.transform.rotation).eulerAngles; if (!prop.detailInfo.alignRadial.GetValueOrDefault()) prop.detailInfo.rotation = rootTransform.InverseTransformRotation(prop.gameObject.transform.rotation).eulerAngles;
infoArray[i] = prop.detailInfo; infoArray[i] = prop.detailInfo;
} }