diff --git a/NewHorizons/Builder/Body/StellarRemnantBuilder.cs b/NewHorizons/Builder/Body/StellarRemnantBuilder.cs index 5dd00158..f34c3b67 100644 --- a/NewHorizons/Builder/Body/StellarRemnantBuilder.cs +++ b/NewHorizons/Builder/Body/StellarRemnantBuilder.cs @@ -26,6 +26,7 @@ namespace NewHorizons.Builder.Body NHLogger.Log($"Creating stellar remnant for [{star.Config.name}]"); var sector = SectorBuilder.Make(go, rb, soi); + sector._idString = star.Config.name; sector.name = "StellarRemnant"; sector.gameObject.SetActive(false); diff --git a/NewHorizons/Builder/General/GravityBuilder.cs b/NewHorizons/Builder/General/GravityBuilder.cs index 3f138682..7d202e27 100644 --- a/NewHorizons/Builder/General/GravityBuilder.cs +++ b/NewHorizons/Builder/General/GravityBuilder.cs @@ -15,10 +15,11 @@ namespace NewHorizons.Builder.General var gravityRadius = GM / 0.1f; if (exponent == 2f) gravityRadius = Mathf.Sqrt(gravityRadius); + if (config.FocalPoint != null) gravityRadius = 0; // keep it at the lowest possible + else if (config.Base.soiOverride != 0f) gravityRadius = config.Base.soiOverride; + else if (config.Star != null) gravityRadius = Mathf.Min(gravityRadius, 15 * config.Base.surfaceSize); // To let you actually orbit things the way you would expect we cap this at 4x the diameter if its not a star (this is what giants deep has) - if (config.Star == null) gravityRadius = Mathf.Min(gravityRadius, 4 * config.Base.surfaceSize); - else gravityRadius = Mathf.Min(gravityRadius, 15 * config.Base.surfaceSize); - if (config.Base.soiOverride != 0f) gravityRadius = config.Base.soiOverride; + else gravityRadius = Mathf.Min(gravityRadius, 4 * config.Base.surfaceSize); var gravityGO = new GameObject("GravityWell"); gravityGO.transform.parent = planetGO.transform; @@ -48,7 +49,7 @@ namespace NewHorizons.Builder.General if (config.Base.surfaceGravity == 0) alignmentRadius = 0; gravityVolume._alignmentRadius = config.Base.gravityAlignmentRadiusOverride ?? alignmentRadius; - gravityVolume._upperSurfaceRadius = config.Base.surfaceSize; + gravityVolume._upperSurfaceRadius = config.FocalPoint != null ? 0 : config.Base.surfaceSize; gravityVolume._lowerSurfaceRadius = 0; gravityVolume._layer = 3; gravityVolume._priority = config.Base.gravityVolumePriority; diff --git a/NewHorizons/Builder/Orbital/FocalPointBuilder.cs b/NewHorizons/Builder/Orbital/FocalPointBuilder.cs index 90aebab3..b3e63391 100644 --- a/NewHorizons/Builder/Orbital/FocalPointBuilder.cs +++ b/NewHorizons/Builder/Orbital/FocalPointBuilder.cs @@ -57,12 +57,13 @@ namespace NewHorizons.Builder.Orbital config.Base.surfaceGravity = gravitationalMass * GravityVolume.GRAVITATIONAL_CONSTANT; config.Base.gravityFallOff = primary.Config.Base.gravityFallOff; - // Other stuff to make the barycenter not interact with anything in any way - config.Base.soiOverride = 0; - var separation = primary.Config.Orbit.semiMajorAxis + secondary.Config.Orbit.semiMajorAxis; - config.ReferenceFrame.bracketRadius = separation; - config.ReferenceFrame.targetColliderRadius = separation; + var separationRadius = (separation / 2); + config.Base.soiOverride = separationRadius * 1.5f; + config.ReferenceFrame.bracketRadius = separationRadius; + config.ReferenceFrame.targetColliderRadius = separationRadius; + + config.Base.showMinimap = false; } private static float GetGravitationalMass(PlanetConfig config) diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index 72392fa5..6cf3dd86 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -51,6 +51,7 @@ namespace NewHorizons.Builder.Props _detailInfoToCorrespondingSpawnedGameObject.Clear(); } + // i dont like how this is just a random collection in this class but quantum guy uses it :( public static GameObject GetSpawnedGameObjectByDetailInfo(DetailInfo detail) { if (!_detailInfoToCorrespondingSpawnedGameObject.ContainsKey(detail)) diff --git a/NewHorizons/External/SerializableData/MVector2.cs b/NewHorizons/External/SerializableData/MVector2.cs index 0e4aadd6..5ab03248 100644 --- a/NewHorizons/External/SerializableData/MVector2.cs +++ b/NewHorizons/External/SerializableData/MVector2.cs @@ -1,6 +1,5 @@ #region -using NewHorizons.Utility.DebugTools.Menu; using NewHorizons.Utility.OWML; using Newtonsoft.Json; using System; diff --git a/NewHorizons/Handlers/PlanetCreationHandler.cs b/NewHorizons/Handlers/PlanetCreationHandler.cs index 18618c4a..fc8b8ae7 100644 --- a/NewHorizons/Handlers/PlanetCreationHandler.cs +++ b/NewHorizons/Handlers/PlanetCreationHandler.cs @@ -235,6 +235,7 @@ namespace NewHorizons.Handlers var rb = existingPlanet.GetComponent(); var sector = SectorBuilder.Make(existingPlanet, rb, GetSphereOfInfluence(body)); + sector._idString = body.Config.name; sector.name = $"Sector-{existingPlanet.GetComponentsInChildren().Count()}"; SharedGenerateBody(body, existingPlanet, sector, rb); @@ -394,6 +395,7 @@ namespace NewHorizons.Handlers var ao = AstroObjectBuilder.Make(go, null, body, false); var sector = SectorBuilder.Make(go, owRigidBody, sphereOfInfluence); + sector._idString = body.Config.name; ao._rootSector = sector; ao._type = AstroObject.Type.None; @@ -470,6 +472,7 @@ namespace NewHorizons.Handlers var ao = AstroObjectBuilder.Make(go, primaryBody, body, false); var sector = SectorBuilder.Make(go, owRigidBody, sphereOfInfluence * 2f); + sector._idString = body.Config.name; ao._rootSector = sector; if (body.Config.Base.surfaceGravity != 0) @@ -595,6 +598,7 @@ namespace NewHorizons.Handlers var remnant = Main.BodyDict[body.Config.starSystem].Where(x => x.Config.name == body.Config.name && x.Config.isStellarRemnant).FirstOrDefault(); var remnantSector = SectorBuilder.Make(go, rb, sphereOfInfluence); + remnantSector._idString = body.Config.name; remnantSector.name = "CustomStellarRemnant"; SharedGenerateBody(remnant, go, remnantSector, rb); diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 20123633..f3c37115 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -20,7 +20,6 @@ using NewHorizons.OtherMods.VoiceActing; using NewHorizons.Streaming; using NewHorizons.Utility; using NewHorizons.Utility.DebugTools; -using NewHorizons.Utility.DebugTools.Menu; using NewHorizons.Utility.Files; using NewHorizons.Utility.OuterWilds; using NewHorizons.Utility.OWML; @@ -142,7 +141,6 @@ namespace NewHorizons if (currentScene == "SolarSystem") { DebugReload.UpdateReloadButton(); - DebugMenu.UpdatePauseMenuButton(); } if (VerboseLogs) NHLogger.UpdateLogLevel(NHLogger.LogType.Verbose); @@ -291,7 +289,6 @@ namespace NewHorizons { base.SetupPauseMenu(pauseMenu); DebugReload.InitializePauseMenu(pauseMenu); - DebugMenu.InitializePauseMenu(pauseMenu); } public void OnDestroy() @@ -622,8 +619,6 @@ namespace NewHorizons } Locator.GetPlayerBody().gameObject.AddComponent(); - Locator.GetPlayerBody().gameObject.AddComponent(); - Locator.GetPlayerBody().gameObject.AddComponent(); Locator.GetPlayerBody().gameObject.AddComponent(); if (HasDLC) Locator.GetPlayerBody().gameObject.AddComponent(); diff --git a/NewHorizons/Utility/DebugTools/DebugPropPlacer.cs b/NewHorizons/Utility/DebugTools/DebugPropPlacer.cs deleted file mode 100644 index 088d3ec5..00000000 --- a/NewHorizons/Utility/DebugTools/DebugPropPlacer.cs +++ /dev/null @@ -1,312 +0,0 @@ -using NewHorizons.Builder.Props; -using NewHorizons.External.Configs; -using NewHorizons.External.Modules.Props; -using NewHorizons.Handlers; -using NewHorizons.Utility.Files; -using NewHorizons.Utility.OWML; -using NewHorizons.Utility.OuterWilds; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.InputSystem; - -namespace NewHorizons.Utility.DebugTools -{ - - // - // The prop placer. Doesn't interact with any files, just places and tracks props. - // - - [RequireComponent(typeof(DebugRaycaster))] - class DebugPropPlacer : MonoBehaviour - { - private struct PropPlacementData - { - public AstroObject body; - public string system; - public GameObject gameObject; - public DetailInfo detailInfo; - } - - // VASE - public static readonly string DEFAULT_OBJECT = "BrittleHollow_Body/Sector_BH/Sector_NorthHemisphere/Sector_NorthPole/Sector_HangingCity/Sector_HangingCity_District1/Props_HangingCity_District1/OtherComponentsGroup/Props_HangingCity_Building_10/Prefab_NOM_VaseThin"; - - public string currentObject { get; private set; } // path of the prop to be placed - private bool hasAddedCurrentObjectToRecentsList = false; - private List props = new List(); - private List deletedProps = new List(); - private DebugRaycaster _rc; - - public static HashSet RecentlyPlacedProps = new HashSet(); - - public static bool active = false; - public GameObject mostRecentlyPlacedPropGO { get { return props.Count() <= 0 ? null : props[props.Count() - 1].gameObject; } } - public string mostRecentlyPlacedPropPath { get { return props.Count() <= 0 ? "" : props[props.Count() - 1].detailInfo.path; } } - - private ScreenPrompt _placePrompt; - private ScreenPrompt _undoPrompt; - private ScreenPrompt _redoPrompt; - - private void Awake() - { - _rc = this.GetRequiredComponent(); - currentObject = DEFAULT_OBJECT; - - _placePrompt = new ScreenPrompt(TranslationHandler.GetTranslation("DEBUG_PLACE", TranslationHandler.TextType.UI) + " ", ImageUtilities.GetButtonSprite(KeyCode.G)); - _undoPrompt = new ScreenPrompt(TranslationHandler.GetTranslation("DEBUG_UNDO", TranslationHandler.TextType.UI) + " ", ImageUtilities.GetButtonSprite(KeyCode.Minus)); - _redoPrompt = new ScreenPrompt(TranslationHandler.GetTranslation("DEBUG_REDO", TranslationHandler.TextType.UI) + " ", ImageUtilities.GetButtonSprite(KeyCode.Equals)); - - Locator.GetPromptManager().AddScreenPrompt(_placePrompt, PromptPosition.UpperRight, false); - Locator.GetPromptManager().AddScreenPrompt(_undoPrompt, PromptPosition.UpperRight, false); - Locator.GetPromptManager().AddScreenPrompt(_redoPrompt, PromptPosition.UpperRight, false); - } - - private void OnDestroy() - { - var promptManager = Locator.GetPromptManager(); - if (promptManager == null) return; - promptManager.RemoveScreenPrompt(_placePrompt, PromptPosition.UpperRight); - promptManager.RemoveScreenPrompt(_undoPrompt, PromptPosition.UpperRight); - promptManager.RemoveScreenPrompt(_redoPrompt, PromptPosition.UpperRight); - } - - private void Update() - { - UpdatePromptVisibility(); - if (!Main.Debug) return; - if (!active) return; - - if (Keyboard.current[Key.G].wasReleasedThisFrame) - { - PlaceObject(); - } - - if (Keyboard.current[Key.Minus].wasReleasedThisFrame) - { - DeleteLast(); - } - - if (Keyboard.current[Key.Equals].wasReleasedThisFrame) - { - UndoDelete(); - } - } - - public void UpdatePromptVisibility() - { - var visible = !OWTime.IsPaused() && Main.Debug && active; - _placePrompt.SetVisibility(visible); - _undoPrompt.SetVisibility(visible && props.Count > 0); - _redoPrompt.SetVisibility(visible && deletedProps.Count > 0); - } - - public void SetCurrentObject(string s) - { - currentObject = s; - hasAddedCurrentObjectToRecentsList = false; - } - - internal void PlaceObject() - { - DebugRaycastData data = _rc.Raycast(); - PlaceObject(data); - - //TODO: use DropItem logic to make props not clip through the ground when placed - //public virtual void DropItem(Vector3 position, Vector3 normal, Transform parent, Sector sector, IItemDropTarget customDropTarget) - - if (!hasAddedCurrentObjectToRecentsList) - { - hasAddedCurrentObjectToRecentsList = true; - - if (!RecentlyPlacedProps.Contains(currentObject)) - { - RecentlyPlacedProps.Add(currentObject); - } - } - } - - public void PlaceObject(DebugRaycastData data) - { - // TODO: implement sectors - // if this hits a sector, store that sector and add a config file option for it - - if (data.hitBodyGameObject == null) - { - NHLogger.LogError($"Failed to place object {currentObject} on nothing."); - return; - } - - try - { - if (currentObject == "" || currentObject == null) - { - SetCurrentObject(DEFAULT_OBJECT); - } - - var planetGO = data.hitBodyGameObject; - - if (!planetGO.name.EndsWith("_Body")) - { - NHLogger.LogWarning("Cannot place object on non-body object: " + data.hitBodyGameObject.name); - } - - var sector = planetGO.GetComponentInChildren(); - var prefab = SearchUtilities.Find(currentObject); - var detailInfo = new DetailInfo() - { - position = data.pos, - rotation = data.rot.eulerAngles, - keepLoaded = true - }; - var prop = DetailBuilder.Make(planetGO, sector, null, prefab, detailInfo); - - var body = data.hitBodyGameObject.GetComponent(); - if (body != null) RegisterProp(body, prop); - } - catch - { - NHLogger.LogError($"Failed to place object {currentObject} on body ${data.hitBodyGameObject} at location ${data.pos}."); - } - } - - - - public static string GetAstroObjectName(string bodyName) - { - var astroObject = AstroObjectLocator.GetAstroObject(bodyName); - if (astroObject == null) return null; - - var astroObjectName = astroObject.name; - - return astroObjectName; - } - - public void FindAndRegisterPropsFromConfig(PlanetConfig config, List pathsList = null) - { - if (config.starSystem != Main.Instance.CurrentStarSystem) return; - - var planet = AstroObjectLocator.GetAstroObject(config.name); - - if (planet == null) return; - if (config.Props == null || config.Props.details == null) return; - - var astroObject = AstroObjectLocator.GetAstroObject(config.name); - - foreach (var detail in config.Props.details) - { - var spawnedProp = DetailBuilder.GetSpawnedGameObjectByDetailInfo(detail); - - if (spawnedProp == null) - { - NHLogger.LogError("No spawned prop found for " + detail.path); - continue; - } - - var data = RegisterProp_WithReturn(astroObject, spawnedProp, detail.path, detail); - - // note: we do not support placing props from assetbundles, so they will not be added to the - // selectable list of placed props - if (detail.assetBundle == null && !RecentlyPlacedProps.Contains(data.detailInfo.path)) - { - if (pathsList != null) pathsList.Add(data.detailInfo.path); - } - } - } - - public void RegisterProp(AstroObject body, GameObject prop) - { - RegisterProp_WithReturn(body, prop); - } - - private PropPlacementData RegisterProp_WithReturn(AstroObject body, GameObject prop, string propPath = null, DetailInfo detailInfo = null) - { - if (Main.Debug) - { - // TOOD: make this prop an item - } - - //var body = AstroObjectLocator.GetAstroObject(bodyGameObjectName); - - NHLogger.LogVerbose($"Adding prop to {Main.Instance.CurrentStarSystem}::{body.name}"); - - - detailInfo = detailInfo == null ? new DetailInfo() : detailInfo; - detailInfo.path = propPath == null ? currentObject : propPath; - - PropPlacementData data = new PropPlacementData - { - body = body, - gameObject = prop, - system = Main.Instance.CurrentStarSystem, - detailInfo = detailInfo - }; - - props.Add(data); - return data; - } - - public Dictionary GetPropsConfigByBody() - { - var groupedProps = props - .GroupBy(p => p.system + "." + p.body) - .Select(grp => grp.ToList()) - .ToList(); - - Dictionary propConfigs = new(); - - foreach (List bodyProps in groupedProps) - { - if (bodyProps == null || bodyProps.Count == 0) continue; - if (bodyProps[0].body == null) continue; - var body = bodyProps[0].body; - NHLogger.LogVerbose("getting prop group for body " + body.name); - //string bodyName = GetAstroObjectName(bodyProps[0].body); - - DetailInfo[] infoArray = new DetailInfo[bodyProps.Count]; - propConfigs[body] = infoArray; - - for (int i = 0; i < bodyProps.Count; i++) - { - var prop = bodyProps[i]; - var rootTransform = prop.gameObject.transform.root; - - // Objects are parented to the sector and not to the planet - // However, raycasted positions are reported relative to the root game object - // Normally these two are the same, but there are some notable exceptions (ex, floating islands) - // 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.scale = prop.gameObject.transform.localScale.x; - if (!prop.detailInfo.alignRadial.GetValueOrDefault()) prop.detailInfo.rotation = rootTransform.InverseTransformRotation(prop.gameObject.transform.rotation).eulerAngles; - - infoArray[i] = prop.detailInfo; - } - } - - return propConfigs; - } - - public void DeleteLast() - { - if (props.Count <= 0) return; - - PropPlacementData last = props[props.Count - 1]; - props.RemoveAt(props.Count - 1); - - last.gameObject.SetActive(false); - - deletedProps.Add(last); - } - - public void UndoDelete() - { - if (deletedProps.Count <= 0) return; - - PropPlacementData last = deletedProps[deletedProps.Count - 1]; - deletedProps.RemoveAt(deletedProps.Count - 1); - - last.gameObject.SetActive(true); - - props.Add(last); - } - } -} diff --git a/NewHorizons/Utility/DebugTools/Menu/DebugMenu.cs b/NewHorizons/Utility/DebugTools/Menu/DebugMenu.cs deleted file mode 100644 index 882b9cee..00000000 --- a/NewHorizons/Utility/DebugTools/Menu/DebugMenu.cs +++ /dev/null @@ -1,321 +0,0 @@ -using NewHorizons.External.Configs; -using NewHorizons.Handlers; -using NewHorizons.Utility.Files; -using NewHorizons.Utility.OWML; -using Newtonsoft.Json; -using OWML.Common; -using OWML.Common.Menus; -using OWML.Utils; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEngine; - -namespace NewHorizons.Utility.DebugTools.Menu -{ - class DebugMenu : MonoBehaviour - { - private static SubmitAction pauseMenuButton; - - public GUIStyle _editorMenuStyle; - public GUIStyle _tabBarStyle; - public GUIStyle _submenuStyle; - internal Vector2 EditorMenuSize = new Vector2(600, 900); - bool menuOpen = false; - static bool openMenuOnPause; - - // Menu params - internal static IModBehaviour loadedMod = null; - internal Dictionary loadedConfigFiles = new Dictionary(); - private bool saveButtonUnlocked = false; - private Vector2 recentModListScrollPosition = Vector2.zero; - - // Submenus - private List submenus; - private int activeSubmenu = 0; - - private static DebugMenu _instance; - - internal static JsonSerializerSettings jsonSettings = new JsonSerializerSettings - { - NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore, - Formatting = Formatting.Indented, - }; - - private void Awake() - { - submenus = new List() - { - new DebugMenuPropPlacer(), - new DebugMenuShipLogs(), - }; - - submenus.ForEach((submenu) => submenu.OnAwake(this)); - } - - private void Start() - { - _instance = this; - - Main.Instance.ModHelper.MenuHelper.PauseMenuManager.PauseMenuOpened += OnOpenMenu; - Main.Instance.ModHelper.MenuHelper.PauseMenuManager.PauseMenuClosed += OnCloseMenu; - Main.Instance.OnChangeStarSystem.AddListener(OnChangeStarSystem); - - InitMenu(); - - if (loadedMod != null) - { - LoadMod(loadedMod); - } - } - - public void OnDestroy() - { - Main.Instance.ModHelper.MenuHelper.PauseMenuManager.PauseMenuOpened -= OnOpenMenu; - Main.Instance.ModHelper.MenuHelper.PauseMenuManager.PauseMenuClosed -= OnCloseMenu; - Main.Instance.OnChangeStarSystem.RemoveListener(OnChangeStarSystem); - } - - private void OnChangeStarSystem(string _) - { - if (saveButtonUnlocked) - { - SaveLoadedConfigsForRecentSystem(); - saveButtonUnlocked = false; - } - } - - public static void InitializePauseMenu(IPauseMenuManager pauseMenu) - { - pauseMenuButton = pauseMenu.MakeSimpleButton(TranslationHandler.GetTranslation("Toggle Dev Tools Menu", TranslationHandler.TextType.UI).ToUpperFixed(), 3, true); - _instance?.InitMenu(); - } - - public static void UpdatePauseMenuButton() - { - pauseMenuButton?.SetButtonVisible(Main.Debug); - } - - private void OnOpenMenu() { menuOpen = openMenuOnPause; } - - private void ToggleMenu() { menuOpen = !menuOpen; openMenuOnPause = !openMenuOnPause; } - - private void OnCloseMenu() { menuOpen = false; } - - private void OnGUI() - { - if (!menuOpen) return; - if (!Main.Debug) return; - - Vector2 menuPosition = new Vector2(10, 40); - - GUILayout.BeginArea(new Rect(menuPosition.x, menuPosition.y, EditorMenuSize.x, EditorMenuSize.y), _editorMenuStyle); - - // Continue working on existing mod - GUILayout.Label("Name of your mod"); - if (loadedMod == null) - { - recentModListScrollPosition = GUILayout.BeginScrollView(recentModListScrollPosition, GUILayout.Width(EditorMenuSize.x), GUILayout.Height(100)); - - foreach (var mod in Main.MountedAddons) - { - if (GUILayout.Button(mod.ModHelper.Manifest.UniqueName)) - { - LoadMod(mod); - submenus[activeSubmenu].GainActive(); - } - } - - GUILayout.EndScrollView(); - } - else - { - GUILayout.Label(loadedMod.ModHelper.Manifest.UniqueName); - } - - GUILayout.Space(5); - - // Save your work - if (loadedMod != null) - { - GUILayout.BeginHorizontal(); - if (GUILayout.Button(saveButtonUnlocked ? " O " : " | ", GUILayout.ExpandWidth(false))) - { - saveButtonUnlocked = !saveButtonUnlocked; - } - GUI.enabled = saveButtonUnlocked; - if (GUILayout.Button("Update your mod's configs")) - { - SaveLoadedConfigsForRecentSystem(); - saveButtonUnlocked = false; - } - GUI.enabled = true; - GUILayout.EndHorizontal(); - - if (GUILayout.Button("Print config changes for your mod")) - { - PrintLoadedConfigChangesForRecentSystem(); - saveButtonUnlocked = false; - } - } - - GUILayout.Space(20); - - // Draw submenu stuff - if (loadedMod != null) - { - GUILayout.BeginHorizontal(_tabBarStyle); - GUILayout.Space(5); - for (int i = 0; i < submenus.Count; i++) - { - GUI.enabled = i != activeSubmenu; - var style = i == activeSubmenu ? _submenuStyle : _tabBarStyle; - if (GUILayout.Button(" " + submenus[i].SubmenuName() + " ", style, GUILayout.ExpandWidth(false))) - { - GUI.enabled = true; - submenus[activeSubmenu].LoseActive(); - activeSubmenu = i; - submenus[activeSubmenu].GainActive(); - - } - GUI.enabled = true; - - // if (i < submenus.Count-1) GUILayout.Label("|", GUILayout.ExpandWidth(false)); - } - GUILayout.EndHorizontal(); - - GUILayout.BeginVertical(_submenuStyle); - GUILayout.Space(10); - submenus[activeSubmenu].OnGUI(this); - GUILayout.EndVertical(); - } - - GUILayout.EndArea(); - } - - private void LoadMod(IModBehaviour mod) - { - loadedMod = mod; - submenus.ForEach(submenu => submenu.OnBeginLoadMod(this)); - - var folder = loadedMod.ModHelper.Manifest.ModFolderPath; - - var bodiesForThisMod = Main.BodyDict.Values.SelectMany(x => x).Where(x => x.Mod == loadedMod).ToList(); - foreach (var body in bodiesForThisMod) - { - if (body.RelativePath == null) - { - NHLogger.LogWarning($"Error loading config for {body.Config.name} in {body.Config.starSystem}"); - continue; - } - - loadedConfigFiles[Path.Combine(folder, body.RelativePath)] = body.Config; - submenus.ForEach(submenu => submenu.LoadConfigFile(this, body.Config)); - } - } - - private void SaveLoadedConfigsForRecentSystem() - { - submenus.ForEach(submenu => submenu.PreSave(this)); - - var backupFolderName = $"configBackups\\{DateTime.Now.ToString("yyyyMMddTHHmmss")}\\"; - - NHLogger.Log($"Potentially saving {loadedConfigFiles.Keys.Count} files"); - - foreach (var filePath in loadedConfigFiles.Keys) - { - NHLogger.LogVerbose($"Possibly Saving... {loadedConfigFiles[filePath].name} @ {filePath}"); - - if (loadedConfigFiles[filePath].starSystem != Main.Instance.CurrentStarSystem) continue; - - var relativePath = filePath.Replace(loadedMod.ModHelper.Manifest.ModFolderPath, ""); - - var json = loadedConfigFiles[filePath].ToSerializedJson(); - - try - { - var path = Path.Combine(loadedMod.ModHelper.Manifest.ModFolderPath, backupFolderName, relativePath); - NHLogger.LogVerbose($"Backing up... {relativePath} to {path}"); - var oldPath = Path.Combine(loadedMod.ModHelper.Manifest.ModFolderPath, relativePath); - var directoryName = Path.GetDirectoryName(path); - Directory.CreateDirectory(directoryName); - - if (File.Exists(oldPath)) - File.WriteAllBytes(path, File.ReadAllBytes(oldPath)); - else - File.WriteAllText(path, json); - } - catch (Exception e) - { - NHLogger.LogError($"Failed to save backup file {backupFolderName}{relativePath}:\n{e}"); - } - - try - { - NHLogger.Log($"Saving... {relativePath} to {filePath}"); - var path = Path.Combine(loadedMod.ModHelper.Manifest.ModFolderPath, relativePath); - var directoryName = Path.GetDirectoryName(path); - Directory.CreateDirectory(directoryName); - - File.WriteAllText(path, json); - } - catch (Exception e) - { - NHLogger.LogError($"Failed to save file {relativePath}:\n{e}"); - } - } - } - - private void PrintLoadedConfigChangesForRecentSystem() - { - foreach(DebugSubmenu menu in submenus) - { - menu.PrintNewConfigSection(this); - } - } - - private void InitMenu() - { - if (_editorMenuStyle != null) return; - - UpdatePauseMenuButton(); - - // TODO: figure out how to clear this event list so that we don't pile up useless instances of the DebugMenu that can't get garbage collected - pauseMenuButton.OnSubmitAction += ToggleMenu; - - submenus.ForEach(submenu => submenu.OnInit(this)); - - _editorMenuStyle = new GUIStyle - { - normal = - { - background = ImageUtilities.MakeSolidColorTexture(1, 1, Color.black) - } - }; - - _tabBarStyle = new GUIStyle - { - normal = - { - background = ImageUtilities.MakeSolidColorTexture(1, 1, new Color(0.2f, 0.2f, 0.2f, 1)), - textColor = Color.white - }, - fontStyle = FontStyle.Bold, - fontSize = 16 - }; - - _submenuStyle = new GUIStyle - { - normal = - { - background = ImageUtilities.MakeSolidColorTexture(1, 1, new Color(0.1f, 0.1f, 0.1f, 1)), - textColor = Color.white - }, - fontStyle = FontStyle.Bold, - fontSize = 16 - }; - } - } -} diff --git a/NewHorizons/Utility/DebugTools/Menu/DebugMenuPropPlacer.cs b/NewHorizons/Utility/DebugTools/Menu/DebugMenuPropPlacer.cs deleted file mode 100644 index 74d67169..00000000 --- a/NewHorizons/Utility/DebugTools/Menu/DebugMenuPropPlacer.cs +++ /dev/null @@ -1,401 +0,0 @@ -using HarmonyLib; -using NewHorizons.External.Configs; -using NewHorizons.External.Modules; -using NewHorizons.Utility.Geometry; -using NewHorizons.Utility.OWML; -using NewHorizons.Utility.OuterWilds; -using Newtonsoft.Json; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace NewHorizons.Utility.DebugTools.Menu -{ - class DebugMenuPropPlacer : DebugSubmenu - { - private HashSet favoriteProps = new HashSet(); - private List propsLoadedFromConfig = new List(); - public static readonly char separatorCharacter = '☧'; // since no chars are illegal in game object names, I picked one that's extremely unlikely to be used to be a separator - private static readonly string favoritePropsPlayerPrefKey = "FavoriteProps"; - - internal DebugPropPlacer _dpp; - internal DebugRaycaster _drc; - - // misc - private GameObject mostRecentlyPlacedProp; - private Vector3 mostRecentlyPlacedPropSphericalPos; - - // menu params - private Vector2 recentPropsScrollPosition = Vector2.zero; - private bool propsCollapsed = false; - private bool propPositioningCollapsed = false; - private Vector3 propPosDelta = new Vector3(0.1f, 0.1f, 0.1f); - private Vector3 propRotDelta = new Vector3(0.1f, 0.1f, 0.1f); - private Vector3 propSphericalPosDelta = new Vector3(0.1f, 0.1f, 0.1f); - private float propRotationAboutLocalUpDelta = 0.1f; - private float propScaleDelta = 0.1f; - - internal override string SubmenuName() - { - return "Prop Placer"; - } - - internal override void OnInit(DebugMenu menu) - { - _dpp = menu.GetComponent(); - _drc = menu.GetComponent(); - } - - internal override void OnAwake(DebugMenu menu) - { - _dpp = menu.GetComponent(); - _drc = menu.GetComponent(); - LoadFavoriteProps(); - } - - internal override void OnBeginLoadMod(DebugMenu debugMenu) - { - - } - - internal override void GainActive() - { - DebugPropPlacer.active = true; - } - - internal override void LoseActive() - { - DebugPropPlacer.active = false; - } - - internal override void LoadConfigFile(DebugMenu menu, PlanetConfig config) - { - _dpp.FindAndRegisterPropsFromConfig(config, propsLoadedFromConfig); - } - - private void LoadFavoriteProps() - { - string favoritePropsPlayerPref = PlayerPrefs.GetString(favoritePropsPlayerPrefKey); - - if (favoritePropsPlayerPref == null || favoritePropsPlayerPref == "") return; - - var favoritePropPaths = favoritePropsPlayerPref.Split(separatorCharacter); - foreach (string favoriteProp in favoritePropPaths) - { - DebugPropPlacer.RecentlyPlacedProps.Add(favoriteProp); - this.favoriteProps.Add(favoriteProp); - } - } - - internal override void OnGUI(DebugMenu menu) - { - // - // DebugPropPlacer - // - GUILayout.Label("Currently placing: "); - _dpp.SetCurrentObject(GUILayout.TextArea(_dpp.currentObject)); - - GUILayout.Space(5); - GUILayout.Space(5); - - - var arrow = propsCollapsed ? " > " : " v "; - if (GUILayout.Button(arrow + "Recently placed objects", menu._tabBarStyle)) propsCollapsed = !propsCollapsed; - if (!propsCollapsed) DrawPropsList(menu); - GUILayout.Space(5); - - if (_dpp.mostRecentlyPlacedPropGO != null) - { - arrow = propPositioningCollapsed ? " > " : " v "; - if (GUILayout.Button(arrow + "Position last placed prop", menu._tabBarStyle)) propPositioningCollapsed = !propPositioningCollapsed; - if (!propPositioningCollapsed) DrawPropsAdustmentControls(menu); - } - } - - private void DrawPropsAdustmentControls(DebugMenu menu) - { - var propPath = _dpp.mostRecentlyPlacedPropPath; - var propPathElements = propPath[propPath.Length - 1] == '/' - ? propPath.Substring(0, propPath.Length - 1).Split('/') - : propPath.Split('/'); - string propName = propPathElements[propPathElements.Length - 1]; - GUILayout.Label($"Reposition {propName}: "); - - - Vector3 latestPropPosDelta = VectorInput(_dpp.mostRecentlyPlacedPropGO.transform.localPosition, propPosDelta, out propPosDelta, "x", "y", "z"); - _dpp.mostRecentlyPlacedPropGO.transform.localPosition += latestPropPosDelta; - if (latestPropPosDelta != Vector3.zero) mostRecentlyPlacedPropSphericalPos = DeltaSphericalPosition(mostRecentlyPlacedProp, Vector3.zero); - - //GUILayout.Space(5); - //Vector3 latestPropRotDelta = VectorInput(_dpp.mostRecentlyPlacedPropGO.transform.localEulerAngles, propRotDelta, out propRotDelta, "x", "y", "z"); - //_dpp.mostRecentlyPlacedPropGO.transform.localEulerAngles += latestPropRotDelta; - - GUILayout.Space(5); - GUILayout.Space(5); - - - if (mostRecentlyPlacedProp != _dpp.mostRecentlyPlacedPropGO) - { - mostRecentlyPlacedProp = _dpp.mostRecentlyPlacedPropGO; - mostRecentlyPlacedPropSphericalPos = DeltaSphericalPosition(mostRecentlyPlacedProp, Vector3.zero); - } - - Vector3 latestPropSphericalPosDelta = VectorInput(mostRecentlyPlacedPropSphericalPos, propSphericalPosDelta, out propSphericalPosDelta, "lat ", "lon ", "height"); - if (latestPropSphericalPosDelta != Vector3.zero) - { - SetSphericalPosition(mostRecentlyPlacedProp, mostRecentlyPlacedPropSphericalPos + latestPropSphericalPosDelta); - mostRecentlyPlacedPropSphericalPos = mostRecentlyPlacedPropSphericalPos + latestPropSphericalPosDelta; - } - - GUILayout.Space(5); - GUILayout.Space(5); - - - GUILayout.BeginHorizontal(); - GUILayout.Label("Rotate about up: ", GUILayout.Width(50)); - float deltaRot = 0; - if (GUILayout.Button("+", GUILayout.ExpandWidth(false))) deltaRot += propRotationAboutLocalUpDelta; - if (GUILayout.Button("-", GUILayout.ExpandWidth(false))) deltaRot -= propRotationAboutLocalUpDelta; - propRotationAboutLocalUpDelta = float.Parse(GUILayout.TextField(propRotationAboutLocalUpDelta + "", GUILayout.Width(100))); - - if (deltaRot != 0) - { - Transform astroObject = mostRecentlyPlacedProp.transform.parent.parent; - mostRecentlyPlacedProp.transform.RotateAround(mostRecentlyPlacedProp.transform.position, mostRecentlyPlacedProp.transform.up, deltaRot); - } - GUILayout.EndHorizontal(); - - - GUILayout.BeginHorizontal(); - GUILayout.Label("scale: ", GUILayout.Width(50)); - var scaleString = mostRecentlyPlacedProp.transform.localScale.x + ""; - var newScaleString = GUILayout.TextField(scaleString, GUILayout.Width(50)); - var parsedScaleString = mostRecentlyPlacedProp.transform.localScale.x; try { parsedScaleString = float.Parse(newScaleString); } catch { } - float deltaScale = scaleString == newScaleString ? 0 : parsedScaleString - mostRecentlyPlacedProp.transform.localScale.x; - if (GUILayout.Button("+", GUILayout.ExpandWidth(false))) deltaScale += propScaleDelta; - if (GUILayout.Button("-", GUILayout.ExpandWidth(false))) deltaScale -= propScaleDelta; - propScaleDelta = float.Parse(GUILayout.TextField(propScaleDelta + "", GUILayout.Width(100))); - - if (deltaScale != 0) - { - float newScale = mostRecentlyPlacedProp.transform.localScale.x + deltaScale; - mostRecentlyPlacedProp.transform.localScale = new Vector3(newScale, newScale, newScale); - } - GUILayout.EndHorizontal(); - } - private Vector3 DeltaSphericalPosition(GameObject prop, Vector3 deltaSpherical) - { - Transform astroObject = prop.transform.parent.parent; - Transform sector = prop.transform.parent; - Vector3 originalLocalPos = astroObject.InverseTransformPoint(prop.transform.position); // parent is the sector, this gives localPos relative to the astroobject (what the DetailBuilder asks for) - Vector3 sphericalPos = CoordinateUtilities.CartesianToSpherical(originalLocalPos); - - if (deltaSpherical == Vector3.zero) return sphericalPos; - Vector3 newSpherical = sphericalPos + deltaSpherical; - - Vector3 finalLocalPosition = CoordinateUtilities.SphericalToCartesian(newSpherical); - Vector3 finalAbsolutePosition = astroObject.TransformPoint(finalLocalPosition); - prop.transform.localPosition = prop.transform.parent.InverseTransformPoint(finalAbsolutePosition); - // prop.transform.rotation = Quaternion.FromToRotation(originalLocalPos.normalized, finalLocalPosition.normalized) * prop.transform.rotation; - - // first, rotate the object by the astroObject's rotation, that means anything afterwards is relative to this rotation (ie, we can pretend the astroObject has 0 rotation) - // then, rotate by the difference in position, basically accounting for the curvature of a sphere - // then re-apply the local rotations of the hierarchy down to the prop (apply the sector local rotation, then the prop local rotation) - - // since we're doing all rotation relative to the astro object, we start with its absolute rotation - // then we apply the rotation about the astroobject using FromTooRotation - // then we reapply the local rotations down through the hierarchy - prop.transform.rotation = astroObject.rotation * Quaternion.FromToRotation(originalLocalPos.normalized, finalLocalPosition.normalized) * sector.localRotation * prop.transform.localRotation; - - return newSpherical; - } - - // DB_EscapePodDimension_Body/Sector_EscapePodDimension/Interactables_EscapePodDimension/InnerWarp_ToAnglerNest - // DB_ExitOnlyDimension_Body/Sector_ExitOnlyDimension/Interactables_ExitOnlyDimension/InnerWarp_ToExitOnly // need to change the colors - // DB_HubDimension_Body/Sector_HubDimension/Interactables_HubDimension/InnerWarp_ToCluster // need to delete the child "Signal_Harmonica" - - private Vector3 SetSphericalPosition(GameObject prop, Vector3 newSpherical) - { - Transform astroObject = prop.transform.parent.parent; - Transform sector = prop.transform.parent; - Vector3 originalLocalPos = astroObject.InverseTransformPoint(prop.transform.position); // parent is the sector, this gives localPos relative to the astroobject (what the DetailBuilder asks for) - Vector3 sphericalPos = CoordinateUtilities.CartesianToSpherical(originalLocalPos); - - if (newSpherical == sphericalPos) return sphericalPos; - - Vector3 finalLocalPosition = CoordinateUtilities.SphericalToCartesian(newSpherical); - Vector3 finalAbsolutePosition = astroObject.TransformPoint(finalLocalPosition); - prop.transform.localPosition = prop.transform.parent.InverseTransformPoint(finalAbsolutePosition); - NHLogger.Log("new position: " + prop.transform.localPosition); - - var onlyChangingRAndRIsNegative = false; - - // first, rotate the object by the astroObject's rotation, that means anything afterwards is relative to this rotation (ie, we can pretend the astroObject has 0 rotation) - // then, rotate by the difference in position, basically accounting for the curvature of a sphere - // then re-apply the local rotations of the hierarchy down to the prop (apply the sector local rotation, then the prop local rotation) - - // since we're doing all rotation relative to the astro object, we start with its absolute rotation - // then we apply the rotation about the astroobject using FromTooRotation - // then we reapply the local rotations down through the hierarchy - Vector3 originalLocalPos_ForcedPositiveR = CoordinateUtilities.SphericalToCartesian(new Vector3(sphericalPos.x, sphericalPos.y, Mathf.Abs(sphericalPos.z))); - Vector3 finalLocalPos_ForcedPositiveR = CoordinateUtilities.SphericalToCartesian(new Vector3(newSpherical.x, newSpherical.y, Mathf.Abs(newSpherical.z))); - if (!onlyChangingRAndRIsNegative) prop.transform.rotation = astroObject.rotation * Quaternion.FromToRotation(originalLocalPos_ForcedPositiveR.normalized, finalLocalPos_ForcedPositiveR.normalized) * sector.localRotation * prop.transform.localRotation; - - return newSpherical; - } - - private Vector3 VectorInput(Vector3 input, Vector3 deltaControls, out Vector3 deltaControlsOut, string labelX, string labelY, string labelZ) - { - var dx = deltaControls.x; - var dy = deltaControls.y; - var dz = deltaControls.z; - - // x - GUILayout.BeginHorizontal(); - GUILayout.Label(labelX + ": ", GUILayout.Width(50)); - var xString = input.x + ""; - var newXString = GUILayout.TextField(xString, GUILayout.Width(50)); - var parsedXString = input.x; try { parsedXString = float.Parse(newXString); } catch { } - float deltaX = xString == newXString ? 0 : parsedXString - input.x; - 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(labelY + ": ", GUILayout.Width(50)); - var yString = input.y + ""; - var newYString = GUILayout.TextField(yString, GUILayout.Width(50)); - var parsedYString = input.y; try { parsedYString = float.Parse(newYString); } catch { } - float deltaY = yString == newYString ? 0 : parsedYString - input.y; - 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(); - - // z - GUILayout.BeginHorizontal(); - GUILayout.Label(labelZ + ": ", GUILayout.Width(50)); - var zString = input.z + ""; - var newZString = GUILayout.TextField(zString, GUILayout.Width(50)); - var parsedZString = input.z; try { parsedZString = float.Parse(newZString); } catch { } - float deltaZ = zString == newZString ? 0 : parsedZString - input.z; - if (GUILayout.Button("+", GUILayout.ExpandWidth(false))) deltaZ += dz; - if (GUILayout.Button("-", GUILayout.ExpandWidth(false))) deltaZ -= dz; - dz = float.Parse(GUILayout.TextField(dz + "", GUILayout.Width(100))); - GUILayout.EndHorizontal(); - - deltaControlsOut = new Vector3(dx, dy, dz); - return new Vector3(deltaX, deltaY, deltaZ); - } - - private void DrawPropsList(DebugMenu menu) - { - // List of recently placed objects - recentPropsScrollPosition = GUILayout.BeginScrollView(recentPropsScrollPosition, GUILayout.Width(menu.EditorMenuSize.x), GUILayout.Height(500)); - foreach (string propPath in DebugPropPlacer.RecentlyPlacedProps) - { - GUILayout.BeginHorizontal(); - - var propPathElements = propPath[propPath.Length - 1] == '/' - ? propPath.Substring(0, propPath.Length - 1).Split('/') - : propPath.Split('/'); - string propName = propPathElements[propPathElements.Length - 1]; - - string favoriteButtonIcon = favoriteProps.Contains(propPath) ? "★" : "☆"; - if (GUILayout.Button(favoriteButtonIcon, GUILayout.ExpandWidth(false))) - { - if (favoriteProps.Contains(propPath)) - { - favoriteProps.Remove(propPath); - } - else - { - favoriteProps.Add(propPath); - } - - string[] favoritePropsArray = favoriteProps.ToArray(); - PlayerPrefs.SetString(favoritePropsPlayerPrefKey, string.Join(separatorCharacter + "", favoritePropsArray)); - } - - if (GUILayout.Button(propName)) - { - _dpp.SetCurrentObject(propPath); - } - - GUILayout.EndHorizontal(); - } - GUILayout.EndScrollView(); - } - - internal override void PreSave(DebugMenu menu) - { - UpdateLoadedConfigsForRecentSystem(menu); - } - - private void UpdateLoadedConfigsForRecentSystem(DebugMenu menu) - { - var newDetails = _dpp.GetPropsConfigByBody(); - - var newDetailsCountsByPlanet = string.Join(", ", newDetails.Keys.Select(x => $"{x.name} ({newDetails[x].Length})")); - NHLogger.Log($"Updating config files. New Details Counts by planet: {newDetailsCountsByPlanet}"); - - var planetToConfigPath = new Dictionary(); - - // Get all configs - foreach (var filePath in menu.loadedConfigFiles.Keys) - { - NHLogger.LogVerbose($"Potentially updating copy of config at {filePath}"); - NHLogger.LogVerbose($"{menu.loadedConfigFiles[filePath].name} {AstroObjectLocator.GetAstroObject(menu.loadedConfigFiles[filePath].name)?.name}"); - NHLogger.LogVerbose($"{menu.loadedConfigFiles[filePath].name}"); - - if (menu.loadedConfigFiles[filePath].starSystem != Main.Instance.CurrentStarSystem) return; - if (menu.loadedConfigFiles[filePath].name == null || AstroObjectLocator.GetAstroObject(menu.loadedConfigFiles[filePath].name) == null) - { - NHLogger.LogWarning("Failed to update copy of config at " + filePath); - continue; - } - - var astroObject = AstroObjectLocator.GetAstroObject(menu.loadedConfigFiles[filePath].name); - planetToConfigPath[astroObject] = filePath; - - if (!newDetails.ContainsKey(astroObject)) continue; - - if (menu.loadedConfigFiles[filePath].Props == null) menu.loadedConfigFiles[filePath].Props = new PropModule(); - menu.loadedConfigFiles[filePath].Props.details = newDetails[astroObject]; - - NHLogger.Log($"Successfully updated copy of config file for {astroObject.name}"); - } - - // find all new planets that do not yet have config paths - var planetsThatDoNotHaveConfigFiles = newDetails.Keys.Where(x => !planetToConfigPath.ContainsKey(x)).ToList(); - foreach (var astroObject in planetsThatDoNotHaveConfigFiles) - { - NHLogger.Log("Fabricating new config file for " + astroObject.name); - - var filepath = $"planets/{Main.Instance.CurrentStarSystem}/{astroObject.name}.json"; - - var config = new PlanetConfig(); - config.starSystem = Main.Instance.CurrentStarSystem; - config.name = astroObject._name == AstroObject.Name.CustomString ? astroObject.GetCustomName() : astroObject._name.ToString(); - config.Props = new PropModule(); - config.Props.details = newDetails[astroObject]; - - menu.loadedConfigFiles[filepath] = config; - } - } - - internal override void PrintNewConfigSection(DebugMenu menu) - { - foreach (var body in _dpp.GetPropsConfigByBody()) - { - var json = body.Value.Join( - detail => "\t" + JsonConvert.SerializeObject(detail, DebugMenu.jsonSettings), - ",\n" - ); - NHLogger.Log($"{body.Key.name} ({body.Value.Length})\n[\n{json}\n]"); - } - } - } -} diff --git a/NewHorizons/Utility/DebugTools/Menu/DebugMenuShipLogs.cs b/NewHorizons/Utility/DebugTools/Menu/DebugMenuShipLogs.cs deleted file mode 100644 index 77053a88..00000000 --- a/NewHorizons/Utility/DebugTools/Menu/DebugMenuShipLogs.cs +++ /dev/null @@ -1,81 +0,0 @@ -using HarmonyLib; -using NewHorizons.External.Configs; -using NewHorizons.External.Modules; -using NewHorizons.External.SerializableData; -using NewHorizons.Utility.OWML; -using Newtonsoft.Json; -using System.Linq; -using UnityEngine; - -namespace NewHorizons.Utility.DebugTools.Menu -{ - class DebugMenuShipLogs : DebugSubmenu - { - string entryPositionsText = ""; - - internal override void GainActive() - { - - } - internal override void LoseActive() - { - - } - - internal override void LoadConfigFile(DebugMenu menu, PlanetConfig config) - { - - } - - - internal override void OnAwake(DebugMenu menu) - { - } - - internal override void OnBeginLoadMod(DebugMenu debugMenu) - { - } - - private string GetEntryPositionsJSON() => - Resources - .FindObjectsOfTypeAll() - .Join( - entry => JsonConvert.SerializeObject(new ShipLogModule.EntryPositionInfo - { - id = entry.name, - position = new MVector2(entry.transform.localPosition.x, entry.transform.localPosition.y) - }, DebugMenu.jsonSettings), - ",\n" - ); - - internal override void OnGUI(DebugMenu menu) - { - if (GUILayout.Button("Print Ship Log Positions")) - { - entryPositionsText = GetEntryPositionsJSON(); - } - - GUILayout.TextArea(entryPositionsText); - } - - internal override void OnInit(DebugMenu menu) - { - - } - - internal override void PreSave(DebugMenu menu) - { - - } - - internal override string SubmenuName() - { - return "Ship Log"; - } - - internal override void PrintNewConfigSection(DebugMenu menu) - { - NHLogger.Log(GetEntryPositionsJSON()); - } - } -} diff --git a/NewHorizons/Utility/DebugTools/Menu/DebugSubmenu.cs b/NewHorizons/Utility/DebugTools/Menu/DebugSubmenu.cs deleted file mode 100644 index 0bcc9099..00000000 --- a/NewHorizons/Utility/DebugTools/Menu/DebugSubmenu.cs +++ /dev/null @@ -1,21 +0,0 @@ -using NewHorizons.External.Configs; - -namespace NewHorizons.Utility.DebugTools.Menu -{ - abstract class DebugSubmenu - { - internal abstract void OnAwake(DebugMenu menu); - internal abstract void OnGUI(DebugMenu menu); - internal abstract void PrintNewConfigSection(DebugMenu menu); - internal abstract void PreSave(DebugMenu menu); - internal abstract void OnInit(DebugMenu menu); - internal abstract void LoadConfigFile(DebugMenu menu, PlanetConfig config); - internal abstract void OnBeginLoadMod(DebugMenu debugMenu); - - internal abstract string SubmenuName(); - - internal abstract void GainActive(); - internal abstract void LoseActive(); - - } -} diff --git a/docs/src/assets/docs-images/details/asset_bundle.webp b/docs/src/assets/docs-images/details/asset_bundle.webp deleted file mode 100644 index 9484111f..00000000 Binary files a/docs/src/assets/docs-images/details/asset_bundle.webp and /dev/null differ diff --git a/docs/src/content/docs/guides/details.md b/docs/src/content/docs/guides/details.md index ebb2be47..fd26d3ca 100644 --- a/docs/src/content/docs/guides/details.md +++ b/docs/src/content/docs/guides/details.md @@ -9,73 +9,23 @@ For physical objects there are currently two ways of setting them up: specify an - Generally you can find planets by writing their name with no spaces/punctuation followed by "\_Body". - There's also [this community-maintained list of props](https://docs.google.com/spreadsheets/d/1VJaglB1kRL0VqaXhvXepIeymo93zqhWex-j7_QDm6NE/edit?usp=sharing) which you can use to find interesting props and check to see if they have collision. -## Using the Prop Placer +## Debug Raycast -The Prop Placer is a convenience tool that lets you manually place details from inside the game. Once enabled, press "G" and your currently selected prop will be placed wherever your crosshair is pointing. +If you turn on debug mode (the mod option), you can press P to shoot a ray where you're looking. This will print location info to the console that you can paste into your configs, as well as paths that you can explore further in Unity Explorer. +Of note: the rotation of the raycast will have the up direction facing away from the ground/wall/ceiling and the forward direction facing you. -### Enabling +## [Unity Explorer](https://outerwildsmods.com/mods/unityexplorer/) -1. Pause the game. You will see an extra menu option titled "Toggle Prop Placer Menu". Click it -2. The prop placer menu should now be open. At the bottom of the menu, you will see a list of mods. Click yours. - 1. This menu scrolls. If you do not see your mod, it may be further down the list. -3. The Prop Placer is now active! Unpause the game, and you can now place Nomai vases using "G" - -### How to Select Props - -1. Pause the game again. The prop placer menu should still be visible. -2. At the top of the menu, you'll see a text box containing the path for the vase. Replace this with the path for the prop you want to place. For example: `DreamWorld_Body/Sector_DreamWorld/Sector_DreamZone_1/Props_DreamZone_1/OtherComponentsGroup/Trees_Z1/DreamHouseIsland/Tree_DW_M_Var` -3. Tip: use the Unity Explorer mod to find the path for the object you want to place. You only have to do this once. -4. Unpause the game and press "G". Say hello to your new tree! -5. Pause the game again. You will now see the prop you just placed on the list of recently placed props just below the "path" text box. -6. Click on the button titled "Prefab_NOM_VaseThin". You can now place vases again. - -### Extra features - -1. Made a mistake? **Press the "-" key to undo.** Press the "+" key to redo. -2. If you have the Unity Explorer mod enabled, you can use this to tweak the position, rotation, and scale of your props. Your changes will be saved. -3. Want to save some recently placed props between game launches? On the recently placed props list, click the star next to the prop's name to favorite it. -4. Found a bug that ruined your configs? Check `AppData\Roaming\OuterWildsModManager\OWML\Mods\xen.NewHorizons\configBackups` for backup saves of your work. Folders are titled "\[date\]T\[time\]". -5. Want to add props to Ember Twin but don't feel like making a config file for it? We got you! Place that prop and the config file will be created automatically on your next save. -6. This even works for planets that were created by other mods! +You can use this to tweak the position, rotation, and scale of your props. These docs will not elaborate too much on this tool. There are other tutorials out there. ## Asset Bundles -Here is a template project: [Outer Wilds Unity Template](https://github.com/xen-42/outer-wilds-unity-template) +There is an [old unity template](https://github.com/xen-42/outer-wilds-unity-template) and a [new one](https://github.com/ow-mods/outer-wilds-unity-wiki/wiki#outer-wilds-unity-assets) -The template project contains ripped versions of all the game scripts, meaning you can put things like DirectionalForceVolumes in your Unity project to have artificial gravity volumes loaded right into the game. +The project contains ripped versions of all the game scripts, meaning you can put things like DirectionalForceVolumes in your Unity project to have artificial gravity volumes loaded right into the game. +Either one works, but the tool one has more tools and more feature-full versions of the scripts (in exchange for being invite-only) -If for whatever reason you want to set up a Unity project manually instead of using the template, follow these instructions: - -1. Start up a Unity 2019.4.39f1 project -2. In the "Assets" folder in Unity, create a new folder called "Editor". In it create a file called "CreateAssetBundle.cs" with the following code in it: - -```cs title="Editor/CreateAssetBundle.cs" -using UnityEditor; -using UnityEngine; -using System.IO; - -public class CreateAssetBundles -{ - [MenuItem("Assets/Build AssetBundles")] - static void BuildAllAssetBundles() - { - string assetBundleDirectory = "Assets/StreamingAssets"; - if (!Directory.Exists(Application.streamingAssetsPath)) - { - Directory.CreateDirectory(assetBundleDirectory); - } - BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64); - } -} -``` - -3. Create your object in the Unity scene and save it as a prefab. -4. Add all files used (models, prefabs, textures, materials, etc.) to an asset bundle by selecting them and using the dropdown in the bottom right. Here I am adding a rover model to my "rss" asset bundle for the Real Solar System add-on. - -![setting asset bundle](@/assets/docs-images/details/asset_bundle.webp) - -1. In the top left click the "Assets" drop-down and select "Build AssetBundles". This should create your asset bundle in a folder in the root directory called "StreamingAssets". -2. Copy the asset bundle and asset bundle .manifest files from StreamingAssets into your mod's "planets" folder. If you did everything properly they should work in game. To double-check everything is included, open the .manifest file in a text editor to see the files included and their paths. +Read [this guide](https://github.com/ow-mods/outer-wilds-unity-wiki/wiki/Tutorials-%E2%80%90-Using-asset-bundles) on how to work with asset bundles in editor. ## Importing a planet's surface from Unity diff --git a/docs/src/content/docs/guides/troubleshooting.md b/docs/src/content/docs/guides/troubleshooting.md index 879bd30a..d4650d40 100644 --- a/docs/src/content/docs/guides/troubleshooting.md +++ b/docs/src/content/docs/guides/troubleshooting.md @@ -17,3 +17,7 @@ which interact poorly with the fluid detector and can mess up the movement of th ## My Nomai text isn't updating Either clear the .nhcache files or enable Debug mode to always regenerate the text cache. + +## Prop placer is gone! +This is not a bug, actually. We removed prop placer because it was inconsistent and buggy, and no one in years cared enough to fix it. +Use the debug raycast button and Unity Explorer to place your props, or otherwise work in unity editor.