#include #include "ComponentEditors/ScriptComponentEditorUtils.h" #include namespace XCEngine::Editor { namespace { TEST(ScriptComponentEditorUtils_Test, BuildsReadableScriptClassDisplayNames) { const ::XCEngine::Scripting::ScriptClassDescriptor gameScript{ "GameScripts", "Gameplay", "PlayerController" }; const ::XCEngine::Scripting::ScriptClassDescriptor toolScript{ "EditorTools", "Gameplay", "PlayerController" }; EXPECT_EQ( ScriptComponentEditorUtils::BuildScriptClassDisplayName(gameScript), "Gameplay.PlayerController"); EXPECT_EQ( ScriptComponentEditorUtils::BuildScriptClassDisplayName(toolScript), "Gameplay.PlayerController (EditorTools)"); ::XCEngine::Scripting::ScriptComponent component; component.SetScriptClass("GameScripts", "ProjectScripts", "Mover"); EXPECT_EQ( ScriptComponentEditorUtils::BuildScriptClassDisplayName(component), "ProjectScripts.Mover"); } TEST(ScriptComponentEditorUtils_Test, FindsGameObjectIdsByUuidAcrossHierarchy) { ::XCEngine::Components::GameObject root("Root"); ::XCEngine::Components::GameObject child("Child"); ::XCEngine::Components::GameObject grandChild("GrandChild"); child.SetParent(&root); grandChild.SetParent(&child); const std::vector<::XCEngine::Components::GameObject*> roots = { &root }; EXPECT_EQ( ScriptComponentEditorUtils::FindGameObjectIdByUuid(roots, child.GetUUID()), child.GetID()); EXPECT_EQ( ScriptComponentEditorUtils::FindGameObjectIdByUuid(roots, grandChild.GetUUID()), grandChild.GetID()); EXPECT_EQ( ScriptComponentEditorUtils::FindGameObjectIdByUuid(roots, 0), ::XCEngine::Components::GameObject::INVALID_ID); } TEST(ScriptComponentEditorUtils_Test, ReportsFieldEditabilityClearabilityAndIssues) { ::XCEngine::Scripting::ScriptFieldSnapshot declaredField; declaredField.metadata = { "Health", ::XCEngine::Scripting::ScriptFieldType::Int32 }; declaredField.declaredInClass = true; ::XCEngine::Scripting::ScriptFieldSnapshot storedOnlyField; storedOnlyField.metadata = { "LegacyValue", ::XCEngine::Scripting::ScriptFieldType::String }; storedOnlyField.hasValue = true; storedOnlyField.value = std::string("legacy"); storedOnlyField.valueSource = ::XCEngine::Scripting::ScriptFieldValueSource::StoredValue; storedOnlyField.issue = ::XCEngine::Scripting::ScriptFieldIssue::StoredOnly; storedOnlyField.hasStoredValue = true; storedOnlyField.storedType = ::XCEngine::Scripting::ScriptFieldType::String; storedOnlyField.storedValue = std::string("legacy"); ::XCEngine::Scripting::ScriptFieldSnapshot mismatchedField; mismatchedField.metadata = { "Speed", ::XCEngine::Scripting::ScriptFieldType::Float }; mismatchedField.declaredInClass = true; mismatchedField.issue = ::XCEngine::Scripting::ScriptFieldIssue::TypeMismatch; mismatchedField.hasStoredValue = true; mismatchedField.storedType = ::XCEngine::Scripting::ScriptFieldType::UInt64; mismatchedField.storedValue = uint64_t(5); EXPECT_TRUE(ScriptComponentEditorUtils::CanEditScriptField( ::XCEngine::Scripting::ScriptFieldClassStatus::Available, declaredField)); EXPECT_FALSE(ScriptComponentEditorUtils::CanEditScriptField( ::XCEngine::Scripting::ScriptFieldClassStatus::Available, storedOnlyField)); EXPECT_TRUE(ScriptComponentEditorUtils::CanEditScriptField( ::XCEngine::Scripting::ScriptFieldClassStatus::Missing, storedOnlyField)); EXPECT_FALSE(ScriptComponentEditorUtils::CanClearScriptFieldOverride(declaredField)); EXPECT_TRUE(ScriptComponentEditorUtils::CanClearScriptFieldOverride(storedOnlyField)); EXPECT_TRUE(ScriptComponentEditorUtils::CanClearScriptFieldOverride(mismatchedField)); EXPECT_EQ( ScriptComponentEditorUtils::BuildScriptFieldIssueText(storedOnlyField), "Stored override is not declared by the selected script."); EXPECT_EQ( ScriptComponentEditorUtils::BuildScriptFieldIssueText(mismatchedField), "Stored override type is UInt64, but the script field expects Float."); } TEST(ScriptComponentEditorUtils_Test, BuildsRuntimeUnavailableHintsAndReloadAvailability) { EditorScriptRuntimeStatus missingAssembliesStatus; missingAssembliesStatus.backendEnabled = true; missingAssembliesStatus.assemblyDirectory = "D:/Project/Library/ScriptAssemblies"; missingAssembliesStatus.statusMessage = "Script assemblies were not found in D:/Project/Library/ScriptAssemblies. " "Script class discovery is disabled until the managed assemblies are built."; EXPECT_EQ( ScriptComponentEditorUtils::BuildScriptRuntimeUnavailableHint(missingAssembliesStatus), missingAssembliesStatus.statusMessage); EXPECT_TRUE(ScriptComponentEditorUtils::CanReloadScriptRuntime(missingAssembliesStatus)); EXPECT_TRUE(ScriptComponentEditorUtils::CanRebuildScriptAssemblies(missingAssembliesStatus)); EditorScriptRuntimeStatus fallbackStatus; fallbackStatus.backendEnabled = true; fallbackStatus.assemblyDirectory = "D:/Project/Library/ScriptAssemblies"; EXPECT_EQ( ScriptComponentEditorUtils::BuildScriptRuntimeUnavailableHint(fallbackStatus), "No script assemblies are currently loaded from D:/Project/Library/ScriptAssemblies."); EXPECT_TRUE(ScriptComponentEditorUtils::CanReloadScriptRuntime(fallbackStatus)); EXPECT_TRUE(ScriptComponentEditorUtils::CanRebuildScriptAssemblies(fallbackStatus)); EditorScriptRuntimeStatus backendDisabledStatus; EXPECT_EQ( ScriptComponentEditorUtils::BuildScriptRuntimeUnavailableHint(backendDisabledStatus), "This editor build does not include Mono scripting support."); EXPECT_FALSE(ScriptComponentEditorUtils::CanReloadScriptRuntime(backendDisabledStatus)); EXPECT_FALSE(ScriptComponentEditorUtils::CanRebuildScriptAssemblies(backendDisabledStatus)); } } // namespace } // namespace XCEngine::Editor