using NewHorizons.Builder.Props; using NewHorizons.External.Configs; using NewHorizons.External.Modules; using NewHorizons.Utility.DebugUtilities; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; using static NewHorizons.External.Modules.PropModule; namespace NewHorizons.Utility.DebugMenu { /* * Strategy: * load all existing nomai text and allow the user to select them from a list * from there, allow them to edit the placement of the one selected */ class DebugMenuNomaiText : DebugSubmenu { internal DebugRaycaster _drc; internal DebugNomaiTextPlacer _dnp; class ConversationMetadata { public NomaiTextInfo conversation; public GameObject conversationGo; public PlanetConfig planetConfig; public List spirals; public bool collapsed; } class SpiralMetadata { public NomaiTextArcInfo spiral; public GameObject spiralGo; public NomaiTextInfo conversation; public PlanetConfig planetConfig; public string planetName; public int id; } List conversations = new List(); // menu stuff Vector2 conversationsScrollPosition = new Vector2(); float dx = 0.1f; float dy = 0.1f; float dT = 1f; internal override string SubmenuName() { return "Text Placer"; } internal override void OnInit(DebugMenu menu) { _drc = menu.GetComponent(); _dnp = menu.GetComponent(); } internal override void OnAwake(DebugMenu menu) { _drc = menu.GetComponent(); _dnp = menu.GetComponent(); } internal override void OnBeginLoadMod(DebugMenu debugMenu) {} internal override void GainActive() {} // intentionally blank. do not set `DebugNomaiTextPlacer.active = true;` here internal override void LoseActive() { DebugNomaiTextPlacer.active = false; } internal override void LoadConfigFile(DebugMenu menu, PlanetConfig config) { if (config?.Props?.nomaiText == null) return; foreach(NomaiTextInfo conversation in config.Props.nomaiText) { ConversationMetadata conversationMetadata = new ConversationMetadata() { conversation = conversation, conversationGo = NomaiTextBuilder.GetSpawnedGameObjectByNomaiTextInfo(conversation), planetConfig = config, spirals = new List(), collapsed = true }; Logger.Log("adding go " + conversationMetadata.conversationGo); conversations.Add(conversationMetadata); var numArcs = conversation.arcInfo == null ? 0 : conversation.arcInfo.Length; for(int id = 0; id < numArcs; id++) { NomaiTextArcInfo arcInfo = conversation.arcInfo[id]; SpiralMetadata metadata = new SpiralMetadata() { spiral = arcInfo, spiralGo = NomaiTextBuilder.GetSpawnedGameObjectByNomaiTextArcInfo(arcInfo), conversation = conversation, planetConfig = config, planetName = config.name, id = id }; conversationMetadata.spirals.Add(metadata); } } } /* Conversations: +---------------------------+ |1) comment | | |o Visible| |Place| | // replace is greyed out if the user is currently replacing this plane (replacing is done after the user presses G |2) ... | +---------------------------+ Spirals: +---------------------------+ | v Planet - Comment | | +----------------------+ | | | v ID | | | | | | | | | > Surface 2 | | | | | x: 5 ---o--- | | | | y: 2 ---o--- | | | | theta: 45 ---o--- | | | | | | | | o Child o Adult o ...| | | | variation: o1 o2 o3..| | | +----------------------+ | | | | +----------------------+ | | | > ID | | | +----------------------+ | | | | ... | +---------------------------+ +---------------------------+ | > Planet - Comment | +---------------------------+ ... */ internal override void OnGUI(DebugMenu menu) { conversationsScrollPosition = GUILayout.BeginScrollView(conversationsScrollPosition); for(int i = 0; i < conversations.Count(); i++) { ConversationMetadata conversationMeta = conversations[i]; GUILayout.BeginHorizontal(); GUILayout.Space(5); GUILayout.BeginVertical(menu._editorMenuStyle); var arrow = conversationMeta.collapsed ? " > " : " v "; if (GUILayout.Button(arrow + conversationMeta.planetConfig.name + " - " + i, menu._submenuStyle)) { conversationMeta.collapsed = !conversationMeta.collapsed; Logger.Log("BUTTON " + i); } if (!conversationMeta.collapsed) { GUILayout.Space(5); // button to set this one to place with a raycast GUILayout.Label(conversationMeta.conversation.type.ToString()); // only show the button if this conversation is a wall text, do not show it if it is a scroll text or something if ( //conversationMeta.conversation.type == PropModule.NomaiTextInfo.NomaiTextType.Wall && GUILayout.Button("Place conversation with G") ) { Logger.Log(conversationMeta.conversationGo+" 0"); DebugNomaiTextPlacer.active = true; _dnp.onRaycast = (DebugRaycastData data) => { // I think this should be looking for AstroObject and then doing ._rootSector var sectorObject = data.hitBodyGameObject.GetComponentInChildren()?.gameObject; if (sectorObject == null) sectorObject = data.hitBodyGameObject.GetComponentInParent()?.gameObject; if (conversationMeta.conversation.type == NomaiTextInfo.NomaiTextType.Wall) { conversationMeta.conversation.position = data.pos; conversationMeta.conversation.normal = data.norm; conversationMeta.conversation.rotation = null; UpdateConversationTransform(conversationMeta, sectorObject); } else { conversationMeta.conversationGo.transform.localPosition = data.pos; DebugPropPlacer.SetGameObjectRotation(conversationMeta.conversationGo, data, _dnp.gameObject.transform.position); conversationMeta.conversation.position = conversationMeta.conversationGo.transform.localPosition; conversationMeta.conversation.rotation = conversationMeta.conversationGo.transform.localEulerAngles; } DebugNomaiTextPlacer.active = false; }; } // // spirals // for(int j = 0; j < conversationMeta.spirals.Count(); j++) { var spiralMeta = conversationMeta.spirals[j]; bool changed = false; GUILayout.BeginHorizontal(); GUILayout.Space(5); GUILayout.BeginVertical(menu._submenuStyle); // spiral controls GUILayout.Label("Spiral"); GUILayout.Label("Type"); GUILayout.BeginHorizontal(); GUI.enabled = spiralMeta.spiral.type != NomaiTextArcInfo.NomaiTextArcType.Adult; if (GUILayout.Button("Adult")) { spiralMeta.spiral.type = NomaiTextArcInfo.NomaiTextArcType.Adult; changed = true; } GUI.enabled = spiralMeta.spiral.type != NomaiTextArcInfo.NomaiTextArcType.Child; if (GUILayout.Button("Child")) { spiralMeta.spiral.type = NomaiTextArcInfo.NomaiTextArcType.Child; changed = true; } GUI.enabled = spiralMeta.spiral.type != NomaiTextArcInfo.NomaiTextArcType.Stranger; if (GUILayout.Button("Stranger")) { spiralMeta.spiral.type = NomaiTextArcInfo.NomaiTextArcType.Stranger; changed = true; } GUI.enabled = true; GUILayout.EndHorizontal(); GUILayout.Label("Variation"); GUILayout.BeginHorizontal(); var varietyCount = GetVarietyCountForType(spiralMeta.spiral.type); if (GUILayout.Button("Reroll variation")) { spiralMeta.spiral.variation = UnityEngine.Random.Range(0, varietyCount); } GUI.enabled = true; GUILayout.EndHorizontal(); // x GUILayout.BeginHorizontal(); GUILayout.Label("x: " + (spiralMeta.spiral.position?.x ?? 0), GUILayout.Width(100)); //var deltaX = GUILayout.HorizontalSlider(0, -1, 1); float deltaX = 0; if (GUILayout.Button("+", GUILayout.ExpandWidth(false))) deltaX += dx; if (GUILayout.Button("-", GUILayout.ExpandWidth(false))) deltaX -= dx; dx = float.Parse(GUILayout.TextField(dx+"", GUILayout.Width(100))); GUILayout.EndHorizontal(); // y GUILayout.BeginHorizontal(); GUILayout.Label("y: " + (spiralMeta.spiral.position?.y ?? 0), GUILayout.Width(100)); //var deltaY = GUILayout.HorizontalSlider(0, -1, 1); float deltaY = 0; if (GUILayout.Button("+", GUILayout.ExpandWidth(false))) deltaY += dy; if (GUILayout.Button("-", GUILayout.ExpandWidth(false))) deltaY -= dy; dy = float.Parse(GUILayout.TextField(dy+"", GUILayout.Width(100))); GUILayout.EndHorizontal(); // theta GUILayout.BeginHorizontal(); GUILayout.Label("theta: " + spiralMeta.spiral.zRotation, GUILayout.Width(100)); //var deltaTheta = GUILayout.HorizontalSlider(0, -1, 1); float deltaTheta = 0; if (GUILayout.Button("+", GUILayout.ExpandWidth(false))) deltaTheta += dT; if (GUILayout.Button("-", GUILayout.ExpandWidth(false))) deltaTheta -= dT; dT = float.Parse(GUILayout.TextField(dT+"", GUILayout.Width(100))); GUILayout.EndHorizontal(); if (deltaX != 0 || deltaY != 0 || deltaTheta != 0) { spiralMeta.spiral.position = (spiralMeta.spiral.position??Vector2.zero) + new Vector2(deltaX, deltaY); spiralMeta.spiral.zRotation += deltaTheta; spiralMeta.spiralGo.transform.localPosition = new Vector3(spiralMeta.spiral.position.x, spiralMeta.spiral.position.y, 0); spiralMeta.spiralGo.transform.localRotation = Quaternion.Euler(0, 0, spiralMeta.spiral.zRotation); } GUILayout.EndVertical(); GUILayout.Space(5); GUILayout.EndHorizontal(); if (changed) { // cache required stuff, destroy spiralMeta.go, call NomaiTextBuilder.MakeArc using spiralMeta.spiral and cached stuff // PropModule.NomaiTextArcInfo arcInfo, GameObject conversationZone, GameObject parent, int textEntryID, int i var conversationZone = spiralMeta.spiralGo.transform.parent.gameObject; var textEntryId = spiralMeta.spiralGo.GetComponent()._entryID; GameObject.Destroy(spiralMeta.spiralGo); spiralMeta.spiralGo = NomaiTextBuilder.MakeArc(spiralMeta.spiral, conversationZone, null, textEntryId, 0); } GUILayout.Space(10); } } GUILayout.EndVertical(); GUILayout.Space(5); GUILayout.EndHorizontal(); GUILayout.Space(10); } GUILayout.EndScrollView(); } private int GetVarietyCountForType(NomaiTextArcInfo.NomaiTextArcType type) { switch(type) { case NomaiTextArcInfo.NomaiTextArcType.Stranger: return NomaiTextBuilder._ghostArcPrefabs.Count(); case NomaiTextArcInfo.NomaiTextArcType.Child: return NomaiTextBuilder._childArcPrefabs.Count(); default: case NomaiTextArcInfo.NomaiTextArcType.Adult: return NomaiTextBuilder._arcPrefabs.Count(); } return 0; } void UpdateConversationTransform(ConversationMetadata conversationMetadata, GameObject sectorParent) { var nomaiWallTextObj = conversationMetadata.conversationGo; var planetGO = sectorParent; var info = conversationMetadata.conversation; Logger.Log(nomaiWallTextObj + " 1"); Logger.Log(nomaiWallTextObj?.transform + " 2"); Logger.Log(planetGO + " 3"); Logger.Log(planetGO?.transform + " 4"); Logger.Log(info + " 5"); Logger.Log(info?.position + " 6"); nomaiWallTextObj.transform.position = planetGO.transform.TransformPoint(info.position); 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)); } } internal override void PreSave(DebugMenu menu) { conversations.ForEach(metadata => { metadata.conversation.position = metadata.conversationGo.transform.localPosition; metadata.conversation.rotation = metadata.conversationGo.transform.localEulerAngles; }); // Spirals' configs do not need to be updated. They are always up to date //spirals.ForEach(metadata => //{ // metadata.spiral.position = metadata.spiral.position; // metadata.spiral.zRotation = metadata.spiral.zRotation; //}); } } }