feat(scripting): add mesh component script wrappers

This commit is contained in:
2026-03-27 14:52:00 +08:00
parent 2b0df52446
commit bea849646f
12 changed files with 448 additions and 8 deletions

View File

@@ -17,6 +17,7 @@ public:
const Resources::ResourceHandle<Resources::Mesh>& GetMeshHandle() const { return m_mesh; }
const std::string& GetMeshPath() const { return m_meshPath; }
void SetMeshPath(const std::string& meshPath);
void SetMesh(const Resources::ResourceHandle<Resources::Mesh>& mesh);
void SetMesh(Resources::Mesh* mesh);
void ClearMesh();

View File

@@ -18,8 +18,10 @@ public:
size_t GetMaterialCount() const { return m_materials.size(); }
Resources::Material* GetMaterial(size_t index) const;
const Resources::ResourceHandle<Resources::Material>& GetMaterialHandle(size_t index) const;
const std::string& GetMaterialPath(size_t index) const;
const std::vector<std::string>& GetMaterialPaths() const { return m_materialPaths; }
void SetMaterialPath(size_t index, const std::string& materialPath);
void SetMaterial(size_t index, const Resources::ResourceHandle<Resources::Material>& material);
void SetMaterial(size_t index, Resources::Material* material);
void SetMaterials(const std::vector<Resources::ResourceHandle<Resources::Material>>& materials);

View File

@@ -15,6 +15,16 @@ std::string ToStdString(const Containers::String& value) {
} // namespace
void MeshFilterComponent::SetMeshPath(const std::string& meshPath) {
m_meshPath = meshPath;
if (m_meshPath.empty()) {
m_mesh.Reset();
return;
}
m_mesh = Resources::ResourceManager::Get().Load<Resources::Mesh>(m_meshPath.c_str());
}
void MeshFilterComponent::SetMesh(const Resources::ResourceHandle<Resources::Mesh>& mesh) {
m_mesh = mesh;
m_meshPath = mesh.Get() != nullptr ? ToStdString(mesh->GetPath()) : std::string();
@@ -52,10 +62,7 @@ void MeshFilterComponent::Deserialize(std::istream& is) {
const std::string value = token.substr(eqPos + 1);
if (key == "mesh") {
m_meshPath = value;
if (!m_meshPath.empty()) {
m_mesh = Resources::ResourceManager::Get().Load<Resources::Mesh>(m_meshPath.c_str());
}
SetMeshPath(value);
}
}
}

View File

