#include "BsScriptMesh.h" #include "BsScriptResourceManager.h" #include "BsScriptMeta.h" #include "BsMonoField.h" #include "BsMonoClass.h" #include "BsMonoArray.h" #include "BsMonoManager.h" #include "BsCoreThread.h" namespace BansheeEngine { ScriptSubMesh::ScriptSubMesh(MonoObject* instance) :ScriptObject(instance) { } void ScriptSubMesh::initRuntimeData() { } MonoObject* ScriptSubMesh::box(const SubMeshData& value) { // We're casting away const but it's fine since structs are passed by value anyway return mono_value_box(MonoManager::instance().getDomain(), metaData.scriptClass->_getInternalClass(), (void*)&value); } SubMeshData ScriptSubMesh::unbox(MonoObject* obj) { return *(SubMeshData*)mono_object_unbox(obj); } ScriptMesh::ScriptMesh(MonoObject* instance, const HMesh& mesh) :TScriptResource(instance, mesh) { } void ScriptMesh::initRuntimeData() { metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptMesh::internal_CreateInstance); metaData.scriptClass->addInternalCall("Internal_CreateInstanceMeshData", &ScriptMesh::internal_CreateInstanceMeshData); metaData.scriptClass->addInternalCall("Internal_GetSubMeshes", &ScriptMesh::internal_GetSubMeshes); metaData.scriptClass->addInternalCall("Internal_GetSubMeshCount", &ScriptMesh::internal_GetSubMeshCount); metaData.scriptClass->addInternalCall("Internal_GetBounds", &ScriptMesh::internal_GetBounds); metaData.scriptClass->addInternalCall("Internal_GetMeshData", &ScriptMesh::internal_GetMeshData); metaData.scriptClass->addInternalCall("Internal_SetMeshData", &ScriptMesh::internal_SetMeshData); } void ScriptMesh::internal_CreateInstance(MonoObject* instance, int numVertices, int numIndices, MonoArray* subMeshes, MeshUsage usage, VertexLayout vertex, ScriptIndexType index) { VertexDataDescPtr vertexDesc = RendererMeshData::vertexLayoutVertexDesc(vertex); IndexType indexType = IT_16BIT; if (index == ScriptIndexType::Index32) indexType = IT_32BIT; Vector nativeSubMeshes = monoToNativeSubMeshes(subMeshes); HMesh mesh = Mesh::create(numVertices, numIndices, vertexDesc, nativeSubMeshes, usage, indexType); ScriptMesh* scriptInstance; ScriptResourceManager::instance().createScriptResource(instance, mesh, &scriptInstance); } void ScriptMesh::internal_CreateInstanceMeshData(MonoObject* instance, ScriptMeshData* data, MonoArray* subMeshes, MeshUsage usage) { MeshDataPtr meshData; if (data != nullptr) meshData = data->getInternalValue()->getData(); Vector nativeSubMeshes = monoToNativeSubMeshes(subMeshes); HMesh mesh = Mesh::create(meshData, nativeSubMeshes, usage); ScriptMesh* scriptInstance; ScriptResourceManager::instance().createScriptResource(instance, mesh, &scriptInstance); } MonoArray* ScriptMesh::internal_GetSubMeshes(ScriptMesh* thisPtr) { HMesh mesh = thisPtr->getHandle(); UINT32 numSubMeshes = mesh->getProperties().getNumSubMeshes(); ScriptArray subMeshArray = ScriptArray::create(numSubMeshes); for (UINT32 i = 0; i < numSubMeshes; i++) { SubMesh curSubMesh = mesh->getProperties().getSubMesh(i); SubMeshData data; data.indexOffset = curSubMesh.indexOffset; data.indexCount = curSubMesh.indexCount; data.topology = drawOpToMeshTopology(curSubMesh.drawOp); subMeshArray.set(i, data); } return subMeshArray.getInternal(); } UINT32 ScriptMesh::internal_GetSubMeshCount(ScriptMesh* thisPtr) { HMesh mesh = thisPtr->getHandle(); return mesh->getProperties().getNumSubMeshes(); } void ScriptMesh::internal_GetBounds(ScriptMesh* thisPtr, AABox* box, Sphere* sphere) { HMesh mesh = thisPtr->getHandle(); Bounds bounds = mesh->getProperties().getBounds(); *box = bounds.getBox(); *sphere = bounds.getSphere(); } MonoObject* ScriptMesh::internal_GetMeshData(ScriptMesh* thisPtr) { HMesh mesh = thisPtr->getHandle(); MeshDataPtr meshData = mesh->allocateSubresourceBuffer(0); mesh->readData(*meshData); return ScriptMeshData::create(meshData); } void ScriptMesh::internal_SetMeshData(ScriptMesh* thisPtr, ScriptMeshData* value) { HMesh mesh = thisPtr->getHandle(); if (value != nullptr) { MeshDataPtr meshData = value->getInternalValue()->getData(); mesh->writeSubresource(gCoreAccessor(), 0, meshData, true); } } MonoObject* ScriptMesh::createInstance() { return metaData.scriptClass->createInstance(); } DrawOperationType ScriptMesh::meshTopologyToDrawOp(MeshTopology topology) { switch (topology) { case MeshTopology::PointList: return DOT_POINT_LIST; case MeshTopology::LineList: return DOT_LINE_LIST; case MeshTopology::LineStrip: return DOT_LINE_STRIP; case MeshTopology::TriangleList: return DOT_TRIANGLE_LIST; case MeshTopology::TriangleStrip: return DOT_TRIANGLE_STRIP; case MeshTopology::TriangleFan: return DOT_TRIANGLE_FAN; } return DOT_TRIANGLE_LIST; } MeshTopology ScriptMesh::drawOpToMeshTopology(DrawOperationType drawOp) { switch (drawOp) { case DOT_POINT_LIST: return MeshTopology::PointList; case DOT_LINE_LIST: return MeshTopology::TriangleList; case DOT_LINE_STRIP: return MeshTopology::TriangleStrip; case DOT_TRIANGLE_LIST: return MeshTopology::TriangleList; case DOT_TRIANGLE_STRIP: return MeshTopology::TriangleStrip; case DOT_TRIANGLE_FAN: return MeshTopology::TriangleFan; } return MeshTopology::TriangleList; } Vector ScriptMesh::monoToNativeSubMeshes(MonoArray* subMeshes) { Vector nativeSubMeshes; if (subMeshes != nullptr) { ScriptArray subMeshArray(subMeshes); UINT32 numSubMeshes = subMeshArray.size(); for (UINT32 i = 0; i < numSubMeshes; i++) { SubMeshData curData = subMeshArray.get(i); SubMesh subMesh; subMesh.indexOffset = curData.indexOffset; subMesh.indexCount = curData.indexCount; subMesh.drawOp = meshTopologyToDrawOp(curData.topology); nativeSubMeshes.push_back(subMesh); } } return nativeSubMeshes; } }