From d35325eb69e23eccc94c7e8bea015e402be8e885 Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 3 May 2022 17:45:43 -0400 Subject: [PATCH] Scrolls work - The text wall is visible on the scroll on the ground - Text still isn't positioned nicely --- NewHorizons/Builder/Props/NomaiTextBuilder.cs | 185 ++++++++++++------ NewHorizons/External/PropModule.cs | 2 + NewHorizons/Tools/Patches.cs | 58 ++++++ NewHorizons/Utility/DebugRaycaster.cs | 7 +- 4 files changed, 190 insertions(+), 62 deletions(-) diff --git a/NewHorizons/Builder/Props/NomaiTextBuilder.cs b/NewHorizons/Builder/Props/NomaiTextBuilder.cs index d081014b..a146635a 100644 --- a/NewHorizons/Builder/Props/NomaiTextBuilder.cs +++ b/NewHorizons/Builder/Props/NomaiTextBuilder.cs @@ -1,5 +1,6 @@ using NewHorizons.External; using NewHorizons.Handlers; +using NewHorizons.Utility; using OWML.Common; using System; using System.Collections.Generic; @@ -14,110 +15,172 @@ namespace NewHorizons.Builder.Props { public static class NomaiTextBuilder { + private static GameObject _arcPrefab; + private static GameObject _scrollPrefab; + //TODO Scrolls public static void Make(GameObject go, Sector sector, PropModule.NomaiTextInfo info, IModBehaviour mod) { + if (_arcPrefab == null) + { + _arcPrefab = GameObject.Find("TimberHearth_Body/Sector_TH/Sector_Village/Sector_Observatory/Interactables_Observatory/NomaiEyeExhibit/NomaiEyePivot/Arc_TH_Museum_EyeSymbol/Arc 1").InstantiateInactive(); + _arcPrefab.name = "Arc"; + } + if (_scrollPrefab == null) + { + _scrollPrefab = GameObject.Find("BrittleHollow_Body/Sector_BH/Sector_NorthHemisphere/Sector_NorthPole/Sector_HangingCity/Sector_HangingCity_District2/Interactables_HangingCity_District2/Prefab_NOM_Scroll").InstantiateInactive(); + _scrollPrefab.name = "Prefab_NOM_Scroll"; + } - GameObject conversationZone = new GameObject("ConversationZone"); - conversationZone.SetActive(false); - conversationZone.name = "NomaiText"; + if (info.type == "wall") + { + var nomaiWallTextObj = MakeWallText(go, sector, info, mod).gameObject; + nomaiWallTextObj.transform.parent = sector?.transform ?? go.transform; + nomaiWallTextObj.transform.localPosition = info.position; + nomaiWallTextObj.transform.localRotation = Quaternion.FromToRotation(Vector3.up, info.normal ?? Vector3.forward); + + nomaiWallTextObj.SetActive(true); + } + else if (info.type == "scroll") + { + var customScroll = _scrollPrefab.InstantiateInactive(); + + var nomaiWallText = MakeWallText(go, sector, info, mod); + nomaiWallText.transform.parent = customScroll.transform; + nomaiWallText.transform.localPosition = Vector3.zero; + nomaiWallText.transform.localRotation = Quaternion.identity; + + // Don't want to be able to translate until its in a socket + nomaiWallText.GetComponent().enabled = false; + + nomaiWallText.gameObject.SetActive(true); + + var scrollItem = customScroll.GetComponent(); + + // Idk why this thing is always around + GameObject.Destroy(customScroll.transform.Find("Arc_BH_City_Forum_2").gameObject); + + // This variable is the bane of my existence i dont get it + scrollItem._nomaiWallText = nomaiWallText; + + // Because the scroll was already awake it does weird shit in Awake and makes some of the entries in this array be null + scrollItem._colliders = new OWCollider[] { scrollItem.GetComponent() }; + + // Else when you put them down you can't pick them back up + customScroll.GetComponent()._physicsRemoved = false; + + // Place scroll + customScroll.transform.parent = sector?.transform ?? go.transform; + customScroll.transform.localPosition = info.position ?? Vector3.zero; + + var up = customScroll.transform.localPosition.normalized; + customScroll.transform.rotation = Quaternion.FromToRotation(customScroll.transform.up, up) * customScroll.transform.rotation; + + customScroll.SetActive(true); + + // Enable the collider and renderer + Main.Instance.ModHelper.Events.Unity.RunWhen( + () => Main.IsSystemReady, + () => + { + Logger.Log("Fixing scroll!"); + scrollItem._nomaiWallText = nomaiWallText; + scrollItem.SetSector(sector); + customScroll.transform.Find("Props_NOM_Scroll/Props_NOM_Scroll_Geo").GetComponent().enabled = true; + customScroll.transform.Find("Props_NOM_Scroll/Props_NOM_Scroll_Collider").gameObject.SetActive(true); + nomaiWallText.gameObject.GetComponent().enabled = false; + customScroll.GetComponent().enabled = true; + } + ); + } + else + { + Logger.LogError($"Unsupported NomaiText type {info.type}"); + } + } + + private static NomaiWallText MakeWallText(GameObject go, Sector sector, PropModule.NomaiTextInfo info, IModBehaviour mod) + { + GameObject nomaiWallTextObj = new GameObject("NomaiWallText"); + nomaiWallTextObj.SetActive(false); + + // TODO better bounds + var box = nomaiWallTextObj.AddComponent(); + box.center = new Vector3(-0.0643f, 1.1254f, 0f); + box.size = new Vector3(6.1424f, 5.2508f, 0.5f); - var box = conversationZone.AddComponent(); - //TODO better bounds - box.size = new Vector3(3f, 6f, 1f); box.isTrigger = true; - conversationZone.AddComponent(); - var NomaiWall = conversationZone.AddComponent(); - + nomaiWallTextObj.AddComponent(); + var nomaiWallText = nomaiWallTextObj.AddComponent(); var xml = System.IO.File.ReadAllText(mod.ModHelper.Manifest.ModFolderPath + info.xmlFile); var text = new TextAsset(xml); - NomaiWall._dictNomaiTextData = new Dictionary(ComparerLibrary.intEqComparer); - NomaiWall._nomaiTextAsset = text; + nomaiWallText._dictNomaiTextData = new Dictionary(ComparerLibrary.intEqComparer); + nomaiWallText._nomaiTextAsset = text; - conversationZone.transform.parent = sector?.transform ?? go.transform; - conversationZone.transform.localPosition = info.position; + BuildArcs(xml, nomaiWallText, nomaiWallTextObj); + AddTranslation(xml); - buildArcs(xml, NomaiWall, conversationZone); - NomaiWall.SetTextAsset(text); - - - conversationZone.SetActive(true); + nomaiWallText.SetTextAsset(text); + return nomaiWallText; } - public static void buildArcs(string xml, NomaiWallText nomai, GameObject conversationZone) + private static void BuildArcs(string xml, NomaiWallText nomai, GameObject conversationZone) { XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(xml); XmlNode rootNode = xmlDocument.SelectSingleNode("NomaiObject"); - + var i = 1; foreach (object obj in rootNode.SelectNodes("TextBlock")) { XmlNode xmlNode = (XmlNode)obj; - int num = -1; + int textEntryID = -1; XmlNode xmlNode2 = xmlNode.SelectSingleNode("ID"); XmlNode textNode = xmlNode.SelectSingleNode("Text"); XmlNode xmlNode3 = xmlNode.SelectSingleNode("ParentID"); int parentID = -1; - if (xmlNode2 != null && !int.TryParse(xmlNode2.InnerText, out num)) + if (xmlNode2 != null && !int.TryParse(xmlNode2.InnerText, out textEntryID)) { - num = -1; + textEntryID = -1; } if (xmlNode3 != null && !int.TryParse(xmlNode3.InnerText, out parentID)) { parentID = -1; } - //TODO translation table - //TODO verify shiplogs - NomaiText.NomaiTextData value = new NomaiText.NomaiTextData(num, parentID, textNode, false, NomaiText.Location.UNSPECIFIED); - nomai._dictNomaiTextData.Add(num, value); - GameObject Arc = new GameObject($"Arc {num}"); - Arc.SetActive(false); - var textLine = Arc.AddComponent(); - textLine.SetEntryID(num); + NomaiText.NomaiTextData value = new NomaiText.NomaiTextData(textEntryID, parentID, textNode, false, NomaiText.Location.UNSPECIFIED); + nomai._dictNomaiTextData.Add(textEntryID, value); - Arc.transform.parent = conversationZone.transform; - - //TODO Modify so spirals are connected - Vector3 center = new Vector3(Mathf.Sin((num * 90 * Mathf.PI) / 180), Mathf.Cos((num * 90 * Mathf.PI) / 180), 0); - Arc.transform.localPosition = center; - //TODO fix centering - textLine._center = center; - textLine._radius = 1; - - textLine.SetPoints(makePoints(5, num)); - - //TODO pull assets directly instead of ripping off existing text - GameObject copiedArc = GameObject.Find("TimberHearth_Body/Sector_TH/Sector_Village/Sector_Observatory/Interactables_Observatory/NomaiEyeExhibit/NomaiEyePivot/Arc_TH_Museum_EyeSymbol/Arc 1"); - - MeshFilter meshFilter = Arc.AddComponent(); - meshFilter.sharedMesh = copiedArc.GetComponent().sharedMesh; - - - MeshRenderer meshRenderer = Arc.AddComponent(); - meshRenderer.materials = copiedArc.GetComponent().materials; - Arc.SetActive(true); + var arc = _arcPrefab.InstantiateInactive(); + arc.name = $"Arc {i++}"; + arc.transform.parent = conversationZone.transform; + arc.transform.localPosition = Vector3.zero; + arc.transform.LookAt(Vector3.forward); + arc.GetComponent().SetEntryID(textEntryID); + arc.GetComponent().enabled = false; + arc.SetActive(true); } - } - - private static Vector3[] makePoints(int length, int num) + private static void AddTranslation(string xml) { - Vector3[] array = new Vector3[length]; - for (int i = 0; i < length; i++) - { - //TODO figure out an actual formula - array[i] = new Vector3((i + num + 1) / 50F, (i + num + 1) / 10F, 0); + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(xml); + XmlNode xmlNode = xmlDocument.SelectSingleNode("NomaiObject"); + XmlNodeList xmlNodeList = xmlNode.SelectNodes("TextBlock"); + + foreach (object obj in xmlNodeList) + { + XmlNode xmlNode2 = (XmlNode)obj; + var text = xmlNode2.SelectSingleNode("Text").InnerText; + TranslationHandler.AddDialogue(text); } - return array; } } } diff --git a/NewHorizons/External/PropModule.cs b/NewHorizons/External/PropModule.cs index 956273da..474e50c9 100644 --- a/NewHorizons/External/PropModule.cs +++ b/NewHorizons/External/PropModule.cs @@ -106,6 +106,8 @@ namespace NewHorizons.External public class NomaiTextInfo { public MVector3 position; + public MVector3 normal; + public string type = "wall"; public string xmlFile; } diff --git a/NewHorizons/Tools/Patches.cs b/NewHorizons/Tools/Patches.cs index 4fd7ad9a..25a653a2 100644 --- a/NewHorizons/Tools/Patches.cs +++ b/NewHorizons/Tools/Patches.cs @@ -76,6 +76,8 @@ namespace NewHorizons.Tools // Postfixes Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Awake", typeof(Patches), nameof(Patches.OnMapControllerAwake)); Main.Instance.ModHelper.HarmonyHelper.AddPostfix("OnTargetReferenceFrame", typeof(Patches), nameof(Patches.OnMapControllerOnTargetReferenceFrame)); + + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Awake", typeof(Patches), nameof(Patches.OnScrollItemAwake)); } public static bool CheckShipOutersideSolarSystem(PlayerState __instance, ref bool __result) @@ -497,5 +499,61 @@ namespace NewHorizons.Tools { return Locator._cloakFieldController == null; } + + public static bool OnScrollItemAwake(ScrollItem __instance) + { + try + { + __instance._type = ItemType.Scroll; + __instance._nomaiWallText = __instance.GetComponentInChildren(); + if (__instance._nomaiWallText == null) + { + Logger.LogError("No NomaiWallText found!"); + return false; + } + __instance._nomaiWallText.InitializeAsWhiteboardText(); + + // base.awake + //base.awake + if (__instance._sector == null) + { + __instance._sector = __instance.GetComponentInParent(); + } + if (__instance._sector != null) + { + __instance._sector.OnOccupantEnterSector += __instance.OnSectorOccupantAdded; + __instance._sector.OnOccupantExitSector += __instance.OnSectorOccupantRemoved; + __instance._sector.OnSectorOccupantsUpdated += __instance.OnSectorOccupantsUpdated; + } + // back + + if (!__instance._prebuilt) + { + __instance.FindComponentsInHierarchy(); + } + __instance._parentFragment = __instance.GetComponentInParent(); + if (__instance._parentFragment != null) + { + __instance._parentFragment.OnChangeSector += __instance.OnParentFragmentChangeSector; + } + GlobalMessenger.AddListener("EnterMapView", new Callback(__instance.OnEnterMapView)); + GlobalMessenger.AddListener("ExitMapView", new Callback(__instance.OnExitMapView)); + + // Back to normal stuff + for (int i = 0; i < __instance._colliders.Length; i++) + { + if (__instance._colliders[i].GetComponent() != null) + { + __instance._colliders[i] = null; + } + } + return false; + } + catch(Exception e) + { + Logger.LogError($"{e.Message}, {e.StackTrace}"); + } + return false; + } } } diff --git a/NewHorizons/Utility/DebugRaycaster.cs b/NewHorizons/Utility/DebugRaycaster.cs index ce398b65..30524f46 100644 --- a/NewHorizons/Utility/DebugRaycaster.cs +++ b/NewHorizons/Utility/DebugRaycaster.cs @@ -32,8 +32,13 @@ namespace NewHorizons.Utility if (Physics.Raycast(origin, direction, out RaycastHit hitInfo, 100f, layerMask)) { var pos = hitInfo.transform.InverseTransformPoint(hitInfo.point); + var norm = hitInfo.transform.InverseTransformPoint(hitInfo.normal); var o = hitInfo.transform.gameObject; - Logger.Log($"Raycast hit {{\"x\": {pos.x}, \"y\": {pos.y}, \"z\": {pos.z}}} on [{o.name}] at [{SearchUtilities.GetPath(o.transform)}]"); + + var posText = $"{{\"x\": {pos.x}, \"y\": {pos.y}, \"z\": {pos.z}}}"; + var normText = $"{{\"x\": {norm.x}, \"y\": {norm.y}, \"z\": {norm.z}}}"; + + Logger.Log($"Raycast hit pos: {posText}, normal: {normText} on [{o.name}] at [{SearchUtilities.GetPath(o.transform)}]"); } _rb.EnableCollisionDetection(); }