protected AdvancedDropdownItem AddWorlds(AdvancedDropdownItem parent, GameInfo_Volume vol) { int id = 0; foreach (var w in vol.Worlds.Where(x => x.Maps.Length > 0)) { var worldItem = new AdvancedDropdownItem(GetName(w.Index, WorldNames?.TryGetItem(w.Index))) { id = -1 }; foreach (var m in w.Maps.OrderBy(x => x)) { worldItem.AddChild(new MapSelectionDropdownItem(GetLevelName(w.Index, m), vol.Name, w.Index, m) { id = id++ }); } parent.AddChild(worldItem); } return(parent); }
protected override async UniTask UpdateEditorFieldsAsync() { FileSystem.Mode fileMode = FileSystem.Mode.Normal; if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.WebGL) { fileMode = FileSystem.Mode.Web; } bool refreshGameActions = (GameModeDropdown?.HasChanged ?? false) || (MapSelectionDropdown?.HasChanged ?? false); // Increase label width due to it being cut off otherwise EditorGUIUtility.labelWidth = 192; if (TotalyPos == 0f) { TotalyPos = position.height; } scrollbarShown = TotalyPos > position.height; ScrollPosition = GUI.BeginScrollView(new Rect(0, 0, EditorGUIUtility.currentViewWidth, position.height), ScrollPosition, new Rect(0, 0, EditorGUIUtility.currentViewWidth - (scrollbarShown ? scrollbarWidth : 0f), TotalyPos)); EditorGUI.BeginChangeCheck(); if (fileMode == FileSystem.Mode.Web) { EditorGUI.HelpBox(GetNextRect(ref YPos, height: 40f), "Your build target is configured as WebGL. Ray1Map will attempt to load from the server.", MessageType.Warning); } // Mode DrawHeader("Mode"); if (GameModeDropdown == null) { GameModeDropdown = new GameModeSelectionDropdown(new AdvancedDropdownState()); } var rectTemp = GetNextRect(ref YPos); var rbutton = EditorGUI.PrefixLabel(rectTemp, new GUIContent("Game")); rectTemp = new Rect(rbutton.x + rbutton.width - Mathf.Max(400f, rbutton.width), rbutton.y, Mathf.Max(400f, rbutton.width), rbutton.height); if (EditorGUI.DropdownButton(rbutton, new GUIContent(GameModeDropdown.SelectionName), FocusType.Passive)) { GameModeDropdown.Show(rectTemp); } Settings.LoadFromMemory = EditorField("Load from memory", Settings.LoadFromMemory); // Memory if (Settings.LoadFromMemory) { DrawHeader("Memory"); DefaultMemoryOptionsIndex = EditorField("Default memory options", DefaultMemoryOptionsIndex, DefaultMemoryOptionDisplayNames); if (DefaultMemoryOptionsIndex != PreviousDefaultMemoryOptionsIndex) { if (PreviousDefaultMemoryOptionsIndex == -1) { var match = Enumerable.Range(0, DefaultMemoryOptionDisplayNames.Length - 1).FirstOrDefault(x => DefaultMemoryConfigs[x].IsPointer == Settings.IsGameBaseAPointer && DefaultMemoryConfigs[x].ProcessName == Settings.ProcessName && DefaultMemoryConfigs[x].ModuleName == Settings.ModuleName && DefaultMemoryConfigs[x].Offset == Settings.GameBasePointer); DefaultMemoryOptionsIndex = match + 1; } PreviousDefaultMemoryOptionsIndex = DefaultMemoryOptionsIndex; if (DefaultMemoryOptionsIndex != 0) { Settings.IsGameBaseAPointer = DefaultMemoryConfigs[DefaultMemoryOptionsIndex - 1].IsPointer; Settings.ProcessName = DefaultMemoryConfigs[DefaultMemoryOptionsIndex - 1].ProcessName; Settings.ModuleName = DefaultMemoryConfigs[DefaultMemoryOptionsIndex - 1].ModuleName; Settings.GameBasePointer = DefaultMemoryConfigs[DefaultMemoryOptionsIndex - 1].Offset; } } EditorGUI.BeginDisabledGroup(DefaultMemoryOptionsIndex != 0); Settings.ProcessName = EditorField("Process name", Settings.ProcessName); Settings.ModuleName = EditorField("Module name", Settings.ModuleName); Settings.GameBasePointer = EditorField("Game memory offset", Settings.GameBasePointer); Settings.IsGameBaseAPointer = EditorField("Is offset a pointer", Settings.IsGameBaseAPointer); EditorGUI.EndDisabledGroup(); Settings.FindPointerAutomatically = EditorField("Find pointer automatically", Settings.FindPointerAutomatically); } // Map DrawHeader("Map"); if (fileMode == FileSystem.Mode.Normal) { rectTemp = GetNextRect(ref YPos); rbutton = EditorGUI.PrefixLabel(rectTemp, new GUIContent("Map")); rectTemp = new Rect(rbutton.x + rbutton.width - Mathf.Max(400f, rbutton.width), rbutton.y, Mathf.Max(400f, rbutton.width), rbutton.height); if (MapSelectionDropdown == null || GameModeDropdown.HasChanged) { if (GameModeDropdown.HasChanged) { Settings.SelectedGameMode = GameModeDropdown.Selection; GameModeDropdown.HasChanged = false; Dirty = true; } GameInfo_Volume[] volumes; try { var manager = Settings.GetGameManager; var settings = Settings.GetGameSettings; volumes = manager.GetLevels(settings); } catch (Exception ex) { volumes = new GameInfo_Volume[0]; Debug.LogWarning(ex.Message); } MapSelectionDropdown = new MapSelectionDropdown(new AdvancedDropdownState(), volumes, Settings.SelectedGameMode.GetAttribute <GameModeAttribute>().Game); // Debug.Log($"Map selection updated with {volumes.Length} volumes"); } if (EditorGUI.DropdownButton(rbutton, new GUIContent($"{(!string.IsNullOrEmpty(Settings.EduVolume) ? $"{Settings.EduVolume} - " : String.Empty)}{MapSelectionDropdown.GetWorldName(Settings.World)} {MapSelectionDropdown.GetLevelName(Settings.World, Settings.Level)}"), FocusType.Passive)) { MapSelectionDropdown.Show(rectTemp); } } else if (fileMode == FileSystem.Mode.Web) { if (GameModeDropdown.HasChanged) { Settings.SelectedGameMode = GameModeDropdown.Selection; GameModeDropdown.HasChanged = false; Dirty = true; } Settings.World = EditorField("World", Settings.World); Settings.Level = EditorField("Level", Settings.Level); Settings.EduVolume = EditorField("Volume", Settings.EduVolume); } // Directories DrawHeader("Directories" + (fileMode == FileSystem.Mode.Web ? " (Web)" : "")); Settings.HideDirSettings = !EditorGUI.Foldout(GetNextRect(ref YPos), !Settings.HideDirSettings, "Directories", true); if (!Settings.HideDirSettings) { var modes = EnumHelpers.GetValues <GameModeSelection>(); if (fileMode == FileSystem.Mode.Web) { foreach (var mode in modes) { Settings.GameDirectoriesWeb[mode] = EditorField(mode.GetAttribute <GameModeAttribute>()?.DisplayName ?? "N/A", Settings.GameDirectoriesWeb.TryGetItem(mode, String.Empty)); } } else { foreach (var mode in modes) { Settings.GameDirectories[mode] = DirectoryField(GetNextRect(ref YPos), mode.GetAttribute <GameModeAttribute>()?.DisplayName ?? "N/A", Settings.GameDirectories.TryGetItem(mode, String.Empty)); } } } // Visibility DrawHeader("Visibility"); Settings.ShowObjects = EditorField("Show objects (O)", Settings.ShowObjects); Settings.ShowLinks = EditorField("Show links (L)", Settings.ShowLinks); Settings.ShowTiles = EditorField("Show tiles (T)", Settings.ShowTiles); Settings.ShowCollision = EditorField("Show tile collision (C)", Settings.ShowCollision); Settings.ShowGridMap = EditorField("Show grid map", Settings.ShowGridMap); Settings.ShowObjCollision = EditorField("Show object collision (B)", Settings.ShowObjCollision); Settings.ShowAlwaysObjects = EditorField("Show always objects (G)", Settings.ShowAlwaysObjects); Settings.ShowEditorObjects = EditorField("Show editor objects (E)", Settings.ShowEditorObjects); Settings.ShowDefaultObjIcons = EditorField("Show gizmos", Settings.ShowDefaultObjIcons); Settings.ShowObjOffsets = EditorField("Show object offsets (X)", Settings.ShowObjOffsets); Settings.ShowRayman = EditorField("Show Rayman object (R)", Settings.ShowRayman); Settings.HideUnusedLinks = EditorField("Hide unused links", Settings.HideUnusedLinks); // Miscellaneous DrawHeader("Miscellaneous"); Settings.UseHDCollisionSheet = EditorField("Use HD collision sheet", Settings.UseHDCollisionSheet); Settings.AnimateSprites = EditorField("Animate sprites (P)", Settings.AnimateSprites); Settings.AnimateTiles = EditorField("Animate tiles (Y)", Settings.AnimateTiles); Settings.ShowDebugInfo = EditorField("Show debug info", Settings.ShowDebugInfo); Settings.FollowRaymanInMemoryMode = EditorField("Follow Rayman in memory mode", Settings.FollowRaymanInMemoryMode); // Game Settings DrawHeader("Game Settings"); Settings.StateSwitchingMode = EditorField("R1: State switching", Settings.StateSwitchingMode); Settings.LoadIsometricMapLayer = EditorField("Isometric: Load map layer", Settings.LoadIsometricMapLayer); Settings.GBAVV_Crash_TimeTrialMode = EditorField("GBAVV Crash: Time trial mode", Settings.GBAVV_Crash_TimeTrialMode); // Editor Tools if (Application.isPlaying && Controller.LoadState == Controller.State.Finished) { var lvl = LevelEditorData.Level; if (lvl != null) { DrawHeader("Editor Tools"); if (EditorButton("Copy localization")) { if (lvl.Localization != null) { JsonConvert.SerializeObject(lvl.Localization, Formatting.Indented).CopyToClipboard(); } } if (LevelEditorData.ObjManager is Unity_ObjectManager_R1 r1 && r1.EventFlags != null) { if (EditorButton("Copy event flag info")) { r1.GetEventFlagsDebugInfo().CopyToClipboard(); } } if (LevelEditorData.Level?.IsometricData != null) { var cam = Controller.obj?.levelController?.editor?.cam; if (cam != null) { cam.ToggleFreeCameraMode(EditorField($"Free camera mode (F)", cam.FreeCameraMode)); } } if (Controller.obj?.levelController?.controllerTilemap != null) { var tilemapController = Controller.obj.levelController.controllerTilemap; if (lvl.Background != null && tilemapController.background != null) { var bg = tilemapController.background; var isActive = EditorField($"Show background", bg.gameObject.activeSelf); if (isActive != bg.gameObject.activeSelf) { bg.gameObject.SetActive(isActive); } } if (lvl.ParallaxBackground != null && tilemapController.backgroundParallax != null) { var bg = tilemapController.backgroundParallax; var isActive = EditorField($"Show parallax background", bg.gameObject.activeSelf); if (isActive != bg.gameObject.activeSelf) { bg.gameObject.SetActive(isActive); } } var layerVisibilities = tilemapController.IsLayerVisible; if (layerVisibilities != null) { for (int i = 0; i < layerVisibilities.Length; i++) { layerVisibilities[i] = EditorField($"Show layer {i} ({LevelEditorData.Level.Maps[i].Type})", layerVisibilities[i]); } } if (lvl.Background != null && tilemapController.background != null) { var bg = tilemapController.background; var spr = bg.sprite; if (spr == null || spr.rect.width / spr.pixelsPerUnit != LevelEditorData.MaxWidth * tilemapController.CellSizeInUnits || spr.rect.height / spr.pixelsPerUnit != LevelEditorData.MaxHeight * tilemapController.CellSizeInUnits) { bool wasTiled = bg.drawMode == SpriteDrawMode.Tiled; bool setTiled = EditorField($"Tile background", wasTiled); if (setTiled != wasTiled) { tilemapController.SetGraphicsLayerTiled(LevelTilemapController.Index_Background, setTiled); } } } if (lvl.Background != null && tilemapController.backgroundParallax != null) { var bg = tilemapController.backgroundParallax; var spr = bg.sprite; if (spr == null || spr.rect.width / spr.pixelsPerUnit != LevelEditorData.MaxWidth * tilemapController.CellSizeInUnits || spr.rect.height / spr.pixelsPerUnit != LevelEditorData.MaxHeight * tilemapController.CellSizeInUnits) { bool wasTiled = bg.drawMode == SpriteDrawMode.Tiled; bool setTiled = EditorField($"Tile parallax background", wasTiled); if (setTiled != wasTiled) { tilemapController.SetGraphicsLayerTiled(LevelTilemapController.Index_ParallaxBackground, setTiled); } } } if (tilemapController.GraphicsTilemaps != null) { for (int i = 0; i < tilemapController.GraphicsTilemaps.Length; i++) { if (tilemapController.GraphicsTilemaps[i] != null) { var spr = tilemapController.GraphicsTilemaps[i].sprite; if (spr == null || spr.rect.width / spr.pixelsPerUnit != LevelEditorData.MaxWidth * tilemapController.CellSizeInUnits || spr.rect.height / spr.pixelsPerUnit != LevelEditorData.MaxHeight * tilemapController.CellSizeInUnits) { bool wasTiled = tilemapController.GraphicsTilemaps[i].drawMode == SpriteDrawMode.Tiled; bool setTiled = EditorField($"Tile graphics layer {i}", wasTiled); if (setTiled != wasTiled) { tilemapController.SetGraphicsLayerTiled(i, setTiled); } } } } } } if (LevelEditorData.ShowEventsForMaps != null) { for (int i = 0; i < LevelEditorData.ShowEventsForMaps.Length; i++) { LevelEditorData.ShowEventsForMaps[i] = EditorField($"Show objects for layer {i}", LevelEditorData.ShowEventsForMaps[i]); } } if (LevelEditorData.Level?.Sectors != null) { LevelEditorData.ShowOnlyActiveSector = EditorField("Show only active sector", LevelEditorData.ShowOnlyActiveSector); LevelEditorData.ActiveSector = EditorField("Active sector", LevelEditorData.ActiveSector, LevelEditorData.Level.Sectors.Select((x, i) => i.ToString()).ToArray(), isVisible: LevelEditorData.ShowOnlyActiveSector); } if (PalOptions == null) { if (Controller.obj.levelController.controllerTilemap.HasAutoPaletteOption) { PalOptions = new string[] { "Auto" }.Concat(Enumerable.Range(0, LevelEditorData.Level.Maps.Max(x => x.TileSet.Length)).Select(x => x.ToString())).ToArray(); } else { PalOptions = Enumerable.Range(0, LevelEditorData.Level.Maps.Max(x => x.TileSet.Length)).Select(x => x.ToString()).ToArray(); } } if (Controller.obj?.levelController?.controllerTilemap != null) { if (Controller.obj.levelController.controllerTilemap.HasAutoPaletteOption) { Controller.obj.levelController.controllerTilemap.currentPalette = EditorField("Palette", Controller.obj.levelController.controllerTilemap.currentPalette, PalOptions); } else { Controller.obj.levelController.controllerTilemap.currentPalette = EditorField("Palette", Controller.obj.levelController.controllerTilemap.currentPalette - 1, PalOptions) + 1; } } } } else { PalOptions = null; } // Screenshots DrawHeader("Screenshots"); Settings.ScreenshotEnumeration = EditorField("Screenshot enumeration", Settings.ScreenshotEnumeration); Settings.Screenshot_FileName = EditorField("File name", Settings.Screenshot_FileName); Settings.Screenshot_ShowDefaultObj = EditorField("Show default object", Settings.Screenshot_ShowDefaultObj); Settings.Screenshot_RayWikiMode = EditorField("RayWiki mode", Settings.Screenshot_RayWikiMode); // Serialization DrawHeader("Serialization"); Settings.BackupFiles = EditorField("Create .BAK backup files", Settings.BackupFiles); Rect rect = GetNextRect(ref YPos); rect = EditorGUI.PrefixLabel(rect, new GUIContent("Serialization log")); bool log = Settings.Log; rect = PrefixToggle(rect, ref log); Settings.Log = log; if (Settings.Log) { Settings.LogFile = FileField(rect, "Serialization log File", Settings.LogFile, true, "txt", includeLabel: false); } // External Tools DrawHeader("External Tools"); Settings.Tool_mkpsxiso_filePath = FileField(GetNextRect(ref YPos), "mkpsxiso path", Settings.Tool_mkpsxiso_filePath, false, "exe"); // Game Tools DrawHeader("Game Tools"); // Only update if previous values don't match if (CurrentGameActions == null || refreshGameActions) { if (fileMode != FileSystem.Mode.Web) { MapSelectionDropdown.HasChanged = false; Settings.EduVolume = MapSelectionDropdown.SelectedVolume; Settings.World = MapSelectionDropdown.SelectedWorld; Settings.Level = MapSelectionDropdown.SelectedMap; } Dirty = true; CurrentGameActions = Settings.GetGameManager.GetGameActions(Settings.GetGameSettings); } // Add every game action foreach (GameAction action in CurrentGameActions) { if (EditorButton(action.DisplayName)) { // Get the directories string inputDir = action.RequiresInputDir ? EditorUtility.OpenFolderPanel("Select input directory", null, "") : null; if (string.IsNullOrEmpty(inputDir) && action.RequiresInputDir) { return; } string outputDir = action.RequiresOutputDir ? EditorUtility.OpenFolderPanel("Select output directory", null, "") : null; if (string.IsNullOrEmpty(outputDir) && action.RequiresOutputDir) { return; } try { Controller.StartStopwatch(); // Run the action await action.GameActionFunc(inputDir, outputDir); } catch (Exception ex) { Debug.LogError(ex.ToString()); } finally { Controller.StopStopwatch(); } } } // Global Tools DrawHeader("Global Tools"); async UniTask AddGlobalActionAsync(string actionName) { if (EditorButton(actionName)) { // Get the output directory string outputDir = EditorUtility.OpenFolderPanel("Select output directory", null, ""); if (string.IsNullOrEmpty(outputDir)) { return; } //const GameModeSelection start = GameModeSelection.RaymanJaguar; //var reachedStart = false; // Run each action foreach (var mode in EnumHelpers.GetValues <GameModeSelection>()) { //if (!reachedStart) //{ // if (mode == start) // reachedStart = true; // else // continue; //} // Make sure the mode is valid if (!Settings.GameDirectories.ContainsKey(mode)) { Debug.LogWarning($"Mode {mode} was skipped due to not having a valid directory"); continue; } // Create settings var settings = new GameSettings(mode, Settings.GameDirectories[mode], Settings.World, Settings.Level); // Get manager var manager = settings.GetGameManager; // Set to default EDU volume settings.EduVolume = manager.GetLevels(settings).FirstOrDefault()?.Name; // Get action var action = manager.GetGameActions(settings).FirstOrDefault(x => x.DisplayName.Equals(actionName, StringComparison.CurrentCultureIgnoreCase)); // Make sure an action was found if (action == null) { Debug.LogWarning($"Mode {mode} was skipped due to not having a matching action"); continue; } try { // Run the action await action.GameActionFunc(null, Path.Combine(outputDir, mode.ToString())); } catch (Exception ex) { Debug.LogWarning($"Mode {mode} failed with exception: {ex.Message}"); } finally { // Unload textures await Resources.UnloadUnusedAssets(); } } } } // Add special game actions await AddGlobalActionAsync("Export Sprites"); await AddGlobalActionAsync("Export Animation Frames"); await AddGlobalActionAsync("Export Vignette"); // Randomizer DrawHeader("Randomizer"); if (EditorButton("Run Randomizer")) { string seed = $"{Settings.World},{Settings.Level},{Settings.RandomizerSeed}"; Randomizer.Randomize(LevelEditorData.Level, Settings.World, Settings.Level, Settings.RandomizerFlags, seed.GetHashCode(), 0, null); } if (EditorButton("Run Batch Randomizer")) { await Randomizer.BatchRandomizeAsync(); } Settings.RandomizerSeed = EditorField("Seed", Settings.RandomizerSeed); Settings.RandomizerFlags = (RandomizerFlags)EditorGUI.EnumFlagsField(GetNextRect(ref YPos), "Flags", Settings.RandomizerFlags); TotalyPos = YPos; GUI.EndScrollView(); if (EditorGUI.EndChangeCheck() || Dirty) { Settings.Save(); Dirty = false; } }