feat(physics): dispatch PhysX simulation events to scene scripts
This commit is contained in:
@@ -2097,10 +2097,46 @@ void MonoScriptRuntime::InvokeMethod(
|
||||
|
||||
const float previousDeltaTime = GetInternalCallDeltaTime();
|
||||
GetInternalCallDeltaTime() = deltaTime;
|
||||
InvokeManagedMethod(instance, managedMethod);
|
||||
InvokeManagedMethod(instance, managedMethod, nullptr);
|
||||
GetInternalCallDeltaTime() = previousDeltaTime;
|
||||
}
|
||||
|
||||
void MonoScriptRuntime::InvokePhysicsMessage(
|
||||
const ScriptRuntimeContext& context,
|
||||
ScriptPhysicsMessage message,
|
||||
Components::GameObject* other) {
|
||||
const InstanceData* instanceData = FindInstance(context);
|
||||
if (!instanceData || !instanceData->classMetadata) {
|
||||
return;
|
||||
}
|
||||
|
||||
const PhysicsMessageMethods& methods =
|
||||
instanceData->classMetadata->physicsMessageMethods[static_cast<size_t>(message)];
|
||||
MonoMethod* managedMethod = methods.withGameObject ? methods.withGameObject : methods.withoutArgs;
|
||||
if (!managedMethod) {
|
||||
return;
|
||||
}
|
||||
|
||||
MonoObject* instance = GetManagedObject(*instanceData);
|
||||
if (!instance) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (methods.withGameObject) {
|
||||
MonoObject* managedOther = other ? CreateManagedGameObject(other->GetUUID()) : nullptr;
|
||||
if (other && !managedOther) {
|
||||
return;
|
||||
}
|
||||
|
||||
void* args[1];
|
||||
args[0] = managedOther;
|
||||
InvokeManagedMethod(instance, managedMethod, args);
|
||||
return;
|
||||
}
|
||||
|
||||
InvokeManagedMethod(instance, managedMethod, nullptr);
|
||||
}
|
||||
|
||||
size_t MonoScriptRuntime::InstanceKeyHasher::operator()(const InstanceKey& key) const {
|
||||
const size_t h1 = std::hash<uint64_t>{}(key.gameObjectUUID);
|
||||
const size_t h2 = std::hash<uint64_t>{}(key.scriptComponentUUID);
|
||||
@@ -2346,6 +2382,18 @@ void MonoScriptRuntime::DiscoverScriptClassesInImage(const std::string& assembly
|
||||
0);
|
||||
}
|
||||
|
||||
for (size_t methodIndex = 0; methodIndex < PhysicsMessageCount; ++methodIndex) {
|
||||
PhysicsMessageMethods& methods = metadata.physicsMessageMethods[methodIndex];
|
||||
methods.withGameObject = mono_class_get_method_from_name(
|
||||
monoClass,
|
||||
ToPhysicsMessageMethodName(static_cast<ScriptPhysicsMessage>(methodIndex)),
|
||||
1);
|
||||
methods.withoutArgs = mono_class_get_method_from_name(
|
||||
monoClass,
|
||||
ToPhysicsMessageMethodName(static_cast<ScriptPhysicsMessage>(methodIndex)),
|
||||
0);
|
||||
}
|
||||
|
||||
void* fieldIterator = nullptr;
|
||||
while (MonoClassField* field = mono_class_get_fields(monoClass, &fieldIterator)) {
|
||||
const uint32_t fieldFlags = mono_field_get_flags(field);
|
||||
@@ -2564,6 +2612,19 @@ const char* MonoScriptRuntime::ToLifecycleMethodName(ScriptLifecycleMethod metho
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* MonoScriptRuntime::ToPhysicsMessageMethodName(ScriptPhysicsMessage message) {
|
||||
switch (message) {
|
||||
case ScriptPhysicsMessage::CollisionEnter: return "OnCollisionEnter";
|
||||
case ScriptPhysicsMessage::CollisionStay: return "OnCollisionStay";
|
||||
case ScriptPhysicsMessage::CollisionExit: return "OnCollisionExit";
|
||||
case ScriptPhysicsMessage::TriggerEnter: return "OnTriggerEnter";
|
||||
case ScriptPhysicsMessage::TriggerStay: return "OnTriggerStay";
|
||||
case ScriptPhysicsMessage::TriggerExit: return "OnTriggerExit";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
const MonoScriptRuntime::ClassMetadata* MonoScriptRuntime::FindClassMetadata(
|
||||
const std::string& assemblyName,
|
||||
const std::string& namespaceName,
|
||||
@@ -3207,7 +3268,7 @@ void MonoScriptRuntime::ClearClassCache() {
|
||||
m_classes.clear();
|
||||
}
|
||||
|
||||
bool MonoScriptRuntime::InvokeManagedMethod(MonoObject* instance, MonoMethod* method) {
|
||||
bool MonoScriptRuntime::InvokeManagedMethod(MonoObject* instance, MonoMethod* method, void** args) {
|
||||
if (!instance || !method) {
|
||||
return false;
|
||||
}
|
||||
@@ -3215,7 +3276,7 @@ bool MonoScriptRuntime::InvokeManagedMethod(MonoObject* instance, MonoMethod* me
|
||||
SetCurrentDomain();
|
||||
|
||||
MonoObject* exception = nullptr;
|
||||
mono_runtime_invoke(method, instance, nullptr, &exception);
|
||||
mono_runtime_invoke(method, instance, args, &exception);
|
||||
if (exception) {
|
||||
RecordException(exception);
|
||||
return false;
|
||||
|
||||
@@ -82,5 +82,14 @@ void NullScriptRuntime::InvokeMethod(
|
||||
(void)deltaTime;
|
||||
}
|
||||
|
||||
void NullScriptRuntime::InvokePhysicsMessage(
|
||||
const ScriptRuntimeContext& context,
|
||||
ScriptPhysicsMessage message,
|
||||
Components::GameObject* other) {
|
||||
(void)context;
|
||||
(void)message;
|
||||
(void)other;
|
||||
}
|
||||
|
||||
} // namespace Scripting
|
||||
} // namespace XCEngine
|
||||
|
||||
@@ -258,6 +258,28 @@ void ScriptEngine::OnLateUpdate(float deltaTime) {
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::DispatchPhysicsMessage(
|
||||
Components::GameObject* gameObject,
|
||||
ScriptPhysicsMessage message,
|
||||
Components::GameObject* other) {
|
||||
if (!m_runtimeRunning || !gameObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ScriptComponent* component : gameObject->GetComponents<ScriptComponent>()) {
|
||||
if (!component) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ScriptInstanceState* state = FindState(component);
|
||||
if (!state || !ShouldScriptRun(*state) || !EnsureScriptReady(*state, true) || !state->enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
InvokePhysicsMessage(*state, message, other);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::OnScriptComponentEnabled(ScriptComponent* component) {
|
||||
if (!m_runtimeRunning || !component) {
|
||||
return;
|
||||
@@ -887,6 +909,14 @@ void ScriptEngine::InvokeLifecycleMethod(ScriptInstanceState& state, ScriptLifec
|
||||
m_runtime->SyncManagedFieldsToStorage(state.context);
|
||||
}
|
||||
|
||||
void ScriptEngine::InvokePhysicsMessage(
|
||||
ScriptInstanceState& state,
|
||||
ScriptPhysicsMessage message,
|
||||
Components::GameObject* other) {
|
||||
m_runtime->InvokePhysicsMessage(state.context, message, other);
|
||||
m_runtime->SyncManagedFieldsToStorage(state.context);
|
||||
}
|
||||
|
||||
void ScriptEngine::StopTrackingScript(ScriptInstanceState& state, bool runtimeStopping) {
|
||||
if (state.enabled) {
|
||||
InvokeLifecycleMethod(state, ScriptLifecycleMethod::OnDisable);
|
||||
|
||||
Reference in New Issue
Block a user