Handbuch Scroll-Listen entfernt. Handbuch offen und tabs eingefügt. Upgrades eingefügt. "Garage" eingefügt. Anbindung eines echten Gameplaymanager möglich (theoretisch)
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using DepthsOfGreed.HandbookUI;
|
||||
[InitializeOnLoad]
|
||||
public static class HandbookInspectorValidation
|
||||
{
|
||||
static HandbookInspectorValidation(){if(SessionState.GetBool("InspectorValidation",false))EditorApplication.playModeStateChanged+=Ready;}
|
||||
public static void Validate()
|
||||
{
|
||||
try
|
||||
{
|
||||
var scene=EditorSceneManager.OpenScene("Assets/Scenes/Tim_Test_UI.unity");
|
||||
var main=UnityEngine.Object.FindFirstObjectByType<HandbookController>(FindObjectsInactive.Include);var root=main.transform;
|
||||
if(!root.Find("GeneralFeedback")||!root.Find("OpenBook/ActiveTabLayer"))throw new Exception("Missing permanent UI.");
|
||||
if(root.GetComponentsInChildren<ScrollRect>(true).Length>0)throw new Exception("Scroll views remain in handbook.");
|
||||
var index=UnityEngine.Object.FindFirstObjectByType<HandbookIndexController>(FindObjectsInactive.Include);var iso=new SerializedObject(index);
|
||||
if(iso.FindProperty("entryButtons").arraySize!=24||iso.FindProperty("filterButtons").arraySize!=5)throw new Exception("Index inspector references invalid");
|
||||
var build=UnityEngine.Object.FindFirstObjectByType<BuildMenuController>(FindObjectsInactive.Include);if(new SerializedObject(build).FindProperty("categoryButtons").arraySize!=4)throw new Exception("Four build categories missing");
|
||||
foreach(var sceneRoot in scene.GetRootGameObjects())foreach(var tr in sceneRoot.GetComponentsInChildren<Transform>(true))if(GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(tr.gameObject)>0)throw new Exception("Missing script: "+tr.name);
|
||||
var authorCount=root.GetComponentsInChildren<RectTransform>(true).Count(r=>!r.name.StartsWith("TMP"));SessionState.SetInt("InspectorRectCount",authorCount);
|
||||
SessionState.SetBool("InspectorValidation",true);EditorApplication.playModeStateChanged+=Ready;EditorApplication.EnterPlaymode();
|
||||
}catch(Exception e){Debug.LogException(e);EditorApplication.Exit(1);}
|
||||
}
|
||||
private static void Ready(PlayModeStateChange state)
|
||||
{
|
||||
if(state!=PlayModeStateChange.EnteredPlayMode)return;SessionState.SetBool("InspectorValidation",false);EditorApplication.playModeStateChanged-=Ready;EditorApplication.delayCall+=Run;
|
||||
}
|
||||
private static void Run()
|
||||
{
|
||||
try
|
||||
{
|
||||
var c=UnityEngine.Object.FindFirstObjectByType<HandbookController>();c.Open(0);var root=c.transform;
|
||||
if(root.GetComponentsInChildren<RectTransform>(true).Count(r=>!r.name.StartsWith("TMP"))!=SessionState.GetInt("InspectorRectCount",0))throw new Exception("UI generated at runtime");
|
||||
var menu=UnityEngine.Object.FindFirstObjectByType<BuildMenuController>();int[] expected={6,6,3,4};for(int i=0;i<4;i++){menu.SelectCategory(i);if(menu.GetComponentsInChildren<TowerCardView>().Length!=expected[i])throw new Exception("Category count incorrect: "+i);}
|
||||
var p=root.GetComponent<TestPlacementController>();var catalog=AssetDatabase.LoadAssetAtPath<HandbookTowerCatalog>("Assets/HandbookData/TestTurmkatalog.asset");var gun=catalog.towers.First(t=>t.id=="ammo_0");var energy=catalog.towers.First(t=>t.id=="energy_0");
|
||||
if(!p.Backend.ExecuteBuild(new BuildRequest(gun,new Vector3(3.5f,0,0))).Allowed||!p.Backend.ExecuteBuild(new BuildRequest(energy,new Vector3(0,3.5f,0))).Allowed)throw new Exception("Base placement failed");
|
||||
var obj=p.Backend.BuiltObjects[0].instance;var renderer=obj.GetComponent<SpriteRenderer>();if(!renderer || !renderer.sprite || (gun.baseSprite && renderer.sprite!=gun.baseSprite) || renderer.bounds.size.x>0.8f)throw new Exception("Base sprite or placeholder scaling incorrect");
|
||||
int before=p.Backend.Energy;if(!p.Backend.ExecuteUpgrade(p.Backend.BuiltObjects[0].instanceId).Allowed||p.Backend.Energy>=before)throw new Exception("Upgrade failed");
|
||||
c.Open(2);var upgrades=UnityEngine.Object.FindFirstObjectByType<HandbookUpgradesController>();if(upgrades.VisibleUpgradeCount!=2)throw new Exception("Upgrade listing failed");
|
||||
c.Open(3);var index=UnityEngine.Object.FindFirstObjectByType<HandbookIndexController>();if(index.VisibleEntryCount!=24)throw new Exception("All entries not displayed");int[] counts={24,12,3,4,5};for(int i=0;i<5;i++){index.SelectFilter(i);if(index.VisibleEntryCount!=counts[i])throw new Exception("Index filter count incorrect");}
|
||||
index.SelectEntry(0);if(!index.SelectedEnemy)throw new Exception("Enemy detail missing");c.Open(0);c.Open(3);if(index.SelectedEnemy||index.SelectedEntry)throw new Exception("Index selection not reset");
|
||||
c.Close();Debug.Log("INSPECTOR_RUNTIME_VALIDATION_OK: no runtime UI generation, sprites, 4 build categories, 5 index filters, bases, placement and upgrades passed.");EditorApplication.Exit(0);
|
||||
}catch(Exception e){Debug.LogException(e);EditorApplication.Exit(1);}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d29615975ab3eb04e88d9ffe0715404f
|
||||
@@ -1,242 +0,0 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
|
||||
[InitializeOnLoad]
|
||||
public static class HandbookSceneValidation
|
||||
{
|
||||
public static void ConfigureFeedbackAndValidate()
|
||||
{
|
||||
try
|
||||
{
|
||||
var scene = EditorSceneManager.OpenScene("Assets/Scenes/Tim_Test_UI.unity");
|
||||
var controller = UnityEngine.Object.FindFirstObjectByType<DepthsOfGreed.HandbookUI.HandbookController>(FindObjectsInactive.Include);
|
||||
var serialized = new SerializedObject(controller);
|
||||
serialized.FindProperty("successfulPlacementDelay").floatValue = 0.5f;
|
||||
serialized.ApplyModifiedPropertiesWithoutUndo();
|
||||
EditorSceneManager.SaveScene(scene);
|
||||
Validate();
|
||||
}
|
||||
catch (Exception e) { Debug.LogException(e); EditorApplication.Exit(1); }
|
||||
}
|
||||
public static void SetupAndValidate()
|
||||
{
|
||||
try
|
||||
{
|
||||
const string dataFolder = "Assets/HandbookData";
|
||||
const string towerFolder = dataFolder + "/TestTowers";
|
||||
if (!AssetDatabase.IsValidFolder(dataFolder)) AssetDatabase.CreateFolder("Assets", "HandbookData");
|
||||
if (!AssetDatabase.IsValidFolder(towerFolder)) AssetDatabase.CreateFolder(dataFolder, "TestTowers");
|
||||
var names = new[] {
|
||||
new[] { "Gewehr", "Minigun", "Sniper", "Granatenwerfer", "Howitzer", "Flammenwerfer" },
|
||||
new[] { "Laser-Piercer", "Bouncer", "Pusher", "Knocker", "Laser-Beam" },
|
||||
new[] { "Falle", "Generator", "Staubsauger", "Spiegel" }
|
||||
};
|
||||
var prefixes = new[] { "ammo", "energy", "special" };
|
||||
var entries = new System.Collections.Generic.List<DepthsOfGreed.HandbookUI.HandbookTowerEntry>();
|
||||
for (int category = 0; category < names.Length; category++)
|
||||
for (int i = 0; i < names[category].Length; i++)
|
||||
{
|
||||
string path = towerFolder + "/" + prefixes[category] + "_" + i + "_" + names[category][i] + ".asset";
|
||||
var entry = AssetDatabase.LoadAssetAtPath<DepthsOfGreed.HandbookUI.HandbookTowerEntry>(path);
|
||||
if (!entry)
|
||||
{
|
||||
entry = ScriptableObject.CreateInstance<DepthsOfGreed.HandbookUI.HandbookTowerEntry>();
|
||||
entry.id = prefixes[category] + "_" + i;
|
||||
entry.displayName = names[category][i];
|
||||
entry.category = (DepthsOfGreed.HandbookUI.HandbookTowerCategory)category;
|
||||
entry.energyCost = 100 + i * 25;
|
||||
entry.summary = category == 0 ? "Schaden: 20 · Schüsse/s: 2" : category == 1 ? "Energieverbrauch: 5/s" :
|
||||
new[] { "Falle · Testwirkung", "Energieerzeugung · Testwert: 5/s", "Sammelfunktion · Testeintrag", "Umlenkung · Testeintrag" }[i];
|
||||
entry.description = entry.displayName + " – Testeintrag\n\nHier steht später eine kurze Erklärung der Funktion. Kosten und Werte sind vorläufige Testdaten.\n\nKlicken: zurück zur Baukarte";
|
||||
AssetDatabase.CreateAsset(entry, path);
|
||||
}
|
||||
entries.Add(entry);
|
||||
}
|
||||
const string catalogPath = dataFolder + "/TestTurmkatalog.asset";
|
||||
var catalog = AssetDatabase.LoadAssetAtPath<DepthsOfGreed.HandbookUI.HandbookTowerCatalog>(catalogPath);
|
||||
if (!catalog)
|
||||
{
|
||||
catalog = ScriptableObject.CreateInstance<DepthsOfGreed.HandbookUI.HandbookTowerCatalog>();
|
||||
catalog.towers = entries.ToArray();
|
||||
AssetDatabase.CreateAsset(catalog, catalogPath);
|
||||
}
|
||||
AssetDatabase.SaveAssets();
|
||||
var scene = EditorSceneManager.OpenScene("Assets/Scenes/Tim_Test_UI.unity");
|
||||
catalog = AssetDatabase.LoadAssetAtPath<DepthsOfGreed.HandbookUI.HandbookTowerCatalog>(catalogPath);
|
||||
if (!catalog) throw new Exception("Catalog asset could not be loaded after scene switch.");
|
||||
var controller = UnityEngine.Object.FindFirstObjectByType<DepthsOfGreed.HandbookUI.HandbookController>(FindObjectsInactive.Include);
|
||||
var serialized = new SerializedObject(controller);
|
||||
serialized.FindProperty("towerCatalog").objectReferenceValue = catalog;
|
||||
serialized.FindProperty("successfulPlacementDelay").floatValue = 1f;
|
||||
serialized.ApplyModifiedPropertiesWithoutUndo();
|
||||
EditorSceneManager.SaveScene(scene);
|
||||
Debug.Log("HANDBOOK_DATA_SETUP_OK: 15 editable tower assets and catalog connected; delay set to 1 second.");
|
||||
Validate();
|
||||
}
|
||||
catch (Exception exception) { Debug.LogException(exception); EditorApplication.Exit(1); }
|
||||
}
|
||||
static HandbookSceneValidation()
|
||||
{
|
||||
if (SessionState.GetBool("HandbookValidationPending", false))
|
||||
EditorApplication.playModeStateChanged += CheckPlayMode;
|
||||
}
|
||||
public static void Validate()
|
||||
{
|
||||
try
|
||||
{
|
||||
var scene = EditorSceneManager.OpenScene("Assets/Scenes/Tim_Test_UI.unity");
|
||||
var controllers = UnityEngine.Object.FindObjectsByType<DepthsOfGreed.HandbookUI.HandbookController>(FindObjectsInactive.Include, FindObjectsSortMode.None);
|
||||
if (controllers.Length != 1) throw new Exception("Expected exactly one handbook controller.");
|
||||
var serialized = new SerializedObject(controllers[0]);
|
||||
foreach (var field in new[] { "closedBook", "openBook", "bookButton", "closeButton", "closedTabsRoot", "openTabsRoot", "towerCatalog", "testTowerPrefab" })
|
||||
if (!serialized.FindProperty(field).objectReferenceValue) throw new Exception("Missing reference: " + field);
|
||||
foreach (var field in new[] { "closedTabs", "openTabs", "pages" })
|
||||
{
|
||||
var array = serialized.FindProperty(field);
|
||||
if (array.arraySize != 4) throw new Exception("Invalid array: " + field);
|
||||
for (int i = 0; i < array.arraySize; i++)
|
||||
if (!array.GetArrayElementAtIndex(i).objectReferenceValue) throw new Exception("Missing array reference: " + field);
|
||||
}
|
||||
foreach (var root in scene.GetRootGameObjects())
|
||||
foreach (var transform in root.GetComponentsInChildren<Transform>(true))
|
||||
if (GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(transform.gameObject) != 0)
|
||||
throw new Exception("Missing script on " + transform.name);
|
||||
Debug.Log("HANDBOOK_SCENE_VALIDATION_OK: Scene loaded; all controller references resolved; no missing scripts.");
|
||||
EditorApplication.playModeStateChanged += CheckPlayMode;
|
||||
SessionState.SetBool("HandbookValidationPending", true);
|
||||
EditorApplication.EnterPlaymode();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.LogException(exception);
|
||||
EditorApplication.Exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckPlayMode(PlayModeStateChange state)
|
||||
{
|
||||
if (state != PlayModeStateChange.EnteredPlayMode) return;
|
||||
SessionState.SetBool("HandbookValidationPending", false);
|
||||
EditorApplication.playModeStateChanged -= CheckPlayMode;
|
||||
try
|
||||
{
|
||||
var controller = UnityEngine.Object.FindFirstObjectByType<DepthsOfGreed.HandbookUI.HandbookController>();
|
||||
controller.Open(0);
|
||||
var menu = UnityEngine.Object.FindFirstObjectByType<DepthsOfGreed.HandbookUI.BuildMenuController>();
|
||||
if (!menu) throw new Exception("Build menu did not initialize.");
|
||||
foreach (var pair in new[] { (0, 6), (1, 5), (2, 4) })
|
||||
{
|
||||
menu.SelectCategory(pair.Item1);
|
||||
var cards = menu.GetComponentsInChildren<DepthsOfGreed.HandbookUI.TowerCardView>();
|
||||
if (cards.Length != pair.Item2) throw new Exception("Wrong category card count.");
|
||||
foreach (var card in cards)
|
||||
if (card.Entry == null || !card.transform.Find("Front").gameObject.activeSelf || card.transform.Find("Back").gameObject.activeSelf)
|
||||
throw new Exception("Invalid initial card state.");
|
||||
}
|
||||
menu.SelectCategory(0);
|
||||
var first = menu.GetComponentsInChildren<DepthsOfGreed.HandbookUI.TowerCardView>()[0];
|
||||
menu.ToggleCard(first);
|
||||
double deadline = EditorApplication.timeSinceStartup + 0.6;
|
||||
EditorApplication.CallbackFunction check = null;
|
||||
check = () => {
|
||||
if (EditorApplication.timeSinceStartup < deadline) return;
|
||||
EditorApplication.update -= check;
|
||||
try {
|
||||
if (!first.transform.Find("Back").gameObject.activeSelf) throw new Exception("Card flip did not complete.");
|
||||
menu.SelectCategory(1);
|
||||
if (first.transform.Find("Back").gameObject.activeSelf) throw new Exception("Category did not reset card.");
|
||||
controller.Close();
|
||||
controller.Open(0);
|
||||
if (menu.GetComponentsInChildren<DepthsOfGreed.HandbookUI.TowerCardView>().Length != 6)
|
||||
throw new Exception("Closing did not restore the default build category.");
|
||||
controller.Close();
|
||||
foreach (var card in menu.GetComponentsInChildren<DepthsOfGreed.HandbookUI.TowerCardView>(true))
|
||||
if (card.transform.Find("Back").gameObject.activeSelf) throw new Exception("Book close did not reset cards.");
|
||||
controller.Open(3);
|
||||
var indexMenu = UnityEngine.Object.FindFirstObjectByType<DepthsOfGreed.HandbookUI.HandbookIndexController>();
|
||||
if (!indexMenu || indexMenu.VisibleEntryCount != 15 || indexMenu.SelectedEntry != null)
|
||||
throw new Exception("Index initialization failed.");
|
||||
indexMenu.SelectEntry(0);
|
||||
if (!indexMenu.SelectedEntry) throw new Exception("Index selection failed.");
|
||||
indexMenu.ListScroll.verticalNormalizedPosition = 0f;
|
||||
controller.Open(0);
|
||||
controller.Open(3);
|
||||
if (indexMenu.SelectedEntry != null || indexMenu.ListScroll.verticalNormalizedPosition < 0.99f)
|
||||
throw new Exception("Index re-entry did not reset selection and scroll.");
|
||||
indexMenu.SelectFilter(2);
|
||||
if (indexMenu.VisibleEntryCount != 0 || indexMenu.SelectedEntry != null)
|
||||
throw new Exception("Enemy filter failed.");
|
||||
indexMenu.SelectFilter(1);
|
||||
if (indexMenu.VisibleEntryCount != 15) throw new Exception("Tower filter failed.");
|
||||
indexMenu.SelectEntry(1);
|
||||
controller.Close();
|
||||
controller.Open(3);
|
||||
if (indexMenu.SelectedEntry != null || indexMenu.ListScroll.verticalNormalizedPosition < 0.99f)
|
||||
throw new Exception("Reopening index did not reset selection and scroll.");
|
||||
controller.Close();
|
||||
var placement = controller.GetComponent<DepthsOfGreed.HandbookUI.TestPlacementController>();
|
||||
var entry = first.Entry;
|
||||
if (!placement.enabled) throw new Exception("Placement initialization failed.");
|
||||
controller.Open(0);
|
||||
var validScreen = (Vector2)Camera.main.WorldToScreenPoint(new Vector3(3.5f, 0, 0));
|
||||
if (!placement.Begin(entry, validScreen) || !placement.IsDragging) throw new Exception("Drag did not begin.");
|
||||
placement.Cancel();
|
||||
if (placement.IsDragging || placement.TowerCount != 0) throw new Exception("Cancel created a tower.");
|
||||
if (placement.TryPlaceAt(entry, Vector3.zero, out _)) throw new Exception("Center must be invalid.");
|
||||
if (placement.TryPlaceAt(entry, new Vector3(3.1f, 0, 0), out _)) throw new Exception("Base crosses inner wall.");
|
||||
if (placement.TryPlaceAt(entry, new Vector3(3.9f, 0, 0), out _)) throw new Exception("Base crosses outer wall.");
|
||||
int initialEnergy = placement.Energy;
|
||||
if (!placement.Begin(entry, validScreen)) throw new Exception("Second drag did not begin.");
|
||||
placement.End(validScreen);
|
||||
if (placement.TowerCount != 1 || placement.IsDragging) throw new Exception("Drag release failed.");
|
||||
if (!placement.IsWaitingForReturn) throw new Exception("Successful placement did not start delay.");
|
||||
for (int i = 1; i < 8; i++) {
|
||||
float angle = i * Mathf.PI / 4f;
|
||||
if (!placement.TryPlaceAt(entry, new Vector3(Mathf.Cos(angle) * 3.5f, Mathf.Sin(angle) * 3.5f, 0), out string reason))
|
||||
throw new Exception("Valid placement failed: " + reason);
|
||||
}
|
||||
if (placement.TowerCount != 8 || placement.Energy != initialEnergy - entry.energyCost * 8)
|
||||
throw new Exception("Wrong tower count or resource deduction.");
|
||||
if (placement.TryPlaceAt(entry, new Vector3(3.5f, 0, 0), out _)) throw new Exception("Overlap allowed.");
|
||||
float freeAngle = Mathf.PI / 8f;
|
||||
if (placement.TryPlaceAt(entry, new Vector3(Mathf.Cos(freeAngle) * 3.5f, Mathf.Sin(freeAngle) * 3.5f, 0), out string limitReason) || limitReason != "Turmlimit erreicht")
|
||||
throw new Exception("Tower limit failed.");
|
||||
double delayDeadline = EditorApplication.timeSinceStartup + 1.5;
|
||||
EditorApplication.CallbackFunction delayCheck = null;
|
||||
delayCheck = () => {
|
||||
if (EditorApplication.timeSinceStartup < delayDeadline) return;
|
||||
EditorApplication.update -= delayCheck;
|
||||
try {
|
||||
if (placement.IsWaitingForReturn) throw new Exception("Book delay never expired.");
|
||||
var group = menu.GetComponentInParent<CanvasGroup>();
|
||||
if (!group.blocksRaycasts) throw new Exception("Book input not restored after delay.");
|
||||
if (placement.Begin(entry, validScreen)) throw new Exception("Limit should prevent drag.");
|
||||
var toast = controller.transform.Find("FeedbackBox") ?? controller.transform.Find("Feedbackbox");
|
||||
var message = controller.transform.Find("FeedbackMessage").GetComponent<TMPro.TMP_Text>();
|
||||
if (!toast || !toast.gameObject.activeSelf || message.text != "Turmlimit erreicht")
|
||||
throw new Exception("Limit notice did not show background and message.");
|
||||
double toastDeadline = EditorApplication.timeSinceStartup + 2.9;
|
||||
EditorApplication.CallbackFunction toastCheck = null;
|
||||
toastCheck = () => {
|
||||
if (EditorApplication.timeSinceStartup < toastDeadline) return;
|
||||
EditorApplication.update -= toastCheck;
|
||||
try {
|
||||
if (toast.gameObject.activeSelf || message.text != "") throw new Exception("Notice did not disappear.");
|
||||
controller.Close();
|
||||
Debug.Log("HANDBOOK_RUNTIME_VALIDATION_OK: Category reset, 0.5-second placement delay, limit notice background and automatic dismissal passed; existing placement checks passed.");
|
||||
EditorApplication.Exit(0);
|
||||
} catch (Exception e) { Debug.LogException(e); EditorApplication.Exit(1); }
|
||||
};
|
||||
EditorApplication.update += toastCheck;
|
||||
} catch (Exception e) { Debug.LogException(e); EditorApplication.Exit(1); }
|
||||
};
|
||||
EditorApplication.update += delayCheck;
|
||||
} catch (Exception e) { Debug.LogException(e); EditorApplication.Exit(1); }
|
||||
};
|
||||
EditorApplication.update += check;
|
||||
}
|
||||
catch (Exception e) { Debug.LogException(e); EditorApplication.Exit(1); }
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79121ad9902be844f8f2b736dbf9adb5
|
||||
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using DepthsOfGreed.HandbookUI;
|
||||
|
||||
[InitializeOnLoad]
|
||||
public static class SupplyBasementValidation
|
||||
{
|
||||
static SupplyBasementValidation(){if(SessionState.GetBool("SupplyValidate",false))EditorApplication.playModeStateChanged+=Ready;}
|
||||
public static void Validate()
|
||||
{
|
||||
EditorSceneManager.OpenScene("Assets/Scenes/Tim_Test_UI.unity");
|
||||
SessionState.SetBool("SupplyValidate",true);EditorApplication.playModeStateChanged+=Ready;EditorApplication.EnterPlaymode();
|
||||
}
|
||||
static void Ready(PlayModeStateChange state)
|
||||
{
|
||||
if(state!=PlayModeStateChange.EnteredPlayMode)return;
|
||||
SessionState.SetBool("SupplyValidate",false);EditorApplication.playModeStateChanged-=Ready;
|
||||
double due=EditorApplication.timeSinceStartup+1;int stage=0;SupplyBasementController c=null;int count=0;long first=0;Vector3 bookScale=Vector3.one;
|
||||
EditorApplication.CallbackFunction run=null;run=()=>
|
||||
{
|
||||
if(EditorApplication.timeSinceStartup<due)return;
|
||||
try
|
||||
{
|
||||
if(stage==0)
|
||||
{
|
||||
c=UnityEngine.Object.FindFirstObjectByType<SupplyBasementController>();
|
||||
Assert(c && c.connectionButtons.Length==8 && c.priorityButtons.Length==3,"Authored references");
|
||||
Assert(!c.basementView.activeSelf && c.handbookRoot.activeSelf,"Starts on tower floor");
|
||||
count=Count(c);bookScale=c.handbook.transform.Find("OpenBook").localScale;
|
||||
var catalog=AssetDatabase.LoadAssetAtPath<HandbookTowerCatalog>("Assets/HandbookData/TestTurmkatalog.asset");
|
||||
var result=c.placement.Backend.ExecuteBuild(new BuildRequest(catalog.towers.First(t=>t.id=="ammo_0"),new Vector3(3.5f,0,0)));
|
||||
Assert(result.Allowed,"Test tower build");first=c.placement.Backend.BuiltObjects.Last().instanceId;
|
||||
c.UseLift();c.UseLift();stage=1;due=EditorApplication.timeSinceStartup+1.7;
|
||||
}
|
||||
else if(stage==1)
|
||||
{
|
||||
Assert(c.IsInBasement && !c.IsTravelling && c.basementView.activeSelf && c.handbookVisibility.alpha==0,"Lift arrival");
|
||||
Assert(c.handbookRoot.activeSelf && c.placement.isActiveAndEnabled,"Backend keeps updating in basement");
|
||||
Assert(c.connectionButtons[0].interactable && c.IsConnectionEnabled(first),"Automatic connection");
|
||||
c.ToggleConnection(0);Assert(!c.IsConnectionEnabled(first),"Disconnect");
|
||||
c.ToggleConnection(0);Assert(c.IsConnectionEnabled(first),"Reconnect");
|
||||
c.SetPriority(1);Assert(c.Priority==1,"Set priority");
|
||||
c.SetPriority(1);Assert(c.Priority==-1,"Return to automatic priority");
|
||||
// Force both travel directions independently of the loading pause.
|
||||
var pause=typeof(SupplyBasementController).GetField("truckPauseUntil",System.Reflection.BindingFlags.Instance|System.Reflection.BindingFlags.NonPublic);
|
||||
var truckPosition=c.truck.anchoredPosition;
|
||||
pause.SetValue(c,0f);c.truck.anchoredPosition=new Vector2(10000,truckPosition.y);c.SendMessage("Update");
|
||||
Assert(c.truck.localScale.x<0,"Truck faces left while driving left");
|
||||
pause.SetValue(c,0f);c.truck.anchoredPosition=new Vector2(-10000,truckPosition.y);c.SendMessage("Update");
|
||||
Assert(c.truck.localScale.x>0,"Truck faces right while driving right");
|
||||
c.truck.anchoredPosition=truckPosition;
|
||||
Assert(c.placement.Backend.BuiltObjects.Count==1,"No duplicate towers");
|
||||
if (SystemInfo.graphicsDeviceType != GraphicsDeviceType.Null && Environment.GetCommandLineArgs().Contains("-captureSupplyPreview")) Capture(c);
|
||||
Assert(Count(c)==count,"No generated room UI");
|
||||
c.UseLift();stage=2;due=EditorApplication.timeSinceStartup+1.7;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert(!c.IsInBasement && !c.IsTravelling && c.handbookRoot.activeSelf && c.handbookVisibility.alpha==1,"Return to tower");
|
||||
Assert(c.handbook.transform.Find("OpenBook").localScale==bookScale,"Book scale preserved");
|
||||
Assert(c.placement.Backend.BuiltObjects.Count==1,"Tower retained across trip");
|
||||
Assert(Count(c)==count,"No UI created on second trip");
|
||||
Debug.Log("SUPPLY_BASEMENT_RUNTIME_OK: native hierarchy, auto connection, toggle, priority, two-way lift and preserved book layout.");
|
||||
EditorApplication.update-=run;EditorApplication.Exit(0);
|
||||
}
|
||||
}
|
||||
catch(Exception e){EditorApplication.update-=run;Debug.LogException(e);EditorApplication.Exit(1);}
|
||||
};EditorApplication.update+=run;
|
||||
}
|
||||
static int Count(SupplyBasementController c)=>c.GetComponentInParent<Canvas>().GetComponentsInChildren<RectTransform>(true).Count(t=>!t.name.StartsWith("TMP"));
|
||||
static void Assert(bool condition,string message){if(!condition)throw new Exception(message);}
|
||||
static void Capture(SupplyBasementController c)
|
||||
{
|
||||
var camera=Camera.main;var canvas=c.GetComponentInParent<Canvas>();
|
||||
var rt=new RenderTexture(1920,1080,24);rt.Create();camera.targetTexture=rt;camera.aspect=1920f/1080;
|
||||
canvas.renderMode=RenderMode.ScreenSpaceCamera;canvas.worldCamera=camera;canvas.planeDistance=1;canvas.sortingOrder=200;
|
||||
Canvas.ForceUpdateCanvases();RenderPipeline.SubmitRenderRequest(camera,new UniversalRenderPipeline.SingleCameraRequest{destination=rt});
|
||||
var previous=RenderTexture.active;RenderTexture.active=rt;var tex=new Texture2D(1920,1080,TextureFormat.RGB24,false);tex.ReadPixels(new Rect(0,0,1920,1080),0,0);tex.Apply();RenderTexture.active=previous;
|
||||
var folder=Path.Combine(Path.GetDirectoryName(Application.dataPath),"Temp","HandbookValidation");
|
||||
Directory.CreateDirectory(folder);File.WriteAllBytes(Path.Combine(folder,"basement-preview.png"),tex.EncodeToPNG());
|
||||
UnityEngine.Object.DestroyImmediate(tex);camera.targetTexture=null;rt.Release();UnityEngine.Object.DestroyImmediate(rt);canvas.renderMode=RenderMode.ScreenSpaceOverlay;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5351dea0200aeb346b62d793f21fde75
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using DepthsOfGreed.HandbookUI;
|
||||
|
||||
[InitializeOnLoad]
|
||||
public static class SupplyBindingValidation
|
||||
{
|
||||
static SupplyBindingValidation(){if(SessionState.GetBool("SupplyBindingTest",false))EditorApplication.playModeStateChanged+=Ready;}
|
||||
public static void Validate(){EditorSceneManager.OpenScene("Assets/Scenes/Tim_Test_UI.unity");SessionState.SetBool("SupplyBindingTest",true);EditorApplication.playModeStateChanged+=Ready;EditorApplication.EnterPlaymode();}
|
||||
static void Check(bool value,string message){if(!value)throw new Exception(message);}
|
||||
static void Ready(PlayModeStateChange change)
|
||||
{
|
||||
if(change!=PlayModeStateChange.EnteredPlayMode)return;SessionState.SetBool("SupplyBindingTest",false);EditorApplication.playModeStateChanged-=Ready;
|
||||
double due=EditorApplication.timeSinceStartup+1;int stage=0;SupplyBasementController c=null;SupplyContractTestBackend fake=null;
|
||||
EditorApplication.CallbackFunction run=null;run=()=>
|
||||
{
|
||||
if(EditorApplication.timeSinceStartup<due)return;
|
||||
try
|
||||
{
|
||||
if(stage==0)
|
||||
{
|
||||
c=UnityEngine.Object.FindFirstObjectByType<SupplyBasementController>();fake=new GameObject("TEST_ONLY_SupplyAdapter").AddComponent<SupplyContractTestBackend>();
|
||||
var catalog=AssetDatabase.LoadAssetAtPath<HandbookTowerCatalog>("Assets/HandbookData/TestTurmkatalog.asset");
|
||||
Check(catalog.towers.Count(t=>t.supply.kind!=SupplyKind.None)==12,"Twelve supplied weapons");
|
||||
fake.state.towers=new[]{new TowerSupplyState{instanceId=987,type=catalog.towers.First(t=>t.id=="ammo_0"),magazine=17,magazineCapacity=40}};
|
||||
fake.state.channels=new[]{new SupplyChannelState{kind=SupplyKind.Physical,storage=180,storageCapacity=300,buffer=23,bufferCapacity=50}};
|
||||
fake.state.truck=new SupplyTruckState{phase=SupplyTruckPhase.Driving,from=SupplyStop.PhysicalTank,to=SupplyStop.Distributor,progress=.5f,cargoKind=SupplyKind.Physical,cargo=20,cargoCapacity=40};
|
||||
c.BindSupplyBackend(fake);c.UseLift();stage=1;due=EditorApplication.timeSinceStartup+1.7;
|
||||
}
|
||||
else
|
||||
{
|
||||
Check(c.IsInBasement && c.HasSupplyBackend,"Adapter attached");
|
||||
Check(c.connectionNames[0].text.Contains("987"),"Backend tower IDs, independent of prototype placement");
|
||||
Check(c.storageAmounts[0].text=="180 / 300" && c.bufferAmounts[0].text=="23 / 50","Channel snapshots rendered");
|
||||
Check(c.magazineAmounts[0].gameObject.activeSelf && c.magazineAmounts[0].text.Contains("17 / 40"),"Live magazine rendered");
|
||||
Check(Mathf.Abs(c.truck.anchoredPosition.x-Mathf.Lerp(c.loadingPositions[0],c.unloadingPosition,.5f))<.1f,"Backend drives truck; preview suppressed");
|
||||
c.ToggleConnection(0);Check(!fake.state.towers[0].connected && !c.IsConnectionEnabled(987),"Connection command accepted");
|
||||
fake.reject=true;c.ToggleConnection(0);Check(!c.IsConnectionEnabled(987),"Rejected command does not change connection");
|
||||
fake.reject=false;c.SetPriority(1);Check(fake.state.priority==SupplyKind.EnergyCells && c.Priority==1,"Priority command accepted");
|
||||
fake.reject=true;c.SetPriority(2);Check(c.Priority==1,"Rejected priority remains authoritative");
|
||||
fake.state.towers=Array.Empty<TowerSupplyState>();c.SendMessage("RefreshConnections");Check(!c.connectionButtons[0].interactable,"Removed tower frees slot");
|
||||
Debug.Log("SUPPLY_BINDING_VALIDATION_OK: fields, live amounts, external tower IDs, commands, rejection, truck route and removal.");EditorApplication.update-=run;EditorApplication.Exit(0);
|
||||
}
|
||||
}
|
||||
catch(Exception e){EditorApplication.update-=run;Debug.LogException(e);EditorApplication.Exit(1);}
|
||||
};EditorApplication.update+=run;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d55a01e5b6f36446890591cb0761214
|
||||
Reference in New Issue
Block a user