feat: expand editor scripting asset and viewport flow

This commit is contained in:
2026-04-03 13:22:30 +08:00
parent ed8c27fde2
commit a05d0b80a2
124 changed files with 10397 additions and 1737 deletions

View File

@@ -42,6 +42,12 @@ public:
events.push_back("RuntimeStop:" + (scene ? scene->GetName() : std::string("null")));
}
bool TryGetAvailableScriptClasses(
std::vector<ScriptClassDescriptor>& outClasses) const override {
outClasses = scriptClasses;
return true;
}
bool TryGetClassFieldMetadata(
const std::string& assemblyName,
const std::string& namespaceName,
@@ -117,6 +123,7 @@ public:
}
std::vector<std::string> events;
std::vector<ScriptClassDescriptor> scriptClasses;
std::vector<ScriptFieldMetadata> fieldMetadata;
std::vector<ScriptFieldDefaultValue> fieldDefaultValues;
std::unordered_map<std::string, ScriptFieldValue> managedFieldValues;
@@ -325,6 +332,83 @@ TEST_F(ScriptEngineTest, RuntimeCreatedScriptComponentIsTrackedImmediatelyAndSta
EXPECT_EQ(runtime.events, expectedAfterUpdate);
}
TEST_F(ScriptEngineTest, ScriptClassDiscoveryApiReturnsSortedDescriptorsAndSupportsAssemblyFilter) {
runtime.scriptClasses = {
{"Tools", "", "UtilityProbe"},
{"GameScripts", "Gameplay", "Zombie"},
{"GameScripts", "", "Bootstrap"},
{"GameScripts", "Gameplay", "Actor"},
{"Broken", "", ""}
};
std::vector<ScriptClassDescriptor> allClasses;
ASSERT_TRUE(engine->TryGetAvailableScriptClasses(allClasses));
const std::vector<ScriptClassDescriptor> expectedAllClasses = {
{"GameScripts", "", "Bootstrap"},
{"GameScripts", "Gameplay", "Actor"},
{"GameScripts", "Gameplay", "Zombie"},
{"Tools", "", "UtilityProbe"}
};
EXPECT_EQ(allClasses, expectedAllClasses);
EXPECT_EQ(allClasses[0].GetFullName(), "Bootstrap");
EXPECT_EQ(allClasses[1].GetFullName(), "Gameplay.Actor");
std::vector<ScriptClassDescriptor> gameScriptClasses;
ASSERT_TRUE(engine->TryGetAvailableScriptClasses(gameScriptClasses, "GameScripts"));
const std::vector<ScriptClassDescriptor> expectedGameScriptClasses = {
{"GameScripts", "", "Bootstrap"},
{"GameScripts", "Gameplay", "Actor"},
{"GameScripts", "Gameplay", "Zombie"}
};
EXPECT_EQ(gameScriptClasses, expectedGameScriptClasses);
}
TEST_F(ScriptEngineTest, ChangingScriptClassWhileRuntimeRunningRecreatesTrackedInstance) {
Scene* runtimeScene = CreateScene("RuntimeScene");
GameObject* host = runtimeScene->CreateGameObject("Host");
ScriptComponent* component = AddScriptComponent(host, "Gameplay", "OldClass");
engine->OnRuntimeStart(runtimeScene);
runtime.Clear();
component->SetScriptClass("GameScripts", "Gameplay", "NewClass");
const std::vector<std::string> expected = {
"OnDisable:Host:Gameplay.NewClass",
"OnDestroy:Host:Gameplay.NewClass",
"Destroy:Host:Gameplay.NewClass",
"Create:Host:Gameplay.NewClass",
"Awake:Host:Gameplay.NewClass",
"OnEnable:Host:Gameplay.NewClass"
};
EXPECT_EQ(runtime.events, expected);
EXPECT_TRUE(engine->HasTrackedScriptComponent(component));
EXPECT_TRUE(engine->HasRuntimeInstance(component));
}
TEST_F(ScriptEngineTest, ClearingScriptClassWhileRuntimeRunningDestroysTrackedInstance) {
Scene* runtimeScene = CreateScene("RuntimeScene");
GameObject* host = runtimeScene->CreateGameObject("Host");
ScriptComponent* component = AddScriptComponent(host, "Gameplay", "OldClass");
engine->OnRuntimeStart(runtimeScene);
runtime.Clear();
component->ClearScriptClass();
const std::vector<std::string> expected = {
"OnDisable:Host:",
"OnDestroy:Host:",
"Destroy:Host:"
};
EXPECT_EQ(runtime.events, expected);
EXPECT_FALSE(engine->HasTrackedScriptComponent(component));
EXPECT_FALSE(engine->HasRuntimeInstance(component));
EXPECT_FALSE(component->HasScriptClass());
}
TEST_F(ScriptEngineTest, FieldReadApiPrefersLiveManagedValueAndFallsBackToStoredValue) {
Scene* runtimeScene = CreateScene("RuntimeScene");
GameObject* host = runtimeScene->CreateGameObject("Host");