@@ -39,6 +39,22 @@ const Resources::ResourceHandle<Resources::Material>& MeshRendererComponent::Get
return index < m_materials.size() ? m_materials[index] : kNullHandle;
}
const std::string& MeshRendererComponent::GetMaterialPath(size_t index) const {
static const std::string kEmptyPath;
return index < m_materialPaths.size() ? m_materialPaths[index] : kEmptyPath;
}
void MeshRendererComponent::SetMaterialPath(size_t index, const std::string& materialPath) {
EnsureMaterialSlot(index);
m_materialPaths[index] = materialPath;
if (materialPath.empty()) {
m_materials[index].Reset();
return;
}
m_materials[index] = Resources::ResourceManager::Get().Load<Resources::Material>(materialPath.c_str());
}
void MeshRendererComponent::SetMaterial(size_t index, const Resources::ResourceHandle<Resources::Material>& material) {
EnsureMaterialSlot(index);
m_materials[index] = material;
@@ -100,9 +116,7 @@ void MeshRendererComponent::Deserialize(std::istream& is) {
m_materialPaths = SplitMaterialPaths(value);
m_materials.resize(m_materialPaths.size());
for (size_t i = 0; i < m_materialPaths.size(); ++i) {
if (!m_materialPaths[i].empty()) {
m_materials[i] = Resources::ResourceManager::Get().Load<Resources::Material>(m_materialPaths[i].c_str());
}
SetMaterialPath(i, m_materialPaths[i]);
}
} else if (key == "castShadows") {
m_castShadows = (std::stoi(value) != 0);

View File

@@ -3,6 +3,8 @@
#include "Components/CameraComponent.h"
#include "Components/GameObject.h"
#include "Components/LightComponent.h"
#include "Components/MeshFilterComponent.h"
#include "Components/MeshRendererComponent.h"
#include "Components/TransformComponent.h"
#include "Debug/Logger.h"
#include "Scene/Scene.h"
@@ -39,6 +41,8 @@ enum class ManagedComponentKind {
Transform,
Camera,
Light,
MeshFilter,
MeshRenderer,
};
MonoRootState& GetMonoRootState() {
@@ -116,6 +120,12 @@ ManagedComponentKind ResolveManagedComponentKind(MonoReflectionType* reflectionT
if (namespaceName == "XCEngine" && className == "Light") {
return ManagedComponentKind::Light;
}
if (namespaceName == "XCEngine" && className == "MeshFilter") {
return ManagedComponentKind::MeshFilter;
}
if (namespaceName == "XCEngine" && className == "MeshRenderer") {
return ManagedComponentKind::MeshRenderer;
}
return ManagedComponentKind::Unknown;
}
@@ -200,6 +210,10 @@ bool HasNativeComponent(Components::GameObject* gameObject, ManagedComponentKind
return gameObject->GetComponent<Components::CameraComponent>() != nullptr;
case ManagedComponentKind::Light:
return gameObject->GetComponent<Components::LightComponent>() != nullptr;
case ManagedComponentKind::MeshFilter:
return gameObject->GetComponent<Components::MeshFilterComponent>() != nullptr;
case ManagedComponentKind::MeshRenderer:
return gameObject->GetComponent<Components::MeshRendererComponent>() != nullptr;
case ManagedComponentKind::Unknown:
return false;
}
@@ -217,6 +231,16 @@ Components::LightComponent* FindLightComponent(uint64_t gameObjectUUID) {
return gameObject ? gameObject->GetComponent<Components::LightComponent>() : nullptr;
}
Components::MeshFilterComponent* FindMeshFilterComponent(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return gameObject ? gameObject->GetComponent<Components::MeshFilterComponent>() : nullptr;
}
Components::MeshRendererComponent* FindMeshRendererComponent(uint64_t gameObjectUUID) {
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
return gameObject ? gameObject->GetComponent<Components::MeshRendererComponent>() : nullptr;
}
Components::Space ResolveManagedSpace(int32_t value) {
return value == static_cast<int32_t>(Components::Space::World)
? Components::Space::World
@@ -827,6 +851,94 @@ void InternalCall_Light_SetCastsShadows(uint64_t gameObjectUUID, mono_bool value
component->SetCastsShadows(value != 0);
}
MonoString* InternalCall_MeshFilter_GetMeshPath(uint64_t gameObjectUUID) {
Components::MeshFilterComponent* component = FindMeshFilterComponent(gameObjectUUID);
return mono_string_new(
mono_domain_get(),
component ? component->GetMeshPath().c_str() : "");
}
void InternalCall_MeshFilter_SetMeshPath(uint64_t gameObjectUUID, MonoString* path) {
Components::MeshFilterComponent* component = FindMeshFilterComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetMeshPath(MonoStringToUtf8(path));
}
int32_t InternalCall_MeshRenderer_GetMaterialCount(uint64_t gameObjectUUID) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
return component ? static_cast<int32_t>(component->GetMaterialCount()) : 0;
}
MonoString* InternalCall_MeshRenderer_GetMaterialPath(uint64_t gameObjectUUID, int32_t index) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
const std::string path =
(component && index >= 0) ? component->GetMaterialPath(static_cast<size_t>(index)) : std::string();
return mono_string_new(mono_domain_get(), path.c_str());
}
void InternalCall_MeshRenderer_SetMaterialPath(uint64_t gameObjectUUID, int32_t index, MonoString* path) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
if (!component || index < 0) {
return;
}
component->SetMaterialPath(static_cast<size_t>(index), MonoStringToUtf8(path));
}
void InternalCall_MeshRenderer_ClearMaterials(uint64_t gameObjectUUID) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
if (!component) {
return;
}
component->ClearMaterials();
}
mono_bool InternalCall_MeshRenderer_GetCastShadows(uint64_t gameObjectUUID) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
return (component && component->GetCastShadows()) ? 1 : 0;
}
void InternalCall_MeshRenderer_SetCastShadows(uint64_t gameObjectUUID, mono_bool value) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetCastShadows(value != 0);
}
mono_bool InternalCall_MeshRenderer_GetReceiveShadows(uint64_t gameObjectUUID) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
return (component && component->GetReceiveShadows()) ? 1 : 0;
}
void InternalCall_MeshRenderer_SetReceiveShadows(uint64_t gameObjectUUID, mono_bool value) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetReceiveShadows(value != 0);
}
int32_t InternalCall_MeshRenderer_GetRenderLayer(uint64_t gameObjectUUID) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
return component ? static_cast<int32_t>(component->GetRenderLayer()) : 0;
}
void InternalCall_MeshRenderer_SetRenderLayer(uint64_t gameObjectUUID, int32_t value) {
Components::MeshRendererComponent* component = FindMeshRendererComponent(gameObjectUUID);
if (!component) {
return;
}
component->SetRenderLayer(static_cast<uint32_t>(std::max(value, 0)));
}
void RegisterInternalCalls() {
if (GetInternalCallRegistrationState()) {
return;
@@ -893,6 +1005,18 @@ void RegisterInternalCalls() {
mono_add_internal_call("XCEngine.InternalCalls::Light_SetSpotAngle", reinterpret_cast<const void*>(&InternalCall_Light_SetSpotAngle));
mono_add_internal_call("XCEngine.InternalCalls::Light_GetCastsShadows", reinterpret_cast<const void*>(&InternalCall_Light_GetCastsShadows));
mono_add_internal_call("XCEngine.InternalCalls::Light_SetCastsShadows", reinterpret_cast<const void*>(&InternalCall_Light_SetCastsShadows));
mono_add_internal_call("XCEngine.InternalCalls::MeshFilter_GetMeshPath", reinterpret_cast<const void*>(&InternalCall_MeshFilter_GetMeshPath));
mono_add_internal_call("XCEngine.InternalCalls::MeshFilter_SetMeshPath", reinterpret_cast<const void*>(&InternalCall_MeshFilter_SetMeshPath));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_GetMaterialCount", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_GetMaterialCount));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_GetMaterialPath", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_GetMaterialPath));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_SetMaterialPath", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_SetMaterialPath));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_ClearMaterials", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_ClearMaterials));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_GetCastShadows", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_GetCastShadows));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_SetCastShadows", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_SetCastShadows));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_GetReceiveShadows", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_GetReceiveShadows));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_SetReceiveShadows", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_SetReceiveShadows));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_GetRenderLayer", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_GetRenderLayer));
mono_add_internal_call("XCEngine.InternalCalls::MeshRenderer_SetRenderLayer", reinterpret_cast<const void*>(&InternalCall_MeshRenderer_SetRenderLayer));
GetInternalCallRegistrationState() = true;
}