diff --git a/SCsub b/SCsub index cf6e32d..06945f9 100644 --- a/SCsub +++ b/SCsub @@ -31,6 +31,7 @@ if 'TOOLS_ENABLED' in env["CPPDEFINES"]: module_env.add_source_files(env.modules_sources,"plugin_gltf/editor_plugin_gltf_mdr.cpp") module_env.add_source_files(env.modules_sources,"nodes/mesh_data_instance.cpp") +module_env.add_source_files(env.modules_sources,"nodes/mesh_data_instance_2d.cpp") if os.path.isdir('../props'): module_env.add_source_files(env.modules_sources,"props/prop_data_mesh_data.cpp") diff --git a/mesh_data_resource.cpp b/mesh_data_resource.cpp index d1e870e..6c37268 100644 --- a/mesh_data_resource.cpp +++ b/mesh_data_resource.cpp @@ -290,6 +290,29 @@ void MeshDataResource::recompute_aabb() { } Variant arr = _arrays[Mesh::ARRAY_VERTEX]; + + PoolVector vertices_2d = arr; + + if (vertices_2d.size() > 0) { + AABB aabb; + +#if VERSION_MAJOR < 4 + PoolVector::Read r = vertices_2d.read(); + const Vector2 *vtx = r.ptr(); +#else + const Vector2 *vtx = vertices.ptr(); +#endif + int len = vertices_2d.size(); + aabb.position = Vector3(vtx[0].x, vtx[0].y, 0); + + for (int i = 0; i < len; i++) { + aabb.expand_to(Vector3(vtx[i].x, vtx[i].y, 0)); + } + + _aabb = aabb; + return; + } + PoolVector vertices = arr; int len = vertices.size(); diff --git a/nodes/mesh_data_instance_2d.cpp b/nodes/mesh_data_instance_2d.cpp new file mode 100644 index 0000000..554a35d --- /dev/null +++ b/nodes/mesh_data_instance_2d.cpp @@ -0,0 +1,156 @@ +#include "mesh_data_instance_2d.h" + +#include "core/version.h" + +#include "core/version.h" +#include "scene/resources/texture.h" + +#if VERSION_MAJOR < 4 +#include "core/image.h" +#else +#include "core/io/image.h" +#endif + +#if TEXTURE_PACKER_PRESENT +#include "../../texture_packer/texture_resource/packer_image_resource.h" +#endif + +Ref MeshDataInstance2D::get_mesh_data() { + return _mesh; +} +void MeshDataInstance2D::set_mesh_data(const Ref &mesh) { + if (_mesh == mesh) { + return; + } + + if (_mesh.is_valid()) { + _mesh->disconnect("changed", this, "refresh"); + } + + _mesh = mesh; + + refresh(); + + if (_mesh.is_valid()) { + _mesh->connect("changed", this, "refresh"); + } + + emit_signal("mesh_data_resource_changed"); +} + +Ref MeshDataInstance2D::get_texture() { + return _texture; +} +void MeshDataInstance2D::set_texture(const Ref &texture) { + if (_texture == texture) { + return; + } + + _texture = texture; + + emit_signal("texture_changed"); + _change_notify("texture"); + refresh(); +} + +Ref MeshDataInstance2D::get_normal_map() { + return _normal_map; +} +void MeshDataInstance2D::set_normal_map(const Ref &texture) { + if (_normal_map == texture) { + return; + } + + _normal_map = texture; + + refresh(); +} + +void MeshDataInstance2D::refresh() { + if (!is_inside_tree()) { + return; + } + + VisualServer::get_singleton()->mesh_clear(_mesh_rid); + + if (!_mesh.is_valid()) { + return; + } + + Array arr = _mesh->get_array(); + + if (arr.size() != Mesh::ARRAY_MAX) { + return; + } + + PoolVector vertices = arr[Mesh::ARRAY_VERTEX]; + + if (vertices.size() == 0) { + return; + } + + VisualServer::get_singleton()->mesh_add_surface_from_arrays(_mesh_rid, VisualServer::PRIMITIVE_TRIANGLES, arr); +} + +#ifdef TOOLS_ENABLED +Rect2 MeshDataInstance2D::_edit_get_rect() const { + if (_mesh.is_valid()) { + AABB aabb = _mesh->get_aabb(); + return Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); + } + + return Node2D::_edit_get_rect(); +} + +bool MeshDataInstance2D::_edit_use_rect() const { + return _mesh.is_valid(); +} +#endif + +MeshDataInstance2D::MeshDataInstance2D() { + _mesh_rid = VisualServer::get_singleton()->mesh_create(); +} +MeshDataInstance2D::~MeshDataInstance2D() { + _mesh.unref(); + _texture.unref(); + + if (_mesh_rid != RID()) { + VS::get_singleton()->free(_mesh_rid); + _mesh_rid = RID(); + } +} + +void MeshDataInstance2D::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + refresh(); + } break; + case NOTIFICATION_DRAW: { + if (_mesh.is_valid()) { + RID texture_rid = _texture.is_valid() ? _texture->get_rid() : RID(); + RID normal_map_rid = _normal_map.is_valid() ? _normal_map->get_rid() : RID(); + + VisualServer::get_singleton()->canvas_item_add_mesh(get_canvas_item(), _mesh_rid, Transform2D(), get_modulate(), texture_rid, normal_map_rid); + } + } break; + } +} + +void MeshDataInstance2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_mesh_data"), &MeshDataInstance2D::get_mesh_data); + ClassDB::bind_method(D_METHOD("set_mesh_data", "value"), &MeshDataInstance2D::set_mesh_data); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh_data", PROPERTY_HINT_RESOURCE_TYPE, "MeshDataResource"), "set_mesh_data", "get_mesh_data"); + + ClassDB::bind_method(D_METHOD("get_texture"), &MeshDataInstance2D::get_texture); + ClassDB::bind_method(D_METHOD("set_texture", "value"), &MeshDataInstance2D::set_texture); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); + + ClassDB::bind_method(D_METHOD("get_normal_map"), &MeshDataInstance2D::get_normal_map); + ClassDB::bind_method(D_METHOD("set_normal_map", "value"), &MeshDataInstance2D::set_normal_map); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map"); + + ClassDB::bind_method(D_METHOD("refresh"), &MeshDataInstance2D::refresh); + + ADD_SIGNAL(MethodInfo("mesh_data_resource_changed")); + ADD_SIGNAL(MethodInfo("texture_changed")); +} diff --git a/nodes/mesh_data_instance_2d.h b/nodes/mesh_data_instance_2d.h new file mode 100644 index 0000000..7dc327b --- /dev/null +++ b/nodes/mesh_data_instance_2d.h @@ -0,0 +1,72 @@ +/* +Copyright (c) 2020-2022 Péter Magyar + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef PROP_MESH_DATA_INSTANCE_2D_H +#define PROP_MESH_DATA_INSTANCE_2D_H + +#include "core/version.h" +#include "scene/resources/texture.h" + +#include "scene/2d/node_2d.h" + +#include "core/math/vector3.h" + +#include "../mesh_data_resource.h" + +class PropInstance; + +class MeshDataInstance2D : public Node2D { + GDCLASS(MeshDataInstance2D, Node2D); + +public: + Ref get_mesh_data(); + void set_mesh_data(const Ref &mesh); + + Ref get_texture(); + void set_texture(const Ref &texture); + + Ref get_normal_map(); + void set_normal_map(const Ref &texture); + + void refresh(); + +#ifdef TOOLS_ENABLED + virtual Rect2 _edit_get_rect() const; + virtual bool _edit_use_rect() const; +#endif + + MeshDataInstance2D(); + ~MeshDataInstance2D(); + +protected: + void _notification(int p_what); + static void _bind_methods(); + +private: + Ref _mesh; + Ref _texture; + Ref _normal_map; + + RID _mesh_rid; +}; + +#endif diff --git a/register_types.cpp b/register_types.cpp index 880ba98..7816fec 100644 --- a/register_types.cpp +++ b/register_types.cpp @@ -25,6 +25,7 @@ SOFTWARE. #include "mesh_data_resource.h" #include "mesh_data_resource_collection.h" #include "nodes/mesh_data_instance.h" +#include "nodes/mesh_data_instance_2d.h" #ifdef TOOLS_ENABLED #include "editor/editor_plugin.h" @@ -49,6 +50,7 @@ void register_mesh_data_resource_types() { ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); #if PROPS_PRESENT ClassDB::register_class();