Reworked MeshDataInstance now it's using the VisualServer directly instead of it being inherited from MeshInstance. now it's a lot more reliable.

This commit is contained in:
Relintai 2021-08-10 18:37:46 +02:00
parent efb1d42957
commit 2a2b2ae31a
2 changed files with 75 additions and 32 deletions

View File

@ -7,8 +7,12 @@
#if VERSION_MAJOR < 4 #if VERSION_MAJOR < 4
#include "core/image.h" #include "core/image.h"
#define GET_WORLD get_world
#else #else
#include "core/io/image.h" #include "core/io/image.h"
#define GET_WORLD get_world_3d
#endif #endif
#if TEXTURE_PACKER_PRESENT #if TEXTURE_PACKER_PRESENT
@ -35,11 +39,7 @@ Ref<MeshDataResource> MeshDataInstance::get_mesh_data() {
void MeshDataInstance::set_mesh_data(const Ref<MeshDataResource> &mesh) { void MeshDataInstance::set_mesh_data(const Ref<MeshDataResource> &mesh) {
_mesh = mesh; _mesh = mesh;
if (is_inside_tree()) { refresh();
refresh();
} else {
_dirty = true;
}
} }
Ref<Texture> MeshDataInstance::get_texture() { Ref<Texture> MeshDataInstance::get_texture() {
@ -63,25 +63,26 @@ void MeshDataInstance::set_material(const Ref<Material> &mat) {
} }
void MeshDataInstance::refresh() { void MeshDataInstance::refresh() {
Ref<ArrayMesh> mesh = get_mesh(); if (!is_inside_tree()) {
return;
if (!mesh.is_valid()) {
mesh.instance();
} }
#if VERSION_MAJOR < 4 if (_mesh_rid == RID()) {
for (int i = 0; i < mesh->get_surface_count(); ++i) { _mesh_instance = VisualServer::get_singleton()->instance_create();
mesh->surface_remove(i);
}
#else
mesh->clear_surfaces();
#endif
//Always check/set mesh in MeshInstance in case it got set to something else. For example got cleared in the editor. if (GET_WORLD().is_valid())
if (get_mesh() != mesh) { VS::get_singleton()->instance_set_scenario(_mesh_instance, GET_WORLD()->get_scenario());
set_mesh(mesh);
_mesh_rid = VisualServer::get_singleton()->mesh_create();
VS::get_singleton()->instance_set_base(_mesh_instance, _mesh_rid);
VS::get_singleton()->instance_set_transform(_mesh_instance, get_transform());
VS::get_singleton()->instance_set_visible(_mesh_instance, true);
} }
VisualServer::get_singleton()->mesh_clear(_mesh_rid);
if (!_mesh.is_valid()) { if (!_mesh.is_valid()) {
return; return;
} }
@ -98,19 +99,31 @@ void MeshDataInstance::refresh() {
return; return;
} }
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arr); VisualServer::get_singleton()->mesh_add_surface_from_arrays(_mesh_rid, VisualServer::PRIMITIVE_TRIANGLES, arr);
if (_material.is_valid() && mesh->get_surface_count() > 0) { if (_material.is_valid()) {
mesh->surface_set_material(0, _material); VisualServer::get_singleton()->mesh_surface_set_material(_mesh_rid, 0, _material->get_rid());
} }
} }
void MeshDataInstance::setup_material_texture() { void MeshDataInstance::setup_material_texture() {
if (!_texture.is_valid()) { if (!is_inside_tree()) {
return; return;
} }
if (_material.is_valid()) { if (!_texture.is_valid()) {
if (_material.is_valid()) {
Ref<SpatialMaterial> sm = _material;
if (!sm.is_valid()) {
return;
}
sm->set_texture(SpatialMaterial::TEXTURE_ALBEDO, _texture);
}
return;
} else {
Ref<SpatialMaterial> sm = _material; Ref<SpatialMaterial> sm = _material;
if (!sm.is_valid()) { if (!sm.is_valid()) {
@ -143,10 +156,24 @@ void MeshDataInstance::setup_material_texture() {
} }
} }
void MeshDataInstance::free_meshes() {
if (_mesh_instance != RID()) {
VS::get_singleton()->free(_mesh_instance);
_mesh_instance = RID();
}
if (_mesh_rid != RID()) {
VS::get_singleton()->free(_mesh_rid);
_mesh_rid = RID();
}
}
MeshDataInstance::MeshDataInstance() { MeshDataInstance::MeshDataInstance() {
_dirty = false; _dirty = false;
_snap_to_mesh = false; _snap_to_mesh = false;
_snap_axis = Vector3(0, -1, 0); _snap_axis = Vector3(0, -1, 0);
set_notify_transform(true);
} }
MeshDataInstance::~MeshDataInstance() { MeshDataInstance::~MeshDataInstance() {
_mesh.unref(); _mesh.unref();
@ -156,11 +183,23 @@ MeshDataInstance::~MeshDataInstance() {
void MeshDataInstance::_notification(int p_what) { void MeshDataInstance::_notification(int p_what) {
switch (p_what) { switch (p_what) {
case NOTIFICATION_ENTER_TREE: { case NOTIFICATION_ENTER_TREE: {
if (_dirty) { setup_material_texture();
_dirty = false; refresh();
refresh(); break;
}
case NOTIFICATION_EXIT_TREE: {
free_meshes();
break;
}
case NOTIFICATION_TRANSFORM_CHANGED: {
VisualServer *vs = VisualServer::get_singleton();
if (_mesh_instance != RID()) {
vs->instance_set_transform(_mesh_instance, get_transform());
} }
break;
} }
} }
} }

View File

@ -27,12 +27,12 @@ SOFTWARE.
#include "scene/resources/texture.h" #include "scene/resources/texture.h"
#if VERSION_MAJOR < 4 #if VERSION_MAJOR < 4
#include "scene/3d/mesh_instance.h" #include "scene/3d/spatial.h"
#else #else
#include "scene/3d/mesh_instance_3d.h" #include "scene/3d/node_3d.h"
#define SpatialMaterial StandardMaterial3D #define SpatialMaterial StandardMaterial3D
#define MeshInstance MeshInstance3D #define Spatial Node3D
#define Texture Texture2D #define Texture Texture2D
#endif #endif
@ -42,8 +42,8 @@ SOFTWARE.
class PropInstance; class PropInstance;
class MeshDataInstance : public MeshInstance { class MeshDataInstance : public Spatial {
GDCLASS(MeshDataInstance, MeshInstance); GDCLASS(MeshDataInstance, Spatial);
public: public:
bool get_snap_to_mesh() const; bool get_snap_to_mesh() const;
@ -63,6 +63,7 @@ public:
void refresh(); void refresh();
void setup_material_texture(); void setup_material_texture();
void free_meshes();
MeshDataInstance(); MeshDataInstance();
~MeshDataInstance(); ~MeshDataInstance();
@ -78,6 +79,9 @@ private:
Ref<MeshDataResource> _mesh; Ref<MeshDataResource> _mesh;
Ref<Texture> _texture; Ref<Texture> _texture;
Ref<Material> _material; Ref<Material> _material;
RID _mesh_rid;
RID _mesh_instance;
}; };
#endif #endif