feat(scripting): add mesh component script wrappers
This commit is contained in:
@@ -17,6 +17,7 @@ public:
|
|||||||
const Resources::ResourceHandle<Resources::Mesh>& GetMeshHandle() const { return m_mesh; }
|
const Resources::ResourceHandle<Resources::Mesh>& GetMeshHandle() const { return m_mesh; }
|
||||||
const std::string& GetMeshPath() const { return m_meshPath; }
|
const std::string& GetMeshPath() const { return m_meshPath; }
|
||||||
|
|
||||||
|
void SetMeshPath(const std::string& meshPath);
|
||||||
void SetMesh(const Resources::ResourceHandle<Resources::Mesh>& mesh);
|
void SetMesh(const Resources::ResourceHandle<Resources::Mesh>& mesh);
|
||||||
void SetMesh(Resources::Mesh* mesh);
|
void SetMesh(Resources::Mesh* mesh);
|
||||||
void ClearMesh();
|
void ClearMesh();
|
||||||
|
|||||||
@@ -18,8 +18,10 @@ public:
|
|||||||
size_t GetMaterialCount() const { return m_materials.size(); }
|
size_t GetMaterialCount() const { return m_materials.size(); }
|
||||||
Resources::Material* GetMaterial(size_t index) const;
|
Resources::Material* GetMaterial(size_t index) const;
|
||||||
const Resources::ResourceHandle<Resources::Material>& GetMaterialHandle(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; }
|
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, const Resources::ResourceHandle<Resources::Material>& material);
|
||||||
void SetMaterial(size_t index, Resources::Material* material);
|
void SetMaterial(size_t index, Resources::Material* material);
|
||||||
void SetMaterials(const std::vector<Resources::ResourceHandle<Resources::Material>>& materials);
|
void SetMaterials(const std::vector<Resources::ResourceHandle<Resources::Material>>& materials);
|
||||||
|
|||||||
@@ -15,6 +15,16 @@ std::string ToStdString(const Containers::String& value) {
|
|||||||
|
|
||||||
} // namespace
|
} // 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) {
|
void MeshFilterComponent::SetMesh(const Resources::ResourceHandle<Resources::Mesh>& mesh) {
|
||||||
m_mesh = mesh;
|
m_mesh = mesh;
|
||||||
m_meshPath = mesh.Get() != nullptr ? ToStdString(mesh->GetPath()) : std::string();
|
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);
|
const std::string value = token.substr(eqPos + 1);
|
||||||
|
|
||||||
if (key == "mesh") {
|
if (key == "mesh") {
|
||||||
m_meshPath = value;
|
SetMeshPath(value);
|
||||||
if (!m_meshPath.empty()) {
|
|
||||||
m_mesh = Resources::ResourceManager::Get().Load<Resources::Mesh>(m_meshPath.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,22 @@ const Resources::ResourceHandle<Resources::Material>& MeshRendererComponent::Get
|
|||||||
return index < m_materials.size() ? m_materials[index] : kNullHandle;
|
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) {
|
void MeshRendererComponent::SetMaterial(size_t index, const Resources::ResourceHandle<Resources::Material>& material) {
|
||||||
EnsureMaterialSlot(index);
|
EnsureMaterialSlot(index);
|
||||||
m_materials[index] = material;
|
m_materials[index] = material;
|
||||||
@@ -100,9 +116,7 @@ void MeshRendererComponent::Deserialize(std::istream& is) {
|
|||||||
m_materialPaths = SplitMaterialPaths(value);
|
m_materialPaths = SplitMaterialPaths(value);
|
||||||
m_materials.resize(m_materialPaths.size());
|
m_materials.resize(m_materialPaths.size());
|
||||||
for (size_t i = 0; i < m_materialPaths.size(); ++i) {
|
for (size_t i = 0; i < m_materialPaths.size(); ++i) {
|
||||||
if (!m_materialPaths[i].empty()) {
|
SetMaterialPath(i, m_materialPaths[i]);
|
||||||
m_materials[i] = Resources::ResourceManager::Get().Load<Resources::Material>(m_materialPaths[i].c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (key == "castShadows") {
|
} else if (key == "castShadows") {
|
||||||
m_castShadows = (std::stoi(value) != 0);
|
m_castShadows = (std::stoi(value) != 0);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "Components/CameraComponent.h"
|
#include "Components/CameraComponent.h"
|
||||||
#include "Components/GameObject.h"
|
#include "Components/GameObject.h"
|
||||||
#include "Components/LightComponent.h"
|
#include "Components/LightComponent.h"
|
||||||
|
#include "Components/MeshFilterComponent.h"
|
||||||
|
#include "Components/MeshRendererComponent.h"
|
||||||
#include "Components/TransformComponent.h"
|
#include "Components/TransformComponent.h"
|
||||||
#include "Debug/Logger.h"
|
#include "Debug/Logger.h"
|
||||||
#include "Scene/Scene.h"
|
#include "Scene/Scene.h"
|
||||||
@@ -39,6 +41,8 @@ enum class ManagedComponentKind {
|
|||||||
Transform,
|
Transform,
|
||||||
Camera,
|
Camera,
|
||||||
Light,
|
Light,
|
||||||
|
MeshFilter,
|
||||||
|
MeshRenderer,
|
||||||
};
|
};
|
||||||
|
|
||||||
MonoRootState& GetMonoRootState() {
|
MonoRootState& GetMonoRootState() {
|
||||||
@@ -116,6 +120,12 @@ ManagedComponentKind ResolveManagedComponentKind(MonoReflectionType* reflectionT
|
|||||||
if (namespaceName == "XCEngine" && className == "Light") {
|
if (namespaceName == "XCEngine" && className == "Light") {
|
||||||
return ManagedComponentKind::Light;
|
return ManagedComponentKind::Light;
|
||||||
}
|
}
|
||||||
|
if (namespaceName == "XCEngine" && className == "MeshFilter") {
|
||||||
|
return ManagedComponentKind::MeshFilter;
|
||||||
|
}
|
||||||
|
if (namespaceName == "XCEngine" && className == "MeshRenderer") {
|
||||||
|
return ManagedComponentKind::MeshRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
return ManagedComponentKind::Unknown;
|
return ManagedComponentKind::Unknown;
|
||||||
}
|
}
|
||||||
@@ -200,6 +210,10 @@ bool HasNativeComponent(Components::GameObject* gameObject, ManagedComponentKind
|
|||||||
return gameObject->GetComponent<Components::CameraComponent>() != nullptr;
|
return gameObject->GetComponent<Components::CameraComponent>() != nullptr;
|
||||||
case ManagedComponentKind::Light:
|
case ManagedComponentKind::Light:
|
||||||
return gameObject->GetComponent<Components::LightComponent>() != nullptr;
|
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:
|
case ManagedComponentKind::Unknown:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -217,6 +231,16 @@ Components::LightComponent* FindLightComponent(uint64_t gameObjectUUID) {
|
|||||||
return gameObject ? gameObject->GetComponent<Components::LightComponent>() : nullptr;
|
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) {
|
Components::Space ResolveManagedSpace(int32_t value) {
|
||||||
return value == static_cast<int32_t>(Components::Space::World)
|
return value == static_cast<int32_t>(Components::Space::World)
|
||||||
? Components::Space::World
|
? Components::Space::World
|
||||||
@@ -827,6 +851,94 @@ void InternalCall_Light_SetCastsShadows(uint64_t gameObjectUUID, mono_bool value
|
|||||||
component->SetCastsShadows(value != 0);
|
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() {
|
void RegisterInternalCalls() {
|
||||||
if (GetInternalCallRegistrationState()) {
|
if (GetInternalCallRegistrationState()) {
|
||||||
return;
|
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_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_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::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;
|
GetInternalCallRegistrationState() = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,13 +50,15 @@ foreach(XCENGINE_REQUIRED_PATH
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
set(XCENGINE_SCRIPT_CORE_SOURCES
|
set(XCENGINE_SCRIPT_CORE_SOURCES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Camera.cs
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Behaviour.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Behaviour.cs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Camera.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Component.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Component.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Debug.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Debug.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/GameObject.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/GameObject.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/InternalCalls.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/InternalCalls.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Light.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Light.cs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/MeshFilter.cs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/MeshRenderer.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/MonoBehaviour.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/MonoBehaviour.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Quaternion.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Quaternion.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Space.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Space.cs
|
||||||
@@ -71,6 +73,7 @@ set(XCENGINE_GAME_SCRIPT_SOURCES
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/BuiltinComponentProbe.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/BuiltinComponentProbe.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/HierarchyProbe.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/HierarchyProbe.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/LifecycleProbe.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/LifecycleProbe.cs
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/MeshComponentProbe.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/TransformConversionProbe.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/TransformConversionProbe.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/TransformMotionProbe.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/TransformMotionProbe.cs
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/TransformOrientationProbe.cs
|
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/TransformOrientationProbe.cs
|
||||||
|
|||||||
60
managed/GameScripts/MeshComponentProbe.cs
Normal file
60
managed/GameScripts/MeshComponentProbe.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using XCEngine;
|
||||||
|
|
||||||
|
namespace Gameplay
|
||||||
|
{
|
||||||
|
public sealed class MeshComponentProbe : MonoBehaviour
|
||||||
|
{
|
||||||
|
public bool HasMeshFilter;
|
||||||
|
public bool HasMeshRenderer;
|
||||||
|
public bool MeshFilterLookupSucceeded;
|
||||||
|
public bool MeshRendererLookupSucceeded;
|
||||||
|
public string ObservedInitialMeshPath = string.Empty;
|
||||||
|
public string ObservedUpdatedMeshPath = string.Empty;
|
||||||
|
public int ObservedInitialMaterialCount;
|
||||||
|
public string ObservedInitialMaterial0Path = string.Empty;
|
||||||
|
public bool ObservedInitialCastShadows;
|
||||||
|
public bool ObservedInitialReceiveShadows;
|
||||||
|
public int ObservedInitialRenderLayer;
|
||||||
|
public int ObservedUpdatedMaterialCount;
|
||||||
|
public string ObservedUpdatedMaterial1Path = string.Empty;
|
||||||
|
public bool ObservedUpdatedCastShadows;
|
||||||
|
public bool ObservedUpdatedReceiveShadows;
|
||||||
|
public int ObservedUpdatedRenderLayer;
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
HasMeshFilter = HasComponent<MeshFilter>();
|
||||||
|
HasMeshRenderer = HasComponent<MeshRenderer>();
|
||||||
|
|
||||||
|
MeshFilterLookupSucceeded = TryGetComponent(out MeshFilter meshFilter);
|
||||||
|
MeshRendererLookupSucceeded = TryGetComponent(out MeshRenderer meshRenderer);
|
||||||
|
|
||||||
|
if (meshFilter != null)
|
||||||
|
{
|
||||||
|
ObservedInitialMeshPath = meshFilter.meshPath;
|
||||||
|
meshFilter.meshPath = "Meshes/runtime_override.mesh";
|
||||||
|
ObservedUpdatedMeshPath = meshFilter.meshPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meshRenderer != null)
|
||||||
|
{
|
||||||
|
ObservedInitialMaterialCount = meshRenderer.materialCount;
|
||||||
|
ObservedInitialMaterial0Path = meshRenderer.GetMaterialPath(0);
|
||||||
|
ObservedInitialCastShadows = meshRenderer.castShadows;
|
||||||
|
ObservedInitialReceiveShadows = meshRenderer.receiveShadows;
|
||||||
|
ObservedInitialRenderLayer = meshRenderer.renderLayer;
|
||||||
|
|
||||||
|
meshRenderer.SetMaterialPath(1, "Materials/runtime_override.mat");
|
||||||
|
meshRenderer.castShadows = false;
|
||||||
|
meshRenderer.receiveShadows = true;
|
||||||
|
meshRenderer.renderLayer = 11;
|
||||||
|
|
||||||
|
ObservedUpdatedMaterialCount = meshRenderer.materialCount;
|
||||||
|
ObservedUpdatedMaterial1Path = meshRenderer.GetMaterialPath(1);
|
||||||
|
ObservedUpdatedCastShadows = meshRenderer.castShadows;
|
||||||
|
ObservedUpdatedReceiveShadows = meshRenderer.receiveShadows;
|
||||||
|
ObservedUpdatedRenderLayer = meshRenderer.renderLayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -187,5 +187,41 @@ namespace XCEngine
|
|||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
internal static extern void Light_SetCastsShadows(ulong gameObjectUUID, bool value);
|
internal static extern void Light_SetCastsShadows(ulong gameObjectUUID, bool value);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern string MeshFilter_GetMeshPath(ulong gameObjectUUID);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern void MeshFilter_SetMeshPath(ulong gameObjectUUID, string path);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern int MeshRenderer_GetMaterialCount(ulong gameObjectUUID);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern string MeshRenderer_GetMaterialPath(ulong gameObjectUUID, int index);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern void MeshRenderer_SetMaterialPath(ulong gameObjectUUID, int index, string path);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern void MeshRenderer_ClearMaterials(ulong gameObjectUUID);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern bool MeshRenderer_GetCastShadows(ulong gameObjectUUID);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern void MeshRenderer_SetCastShadows(ulong gameObjectUUID, bool value);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern bool MeshRenderer_GetReceiveShadows(ulong gameObjectUUID);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern void MeshRenderer_SetReceiveShadows(ulong gameObjectUUID, bool value);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern int MeshRenderer_GetRenderLayer(ulong gameObjectUUID);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern void MeshRenderer_SetRenderLayer(ulong gameObjectUUID, int value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
managed/XCEngine.ScriptCore/MeshFilter.cs
Normal file
22
managed/XCEngine.ScriptCore/MeshFilter.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
namespace XCEngine
|
||||||
|
{
|
||||||
|
public sealed class MeshFilter : Component
|
||||||
|
{
|
||||||
|
internal MeshFilter(ulong gameObjectUUID)
|
||||||
|
: base(gameObjectUUID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MeshPath
|
||||||
|
{
|
||||||
|
get => InternalCalls.MeshFilter_GetMeshPath(GameObjectUUID) ?? string.Empty;
|
||||||
|
set => InternalCalls.MeshFilter_SetMeshPath(GameObjectUUID, value ?? string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string meshPath
|
||||||
|
{
|
||||||
|
get => MeshPath;
|
||||||
|
set => MeshPath = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
64
managed/XCEngine.ScriptCore/MeshRenderer.cs
Normal file
64
managed/XCEngine.ScriptCore/MeshRenderer.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
namespace XCEngine
|
||||||
|
{
|
||||||
|
public sealed class MeshRenderer : Component
|
||||||
|
{
|
||||||
|
internal MeshRenderer(ulong gameObjectUUID)
|
||||||
|
: base(gameObjectUUID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MaterialCount => InternalCalls.MeshRenderer_GetMaterialCount(GameObjectUUID);
|
||||||
|
public int materialCount => MaterialCount;
|
||||||
|
|
||||||
|
public bool CastShadows
|
||||||
|
{
|
||||||
|
get => InternalCalls.MeshRenderer_GetCastShadows(GameObjectUUID);
|
||||||
|
set => InternalCalls.MeshRenderer_SetCastShadows(GameObjectUUID, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool castShadows
|
||||||
|
{
|
||||||
|
get => CastShadows;
|
||||||
|
set => CastShadows = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ReceiveShadows
|
||||||
|
{
|
||||||
|
get => InternalCalls.MeshRenderer_GetReceiveShadows(GameObjectUUID);
|
||||||
|
set => InternalCalls.MeshRenderer_SetReceiveShadows(GameObjectUUID, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool receiveShadows
|
||||||
|
{
|
||||||
|
get => ReceiveShadows;
|
||||||
|
set => ReceiveShadows = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RenderLayer
|
||||||
|
{
|
||||||
|
get => InternalCalls.MeshRenderer_GetRenderLayer(GameObjectUUID);
|
||||||
|
set => InternalCalls.MeshRenderer_SetRenderLayer(GameObjectUUID, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int renderLayer
|
||||||
|
{
|
||||||
|
get => RenderLayer;
|
||||||
|
set => RenderLayer = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetMaterialPath(int index)
|
||||||
|
{
|
||||||
|
return InternalCalls.MeshRenderer_GetMaterialPath(GameObjectUUID, index) ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMaterialPath(int index, string path)
|
||||||
|
{
|
||||||
|
InternalCalls.MeshRenderer_SetMaterialPath(GameObjectUUID, index, path ?? string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearMaterials()
|
||||||
|
{
|
||||||
|
InternalCalls.MeshRenderer_ClearMaterials(GameObjectUUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,6 +66,19 @@ TEST(MeshFilterComponent_Test, SerializeAndDeserializePreservesPath) {
|
|||||||
delete mesh;
|
delete mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(MeshFilterComponent_Test, SetMeshPathPreservesPathWithoutLoadedResource) {
|
||||||
|
MeshFilterComponent component;
|
||||||
|
|
||||||
|
component.SetMeshPath("Meshes/runtime.mesh");
|
||||||
|
|
||||||
|
EXPECT_EQ(component.GetMeshPath(), "Meshes/runtime.mesh");
|
||||||
|
EXPECT_EQ(component.GetMesh(), nullptr);
|
||||||
|
|
||||||
|
component.SetMeshPath("");
|
||||||
|
EXPECT_EQ(component.GetMeshPath(), "");
|
||||||
|
EXPECT_EQ(component.GetMesh(), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(MeshRendererComponent_Test, SetMaterialsKeepsSlotsAndFlags) {
|
TEST(MeshRendererComponent_Test, SetMaterialsKeepsSlotsAndFlags) {
|
||||||
GameObject gameObject("RendererHolder");
|
GameObject gameObject("RendererHolder");
|
||||||
auto* component = gameObject.AddComponent<MeshRendererComponent>();
|
auto* component = gameObject.AddComponent<MeshRendererComponent>();
|
||||||
@@ -122,4 +135,20 @@ TEST(MeshRendererComponent_Test, SerializeAndDeserializePreservesMaterialPathsAn
|
|||||||
delete material1;
|
delete material1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(MeshRendererComponent_Test, SetMaterialPathPreservesPathWithoutLoadedResource) {
|
||||||
|
MeshRendererComponent component;
|
||||||
|
|
||||||
|
component.SetMaterialPath(1, "Materials/runtime.mat");
|
||||||
|
|
||||||
|
ASSERT_EQ(component.GetMaterialCount(), 2u);
|
||||||
|
EXPECT_EQ(component.GetMaterial(0), nullptr);
|
||||||
|
EXPECT_EQ(component.GetMaterial(1), nullptr);
|
||||||
|
EXPECT_EQ(component.GetMaterialPath(0), "");
|
||||||
|
EXPECT_EQ(component.GetMaterialPath(1), "Materials/runtime.mat");
|
||||||
|
|
||||||
|
component.SetMaterialPath(1, "");
|
||||||
|
EXPECT_EQ(component.GetMaterialPath(1), "");
|
||||||
|
EXPECT_EQ(component.GetMaterial(1), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <XCEngine/Components/CameraComponent.h>
|
#include <XCEngine/Components/CameraComponent.h>
|
||||||
#include <XCEngine/Components/LightComponent.h>
|
#include <XCEngine/Components/LightComponent.h>
|
||||||
|
#include <XCEngine/Components/MeshFilterComponent.h>
|
||||||
|
#include <XCEngine/Components/MeshRendererComponent.h>
|
||||||
#include <XCEngine/Core/Math/Vector3.h>
|
#include <XCEngine/Core/Math/Vector3.h>
|
||||||
#include <XCEngine/Core/Math/Vector4.h>
|
#include <XCEngine/Core/Math/Vector4.h>
|
||||||
#include <XCEngine/Scene/Scene.h>
|
#include <XCEngine/Scene/Scene.h>
|
||||||
@@ -315,6 +317,82 @@ TEST_F(MonoScriptRuntimeTest, ManagedBuiltInComponentWrappersReadAndWriteCameraA
|
|||||||
EXPECT_TRUE(light->GetCastsShadows());
|
EXPECT_TRUE(light->GetCastsShadows());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(MonoScriptRuntimeTest, ManagedMeshComponentWrappersReadAndWritePathsAndFlags) {
|
||||||
|
Scene* runtimeScene = CreateScene("MonoRuntimeScene");
|
||||||
|
GameObject* host = runtimeScene->CreateGameObject("Host");
|
||||||
|
MeshFilterComponent* meshFilter = host->AddComponent<MeshFilterComponent>();
|
||||||
|
MeshRendererComponent* meshRenderer = host->AddComponent<MeshRendererComponent>();
|
||||||
|
ScriptComponent* component = AddScript(host, "Gameplay", "MeshComponentProbe");
|
||||||
|
|
||||||
|
meshFilter->SetMeshPath("Meshes/initial.mesh");
|
||||||
|
meshRenderer->SetMaterialPath(0, "Materials/initial.mat");
|
||||||
|
meshRenderer->SetCastShadows(true);
|
||||||
|
meshRenderer->SetReceiveShadows(false);
|
||||||
|
meshRenderer->SetRenderLayer(7);
|
||||||
|
|
||||||
|
engine->OnRuntimeStart(runtimeScene);
|
||||||
|
engine->OnUpdate(0.016f);
|
||||||
|
|
||||||
|
bool hasMeshFilter = false;
|
||||||
|
bool hasMeshRenderer = false;
|
||||||
|
bool meshFilterLookupSucceeded = false;
|
||||||
|
bool meshRendererLookupSucceeded = false;
|
||||||
|
std::string observedInitialMeshPath;
|
||||||
|
std::string observedUpdatedMeshPath;
|
||||||
|
int32_t observedInitialMaterialCount = 0;
|
||||||
|
std::string observedInitialMaterial0Path;
|
||||||
|
bool observedInitialCastShadows = false;
|
||||||
|
bool observedInitialReceiveShadows = true;
|
||||||
|
int32_t observedInitialRenderLayer = 0;
|
||||||
|
int32_t observedUpdatedMaterialCount = 0;
|
||||||
|
std::string observedUpdatedMaterial1Path;
|
||||||
|
bool observedUpdatedCastShadows = true;
|
||||||
|
bool observedUpdatedReceiveShadows = false;
|
||||||
|
int32_t observedUpdatedRenderLayer = 0;
|
||||||
|
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "HasMeshFilter", hasMeshFilter));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "HasMeshRenderer", hasMeshRenderer));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "MeshFilterLookupSucceeded", meshFilterLookupSucceeded));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "MeshRendererLookupSucceeded", meshRendererLookupSucceeded));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedInitialMeshPath", observedInitialMeshPath));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedUpdatedMeshPath", observedUpdatedMeshPath));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedInitialMaterialCount", observedInitialMaterialCount));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedInitialMaterial0Path", observedInitialMaterial0Path));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedInitialCastShadows", observedInitialCastShadows));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedInitialReceiveShadows", observedInitialReceiveShadows));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedInitialRenderLayer", observedInitialRenderLayer));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedUpdatedMaterialCount", observedUpdatedMaterialCount));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedUpdatedMaterial1Path", observedUpdatedMaterial1Path));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedUpdatedCastShadows", observedUpdatedCastShadows));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedUpdatedReceiveShadows", observedUpdatedReceiveShadows));
|
||||||
|
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedUpdatedRenderLayer", observedUpdatedRenderLayer));
|
||||||
|
|
||||||
|
EXPECT_TRUE(hasMeshFilter);
|
||||||
|
EXPECT_TRUE(hasMeshRenderer);
|
||||||
|
EXPECT_TRUE(meshFilterLookupSucceeded);
|
||||||
|
EXPECT_TRUE(meshRendererLookupSucceeded);
|
||||||
|
EXPECT_EQ(observedInitialMeshPath, "Meshes/initial.mesh");
|
||||||
|
EXPECT_EQ(observedUpdatedMeshPath, "Meshes/runtime_override.mesh");
|
||||||
|
EXPECT_EQ(observedInitialMaterialCount, 1);
|
||||||
|
EXPECT_EQ(observedInitialMaterial0Path, "Materials/initial.mat");
|
||||||
|
EXPECT_TRUE(observedInitialCastShadows);
|
||||||
|
EXPECT_FALSE(observedInitialReceiveShadows);
|
||||||
|
EXPECT_EQ(observedInitialRenderLayer, 7);
|
||||||
|
EXPECT_EQ(observedUpdatedMaterialCount, 2);
|
||||||
|
EXPECT_EQ(observedUpdatedMaterial1Path, "Materials/runtime_override.mat");
|
||||||
|
EXPECT_FALSE(observedUpdatedCastShadows);
|
||||||
|
EXPECT_TRUE(observedUpdatedReceiveShadows);
|
||||||
|
EXPECT_EQ(observedUpdatedRenderLayer, 11);
|
||||||
|
|
||||||
|
EXPECT_EQ(meshFilter->GetMeshPath(), "Meshes/runtime_override.mesh");
|
||||||
|
ASSERT_EQ(meshRenderer->GetMaterialCount(), 2u);
|
||||||
|
EXPECT_EQ(meshRenderer->GetMaterialPath(0), "Materials/initial.mat");
|
||||||
|
EXPECT_EQ(meshRenderer->GetMaterialPath(1), "Materials/runtime_override.mat");
|
||||||
|
EXPECT_FALSE(meshRenderer->GetCastShadows());
|
||||||
|
EXPECT_TRUE(meshRenderer->GetReceiveShadows());
|
||||||
|
EXPECT_EQ(meshRenderer->GetRenderLayer(), 11u);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(MonoScriptRuntimeTest, TransformHierarchyApiExposesParentChildAndReparenting) {
|
TEST_F(MonoScriptRuntimeTest, TransformHierarchyApiExposesParentChildAndReparenting) {
|
||||||
Scene* runtimeScene = CreateScene("MonoRuntimeScene");
|
Scene* runtimeScene = CreateScene("MonoRuntimeScene");
|
||||||
GameObject* root = runtimeScene->CreateGameObject("Root");
|
GameObject* root = runtimeScene->CreateGameObject("Root");
|
||||||
|
|||||||
Reference in New Issue
Block a user