summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/editor_node.cpp2
-rw-r--r--editor/icons/icon_c_p_u_particles.svg60
-rw-r--r--editor/plugins/cpu_particles_editor_plugin.cpp114
-rw-r--r--editor/plugins/cpu_particles_editor_plugin.h55
-rw-r--r--editor/plugins/particles_editor_plugin.cpp410
-rw-r--r--editor/plugins/particles_editor_plugin.h34
6 files changed, 480 insertions, 195 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 2ac0364778..8d039f8cc0 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -79,6 +79,7 @@
#include "editor/plugins/collision_polygon_2d_editor_plugin.h"
#include "editor/plugins/collision_polygon_editor_plugin.h"
#include "editor/plugins/collision_shape_2d_editor_plugin.h"
+#include "editor/plugins/cpu_particles_editor_plugin.h"
#include "editor/plugins/cube_grid_theme_editor_plugin.h"
#include "editor/plugins/curve_editor_plugin.h"
#include "editor/plugins/editor_preview_plugins.h"
@@ -5383,6 +5384,7 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(SpriteEditorPlugin(this)));
add_editor_plugin(memnew(Skeleton2DEditorPlugin(this)));
add_editor_plugin(memnew(ParticlesEditorPlugin(this)));
+ add_editor_plugin(memnew(CPUParticlesEditorPlugin(this)));
add_editor_plugin(memnew(ResourcePreloaderEditorPlugin(this)));
add_editor_plugin(memnew(ItemListEditorPlugin(this)));
add_editor_plugin(memnew(Polygon3DEditorPlugin(this)));
diff --git a/editor/icons/icon_c_p_u_particles.svg b/editor/icons/icon_c_p_u_particles.svg
new file mode 100644
index 0000000000..00d79cafd2
--- /dev/null
+++ b/editor/icons/icon_c_p_u_particles.svg
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ version="1.1"
+ viewBox="0 0 16 16"
+ id="svg6"
+ sodipodi:docname="icon_c_p_u_particles.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs10" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1741"
+ inkscape:window-height="753"
+ id="namedview8"
+ showgrid="false"
+ inkscape:zoom="14.75"
+ inkscape:cx="8.1355932"
+ inkscape:cy="7.7288136"
+ inkscape:window-x="67"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg6" />
+ <path
+ style="fill:#fc9c9c;fill-opacity:0.99607843"
+ d="m 4.5587261,0.60940813 c -0.4226244,0 -0.7617187,0.3410473 -0.7617187,0.76367177 v 0.5078126 c 0,0.1028478 0.020058,0.199689 0.056641,0.2890624 H 2.6602887 c -0.4226245,0 -0.7617188,0.3390944 -0.7617188,0.7617188 v 0.921875 C 1.8581419,3.8469787 1.821771,3.8301112 1.7794293,3.8301112 H 1.2716168 c -0.42262448,0 -0.76367188,0.3410475 -0.76367188,0.7636719 v 0.3730468 c 0,0.4226245 0.3410474,0.7617188 0.76367188,0.7617188 h 0.5078125 c 0.042396,0 0.078663,-0.016851 0.1191406,-0.023437 v 4.4531248 c -0.040428,-0.0066 -0.076799,-0.02344 -0.1191406,-0.02344 H 1.2716168 c -0.42262448,0 -0.76367188,0.341047 -0.76367188,0.763672 v 0.373047 c 0,0.422625 0.3410474,0.761718 0.76367188,0.761718 h 0.5078125 c 0.042396,0 0.078663,-0.01685 0.1191406,-0.02344 v 1.125 c 0,0.422624 0.3390944,0.763672 0.7617188,0.763672 h 1.1367187 v 0.457031 c 0,0.422624 0.3390943,0.763672 0.7617187,0.763672 H 4.931773 c 0.4226244,0 0.7636719,-0.341048 0.7636719,-0.763672 v -0.457031 h 4.4062501 v 0.457031 c 0,0.422624 0.339094,0.763672 0.761719,0.763672 h 0.373047 c 0.422624,0 0.763671,-0.341048 0.763671,-0.763672 v -0.457031 h 1.269532 c 0.422625,0 0.763672,-0.341048 0.763672,-0.763672 v -1.111328 c 0.01774,0.0012 0.03272,0.0098 0.05078,0.0098 h 0.507812 c 0.422624,0 0.763672,-0.339093 0.763672,-0.761718 v -0.373047 c 0,-0.422624 -0.341048,-0.763672 -0.763672,-0.763672 h -0.507812 c -0.01803,0 -0.03307,0.0085 -0.05078,0.0098 V 5.7187831 c 0.01774,0.00122 0.03272,0.00977 0.05078,0.00977 h 0.507812 c 0.422624,0 0.763672,-0.3390943 0.763672,-0.7617188 V 4.5937831 c 0,-0.4226244 -0.341048,-0.7636719 -0.763672,-0.7636719 h -0.507812 c -0.01803,0 -0.03307,0.00855 -0.05078,0.00977 V 2.9316737 c 0,-0.4226244 -0.341047,-0.7617187 -0.763672,-0.7617188 h -1.328125 c 0.03658,-0.089375 0.05859,-0.1862118 0.05859,-0.2890624 V 1.3730799 c 0,-0.42262437 -0.341047,-0.76367177 -0.763671,-0.76367177 h -0.373047 c -0.422625,0 -0.761719,0.3410474 -0.761719,0.76367177 v 0.5078126 c 0,0.1028478 0.02006,0.1996891 0.05664,0.2890624 H 5.6368511 C 5.6734361,2.08058 5.6954449,1.9837431 5.6954449,1.8808925 V 1.3730799 c 0,-0.42262437 -0.3410475,-0.76367177 -0.7636719,-0.76367177 z M 7.7970074,2.9668299 A 3.279661,3.6440678 0 0 1 11.009898,5.9062831 2.1864407,2.1864407 0 0 1 12.89857,8.0683925 2.1864407,2.1864407 0 0 1 10.71107,10.25394 H 4.8809918 A 2.1864407,2.1864407 0 0 1 2.6954449,8.0683925 2.1864407,2.1864407 0 0 1 4.5802105,5.9043299 3.279661,3.6440678 0 0 1 7.7970074,2.9668299 Z M 4.8809918,10.982455 A 0.72881355,0.72881355 0 0 1 5.6095074,11.710971 0.72881355,0.72881355 0 0 1 4.8809918,12.44144 0.72881355,0.72881355 0 0 1 4.1524761,11.710971 0.72881355,0.72881355 0 0 1 4.8809918,10.982455 Z m 5.8300782,0 A 0.72881355,0.72881355 0 0 1 11.441539,11.710971 0.72881355,0.72881355 0 0 1 10.71107,12.44144 0.72881355,0.72881355 0 0 1 9.9825543,11.710971 0.72881355,0.72881355 0 0 1 10.71107,10.982455 Z M 7.7970074,11.710971 A 0.72881355,0.72881355 0 0 1 8.525523,12.44144 0.72881355,0.72881355 0 0 1 7.7970074,13.169955 0.72881355,0.72881355 0 0 1 7.0684918,12.44144 0.72881355,0.72881355 0 0 1 7.7970074,11.710971 Z"
+ id="rect822"
+ inkscape:connector-curvature="0" />
+ <g
+ inkscape:groupmode="layer"
+ id="layer1"
+ inkscape:label="Layer 1" />
+</svg>
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..e0325702a8 100644
--- a/editor/plugins/particles_editor_plugin.cpp
+++ b/editor/plugins/particles_editor_plugin.cpp
@@ -31,130 +31,10 @@
#include "particles_editor_plugin.h"
#include "editor/plugins/spatial_editor_plugin.h"
#include "io/resource_loader.h"
+#include "scene/3d/cpu_particles.h"
+bool ParticlesEditorBase::_generate(PoolVector<Vector3> &points, PoolVector<Vector3> &normals) {
-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);
-}
-
-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,210 @@ 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;
+ case MENU_OPTION_CONVERT_TO_CPU_PARTICLES: {
+
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ CPUParticles *cpu_particles = memnew(CPUParticles);
+ cpu_particles->convert_from_particles(node);
+
+ undo_redo->create_action("Replace Particles by CPUParticles");
+ undo_redo->add_do_method(node, "replace_by", cpu_particles);
+ undo_redo->add_undo_method(cpu_particles, "replace_by", node);
+ undo_redo->add_do_reference(cpu_particles);
+ undo_redo->add_undo_reference(node);
+ undo_redo->commit_action();
+
+ } 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 +366,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 +384,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 +396,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 +423,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);
}
@@ -360,49 +439,10 @@ ParticlesEditor::ParticlesEditor() {
options->get_popup()->add_separator();
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");
-
- 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());
- }
+ options->get_popup()->add_separator();
+ options->get_popup()->add_item(TTR("Convert to CPUParticles"), MENU_OPTION_CONVERT_TO_CPU_PARTICLES);
- emission_file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
+ options->get_popup()->connect("id_pressed", this, "_menu_option");
generate_aabb = memnew(ConfirmationDialog);
generate_aabb->set_title(TTR("Generate Visibility AABB"));
diff --git a/editor/plugins/particles_editor_plugin.h b/editor/plugins/particles_editor_plugin.h
index 013b6e7e30..622ce6e8a9 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 {
@@ -67,21 +84,18 @@ class ParticlesEditor : public Control {
MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE,
MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH,
MENU_OPTION_CLEAR_EMISSION_VOLUME,
+ MENU_OPTION_CONVERT_TO_CPU_PARTICLES,
};
- 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);