diff options
author | Juan Linietsky <reduzio@gmail.com> | 2018-07-06 20:21:13 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2018-07-06 20:21:42 -0300 |
commit | 7dcaabaf1989f0e4d6957ca123df522c805ac57a (patch) | |
tree | 7099b9650d72b8820950a5662f6db1ad9956654a /editor/plugins | |
parent | e19388df97743939efd0cfda3dae6de2db393897 (diff) |
Support for CPU based particles, which aids compatibility with OpenGL ES 2.0
Diffstat (limited to 'editor/plugins')
-rw-r--r-- | editor/plugins/cpu_particles_editor_plugin.cpp | 114 | ||||
-rw-r--r-- | editor/plugins/cpu_particles_editor_plugin.h | 55 | ||||
-rw-r--r-- | editor/plugins/particles_editor_plugin.cpp | 390 | ||||
-rw-r--r-- | editor/plugins/particles_editor_plugin.h | 33 |
4 files changed, 398 insertions, 194 deletions
diff --git a/editor/plugins/cpu_particles_editor_plugin.cpp b/editor/plugins/cpu_particles_editor_plugin.cpp new file mode 100644 index 0000000000..b32f927249 --- /dev/null +++ b/editor/plugins/cpu_particles_editor_plugin.cpp @@ -0,0 +1,114 @@ +#include "cpu_particles_editor_plugin.h" +#include "editor/plugins/spatial_editor_plugin.h" + +void CPUParticlesEditor::_node_removed(Node *p_node) { + + if (p_node == node) { + node = NULL; + hide(); + } +} + +void CPUParticlesEditor::_notification(int p_notification) { + + if (p_notification == NOTIFICATION_ENTER_TREE) { + options->set_icon(options->get_popup()->get_icon("CPUParticles", "EditorIcons")); + } +} + +void CPUParticlesEditor::_menu_option(int p_option) { + + switch (p_option) { + + case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH: { + + emission_file_dialog->popup_centered_ratio(); + + } break; + + case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE: { + + emission_tree_dialog->popup_centered_ratio(); + + } break; + } +} + +void CPUParticlesEditor::edit(CPUParticles *p_particles) { + + base_node = p_particles; + node = p_particles; +} + +void CPUParticlesEditor::_generate_emission_points() { + + /// hacer codigo aca + PoolVector<Vector3> points; + PoolVector<Vector3> normals; + + if (!_generate(points, normals)) { + return; + } + + if (normals.size() == 0) { + node->set_emission_shape(CPUParticles::EMISSION_SHAPE_POINTS); + node->set_emission_points(points); + } else { + node->set_emission_shape(CPUParticles::EMISSION_SHAPE_DIRECTED_POINTS); + node->set_emission_points(points); + node->set_emission_normals(normals); + } +} + +void CPUParticlesEditor::_bind_methods() { + + ClassDB::bind_method("_menu_option", &CPUParticlesEditor::_menu_option); +} + +CPUParticlesEditor::CPUParticlesEditor() { + + particles_editor_hb = memnew(HBoxContainer); + SpatialEditor::get_singleton()->add_control_to_menu_panel(particles_editor_hb); + options = memnew(MenuButton); + particles_editor_hb->add_child(options); + particles_editor_hb->hide(); + + options->set_text(TTR("CPUParticles")); + options->get_popup()->add_item(TTR("Create Emission Points From Mesh"), MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH); + options->get_popup()->add_item(TTR("Create Emission Points From Node"), MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE); + options->get_popup()->connect("id_pressed", this, "_menu_option"); +} + +void CPUParticlesEditorPlugin::edit(Object *p_object) { + + particles_editor->edit(Object::cast_to<CPUParticles>(p_object)); +} + +bool CPUParticlesEditorPlugin::handles(Object *p_object) const { + + return p_object->is_class("CPUParticles"); +} + +void CPUParticlesEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + particles_editor->show(); + particles_editor->particles_editor_hb->show(); + } else { + particles_editor->particles_editor_hb->hide(); + particles_editor->hide(); + particles_editor->edit(NULL); + } +} + +CPUParticlesEditorPlugin::CPUParticlesEditorPlugin(EditorNode *p_node) { + + editor = p_node; + particles_editor = memnew(CPUParticlesEditor); + editor->get_viewport()->add_child(particles_editor); + + particles_editor->hide(); +} + +CPUParticlesEditorPlugin::~CPUParticlesEditorPlugin() { +} diff --git a/editor/plugins/cpu_particles_editor_plugin.h b/editor/plugins/cpu_particles_editor_plugin.h new file mode 100644 index 0000000000..f47d17104d --- /dev/null +++ b/editor/plugins/cpu_particles_editor_plugin.h @@ -0,0 +1,55 @@ +#ifndef CPU_PARTICLES_EDITOR_PLUGIN_H +#define CPU_PARTICLES_EDITOR_PLUGIN_H + +#include "editor/plugins/particles_editor_plugin.h" +#include "scene/3d/cpu_particles.h" + +class CPUParticlesEditor : public ParticlesEditorBase { + + GDCLASS(CPUParticlesEditor, ParticlesEditorBase); + + enum Menu { + + MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE, + MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH, + MENU_OPTION_CLEAR_EMISSION_VOLUME, + + }; + + CPUParticles *node; + + void _menu_option(int); + + friend class CPUParticlesEditorPlugin; + + virtual void _generate_emission_points(); + +protected: + void _notification(int p_notification); + void _node_removed(Node *p_node); + static void _bind_methods(); + +public: + void edit(CPUParticles *p_particles); + CPUParticlesEditor(); +}; + +class CPUParticlesEditorPlugin : public EditorPlugin { + + GDCLASS(CPUParticlesEditorPlugin, EditorPlugin); + + CPUParticlesEditor *particles_editor; + EditorNode *editor; + +public: + virtual String get_name() const { return "CPUParticles"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_object); + virtual bool handles(Object *p_object) const; + virtual void make_visible(bool p_visible); + + CPUParticlesEditorPlugin(EditorNode *p_node); + ~CPUParticlesEditorPlugin(); +}; + +#endif // CPU_PARTICLES_EDITOR_PLUGIN_H diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp index 7728995a99..91b307293b 100644 --- a/editor/plugins/particles_editor_plugin.cpp +++ b/editor/plugins/particles_editor_plugin.cpp @@ -32,129 +32,9 @@ #include "editor/plugins/spatial_editor_plugin.h" #include "io/resource_loader.h" -void ParticlesEditor::_node_removed(Node *p_node) { - - if (p_node == node) { - node = NULL; - hide(); - } -} - -void ParticlesEditor::_node_selected(const NodePath &p_path) { - - Node *sel = get_node(p_path); - if (!sel) - return; - - VisualInstance *vi = Object::cast_to<VisualInstance>(sel); - if (!vi) { - - err_dialog->set_text(TTR("Node does not contain geometry.")); - err_dialog->popup_centered_minsize(); - return; - } - - geometry = vi->get_faces(VisualInstance::FACES_SOLID); - - if (geometry.size() == 0) { - - err_dialog->set_text(TTR("Node does not contain geometry (faces).")); - err_dialog->popup_centered_minsize(); - return; - } - - Transform geom_xform = node->get_global_transform().affine_inverse() * vi->get_global_transform(); - - int gc = geometry.size(); - PoolVector<Face3>::Write w = geometry.write(); - - for (int i = 0; i < gc; i++) { - for (int j = 0; j < 3; j++) { - w[i].vertex[j] = geom_xform.xform(w[i].vertex[j]); - } - } - - w = PoolVector<Face3>::Write(); - - emission_dialog->popup_centered(Size2(300, 130)); -} - -void ParticlesEditor::_notification(int p_notification) { - - if (p_notification == NOTIFICATION_ENTER_TREE) { - options->set_icon(options->get_popup()->get_icon("Particles", "EditorIcons")); - } -} - -void ParticlesEditor::_menu_option(int p_option) { - - switch (p_option) { - - case MENU_OPTION_GENERATE_AABB: { - generate_aabb->popup_centered_minsize(); - } break; - case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH: { - - Ref<ParticlesMaterial> material = node->get_process_material(); - if (material.is_null()) { - EditorNode::get_singleton()->show_warning(TTR("A processor material of type 'ParticlesMaterial' is required.")); - return; - } - emission_file_dialog->popup_centered_ratio(); - - } break; - - case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE: { - Ref<ParticlesMaterial> material = node->get_process_material(); - if (material.is_null()) { - EditorNode::get_singleton()->show_warning(TTR("A processor material of type 'ParticlesMaterial' is required.")); - return; - } - - emission_tree_dialog->popup_centered_ratio(); - - } break; - } -} - -void ParticlesEditor::_generate_aabb() { - - float time = generate_seconds->get_value(); - - float running = 0.0; - - EditorProgress ep("gen_aabb", TTR("Generating AABB"), int(time)); - - AABB rect; - while (running < time) { - - uint64_t ticks = OS::get_singleton()->get_ticks_usec(); - ep.step("Generating...", int(running), true); - OS::get_singleton()->delay_usec(1000); - - AABB capture = node->capture_aabb(); - if (rect == AABB()) - rect = capture; - else - rect.merge_with(capture); - - running += (OS::get_singleton()->get_ticks_usec() - ticks) / 1000000.0; - } - - node->set_visibility_aabb(rect); -} +bool ParticlesEditorBase::_generate(PoolVector<Vector3> &points, PoolVector<Vector3> &normals) { -void ParticlesEditor::edit(Particles *p_particles) { - - node = p_particles; -} - -void ParticlesEditor::_generate_emission_points() { - - /// hacer codigo aca - PoolVector<float> points; bool use_normals = emission_fill->get_selected() == 1; - PoolVector<float> normals; if (emission_fill->get_selected() < 2) { @@ -175,7 +55,7 @@ void ParticlesEditor::_generate_emission_points() { err_dialog->set_text(TTR("Faces contain no area!")); err_dialog->popup_centered_minsize(); - return; + return false; } int emissor_count = emission_amount->get_value(); @@ -185,9 +65,9 @@ void ParticlesEditor::_generate_emission_points() { float areapos = Math::random(0.0f, area_accum); Map<float, int>::Element *E = triangle_area_map.find_closest(areapos); - ERR_FAIL_COND(!E) + ERR_FAIL_COND_V(!E, false) int index = E->get(); - ERR_FAIL_INDEX(index, geometry.size()); + ERR_FAIL_INDEX_V(index, geometry.size(), false); // ok FINALLY get face Face3 face = geometry[index]; @@ -195,15 +75,11 @@ void ParticlesEditor::_generate_emission_points() { Vector3 pos = face.get_random_point_inside(); - points.push_back(pos.x); - points.push_back(pos.y); - points.push_back(pos.z); + points.push_back(pos); if (use_normals) { Vector3 normal = face.get_plane().normal; - normals.push_back(normal.x); - normals.push_back(normal.y); - normals.push_back(normal.z); + normals.push_back(normal); } } } else { @@ -214,7 +90,7 @@ void ParticlesEditor::_generate_emission_points() { err_dialog->set_text(TTR("No faces!")); err_dialog->popup_centered_minsize(); - return; + return false; } PoolVector<Face3>::Read r = geometry.read(); @@ -276,15 +152,195 @@ void ParticlesEditor::_generate_emission_points() { Vector3 point = ofs + dir * val; - points.push_back(point.x); - points.push_back(point.y); - points.push_back(point.z); + points.push_back(point); break; } } } - int point_count = points.size() / 3; + return true; +} + +void ParticlesEditorBase::_node_selected(const NodePath &p_path) { + + Node *sel = get_node(p_path); + if (!sel) + return; + + VisualInstance *vi = Object::cast_to<VisualInstance>(sel); + if (!vi) { + + err_dialog->set_text(TTR("Node does not contain geometry.")); + err_dialog->popup_centered_minsize(); + return; + } + + geometry = vi->get_faces(VisualInstance::FACES_SOLID); + + if (geometry.size() == 0) { + + err_dialog->set_text(TTR("Node does not contain geometry (faces).")); + err_dialog->popup_centered_minsize(); + return; + } + + Transform geom_xform = base_node->get_global_transform().affine_inverse() * vi->get_global_transform(); + + int gc = geometry.size(); + PoolVector<Face3>::Write w = geometry.write(); + + for (int i = 0; i < gc; i++) { + for (int j = 0; j < 3; j++) { + w[i].vertex[j] = geom_xform.xform(w[i].vertex[j]); + } + } + + w = PoolVector<Face3>::Write(); + + emission_dialog->popup_centered(Size2(300, 130)); +} + +void ParticlesEditorBase::_bind_methods() { + + ClassDB::bind_method("_node_selected", &ParticlesEditorBase::_node_selected); + ClassDB::bind_method("_generate_emission_points", &ParticlesEditorBase::_generate_emission_points); +} + +ParticlesEditorBase::ParticlesEditorBase() { + + emission_dialog = memnew(ConfirmationDialog); + emission_dialog->set_title(TTR("Create Emitter")); + add_child(emission_dialog); + VBoxContainer *emd_vb = memnew(VBoxContainer); + emission_dialog->add_child(emd_vb); + + emission_amount = memnew(SpinBox); + emission_amount->set_min(1); + emission_amount->set_max(100000); + emission_amount->set_value(512); + emd_vb->add_margin_child(TTR("Emission Points:"), emission_amount); + + emission_fill = memnew(OptionButton); + emission_fill->add_item(TTR("Surface Points")); + emission_fill->add_item(TTR("Surface Points+Normal (Directed)")); + emission_fill->add_item(TTR("Volume")); + emd_vb->add_margin_child(TTR("Emission Source: "), emission_fill); + + emission_dialog->get_ok()->set_text(TTR("Create")); + emission_dialog->connect("confirmed", this, "_generate_emission_points"); + + err_dialog = memnew(ConfirmationDialog); + add_child(err_dialog); + + emission_file_dialog = memnew(EditorFileDialog); + add_child(emission_file_dialog); + emission_file_dialog->connect("file_selected", this, "_resource_seleted"); + emission_tree_dialog = memnew(SceneTreeDialog); + add_child(emission_tree_dialog); + emission_tree_dialog->connect("selected", this, "_node_selected"); + + List<String> extensions; + ResourceLoader::get_recognized_extensions_for_type("Mesh", &extensions); + + emission_file_dialog->clear_filters(); + for (int i = 0; i < extensions.size(); i++) { + + emission_file_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper()); + } + + emission_file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); +} + +void ParticlesEditor::_node_removed(Node *p_node) { + + if (p_node == node) { + node = NULL; + hide(); + } +} + +void ParticlesEditor::_notification(int p_notification) { + + if (p_notification == NOTIFICATION_ENTER_TREE) { + options->set_icon(options->get_popup()->get_icon("Particles", "EditorIcons")); + } +} + +void ParticlesEditor::_menu_option(int p_option) { + + switch (p_option) { + + case MENU_OPTION_GENERATE_AABB: { + generate_aabb->popup_centered_minsize(); + } break; + case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH: { + + Ref<ParticlesMaterial> material = node->get_process_material(); + if (material.is_null()) { + EditorNode::get_singleton()->show_warning(TTR("A processor material of type 'ParticlesMaterial' is required.")); + return; + } + emission_file_dialog->popup_centered_ratio(); + + } break; + + case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE: { + Ref<ParticlesMaterial> material = node->get_process_material(); + if (material.is_null()) { + EditorNode::get_singleton()->show_warning(TTR("A processor material of type 'ParticlesMaterial' is required.")); + return; + } + + emission_tree_dialog->popup_centered_ratio(); + + } break; + } +} + +void ParticlesEditor::_generate_aabb() { + + float time = generate_seconds->get_value(); + + float running = 0.0; + + EditorProgress ep("gen_aabb", TTR("Generating AABB"), int(time)); + + AABB rect; + while (running < time) { + + uint64_t ticks = OS::get_singleton()->get_ticks_usec(); + ep.step("Generating...", int(running), true); + OS::get_singleton()->delay_usec(1000); + + AABB capture = node->capture_aabb(); + if (rect == AABB()) + rect = capture; + else + rect.merge_with(capture); + + running += (OS::get_singleton()->get_ticks_usec() - ticks) / 1000000.0; + } + + node->set_visibility_aabb(rect); +} + +void ParticlesEditor::edit(Particles *p_particles) { + + base_node = p_particles; + node = p_particles; +} + +void ParticlesEditor::_generate_emission_points() { + + /// hacer codigo aca + PoolVector<Vector3> points; + PoolVector<Vector3> normals; + + if (!_generate(points, normals)) { + return; + } + + int point_count = points.size(); int w = 2048; int h = (point_count / 2048) + 1; @@ -295,8 +351,13 @@ void ParticlesEditor::_generate_emission_points() { { PoolVector<uint8_t>::Write iw = point_img.write(); zeromem(iw.ptr(), w * h * 3 * sizeof(float)); - PoolVector<float>::Read r = points.read(); - copymem(iw.ptr(), r.ptr(), point_count * sizeof(float) * 3); + PoolVector<Vector3>::Read r = points.read(); + float *wf = (float *)iw.ptr(); + for (int i = 0; i < point_count; i++) { + wf[i * 3 + 0] = r[i].x; + wf[i * 3 + 1] = r[i].y; + wf[i * 3 + 2] = r[i].z; + } } Ref<Image> image = memnew(Image(w, h, false, Image::FORMAT_RGBF, point_img)); @@ -308,7 +369,7 @@ void ParticlesEditor::_generate_emission_points() { Ref<ParticlesMaterial> material = node->get_process_material(); ERR_FAIL_COND(material.is_null()); - if (use_normals) { + if (normals.size() > 0) { material->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_DIRECTED_POINTS); material->set_emission_point_count(point_count); @@ -320,8 +381,13 @@ void ParticlesEditor::_generate_emission_points() { { PoolVector<uint8_t>::Write iw = point_img2.write(); zeromem(iw.ptr(), w * h * 3 * sizeof(float)); - PoolVector<float>::Read r = normals.read(); - copymem(iw.ptr(), r.ptr(), point_count * sizeof(float) * 3); + PoolVector<Vector3>::Read r = normals.read(); + float *wf = (float *)iw.ptr(); + for (int i = 0; i < point_count; i++) { + wf[i * 3 + 0] = r[i].x; + wf[i * 3 + 1] = r[i].y; + wf[i * 3 + 2] = r[i].z; + } } Ref<Image> image2 = memnew(Image(w, h, false, Image::FORMAT_RGBF, point_img2)); @@ -342,8 +408,6 @@ void ParticlesEditor::_generate_emission_points() { void ParticlesEditor::_bind_methods() { ClassDB::bind_method("_menu_option", &ParticlesEditor::_menu_option); - ClassDB::bind_method("_node_selected", &ParticlesEditor::_node_selected); - ClassDB::bind_method("_generate_emission_points", &ParticlesEditor::_generate_emission_points); ClassDB::bind_method("_generate_aabb", &ParticlesEditor::_generate_aabb); } @@ -362,48 +426,6 @@ ParticlesEditor::ParticlesEditor() { options->get_popup()->add_item(TTR("Create Emission Points From Node"), MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE); options->get_popup()->connect("id_pressed", this, "_menu_option"); - emission_dialog = memnew(ConfirmationDialog); - emission_dialog->set_title(TTR("Create Emitter")); - add_child(emission_dialog); - VBoxContainer *emd_vb = memnew(VBoxContainer); - emission_dialog->add_child(emd_vb); - - emission_amount = memnew(SpinBox); - emission_amount->set_min(1); - emission_amount->set_max(100000); - emission_amount->set_value(512); - emd_vb->add_margin_child(TTR("Emission Points:"), emission_amount); - - emission_fill = memnew(OptionButton); - emission_fill->add_item(TTR("Surface Points")); - emission_fill->add_item(TTR("Surface Points+Normal (Directed)")); - emission_fill->add_item(TTR("Volume")); - emd_vb->add_margin_child(TTR("Emission Source: "), emission_fill); - - emission_dialog->get_ok()->set_text(TTR("Create")); - emission_dialog->connect("confirmed", this, "_generate_emission_points"); - - err_dialog = memnew(ConfirmationDialog); - add_child(err_dialog); - - emission_file_dialog = memnew(EditorFileDialog); - add_child(emission_file_dialog); - emission_file_dialog->connect("file_selected", this, "_resource_seleted"); - emission_tree_dialog = memnew(SceneTreeDialog); - add_child(emission_tree_dialog); - emission_tree_dialog->connect("selected", this, "_node_selected"); - - List<String> extensions; - ResourceLoader::get_recognized_extensions_for_type("Mesh", &extensions); - - emission_file_dialog->clear_filters(); - for (int i = 0; i < extensions.size(); i++) { - - emission_file_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper()); - } - - emission_file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); - generate_aabb = memnew(ConfirmationDialog); generate_aabb->set_title(TTR("Generate Visibility AABB")); VBoxContainer *genvb = memnew(VBoxContainer); diff --git a/editor/plugins/particles_editor_plugin.h b/editor/plugins/particles_editor_plugin.h index 013b6e7e30..d1fef1fbc1 100644 --- a/editor/plugins/particles_editor_plugin.h +++ b/editor/plugins/particles_editor_plugin.h @@ -40,14 +40,14 @@ @author Juan Linietsky <reduzio@gmail.com> */ -class ParticlesEditor : public Control { - - GDCLASS(ParticlesEditor, Control); +class ParticlesEditorBase : public Control { + GDCLASS(ParticlesEditorBase, Control) +protected: + Spatial *base_node; Panel *panel; MenuButton *options; HBoxContainer *particles_editor_hb; - Particles *node; EditorFileDialog *emission_file_dialog; SceneTreeDialog *emission_tree_dialog; @@ -58,8 +58,25 @@ class ParticlesEditor : public Control { SpinBox *emission_amount; OptionButton *emission_fill; + PoolVector<Face3> geometry; + + bool _generate(PoolVector<Vector3> &points, PoolVector<Vector3> &normals); + virtual void _generate_emission_points() = 0; + void _node_selected(const NodePath &p_path); + + static void _bind_methods(); + +public: + ParticlesEditorBase(); +}; + +class ParticlesEditor : public ParticlesEditorBase { + + GDCLASS(ParticlesEditor, ParticlesEditorBase); + ConfirmationDialog *generate_aabb; SpinBox *generate_seconds; + Particles *node; enum Menu { @@ -70,18 +87,14 @@ class ParticlesEditor : public Control { }; - PoolVector<Face3> geometry; - void _generate_aabb(); - void _generate_emission_points(); - void _node_selected(const NodePath &p_path); void _menu_option(int); - void _populate(); - friend class ParticlesEditorPlugin; + virtual void _generate_emission_points(); + protected: void _notification(int p_notification); void _node_removed(Node *p_node); |