diff options
36 files changed, 1089 insertions, 293 deletions
diff --git a/core/variant_op.cpp b/core/variant_op.cpp index c4dee5c8a4..5fda6b1473 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -1109,11 +1109,11 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) const String *str = reinterpret_cast<const String *>(p_index._data._mem); Vector2 *v = reinterpret_cast<Vector2 *>(_data._mem); - if (*str == "x" || *str == "width") { + if (*str == "x") { valid = true; v->x = p_value; return; - } else if (*str == "y" || *str == "height") { + } else if (*str == "y") { valid = true; v->y = p_value; return; @@ -1177,7 +1177,7 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) valid = true; v->elements[1] = p_value; return; - } else if (*str == "o") { + } else if (*str == "origin") { valid = true; v->elements[2] = p_value; return; @@ -1572,10 +1572,10 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { const String *str = reinterpret_cast<const String *>(p_index._data._mem); const Vector2 *v = reinterpret_cast<const Vector2 *>(_data._mem); - if (*str == "x" || *str == "width") { + if (*str == "x") { valid = true; return v->x; - } else if (*str == "y" || *str == "height") { + } else if (*str == "y") { valid = true; return v->y; } @@ -1657,7 +1657,7 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } else if (*str == "y") { valid = true; return v->elements[1]; - } else if (*str == "o") { + } else if (*str == "origin") { valid = true; return v->elements[2]; } @@ -2105,8 +2105,6 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::REAL, "x")); p_list->push_back(PropertyInfo(Variant::REAL, "y")); - p_list->push_back(PropertyInfo(Variant::REAL, "width")); - p_list->push_back(PropertyInfo(Variant::REAL, "height")); } break; // 5 case RECT2: { @@ -2127,7 +2125,7 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::VECTOR2, "x")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "y")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, "o")); + p_list->push_back(PropertyInfo(Variant::VECTOR2, "origin")); } break; case PLANE: { diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 8c3569bec0..268d6b44c6 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -348,6 +348,53 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun glBindVertexArray(0); } +void RasterizerCanvasGLES3::_draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) { + + glBindVertexArray(data.polygon_buffer_pointer_array); + glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer); + + uint32_t buffer_ofs = 0; + + //vertex + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices); + glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs); + buffer_ofs += sizeof(Vector2) * p_vertex_count; + //color + + if (p_singlecolor) { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + Color m = *p_colors; + glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); + } else if (!p_colors) { + glDisableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + } else { + + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); + glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, false, sizeof(Color), ((uint8_t *)0) + buffer_ofs); + buffer_ofs += sizeof(Color) * p_vertex_count; + } + + if (p_uvs) { + + glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); + glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs); + buffer_ofs += sizeof(Vector2) * p_vertex_count; + + } else { + glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + } + + glDrawArrays(p_primitive, 0, p_vertex_count); + + storage->frame.canvas_draw_commands++; + + glBindVertexArray(0); +} + void RasterizerCanvasGLES3::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs) { static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN }; @@ -425,22 +472,83 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur glVertexAttrib4f(VS::ARRAY_COLOR, line->color.r, line->color.g, line->color.b, line->color.a); - Vector2 verts[2] = { - Vector2(line->from.x, line->from.y), - Vector2(line->to.x, line->to.y) - }; + if (line->width <= 1) { + Vector2 verts[2] = { + Vector2(line->from.x, line->from.y), + Vector2(line->to.x, line->to.y) + }; #ifdef GLES_OVER_GL - if (line->antialiased) - glEnable(GL_LINE_SMOOTH); + if (line->antialiased) + glEnable(GL_LINE_SMOOTH); #endif - //glLineWidth(line->width); - _draw_gui_primitive(2, verts, NULL, NULL); + //glLineWidth(line->width); + _draw_gui_primitive(2, verts, NULL, NULL); #ifdef GLES_OVER_GL - if (line->antialiased) + if (line->antialiased) + glDisable(GL_LINE_SMOOTH); +#endif + } else { + //thicker line + + Vector2 t = (line->from - line->to).normalized().tangent() * line->width * 0.5; + + Vector2 verts[4] = { + line->from - t, + line->from + t, + line->to + t, + line->to - t, + }; + + //glLineWidth(line->width); + _draw_gui_primitive(4, verts, NULL, NULL); +#ifdef GLES_OVER_GL + if (line->antialiased) { + glEnable(GL_LINE_SMOOTH); + for (int i = 0; i < 4; i++) { + Vector2 vertsl[2] = { + verts[i], + verts[(i + 1) % 4], + }; + _draw_gui_primitive(2, vertsl, NULL, NULL); + } + glDisable(GL_LINE_SMOOTH); + } +#endif + } + + } break; + case Item::Command::TYPE_POLYLINE: { + + Item::CommandPolyLine *pline = static_cast<Item::CommandPolyLine *>(c); + _set_texture_rect_mode(false); + + _bind_canvas_texture(RID(), RID()); + + if (pline->triangles.size()) { + + _draw_generic(GL_TRIANGLE_STRIP, pline->triangles.size(), pline->triangles.ptr(), NULL, pline->triangle_colors.ptr(), pline->triangle_colors.size() == 1); +#ifdef GLES_OVER_GL + glEnable(GL_LINE_SMOOTH); + if (pline->lines.size()) { + _draw_generic(GL_LINE_LOOP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1); + } glDisable(GL_LINE_SMOOTH); #endif + } else { + +#ifdef GLES_OVER_GL + if (pline->antialiased) + glEnable(GL_LINE_SMOOTH); +#endif + _draw_generic(GL_LINE_STRIP, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1); + +#ifdef GLES_OVER_GL + if (pline->antialiased) + glDisable(GL_LINE_SMOOTH); +#endif + } } break; case Item::Command::TYPE_RECT: { diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index ee018e15ea..c0af22b5e8 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -121,6 +121,8 @@ public: _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs); _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); + _FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); + _FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip); _FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 0024870665..a7a3242ad9 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -509,9 +509,8 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save) { if (p_save) { apply_scripts(); } - if (current->get_edit_menu()) { - memdelete(current->get_edit_menu()); - } + current->clear_edit_menu(); + } else { EditorHelp *help = tab_container->get_child(selected)->cast_to<EditorHelp>(); _add_recent_script(help->get_class()); @@ -2180,13 +2179,15 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { script_list = memnew(ItemList); list_split->add_child(script_list); - script_list->set_custom_minimum_size(Size2(0, 0)); + script_list->set_custom_minimum_size(Size2(150 * EDSCALE, 100)); //need to give a bit of limit to avoid it from disappearing + script_list->set_v_size_flags(SIZE_EXPAND_FILL); script_split->set_split_offset(140); - list_split->set_split_offset(500); + //list_split->set_split_offset(500); members_overview = memnew(ItemList); list_split->add_child(members_overview); - members_overview->set_custom_minimum_size(Size2(0, 0)); + members_overview->set_custom_minimum_size(Size2(0, 100)); //need to give a bit of limit to avoid it from disappearing + members_overview->set_v_size_flags(SIZE_EXPAND_FILL); tab_container = memnew(TabContainer); tab_container->add_style_override("panel", p_editor->get_gui_base()->get_stylebox("ScriptPanel", "EditorStyles")); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 3b444c0883..da8248a1a7 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -106,6 +106,7 @@ public: virtual void set_tooltip_request_func(String p_method, Object *p_obj) = 0; virtual Control *get_edit_menu() = 0; + virtual void clear_edit_menu() = 0; ScriptEditorBase() {} }; @@ -363,6 +364,8 @@ public: bool can_take_away_focus() const; + VSplitContainer *get_left_list_split() { return list_split; } + ScriptEditorDebugger *get_debugger() { return debugger; } void set_live_auto_reload_running_scripts(bool p_enabled); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 60fd9d8e30..83741c7fb8 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1093,6 +1093,10 @@ Control *ScriptTextEditor::get_edit_menu() { return edit_hb; } +void ScriptTextEditor::clear_edit_menu() { + memdelete(edit_hb); +} + void ScriptTextEditor::reload(bool p_soft) { TextEdit *te = code_editor->get_text_edit(); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index ba40645161..e55847832f 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -156,7 +156,7 @@ public: virtual void set_debugger_active(bool p_active); Control *get_edit_menu(); - + virtual void clear_edit_menu(); static void register_editor(); ScriptTextEditor(); diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp index 47e5994e3f..c6af993676 100644 --- a/editor/property_selector.cpp +++ b/editor/property_selector.cpp @@ -167,7 +167,7 @@ void PropertySelector::_update_search() { continue; } - if (!(E->get().usage & PROPERTY_USAGE_EDITOR)) + if (!(E->get().usage & PROPERTY_USAGE_EDITOR) && !(E->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE)) continue; if (search_box->get_text() != String() && E->get().name.find(search_box->get_text()) == -1) diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index c0467a901b..a54d306aff 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -90,6 +90,7 @@ void register_visual_script_types() { ClassDB::register_class<VisualScriptSequence>(); //ClassDB::register_class<VisualScriptInputFilter>(); ClassDB::register_class<VisualScriptSwitch>(); + ClassDB::register_class<VisualScriptSelect>(); ClassDB::register_class<VisualScriptYield>(); ClassDB::register_class<VisualScriptYieldSignal>(); diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index bb8111ce99..a922fdf354 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -140,7 +140,7 @@ VisualScriptNode::TypeGuess VisualScriptNode::guess_output_type(TypeGuess *p_inp tg.type = pinfo.type; if (pinfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { - tg.GDCLASS = pinfo.hint_string; + tg.gdclass = pinfo.hint_string; } return tg; @@ -660,6 +660,9 @@ void VisualScript::set_variable_export(const StringName &p_name, bool p_export) ERR_FAIL_COND(!variables.has(p_name)); variables[p_name]._export = p_export; +#ifdef TOOLS_ENABLED + _update_placeholders(); +#endif } bool VisualScript::get_variable_export(const StringName &p_name) const { @@ -1067,9 +1070,11 @@ void VisualScript::get_script_property_list(List<PropertyInfo> *p_list) const { get_variable_list(&vars); for (List<StringName>::Element *E = vars.front(); E; E = E->next()) { - if (!variables[E->get()]._export) - continue; - p_list->push_back(variables[E->get()].info); + //if (!variables[E->get()]._export) + // continue; + PropertyInfo pi = variables[E->get()].info; + pi.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE; + p_list->push_back(pi); } } @@ -1358,6 +1363,7 @@ void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) c continue; PropertyInfo p = E->get().info; p.name = String(E->key()); + p.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE; p_properties->push_back(p); } } diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index 20a1cf49c5..cdd7eded18 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -89,7 +89,7 @@ public: struct TypeGuess { Variant::Type type; - StringName GDCLASS; + StringName gdclass; Ref<Script> script; TypeGuess() { diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 941668d474..a6b53b67fa 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -52,11 +52,13 @@ public: protected: static void _bind_methods() { ClassDB::bind_method("_sig_changed", &VisualScriptEditorSignalEdit::_sig_changed); + ADD_SIGNAL(MethodInfo("changed")); } void _sig_changed() { _change_notify(); + emit_signal("changed"); } bool _set(const StringName &p_name, const Variant &p_value) { @@ -191,15 +193,18 @@ protected: static void _bind_methods() { ClassDB::bind_method("_var_changed", &VisualScriptEditorVariableEdit::_var_changed); ClassDB::bind_method("_var_value_changed", &VisualScriptEditorVariableEdit::_var_value_changed); + ADD_SIGNAL(MethodInfo("changed")); } void _var_changed() { _change_notify(); + emit_signal("changed"); } void _var_value_changed() { _change_notify("value"); //so the whole tree is not redrawn, makes editing smoother in general + emit_signal("changed"); } bool _set(const StringName &p_name, const Variant &p_value) { @@ -261,6 +266,7 @@ protected: if (String(p_name) == "export") { script->set_variable_export(var, p_value); + EditorNode::get_singleton()->get_property_editor()->update_tree(); return true; } @@ -699,7 +705,7 @@ void VisualScriptEditor::_update_members() { ti->set_selectable(0, true); ti->set_editable(0, true); //ti->add_button(0,Control::get_icon("Edit","EditorIcons"),0); function arguments are in the node now - ti->add_button(0, Control::get_icon("Del", "EditorIcons"), 1); + //ti->add_button(0, Control::get_icon("Del", "EditorIcons"), 1); ti->set_metadata(0, E->get()); if (E->get() == edited_func) { ti->set_custom_bg_color(0, get_color("prop_category", "Editor")); @@ -757,8 +763,8 @@ void VisualScriptEditor::_update_members() { ti->set_selectable(0, true); ti->set_editable(0, true); - ti->add_button(0, Control::get_icon("Edit", "EditorIcons"), 0); - ti->add_button(0, Control::get_icon("Del", "EditorIcons"), 1); + //ti->add_button(0, Control::get_icon("Edit", "EditorIcons"), 0); + //ti->add_button(0, Control::get_icon("Del", "EditorIcons"), 1); ti->set_metadata(0, E->get()); if (selected == E->get()) ti->select(0); @@ -777,8 +783,8 @@ void VisualScriptEditor::_update_members() { ti->set_text(0, E->get()); ti->set_selectable(0, true); ti->set_editable(0, true); - ti->add_button(0, Control::get_icon("Edit", "EditorIcons"), 0); - ti->add_button(0, Control::get_icon("Del", "EditorIcons"), 1); + //ti->add_button(0, Control::get_icon("Edit", "EditorIcons"), 0); + //ti->add_button(0, Control::get_icon("Del", "EditorIcons"), 1); ti->set_metadata(0, E->get()); if (selected == E->get()) ti->select(0); @@ -1068,105 +1074,6 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt undo_redo->commit_action(); return; //or crash because it will become invalid } - - } else { - - if (ti->get_parent() == root->get_children()) { - //edit/remove function - String name = ti->get_metadata(0); - - if (p_button == 1) { - //delete the function - undo_redo->create_action(TTR("Remove Function")); - undo_redo->add_do_method(script.ptr(), "remove_function", name); - undo_redo->add_undo_method(script.ptr(), "add_function", name); - List<int> nodes; - script->get_node_list(name, &nodes); - for (List<int>::Element *E = nodes.front(); E; E = E->next()) { - undo_redo->add_undo_method(script.ptr(), "add_node", name, E->get(), script->get_node(name, E->get()), script->get_node_pos(name, E->get())); - } - - List<VisualScript::SequenceConnection> seq_connections; - - script->get_sequence_connection_list(name, &seq_connections); - - for (List<VisualScript::SequenceConnection>::Element *E = seq_connections.front(); E; E = E->next()) { - undo_redo->add_undo_method(script.ptr(), "sequence_connect", name, E->get().from_node, E->get().from_output, E->get().to_node); - } - - List<VisualScript::DataConnection> data_connections; - - script->get_data_connection_list(name, &data_connections); - - for (List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { - undo_redo->add_undo_method(script.ptr(), "data_connect", name, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); - } - - /* - for(int i=0;i<script->function_get_argument_count(name);i++) { - undo_redo->add_undo_method(script.ptr(),"function_add_argument",name,script->function_get_argument_name(name,i),script->function_get_argument_type(name,i)); - } - */ - undo_redo->add_do_method(this, "_update_members"); - undo_redo->add_undo_method(this, "_update_members"); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); - undo_redo->commit_action(); - - } else if (p_button == 0) { - } - return; //or crash because it will become invalid - } - - if (ti->get_parent() == root->get_children()->get_next()) { - //edit/remove variable - - String name = ti->get_metadata(0); - - if (p_button == 1) { - - undo_redo->create_action(TTR("Remove Variable")); - undo_redo->add_do_method(script.ptr(), "remove_variable", name); - undo_redo->add_undo_method(script.ptr(), "add_variable", name, script->get_variable_default_value(name)); - undo_redo->add_undo_method(script.ptr(), "set_variable_info", name, script->call("get_variable_info", name)); //return as dict - undo_redo->add_do_method(this, "_update_members"); - undo_redo->add_undo_method(this, "_update_members"); - undo_redo->commit_action(); - return; //or crash because it will become invalid - } else if (p_button == 0) { - - variable_editor->edit(name); - edit_variable_dialog->set_title(TTR("Editing Variable:") + " " + name); - edit_variable_dialog->popup_centered_minsize(Size2(400, 200) * EDSCALE); - } - } - - if (ti->get_parent() == root->get_children()->get_next()->get_next()) { - //edit/remove variable - String name = ti->get_metadata(0); - - if (p_button == 1) { - - undo_redo->create_action(TTR("Remove Signal")); - undo_redo->add_do_method(script.ptr(), "remove_custom_signal", name); - undo_redo->add_undo_method(script.ptr(), "add_custom_signal", name); - - for (int i = 0; i < script->custom_signal_get_argument_count(name); i++) { - undo_redo->add_undo_method(script.ptr(), "custom_signal_add_argument", name, script->custom_signal_get_argument_name(name, i), script->custom_signal_get_argument_type(name, i)); - } - - undo_redo->add_do_method(this, "_update_members"); - undo_redo->add_undo_method(this, "_update_members"); - undo_redo->commit_action(); - } else if (p_button == 0) { - - signal_editor->edit(name); - edit_signal_dialog->set_title(TTR("Editing Signal:") + " " + name); - edit_signal_dialog->popup_centered_minsize(Size2(400, 300) * EDSCALE); - } - - return; //or crash because it will become invalid - } } } @@ -2269,6 +2176,11 @@ void VisualScriptEditor::_change_base_type() { select_base_type->popup_create(true); } +void VisualScriptEditor::clear_edit_menu() { + memdelete(edit_menu); + memdelete(left_vsplit); +} + void VisualScriptEditor::_change_base_type_callback() { String bt = select_base_type->get_selected_type(); @@ -2556,7 +2468,7 @@ VisualScriptNode::TypeGuess VisualScriptEditor::_guess_output_type(int p_node, i if (obj) { g.type = Variant::OBJECT; - g.GDCLASS = obj->get_class(); + g.gdclass = obj->get_class(); g.script = obj->get_script(); } } @@ -2596,8 +2508,8 @@ void VisualScriptEditor::_port_action_menu(int p_option) { if (tg.type == Variant::OBJECT) { n->set_call_mode(VisualScriptFunctionCall::CALL_MODE_INSTANCE); - if (tg.GDCLASS != StringName()) { - n->set_base_type(tg.GDCLASS); + if (tg.gdclass != StringName()) { + n->set_base_type(tg.gdclass); } else { n->set_base_type("Object"); } @@ -2627,8 +2539,8 @@ void VisualScriptEditor::_port_action_menu(int p_option) { if (tg.type == Variant::OBJECT) { n->set_call_mode(VisualScriptPropertySet::CALL_MODE_INSTANCE); - if (tg.GDCLASS != StringName()) { - n->set_base_type(tg.GDCLASS); + if (tg.gdclass != StringName()) { + n->set_base_type(tg.gdclass); } else { n->set_base_type("Object"); } @@ -2657,8 +2569,8 @@ void VisualScriptEditor::_port_action_menu(int p_option) { if (tg.type == Variant::OBJECT) { n->set_call_mode(VisualScriptPropertyGet::CALL_MODE_INSTANCE); - if (tg.GDCLASS != StringName()) { - n->set_base_type(tg.GDCLASS); + if (tg.gdclass != StringName()) { + n->set_base_type(tg.gdclass); } else { n->set_base_type("Object"); } @@ -2834,12 +2746,17 @@ void VisualScriptEditor::_notification(int p_what) { if (p_what == NOTIFICATION_READY) { node_filter_icon->set_texture(Control::get_icon("Zoom", "EditorIcons")); + variable_editor->connect("changed", this, "_update_members"); + signal_editor->connect("changed", this, "_update_members"); + } + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + left_vsplit->set_visible(is_visible_in_tree()); } } void VisualScriptEditor::_graph_ofs_changed(const Vector2 &p_ofs) { - if (updating_graph) + if (updating_graph || !script.is_valid()) return; updating_graph = true; @@ -3053,6 +2970,142 @@ void VisualScriptEditor::_menu_option(int p_what) { } } +void VisualScriptEditor::_member_rmb_selected(const Vector2 &p_pos) { + + TreeItem *ti = members->get_selected(); + ERR_FAIL_COND(!ti); + + member_popup->clear(); + member_popup->set_position(members->get_global_position() + p_pos); + member_popup->set_size(Vector2()); + + TreeItem *root = members->get_root(); + + Ref<Texture> del_icon = Control::get_icon("Del", "EditorIcons"); + + Ref<Texture> edit_icon = Control::get_icon("Edit", "EditorIcons"); + + if (ti->get_parent() == root->get_children()) { + + member_type = MEMBER_FUNCTION; + member_name = ti->get_text(0); + member_popup->add_icon_item(del_icon, TTR("Remove Function"), MEMBER_REMOVE); + member_popup->popup(); + return; + } + + if (ti->get_parent() == root->get_children()->get_next()) { + + member_type = MEMBER_VARIABLE; + member_name = ti->get_text(0); + member_popup->add_icon_item(edit_icon, TTR("Edit Variable"), MEMBER_EDIT); + member_popup->add_separator(); + member_popup->add_icon_item(del_icon, TTR("Remove Variable"), MEMBER_REMOVE); + member_popup->popup(); + return; + } + + if (ti->get_parent() == root->get_children()->get_next()->get_next()) { + + member_type = MEMBER_SIGNAL; + member_name = ti->get_text(0); + member_popup->add_icon_item(edit_icon, TTR("Edit Signal"), MEMBER_EDIT); + member_popup->add_separator(); + member_popup->add_icon_item(del_icon, TTR("Remove Signal"), MEMBER_REMOVE); + member_popup->popup(); + return; + } +} + +void VisualScriptEditor::_member_option(int p_option) { + + switch (member_type) { + case MEMBER_FUNCTION: { + + if (p_option == MEMBER_REMOVE) { + //delete the function + String name = member_name; + + undo_redo->create_action(TTR("Remove Function")); + undo_redo->add_do_method(script.ptr(), "remove_function", name); + undo_redo->add_undo_method(script.ptr(), "add_function", name); + List<int> nodes; + script->get_node_list(name, &nodes); + for (List<int>::Element *E = nodes.front(); E; E = E->next()) { + undo_redo->add_undo_method(script.ptr(), "add_node", name, E->get(), script->get_node(name, E->get()), script->get_node_pos(name, E->get())); + } + + List<VisualScript::SequenceConnection> seq_connections; + + script->get_sequence_connection_list(name, &seq_connections); + + for (List<VisualScript::SequenceConnection>::Element *E = seq_connections.front(); E; E = E->next()) { + undo_redo->add_undo_method(script.ptr(), "sequence_connect", name, E->get().from_node, E->get().from_output, E->get().to_node); + } + + List<VisualScript::DataConnection> data_connections; + + script->get_data_connection_list(name, &data_connections); + + for (List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) { + undo_redo->add_undo_method(script.ptr(), "data_connect", name, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + } + + /* + for(int i=0;i<script->function_get_argument_count(name);i++) { + undo_redo->add_undo_method(script.ptr(),"function_add_argument",name,script->function_get_argument_name(name,i),script->function_get_argument_type(name,i)); + } + */ + undo_redo->add_do_method(this, "_update_members"); + undo_redo->add_undo_method(this, "_update_members"); + undo_redo->add_do_method(this, "_update_graph"); + undo_redo->add_undo_method(this, "_update_graph"); + undo_redo->commit_action(); + } + } break; + case MEMBER_VARIABLE: { + + String name = member_name; + + if (p_option == MEMBER_REMOVE) { + undo_redo->create_action(TTR("Remove Variable")); + undo_redo->add_do_method(script.ptr(), "remove_variable", name); + undo_redo->add_undo_method(script.ptr(), "add_variable", name, script->get_variable_default_value(name)); + undo_redo->add_undo_method(script.ptr(), "set_variable_info", name, script->call("get_variable_info", name)); //return as dict + undo_redo->add_do_method(this, "_update_members"); + undo_redo->add_undo_method(this, "_update_members"); + undo_redo->commit_action(); + } else if (p_option == MEMBER_EDIT) { + variable_editor->edit(name); + edit_variable_dialog->set_title(TTR("Editing Variable:") + " " + name); + edit_variable_dialog->popup_centered_minsize(Size2(400, 200) * EDSCALE); + } + } break; + case MEMBER_SIGNAL: { + String name = member_name; + + if (p_option == MEMBER_REMOVE) { + undo_redo->create_action(TTR("Remove Signal")); + undo_redo->add_do_method(script.ptr(), "remove_custom_signal", name); + undo_redo->add_undo_method(script.ptr(), "add_custom_signal", name); + + for (int i = 0; i < script->custom_signal_get_argument_count(name); i++) { + undo_redo->add_undo_method(script.ptr(), "custom_signal_add_argument", name, script->custom_signal_get_argument_name(name, i), script->custom_signal_get_argument_type(name, i)); + } + + undo_redo->add_do_method(this, "_update_members"); + undo_redo->add_undo_method(this, "_update_members"); + undo_redo->commit_action(); + } else if (p_option == MEMBER_EDIT) { + + signal_editor->edit(name); + edit_signal_dialog->set_title(TTR("Editing Signal:") + " " + name); + edit_signal_dialog->popup_centered_minsize(Size2(400, 300) * EDSCALE); + } + } break; + } +} + void VisualScriptEditor::_bind_methods() { ClassDB::bind_method("_member_button", &VisualScriptEditor::_member_button); @@ -3101,6 +3154,10 @@ void VisualScriptEditor::_bind_methods() { ClassDB::bind_method("_selected_method", &VisualScriptEditor::_selected_method); ClassDB::bind_method("_draw_color_over_button", &VisualScriptEditor::_draw_color_over_button); + + ClassDB::bind_method("_member_rmb_selected", &VisualScriptEditor::_member_rmb_selected); + + ClassDB::bind_method("_member_option", &VisualScriptEditor::_member_option); } VisualScriptEditor::VisualScriptEditor() { @@ -3122,17 +3179,16 @@ VisualScriptEditor::VisualScriptEditor() { edit_menu->get_popup()->connect("id_pressed", this, "_menu_option"); - main_hsplit = memnew(HSplitContainer); - add_child(main_hsplit); - main_hsplit->set_area_as_parent_rect(); - left_vsplit = memnew(VSplitContainer); - main_hsplit->add_child(left_vsplit); + ScriptEditor::get_singleton()->get_left_list_split()->call_deferred("add_child", left_vsplit); //add but wait until done settig up this + left_vsplit->set_v_size_flags(SIZE_EXPAND_FILL); + left_vsplit->set_stretch_ratio(2); + left_vsplit->hide(); VBoxContainer *left_vb = memnew(VBoxContainer); left_vsplit->add_child(left_vb); left_vb->set_v_size_flags(SIZE_EXPAND_FILL); - left_vb->set_custom_minimum_size(Size2(230, 1) * EDSCALE); + //left_vb->set_custom_minimum_size(Size2(230, 1) * EDSCALE); base_type_select = memnew(Button); left_vb->add_margin_child(TTR("Base Type:"), base_type_select); @@ -3174,7 +3230,8 @@ VisualScriptEditor::VisualScriptEditor() { nodes->set_drag_forwarding(this); graph = memnew(GraphEdit); - main_hsplit->add_child(graph); + add_child(graph); + graph->set_area_as_parent_rect(); graph->set_h_size_flags(SIZE_EXPAND_FILL); graph->connect("node_selected", this, "_node_selected"); graph->connect("_begin_node_move", this, "_begin_node_move"); @@ -3190,7 +3247,8 @@ VisualScriptEditor::VisualScriptEditor() { select_func_text->set_align(Label::ALIGN_CENTER); select_func_text->set_valign(Label::VALIGN_CENTER); select_func_text->set_h_size_flags(SIZE_EXPAND_FILL); - main_hsplit->add_child(select_func_text); + add_child(select_func_text); + graph->set_area_as_parent_rect(); hint_text = memnew(Label); hint_text->set_anchor_and_margin(MARGIN_TOP, ANCHOR_END, 100); @@ -3280,6 +3338,12 @@ VisualScriptEditor::VisualScriptEditor() { port_action_popup = memnew(PopupMenu); add_child(port_action_popup); port_action_popup->connect("id_pressed", this, "_port_action_menu"); + + member_popup = memnew(PopupMenu); + add_child(member_popup); + members->connect("item_rmb_selected", this, "_member_rmb_selected"); + members->set_allow_rmb_select(true); + member_popup->connect("id_pressed", this, "_member_option"); } VisualScriptEditor::~VisualScriptEditor() { diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 92f31f20da..fee4e27bd5 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -72,15 +72,25 @@ class VisualScriptEditor : public ScriptEditorBase { CREATE_RETURN, }; + enum MemberAction { + MEMBER_EDIT, + MEMBER_REMOVE + + }; + + enum MemberType { + MEMBER_FUNCTION, + MEMBER_VARIABLE, + MEMBER_SIGNAL + }; + + VSplitContainer *left_vsplit; MenuButton *edit_menu; Ref<VisualScript> script; Button *base_type_select; - HSplitContainer *main_hsplit; - VSplitContainer *left_vsplit; - GraphEdit *graph; LineEdit *node_filter; @@ -154,6 +164,10 @@ class VisualScriptEditor : public ScriptEditorBase { static Clipboard *clipboard; PopupMenu *port_action_popup; + PopupMenu *member_popup; + + MemberType member_type; + String member_name; PortAction port_action; int port_action_node; @@ -223,6 +237,9 @@ class VisualScriptEditor : public ScriptEditorBase { VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &visited_nodes); + void _member_rmb_selected(const Vector2 &p_pos); + void _member_option(int p_option); + protected: void _notification(int p_what); static void _bind_methods(); @@ -252,6 +269,7 @@ public: virtual void set_debugger_active(bool p_active); virtual void set_tooltip_request_func(String p_method, Object *p_obj); virtual Control *get_edit_menu(); + virtual void clear_edit_menu(); virtual bool can_lose_focus_on_node_selection() { return false; } static void register_editor(); diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp index 791b5d99ff..78b70934c0 100644 --- a/modules/visual_script/visual_script_expression.cpp +++ b/modules/visual_script/visual_script_expression.cpp @@ -68,12 +68,12 @@ bool VisualScriptExpression::_set(const StringName &p_name, const Variant &p_val return true; } - if (String(p_name).begins_with("input/")) { + if (String(p_name).begins_with("input_")) { - int idx = String(p_name).get_slice("/", 1).to_int(); + int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int(); ERR_FAIL_INDEX_V(idx, inputs.size(), false); - String what = String(p_name).get_slice("/", 2); + String what = String(p_name).get_slice("/", 1); if (what == "type") { @@ -115,12 +115,12 @@ bool VisualScriptExpression::_get(const StringName &p_name, Variant &r_ret) cons return true; } - if (String(p_name).begins_with("input/")) { + if (String(p_name).begins_with("input_")) { - int idx = String(p_name).get_slice("/", 1).to_int(); + int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int(); ERR_FAIL_INDEX_V(idx, inputs.size(), false); - String what = String(p_name).get_slice("/", 2); + String what = String(p_name).get_slice("/", 1); if (what == "type") { @@ -151,8 +151,8 @@ void VisualScriptExpression::_get_property_list(List<PropertyInfo> *p_list) cons for (int i = 0; i < inputs.size(); i++) { - p_list->push_back(PropertyInfo(Variant::INT, "input/" + itos(i) + "/type", PROPERTY_HINT_ENUM, argt)); - p_list->push_back(PropertyInfo(Variant::STRING, "input/" + itos(i) + "/name")); + p_list->push_back(PropertyInfo(Variant::INT, "input_" + itos(i) + "/type", PROPERTY_HINT_ENUM, argt)); + p_list->push_back(PropertyInfo(Variant::STRING, "input_" + itos(i) + "/name")); } } diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index 07d69db207..28622bed47 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -30,6 +30,7 @@ #include "visual_script_flow_control.h" #include "global_config.h" +#include "io/resource_loader.h" #include "os/keyboard.h" ////////////////////////////////////////// @@ -119,8 +120,8 @@ void VisualScriptReturn::_bind_methods() { argt += "," + Variant::get_type_name(Variant::Type(i)); } - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "return_value/enabled"), "set_enable_return_value", "is_return_value_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "return_value/type", PROPERTY_HINT_ENUM, argt), "set_return_type", "get_return_type"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "return_enabled"), "set_enable_return_value", "is_return_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "return_type", PROPERTY_HINT_ENUM, argt), "set_return_type", "get_return_type"); } class VisualScriptNodeInstanceReturn : public VisualScriptNodeInstance { @@ -1725,6 +1726,20 @@ String VisualScriptTypeCast::get_base_script() const { return script; } +VisualScriptTypeCast::TypeGuess VisualScriptTypeCast::guess_output_type(TypeGuess *p_inputs, int p_output) const { + + TypeGuess tg; + tg.type = Variant::OBJECT; + if (script != String()) { + tg.script = ResourceLoader::load(script); + } + //if (!tg.script.is_valid()) { + // tg.gdclass = base_type; + //} + + return tg; +} + class VisualScriptNodeInstanceTypeCast : public VisualScriptNodeInstance { public: VisualScriptInstance *instance; @@ -1815,8 +1830,8 @@ void VisualScriptTypeCast::_bind_methods() { script_ext_hint += "*." + E->get(); } - ADD_PROPERTY(PropertyInfo(Variant::STRING, "function/base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "property/base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script"); } VisualScriptTypeCast::VisualScriptTypeCast() { diff --git a/modules/visual_script/visual_script_flow_control.h b/modules/visual_script/visual_script_flow_control.h index 314804602e..d27fd47f84 100644 --- a/modules/visual_script/visual_script_flow_control.h +++ b/modules/visual_script/visual_script_flow_control.h @@ -261,6 +261,7 @@ public: VisualScriptInputFilter(); }; #endif + class VisualScriptTypeCast : public VisualScriptNode { GDCLASS(VisualScriptTypeCast, VisualScriptNode) @@ -293,6 +294,8 @@ public: void set_base_script(const String &p_path); String get_base_script() const; + virtual TypeGuess guess_output_type(TypeGuess *p_inputs, int p_output) const; + virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); VisualScriptTypeCast(); diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index e0e1a217b3..93b2aa2982 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -546,25 +546,25 @@ Dictionary VisualScriptFunctionCall::_get_argument_cache() const { void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const { - if (property.name == "function/base_type") { + if (property.name == "base_type") { if (call_mode != CALL_MODE_INSTANCE) { property.usage = PROPERTY_USAGE_NOEDITOR; } } - if (property.name == "function/base_script") { + if (property.name == "base_script") { if (call_mode != CALL_MODE_INSTANCE) { property.usage = 0; } } - if (property.name == "function/basic_type") { + if (property.name == "basic_type") { if (call_mode != CALL_MODE_BASIC_TYPE) { property.usage = 0; } } - if (property.name == "function/singleton") { + if (property.name == "singleton") { if (call_mode != CALL_MODE_SINGLETON) { property.usage = 0; } else { @@ -581,7 +581,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const } } - if (property.name == "function/node_path") { + if (property.name == "node_path") { if (call_mode != CALL_MODE_NODE_PATH) { property.usage = 0; } else { @@ -594,7 +594,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const } } - if (property.name == "function/function") { + if (property.name == "function") { if (call_mode == CALL_MODE_BASIC_TYPE) { @@ -648,7 +648,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const } } - if (property.name == "function/use_default_args") { + if (property.name == "use_default_args") { property.hint = PROPERTY_HINT_RANGE; @@ -673,7 +673,7 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const } } - if (property.name == "rpc/call_mode") { + if (property.name == "rpc_call_mode") { if (call_mode == CALL_MODE_BASIC_TYPE) { property.usage = 0; } @@ -735,17 +735,17 @@ void VisualScriptFunctionCall::_bind_methods() { script_ext_hint += "*." + E->get(); } - ADD_PROPERTY(PropertyInfo(Variant::INT, "function/call_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type,Singleton"), "set_call_mode", "get_call_mode"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "function/base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "function/base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "function/singleton"), "set_singleton", "get_singleton"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "function/basic_type", PROPERTY_HINT_ENUM, bt), "set_basic_type", "get_basic_type"); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "function/node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path"); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "function/argument_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_argument_cache", "_get_argument_cache"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "function/function"), "set_function", "get_function"); //when set, if loaded properly, will override argument count. - ADD_PROPERTY(PropertyInfo(Variant::INT, "function/use_default_args"), "set_use_default_args", "get_use_default_args"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "function/validate"), "set_validate", "get_validate"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "rpc/call_mode", PROPERTY_HINT_ENUM, "Disabled,Reliable,Unreliable,ReliableToID,UnreliableToID"), "set_rpc_call_mode", "get_rpc_call_mode"); //when set, if loaded properly, will override argument count. + ADD_PROPERTY(PropertyInfo(Variant::INT, "call_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type,Singleton"), "set_call_mode", "get_call_mode"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "singleton"), "set_singleton", "get_singleton"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "basic_type", PROPERTY_HINT_ENUM, bt), "set_basic_type", "get_basic_type"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "argument_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_argument_cache", "_get_argument_cache"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "function"), "set_function", "get_function"); //when set, if loaded properly, will override argument count. + ADD_PROPERTY(PropertyInfo(Variant::INT, "use_default_args"), "set_use_default_args", "get_use_default_args"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "validate"), "set_validate", "get_validate"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "rpc_call_mode", PROPERTY_HINT_ENUM, "Disabled,Reliable,Unreliable,ReliableToID,UnreliableToID"), "set_rpc_call_mode", "get_rpc_call_mode"); //when set, if loaded properly, will override argument count. BIND_CONSTANT(CALL_MODE_SELF); BIND_CONSTANT(CALL_MODE_NODE_PATH); @@ -1020,6 +1020,18 @@ String VisualScriptPropertySet::get_output_sequence_port_text(int p_port) const return String(); } +void VisualScriptPropertySet::_adjust_input_index(PropertyInfo &pinfo) const { + + if (index != StringName()) { + + Variant v; + Variant::CallError ce; + v = Variant::construct(pinfo.type, NULL, 0, ce); + Variant i = v.get(index); + pinfo.type = i.get_type(); + } +} + PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const { if (call_mode == CALL_MODE_INSTANCE || call_mode == CALL_MODE_BASIC_TYPE) { @@ -1027,6 +1039,7 @@ PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const PropertyInfo pi; pi.type = (call_mode == CALL_MODE_INSTANCE ? Variant::OBJECT : basic_type); pi.name = (call_mode == CALL_MODE_INSTANCE ? String("instance") : Variant::get_type_name(basic_type).to_lower()); + _adjust_input_index(pi); return pi; } else { p_idx--; @@ -1035,6 +1048,7 @@ PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const PropertyInfo pinfo = type_cache; pinfo.name = "value"; + _adjust_input_index(pinfo); return pinfo; } @@ -1051,13 +1065,16 @@ PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) cons String VisualScriptPropertySet::get_caption() const { static const char *cname[4] = { - "SelfSet", - "NodeSet", - "InstanceSet", - "BasicSet" + "Self", + "Node", + "Instance", + "Basic" }; - return cname[call_mode]; + static const char *opname[ASSIGN_OP_MAX] = { + "Set", "Add", "Sub", "Mul", "Div", "Mod", "ShiftLeft", "ShiftRight", "BitAnd", "BitOr", "BitXor" + }; + return String(cname[call_mode]) + opname[assign_op]; } String VisualScriptPropertySet::get_text() const { @@ -1073,6 +1090,9 @@ String VisualScriptPropertySet::get_text() const { else if (call_mode == CALL_MODE_INSTANCE) prop = String(base_type) + ":" + property; + if (index != StringName()) { + prop += "." + String(index); + } return prop; } @@ -1236,6 +1256,7 @@ void VisualScriptPropertySet::set_property(const StringName &p_type) { return; property = p_type; + index = StringName(); _update_cache(); _change_notify(); ports_changed_notify(); @@ -1285,27 +1306,58 @@ Dictionary VisualScriptPropertySet::_get_type_cache() const { return type_cache; } +void VisualScriptPropertySet::set_index(const StringName &p_type) { + + if (index == p_type) + return; + index = p_type; + _update_cache(); + _change_notify(); + ports_changed_notify(); +} + +StringName VisualScriptPropertySet::get_index() const { + + return index; +} + +void VisualScriptPropertySet::set_assign_op(AssignOp p_op) { + + ERR_FAIL_INDEX(p_op, ASSIGN_OP_MAX); + if (assign_op == p_op) + return; + + assign_op = p_op; + _update_cache(); + _change_notify(); + ports_changed_notify(); +} + +VisualScriptPropertySet::AssignOp VisualScriptPropertySet::get_assign_op() const { + return assign_op; +} + void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { - if (property.name == "property/base_type") { + if (property.name == "base_type") { if (call_mode != CALL_MODE_INSTANCE) { property.usage = PROPERTY_USAGE_NOEDITOR; } } - if (property.name == "property/base_script") { + if (property.name == "base_script") { if (call_mode != CALL_MODE_INSTANCE) { property.usage = 0; } } - if (property.name == "property/basic_type") { + if (property.name == "basic_type") { if (call_mode != CALL_MODE_BASIC_TYPE) { property.usage = 0; } } - if (property.name == "property/node_path") { + if (property.name == "node_path") { if (call_mode != CALL_MODE_NODE_PATH) { property.usage = 0; } else { @@ -1318,7 +1370,7 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { } } - if (property.name == "property/property") { + if (property.name == "property") { if (call_mode == CALL_MODE_BASIC_TYPE) { @@ -1360,6 +1412,24 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const { } } } + + if (property.name == "index") { + + Variant::CallError ce; + Variant v = Variant::construct(type_cache.type, NULL, 0, ce); + List<PropertyInfo> plist; + v.get_property_list(&plist); + String options = ""; + for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { + options += "," + E->get().name; + } + + property.hint = PROPERTY_HINT_ENUM; + property.hint_string = options; + property.type = Variant::STRING; + if (options == "") + property.usage = 0; //hide if type has no usable index + } } void VisualScriptPropertySet::_bind_methods() { @@ -1385,6 +1455,12 @@ void VisualScriptPropertySet::_bind_methods() { ClassDB::bind_method(D_METHOD("set_base_path", "base_path"), &VisualScriptPropertySet::set_base_path); ClassDB::bind_method(D_METHOD("get_base_path"), &VisualScriptPropertySet::get_base_path); + ClassDB::bind_method(D_METHOD("set_index", "index"), &VisualScriptPropertySet::set_index); + ClassDB::bind_method(D_METHOD("get_index"), &VisualScriptPropertySet::get_index); + + ClassDB::bind_method(D_METHOD("set_assign_op", "assign_op"), &VisualScriptPropertySet::set_assign_op); + ClassDB::bind_method(D_METHOD("get_assign_op"), &VisualScriptPropertySet::get_assign_op); + String bt; for (int i = 0; i < Variant::VARIANT_MAX; i++) { if (i > 0) @@ -1405,14 +1481,15 @@ void VisualScriptPropertySet::_bind_methods() { script_ext_hint += "*." + E->get(); } - ADD_PROPERTY(PropertyInfo(Variant::INT, "property/set_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type"), "set_call_mode", "get_call_mode"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "property/base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "property/base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "property/type_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_type_cache", "_get_type_cache"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "property/basic_type", PROPERTY_HINT_ENUM, bt), "set_basic_type", "get_basic_type"); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "property/node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "property/property"), "set_property", "get_property"); - + ADD_PROPERTY(PropertyInfo(Variant::INT, "set_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type"), "set_call_mode", "get_call_mode"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_type_cache", "_get_type_cache"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "basic_type", PROPERTY_HINT_ENUM, bt), "set_basic_type", "get_basic_type"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "property"), "set_property", "get_property"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "index"), "set_index", "get_index"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "assign_op", PROPERTY_HINT_ENUM, "Assign,Add,Sub,Mul,Div,Mod,ShiftLeft,ShiftRight,BitAnd,BitOr,Bitxor"), "set_assign_op", "get_assign_op"); BIND_CONSTANT(CALL_MODE_SELF); BIND_CONSTANT(CALL_MODE_NODE_PATH); BIND_CONSTANT(CALL_MODE_INSTANCE); @@ -1426,11 +1503,72 @@ public: VisualScriptPropertySet *node; VisualScriptInstance *instance; + VisualScriptPropertySet::AssignOp assign_op; + StringName index; + bool needs_get; //virtual int get_working_memory_size() const { return 0; } //virtual bool is_output_port_unsequenced(int p_idx) const { return false; } //virtual bool get_output_port_unsequenced(int p_idx,Variant* r_value,Variant* p_working_mem,String &r_error) const { return true; } + _FORCE_INLINE_ void _process_get(Variant &source, const Variant &p_argument, bool &valid) { + + if (index != StringName() && assign_op == VisualScriptPropertySet::ASSIGN_OP_NONE) { + source.set_named(index, p_argument, &valid); + } else { + + Variant value; + if (index != StringName()) { + value = source.get_named(index, &valid); + } else { + value = source; + } + + switch (assign_op) { + case VisualScriptPropertySet::ASSIGN_OP_NONE: { + //should never get here + } break; + case VisualScriptPropertySet::ASSIGN_OP_ADD: { + value = Variant::evaluate(Variant::OP_ADD, value, p_argument); + } break; + case VisualScriptPropertySet::ASSIGN_OP_SUB: { + value = Variant::evaluate(Variant::OP_SUBSTRACT, value, p_argument); + } break; + case VisualScriptPropertySet::ASSIGN_OP_MUL: { + value = Variant::evaluate(Variant::OP_MULTIPLY, value, p_argument); + } break; + case VisualScriptPropertySet::ASSIGN_OP_DIV: { + value = Variant::evaluate(Variant::OP_DIVIDE, value, p_argument); + } break; + case VisualScriptPropertySet::ASSIGN_OP_MOD: { + value = Variant::evaluate(Variant::OP_MODULE, value, p_argument); + } break; + case VisualScriptPropertySet::ASSIGN_OP_SHIFT_LEFT: { + value = Variant::evaluate(Variant::OP_SHIFT_LEFT, value, p_argument); + } break; + case VisualScriptPropertySet::ASSIGN_OP_SHIFT_RIGHT: { + value = Variant::evaluate(Variant::OP_SHIFT_RIGHT, value, p_argument); + } break; + case VisualScriptPropertySet::ASSIGN_OP_BIT_AND: { + value = Variant::evaluate(Variant::OP_BIT_AND, value, p_argument); + } break; + case VisualScriptPropertySet::ASSIGN_OP_BIT_OR: { + value = Variant::evaluate(Variant::OP_BIT_OR, value, p_argument); + } break; + case VisualScriptPropertySet::ASSIGN_OP_BIT_XOR: { + value = Variant::evaluate(Variant::OP_BIT_XOR, value, p_argument); + } break; + default: {} + } + + if (index != StringName()) { + source.set_named(index, value, &valid); + } else { + source = value; + } + } + } + virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) { switch (call_mode) { @@ -1441,7 +1579,13 @@ public: bool valid; - object->set(property, *p_inputs[0], &valid); + if (needs_get) { + Variant value = object->get(property, &valid); + _process_get(value, *p_inputs[0], valid); + object->set(property, value, &valid); + } else { + object->set(property, *p_inputs[0], &valid); + } if (!valid) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; @@ -1466,7 +1610,14 @@ public: bool valid; - another->set(property, *p_inputs[0], &valid); + if (needs_get) { + + Variant value = another->get(property, &valid); + _process_get(value, *p_inputs[0], valid); + another->set(property, value, &valid); + } else { + another->set(property, *p_inputs[0], &valid); + } if (!valid) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; @@ -1481,7 +1632,14 @@ public: bool valid; - v.set(property, *p_inputs[1], &valid); + if (needs_get) { + Variant value = v.get_named(property, &valid); + _process_get(value, *p_inputs[1], valid); + v.set_named(property, value, &valid); + + } else { + v.set_named(property, *p_inputs[1], &valid); + } if (!valid) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; @@ -1504,6 +1662,9 @@ VisualScriptNodeInstance *VisualScriptPropertySet::instance(VisualScriptInstance instance->property = property; instance->call_mode = call_mode; instance->node_path = base_path; + instance->assign_op = assign_op; + instance->index = index; + instance->needs_get = index != StringName() || assign_op != ASSIGN_OP_NONE; return instance; } @@ -1517,6 +1678,7 @@ VisualScriptPropertySet::TypeGuess VisualScriptPropertySet::guess_output_type(Ty } VisualScriptPropertySet::VisualScriptPropertySet() { + assign_op = ASSIGN_OP_NONE; call_mode = CALL_MODE_SELF; base_type = "Object"; basic_type = Variant::NIL; @@ -1641,6 +1803,15 @@ PropertyInfo VisualScriptPropertyGet::get_input_value_port_info(int p_idx) const PropertyInfo VisualScriptPropertyGet::get_output_value_port_info(int p_idx) const { + if (index != StringName()) { + + Variant v; + Variant::CallError ce; + v = Variant::construct(type_cache, NULL, 0, ce); + Variant i = v.get(index); + return PropertyInfo(i.get_type(), "value." + String(index)); + } + return PropertyInfo(type_cache, "value"); } @@ -1867,27 +2038,42 @@ Variant::Type VisualScriptPropertyGet::_get_type_cache() const { return type_cache; } +void VisualScriptPropertyGet::set_index(const StringName &p_type) { + + if (index == p_type) + return; + index = p_type; + _update_cache(); + _change_notify(); + ports_changed_notify(); +} + +StringName VisualScriptPropertyGet::get_index() const { + + return index; +} + void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { - if (property.name == "property/base_type") { + if (property.name == "base_type") { if (call_mode != CALL_MODE_INSTANCE) { property.usage = PROPERTY_USAGE_NOEDITOR; } } - if (property.name == "property/base_script") { + if (property.name == "base_script") { if (call_mode != CALL_MODE_INSTANCE) { property.usage = 0; } } - if (property.name == "property/basic_type") { + if (property.name == "basic_type") { if (call_mode != CALL_MODE_BASIC_TYPE) { property.usage = 0; } } - if (property.name == "property/node_path") { + if (property.name == "node_path") { if (call_mode != CALL_MODE_NODE_PATH) { property.usage = 0; } else { @@ -1900,7 +2086,7 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { } } - if (property.name == "property/property") { + if (property.name == "property") { if (call_mode == CALL_MODE_BASIC_TYPE) { @@ -1941,6 +2127,24 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const { } } } + + if (property.name == "index") { + + Variant::CallError ce; + Variant v = Variant::construct(type_cache, NULL, 0, ce); + List<PropertyInfo> plist; + v.get_property_list(&plist); + String options = ""; + for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { + options += "," + E->get().name; + } + + property.hint = PROPERTY_HINT_ENUM; + property.hint_string = options; + property.type = Variant::STRING; + if (options == "") + property.usage = 0; //hide if type has no usable index + } } void VisualScriptPropertyGet::_bind_methods() { @@ -1966,6 +2170,9 @@ void VisualScriptPropertyGet::_bind_methods() { ClassDB::bind_method(D_METHOD("set_base_path", "base_path"), &VisualScriptPropertyGet::set_base_path); ClassDB::bind_method(D_METHOD("get_base_path"), &VisualScriptPropertyGet::get_base_path); + ClassDB::bind_method(D_METHOD("set_index", "index"), &VisualScriptPropertyGet::set_index); + ClassDB::bind_method(D_METHOD("get_index"), &VisualScriptPropertyGet::get_index); + String bt; for (int i = 0; i < Variant::VARIANT_MAX; i++) { if (i > 0) @@ -1986,13 +2193,14 @@ void VisualScriptPropertyGet::_bind_methods() { script_ext_hint += "." + E->get(); } - ADD_PROPERTY(PropertyInfo(Variant::INT, "property/set_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type"), "set_call_mode", "get_call_mode"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "property/base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "property/base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "property/type_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_type_cache", "_get_type_cache"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "property/basic_type", PROPERTY_HINT_ENUM, bt), "set_basic_type", "get_basic_type"); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "property/node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "property/property"), "set_property", "get_property"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "set_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type"), "set_call_mode", "get_call_mode"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_script", PROPERTY_HINT_FILE, script_ext_hint), "set_base_script", "get_base_script"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type_cache", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_type_cache", "_get_type_cache"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "basic_type", PROPERTY_HINT_ENUM, bt), "set_basic_type", "get_basic_type"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "property"), "set_property", "get_property"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "index", PROPERTY_HINT_ENUM), "set_index", "get_index"); BIND_CONSTANT(CALL_MODE_SELF); BIND_CONSTANT(CALL_MODE_NODE_PATH); @@ -2004,6 +2212,7 @@ public: VisualScriptPropertyGet::CallMode call_mode; NodePath node_path; StringName property; + StringName index; VisualScriptPropertyGet *node; VisualScriptInstance *instance; @@ -2020,6 +2229,10 @@ public: *p_outputs[0] = object->get(property, &valid); + if (index != StringName()) { + *p_outputs[0] = p_outputs[0]->get_named(index); + } + if (!valid) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; r_error_str = RTR("Invalid index property name."); @@ -2046,6 +2259,10 @@ public: *p_outputs[0] = another->get(property, &valid); + if (index != StringName()) { + *p_outputs[0] = p_outputs[0]->get_named(index); + } + if (!valid) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; r_error_str = vformat(RTR("Invalid index property name '%s' in node %s."), String(property), another->get_name()); @@ -2059,6 +2276,9 @@ public: Variant v = *p_inputs[0]; *p_outputs[0] = v.get(property, &valid); + if (index != StringName()) { + *p_outputs[0] = p_outputs[0]->get_named(index); + } if (!valid) { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; @@ -2079,6 +2299,7 @@ VisualScriptNodeInstance *VisualScriptPropertyGet::instance(VisualScriptInstance instance->property = property; instance->call_mode = call_mode; instance->node_path = base_path; + instance->index = index; return instance; } @@ -2182,7 +2403,7 @@ StringName VisualScriptEmitSignal::get_signal() const { void VisualScriptEmitSignal::_validate_property(PropertyInfo &property) const { - if (property.name == "signal/signal") { + if (property.name == "signal") { property.hint = PROPERTY_HINT_ENUM; List<StringName> sigs; @@ -2210,7 +2431,7 @@ void VisualScriptEmitSignal::_bind_methods() { ClassDB::bind_method(D_METHOD("set_signal", "name"), &VisualScriptEmitSignal::set_signal); ClassDB::bind_method(D_METHOD("get_signal"), &VisualScriptEmitSignal::get_signal); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "signal/signal"), "set_signal", "get_signal"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "signal"), "set_signal", "get_signal"); } class VisualScriptNodeInstanceEmitSignal : public VisualScriptNodeInstance { diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h index 3b284952c5..7839748661 100644 --- a/modules/visual_script/visual_script_func_nodes.h +++ b/modules/visual_script/visual_script_func_nodes.h @@ -146,6 +146,21 @@ public: }; + enum AssignOp { + ASSIGN_OP_NONE, + ASSIGN_OP_ADD, + ASSIGN_OP_SUB, + ASSIGN_OP_MUL, + ASSIGN_OP_DIV, + ASSIGN_OP_MOD, + ASSIGN_OP_SHIFT_LEFT, + ASSIGN_OP_SHIFT_RIGHT, + ASSIGN_OP_BIT_AND, + ASSIGN_OP_BIT_OR, + ASSIGN_OP_BIT_XOR, + ASSIGN_OP_MAX + }; + private: PropertyInfo type_cache; @@ -155,6 +170,8 @@ private: String base_script; NodePath base_path; StringName property; + StringName index; + AssignOp assign_op; Node *_get_base_node() const; StringName _get_base_type() const; @@ -166,6 +183,8 @@ private: void _set_type_cache(const Dictionary &p_type); Dictionary _get_type_cache() const; + void _adjust_input_index(PropertyInfo &pinfo) const; + protected: virtual void _validate_property(PropertyInfo &property) const; @@ -205,6 +224,12 @@ public: void set_call_mode(CallMode p_mode); CallMode get_call_mode() const; + void set_index(const StringName &p_type); + StringName get_index() const; + + void set_assign_op(AssignOp p_op); + AssignOp get_assign_op() const; + virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); virtual TypeGuess guess_output_type(TypeGuess *p_inputs, int p_output) const; @@ -212,6 +237,7 @@ public: }; VARIANT_ENUM_CAST(VisualScriptPropertySet::CallMode); +VARIANT_ENUM_CAST(VisualScriptPropertySet::AssignOp); class VisualScriptPropertyGet : public VisualScriptNode { @@ -234,6 +260,7 @@ private: String base_script; NodePath base_path; StringName property; + StringName index; void _update_base_type(); Node *_get_base_node() const; @@ -283,6 +310,9 @@ public: void set_call_mode(CallMode p_mode); CallMode get_call_mode() const; + void set_index(const StringName &p_type); + StringName get_index() const; + virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); VisualScriptPropertyGet(); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 86c98d076e..f707471405 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -59,10 +59,10 @@ bool VisualScriptFunction::_set(const StringName &p_name, const Variant &p_value _change_notify(); return true; } - if (String(p_name).begins_with("argument/")) { - int idx = String(p_name).get_slice("/", 1).to_int() - 1; + if (String(p_name).begins_with("argument_")) { + int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1; ERR_FAIL_INDEX_V(idx, arguments.size(), false); - String what = String(p_name).get_slice("/", 2); + String what = String(p_name).get_slice("/", 1); if (what == "type") { Variant::Type new_type = Variant::Type(int(p_value)); @@ -104,10 +104,10 @@ bool VisualScriptFunction::_get(const StringName &p_name, Variant &r_ret) const r_ret = arguments.size(); return true; } - if (String(p_name).begins_with("argument/")) { - int idx = String(p_name).get_slice("/", 1).to_int() - 1; + if (String(p_name).begins_with("argument_")) { + int idx = String(p_name).get_slicec('_', 1).get_slicec('/', 0).to_int() - 1; ERR_FAIL_INDEX_V(idx, arguments.size(), false); - String what = String(p_name).get_slice("/", 2); + String what = String(p_name).get_slice("/", 1); if (what == "type") { r_ret = arguments[idx].type; return true; @@ -144,8 +144,8 @@ void VisualScriptFunction::_get_property_list(List<PropertyInfo> *p_list) const } for (int i = 0; i < arguments.size(); i++) { - p_list->push_back(PropertyInfo(Variant::INT, "argument/" + itos(i + 1) + "/type", PROPERTY_HINT_ENUM, argt)); - p_list->push_back(PropertyInfo(Variant::STRING, "argument/" + itos(i + 1) + "/name")); + p_list->push_back(PropertyInfo(Variant::INT, "argument_" + itos(i + 1) + "/type", PROPERTY_HINT_ENUM, argt)); + p_list->push_back(PropertyInfo(Variant::STRING, "argument_" + itos(i + 1) + "/name")); } if (!stack_less) { p_list->push_back(PropertyInfo(Variant::INT, "stack/size", PROPERTY_HINT_RANGE, "1,100000")); @@ -559,8 +559,8 @@ void VisualScriptOperator::_bind_methods() { argt += "," + Variant::get_type_name(Variant::Type(i)); } - ADD_PROPERTY(PropertyInfo(Variant::INT, "operator_value/type", PROPERTY_HINT_ENUM, types), "set_operator", "get_operator"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "typed_value/typed", PROPERTY_HINT_ENUM, argt), "set_typed", "get_typed"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, types), "set_operator", "get_operator"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt), "set_typed", "get_typed"); } class VisualScriptNodeInstanceOperator : public VisualScriptNodeInstance { @@ -621,6 +621,113 @@ static Ref<VisualScriptNode> create_op_node(const String &p_name) { } ////////////////////////////////////////// +////////////////OPERATOR////////////////// +////////////////////////////////////////// + +int VisualScriptSelect::get_output_sequence_port_count() const { + + return 0; +} + +bool VisualScriptSelect::has_input_sequence_port() const { + + return false; +} + +int VisualScriptSelect::get_input_value_port_count() const { + + return 3; +} +int VisualScriptSelect::get_output_value_port_count() const { + + return 1; +} + +String VisualScriptSelect::get_output_sequence_port_text(int p_port) const { + + return String(); +} + +PropertyInfo VisualScriptSelect::get_input_value_port_info(int p_idx) const { + + if (p_idx == 0) { + return PropertyInfo(Variant::BOOL, "cond"); + } else if (p_idx == 1) { + return PropertyInfo(typed, "a"); + } else { + return PropertyInfo(typed, "b"); + } +} +PropertyInfo VisualScriptSelect::get_output_value_port_info(int p_idx) const { + + return PropertyInfo(typed, "out"); +} + +String VisualScriptSelect::get_caption() const { + + return "Select"; +} + +String VisualScriptSelect::get_text() const { + + return "a if cond, else b"; +} + +void VisualScriptSelect::set_typed(Variant::Type p_op) { + + if (typed == p_op) + return; + + typed = p_op; + ports_changed_notify(); +} + +Variant::Type VisualScriptSelect::get_typed() const { + + return typed; +} + +void VisualScriptSelect::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_typed", "type"), &VisualScriptSelect::set_typed); + ClassDB::bind_method(D_METHOD("get_typed"), &VisualScriptSelect::get_typed); + + String argt = "Any"; + for (int i = 1; i < Variant::VARIANT_MAX; i++) { + argt += "," + Variant::get_type_name(Variant::Type(i)); + } + + ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt), "set_typed", "get_typed"); +} + +class VisualScriptNodeInstanceSelect : public VisualScriptNodeInstance { +public: + //virtual int get_working_memory_size() const { return 0; } + + virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) { + + bool cond = *p_inputs[0]; + if (cond) + *p_outputs[0] = *p_inputs[1]; + else + *p_outputs[0] = *p_inputs[2]; + + return 0; + } +}; + +VisualScriptNodeInstance *VisualScriptSelect::instance(VisualScriptInstance *p_instance) { + + VisualScriptNodeInstanceSelect *instance = memnew(VisualScriptNodeInstanceSelect); + return instance; +} + +VisualScriptSelect::VisualScriptSelect() { + + typed = Variant::NIL; +} + +////////////////////////////////////////// ////////////////VARIABLE GET////////////////// ////////////////////////////////////////// @@ -691,7 +798,7 @@ StringName VisualScriptVariableGet::get_variable() const { void VisualScriptVariableGet::_validate_property(PropertyInfo &property) const { - if (property.name == "variable/name" && get_visual_script().is_valid()) { + if (property.name == "var_name" && get_visual_script().is_valid()) { Ref<VisualScript> vs = get_visual_script(); List<StringName> vars; vs->get_variable_list(&vars); @@ -714,7 +821,7 @@ void VisualScriptVariableGet::_bind_methods() { ClassDB::bind_method(D_METHOD("set_variable", "name"), &VisualScriptVariableGet::set_variable); ClassDB::bind_method(D_METHOD("get_variable"), &VisualScriptVariableGet::get_variable); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "variable/name"), "set_variable", "get_variable"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "var_name"), "set_variable", "get_variable"); } class VisualScriptNodeInstanceVariableGet : public VisualScriptNodeInstance { @@ -816,7 +923,7 @@ StringName VisualScriptVariableSet::get_variable() const { void VisualScriptVariableSet::_validate_property(PropertyInfo &property) const { - if (property.name == "variable/name" && get_visual_script().is_valid()) { + if (property.name == "var_name" && get_visual_script().is_valid()) { Ref<VisualScript> vs = get_visual_script(); List<StringName> vars; vs->get_variable_list(&vars); @@ -839,7 +946,7 @@ void VisualScriptVariableSet::_bind_methods() { ClassDB::bind_method(D_METHOD("set_variable", "name"), &VisualScriptVariableSet::set_variable); ClassDB::bind_method(D_METHOD("get_variable"), &VisualScriptVariableSet::get_variable); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "variable/name"), "set_variable", "get_variable"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "var_name"), "set_variable", "get_variable"); } class VisualScriptNodeInstanceVariableSet : public VisualScriptNodeInstance { @@ -956,7 +1063,7 @@ Variant VisualScriptConstant::get_constant_value() const { void VisualScriptConstant::_validate_property(PropertyInfo &property) const { - if (property.name == "constant/value") { + if (property.name == "value") { property.type = type; if (type == Variant::NIL) property.usage = 0; //do not save if nil @@ -976,8 +1083,8 @@ void VisualScriptConstant::_bind_methods() { argt += "," + Variant::get_type_name(Variant::Type(i)); } - ADD_PROPERTY(PropertyInfo(Variant::INT, "constant/type", PROPERTY_HINT_ENUM, argt), "set_constant_type", "get_constant_type"); - ADD_PROPERTY(PropertyInfo(Variant::NIL, "constant/value"), "set_constant_value", "get_constant_value"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt), "set_constant_type", "get_constant_type"); + ADD_PROPERTY(PropertyInfo(Variant::NIL, "value"), "set_constant_value", "get_constant_value"); } class VisualScriptNodeInstanceConstant : public VisualScriptNodeInstance { @@ -1842,7 +1949,7 @@ VisualScriptEngineSingleton::TypeGuess VisualScriptEngineSingleton::guess_output TypeGuess tg; tg.type = Variant::OBJECT; if (obj) { - tg.GDCLASS = obj->get_class(); + tg.gdclass = obj->get_class(); tg.script = obj->get_script(); } @@ -2002,7 +2109,7 @@ VisualScriptSceneNode::TypeGuess VisualScriptSceneNode::guess_output_type(TypeGu VisualScriptSceneNode::TypeGuess tg; tg.type = Variant::OBJECT; - tg.GDCLASS = "Node"; + tg.gdclass = "Node"; #ifdef TOOLS_ENABLED Ref<Script> script = get_visual_script(); @@ -2031,7 +2138,7 @@ VisualScriptSceneNode::TypeGuess VisualScriptSceneNode::guess_output_type(TypeGu Node *another = script_node->get_node(path); if (another) { - tg.GDCLASS = another->get_class(); + tg.gdclass = another->get_class(); tg.script = another->get_script(); } #endif @@ -2173,7 +2280,7 @@ VisualScriptSceneTree::TypeGuess VisualScriptSceneTree::guess_output_type(TypeGu TypeGuess tg; tg.type = Variant::OBJECT; - tg.GDCLASS = "SceneTree"; + tg.gdclass = "SceneTree"; return tg; } @@ -2353,13 +2460,13 @@ VisualScriptSelf::TypeGuess VisualScriptSelf::guess_output_type(TypeGuess *p_inp VisualScriptSceneNode::TypeGuess tg; tg.type = Variant::OBJECT; - tg.GDCLASS = "Object"; + tg.gdclass = "Object"; Ref<Script> script = get_visual_script(); if (!script.is_valid()) return tg; - tg.GDCLASS = script->get_instance_base_type(); + tg.gdclass = script->get_instance_base_type(); tg.script = script; return tg; @@ -3088,8 +3195,8 @@ void VisualScriptLocalVar::_bind_methods() { argt += "," + Variant::get_type_name(Variant::Type(i)); } - ADD_PROPERTY(PropertyInfo(Variant::STRING, "variable/name"), "set_var_name", "get_var_name"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "variable/type", PROPERTY_HINT_ENUM, argt), "set_var_type", "get_var_type"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "var_name"), "set_var_name", "get_var_name"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt), "set_var_type", "get_var_type"); } VisualScriptLocalVar::VisualScriptLocalVar() { @@ -3210,8 +3317,8 @@ void VisualScriptLocalVarSet::_bind_methods() { argt += "," + Variant::get_type_name(Variant::Type(i)); } - ADD_PROPERTY(PropertyInfo(Variant::STRING, "variable/name"), "set_var_name", "get_var_name"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "variable/type", PROPERTY_HINT_ENUM, argt), "set_var_type", "get_var_type"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "var_name"), "set_var_name", "get_var_name"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt), "set_var_type", "get_var_type"); } VisualScriptLocalVarSet::VisualScriptLocalVarSet() { @@ -3253,32 +3360,33 @@ PropertyInfo VisualScriptInputAction::get_input_value_port_info(int p_idx) const } PropertyInfo VisualScriptInputAction::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::BOOL, "pressed"); -} - -String VisualScriptInputAction::get_caption() const { - - return "Action"; -} - -String VisualScriptInputAction::get_text() const { - + String mstr; switch (mode) { case MODE_PRESSED: { - return name; + mstr = "pressed"; } break; case MODE_RELEASED: { - return "not " + name; + mstr = "not pressed"; } break; case MODE_JUST_PRESSED: { - return String(name) + " " + TTR("just pressed"); + mstr = "just pressed"; } break; case MODE_JUST_RELEASED: { - return String(name) + " " + TTR("just released"); + mstr = "just released"; } break; } - return String(); + return PropertyInfo(Variant::BOOL, mstr); +} + +String VisualScriptInputAction::get_caption() const { + + return "Action"; +} + +String VisualScriptInputAction::get_text() const { + + return name; } String VisualScriptInputAction::get_category() const { @@ -3319,8 +3427,6 @@ public: StringName action; VisualScriptInputAction::Mode mode; - virtual int get_working_memory_size() const { return 1; } - virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) { switch (mode) { @@ -3628,6 +3734,7 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("operators/logic/xor", create_op_node<Variant::OP_XOR>); VisualScriptLanguage::singleton->add_register_func("operators/logic/not", create_op_node<Variant::OP_NOT>); VisualScriptLanguage::singleton->add_register_func("operators/logic/in", create_op_node<Variant::OP_IN>); + VisualScriptLanguage::singleton->add_register_func("operators/logic/select", create_node_generic<VisualScriptSelect>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct", create_node_generic<VisualScriptDeconstruct>); diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index 402093fa80..5ae9a1b30b 100644 --- a/modules/visual_script/visual_script_nodes.h +++ b/modules/visual_script/visual_script_nodes.h @@ -127,6 +127,39 @@ public: VisualScriptOperator(); }; +class VisualScriptSelect : public VisualScriptNode { + + GDCLASS(VisualScriptSelect, VisualScriptNode) + + Variant::Type typed; + +protected: + static void _bind_methods(); + +public: + virtual int get_output_sequence_port_count() const; + virtual bool has_input_sequence_port() const; + + virtual String get_output_sequence_port_text(int p_port) const; + + virtual int get_input_value_port_count() const; + virtual int get_output_value_port_count() const; + + virtual PropertyInfo get_input_value_port_info(int p_idx) const; + virtual PropertyInfo get_output_value_port_info(int p_idx) const; + + virtual String get_caption() const; + virtual String get_text() const; + virtual String get_category() const { return "operators"; } + + void set_typed(Variant::Type p_op); + Variant::Type get_typed() const; + + virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); + + VisualScriptSelect(); +}; + class VisualScriptVariableGet : public VisualScriptNode { GDCLASS(VisualScriptVariableGet, VisualScriptNode) diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp index be5b218d0a..2e111511b7 100644 --- a/modules/visual_script/visual_script_yield_nodes.cpp +++ b/modules/visual_script/visual_script_yield_nodes.cpp @@ -419,13 +419,13 @@ VisualScriptYieldSignal::CallMode VisualScriptYieldSignal::get_call_mode() const void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const { - if (property.name == "signal/base_type") { + if (property.name == "base_type") { if (call_mode != CALL_MODE_INSTANCE) { property.usage = PROPERTY_USAGE_NOEDITOR; } } - if (property.name == "signal/node_path") { + if (property.name == "node_path") { if (call_mode != CALL_MODE_NODE_PATH) { property.usage = 0; } else { @@ -438,7 +438,7 @@ void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const { } } - if (property.name == "signal/signal") { + if (property.name == "signal") { property.hint = PROPERTY_HINT_ENUM; List<MethodInfo> methods; @@ -488,10 +488,10 @@ void VisualScriptYieldSignal::_bind_methods() { bt += Variant::get_type_name(Variant::Type(i)); } - ADD_PROPERTY(PropertyInfo(Variant::INT, "signal/call_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance"), "set_call_mode", "get_call_mode"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "signal/base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type"); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "signal/node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "signal/signal"), "set_signal", "get_signal"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "call_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance"), "set_call_mode", "get_call_mode"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "node_path", PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE), "set_base_path", "get_base_path"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "signal"), "set_signal", "get_signal"); BIND_CONSTANT(CALL_MODE_SELF); BIND_CONSTANT(CALL_MODE_NODE_PATH); diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 4a80aba355..68a3166aa7 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -609,6 +609,27 @@ void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width, p_antialiased); } +void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width, bool p_antialiased) { + + if (!drawing) { + ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + ERR_FAIL(); + } + + Vector<Color> colors; + colors.push_back(p_color); + VisualServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, colors, p_width, p_antialiased); +} + +void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) { + + if (!drawing) { + ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + ERR_FAIL(); + } + + VisualServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width, p_antialiased); +} void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled) { if (!drawing) { @@ -955,6 +976,8 @@ void CanvasItem::_bind_methods() { //ClassDB::bind_method(D_METHOD("get_transform"),&CanvasItem::get_transform); ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled"), &CanvasItem::draw_rect, DEFVAL(true)); ClassDB::bind_method(D_METHOD("draw_circle", "pos", "radius", "color"), &CanvasItem::draw_circle); ClassDB::bind_method(D_METHOD("draw_texture", "texture:Texture", "pos", "modulate", "normal_map:Texture"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Variant())); diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 06130e3252..27842727ac 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -242,6 +242,8 @@ public: /* DRAWING API */ void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); + void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); + void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false); void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true); void draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color); void draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1), const Ref<Texture> &p_normal_map = Ref<Texture>()); diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index e755b1480b..a0d9c26430 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -281,6 +281,9 @@ void MeshInstance::_bind_methods() { ClassDB::bind_method(D_METHOD("set_skeleton_path", "skeleton_path:NodePath"), &MeshInstance::set_skeleton_path); ClassDB::bind_method(D_METHOD("get_skeleton_path:NodePath"), &MeshInstance::get_skeleton_path); + ClassDB::bind_method(D_METHOD("set_surface_material", "surface", "material:Material"), &MeshInstance::set_surface_material); + ClassDB::bind_method(D_METHOD("get_surface_material:Material", "surface"), &MeshInstance::get_surface_material); + ClassDB::bind_method(D_METHOD("create_trimesh_collision"), &MeshInstance::create_trimesh_collision); ClassDB::set_method_flags("MeshInstance", "create_trimesh_collision", METHOD_FLAGS_DEFAULT); ClassDB::bind_method(D_METHOD("create_convex_collision"), &MeshInstance::create_convex_collision); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 8d085d5399..9d45b6e70a 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -568,7 +568,7 @@ static _FORCE_INLINE_ Vector2 _bezier_interp(real_t t, Vector2 start, Vector2 co return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3; } -void GraphEdit::_bake_segment2d(CanvasItem *p_where, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const { +void GraphEdit::_bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const { float mp = p_begin + (p_end - p_begin) * 0.5; Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b); @@ -581,11 +581,12 @@ void GraphEdit::_bake_segment2d(CanvasItem *p_where, float p_begin, float p_end, if (p_depth >= p_min_depth && (dp < p_tol || p_depth >= p_max_depth)) { - p_where->draw_line(beg, end, p_color.linear_interpolate(p_to_color, mp), 2, true); + points.push_back((beg + end) * 0.5); + colors.push_back(p_color.linear_interpolate(p_to_color, mp)); lines++; } else { - _bake_segment2d(p_where, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines); - _bake_segment2d(p_where, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines); + _bake_segment2d(points, colors, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines); + _bake_segment2d(points, colors, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines); } } @@ -609,7 +610,16 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 c2 = Vector2(-cp_offset * zoom, 0); int lines = 0; - _bake_segment2d(p_where, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 8, p_color, p_to_color, lines); + + Vector<Point2> points; + Vector<Color> colors; + points.push_back(p_from); + colors.push_back(p_color); + _bake_segment2d(points, colors, 0, 1, p_from, c1, p_to, c2, 0, 3, 9, 8, p_color, p_to_color, lines); + points.push_back(p_to); + colors.push_back(p_to_color); + + p_where->draw_polyline_colors(points, colors, 2, true); #else diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 22d053d312..e908829d5f 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -110,7 +110,7 @@ private: bool awaiting_scroll_offset_update; List<Connection> connections; - void _bake_segment2d(CanvasItem *p_where, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const; + void _bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const; void _draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const Color &p_to_color); diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index 31236fa277..e3dad08809 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -131,7 +131,12 @@ void SplitContainer::_resort() { if (ratiomode) { - middle_sep = ms_first[axis] + available / 2; + int first_ratio = first->get_stretch_ratio(); + int second_ratio = second->get_stretch_ratio(); + + float ratio = float(first_ratio) / (first_ratio + second_ratio); + + middle_sep = ms_first[axis] + available * ratio; } else if (expand_first_mode) { @@ -144,12 +149,17 @@ void SplitContainer::_resort() { } else if (ratiomode) { - if (expand_ofs < -(available / 2)) - expand_ofs = -(available / 2); - else if (expand_ofs > (available / 2)) - expand_ofs = (available / 2); + int first_ratio = first->get_stretch_ratio(); + int second_ratio = second->get_stretch_ratio(); + + float ratio = float(first_ratio) / (first_ratio + second_ratio); + + if (expand_ofs < -(available * ratio)) + expand_ofs = -(available * ratio); + else if (expand_ofs > (available * (1.0 - ratio))) + expand_ofs = (available * (1.0 - ratio)); - middle_sep = ms_first[axis] + available / 2 + expand_ofs; + middle_sep = ms_first[axis] + available * ratio + expand_ofs; } else if (expand_first_mode) { diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 8d058377db..6e41cef4a0 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -53,7 +53,15 @@ void PrimitiveMesh::_update() { emit_changed(); } -void PrimitiveMesh::_queue_update() { +void PrimitiveMesh::_queue_update(bool p_first_mesh) { + + if (first_mesh && p_first_mesh) { + first_mesh = false; + cache_is_dirty = true; + _update(); + return; + } + if (!cache_is_dirty) { cache_is_dirty = true; call_deferred("_update"); @@ -145,6 +153,7 @@ PrimitiveMesh::PrimitiveMesh() { // make sure we do an update after we've finished constructing our object cache_is_dirty = false; + first_mesh = true; _queue_update(); } @@ -350,7 +359,7 @@ int CapsuleMesh::get_radial_segments() const { void CapsuleMesh::set_rings(const int p_rings) { rings = p_rings > 1 ? p_rings : 1; - _queue_update(); + _queue_update(true); //last property set, force update mesh } int CapsuleMesh::get_rings() const { @@ -608,7 +617,7 @@ int CubeMesh::get_subdivide_height() const { void CubeMesh::set_subdivide_depth(const int p_subdivide) { subdivide_d = p_subdivide > 0 ? p_subdivide : 0; - _queue_update(); + _queue_update(true); //last property set, force update mesh } int CubeMesh::get_subdivide_depth() const { @@ -825,7 +834,7 @@ int CylinderMesh::get_radial_segments() const { void CylinderMesh::set_rings(const int p_rings) { rings = p_rings > 0 ? p_rings : 0; - _queue_update(); + _queue_update(true); //last property set, force update mesh } int CylinderMesh::get_rings() const { @@ -942,7 +951,7 @@ int PlaneMesh::get_subdivide_width() const { void PlaneMesh::set_subdivide_depth(const int p_subdivide) { subdivide_d = p_subdivide > 0 ? p_subdivide : 0; - _queue_update(); + _queue_update(true); //last property set, force update mesh } int PlaneMesh::get_subdivide_depth() const { @@ -1232,7 +1241,7 @@ int PrismMesh::get_subdivide_height() const { void PrismMesh::set_subdivide_depth(const int p_divisions) { subdivide_d = p_divisions > 0 ? p_divisions : 0; - _queue_update(); + _queue_update(true); //last property set, force update mesh } int PrismMesh::get_subdivide_depth() const { @@ -1301,6 +1310,7 @@ void QuadMesh::_bind_methods() { QuadMesh::QuadMesh() { primitive_type = PRIMITIVE_TRIANGLE_FAN; + _queue_update(true); } /** @@ -1437,7 +1447,7 @@ int SphereMesh::get_rings() const { void SphereMesh::set_is_hemisphere(const bool p_is_hemisphere) { is_hemisphere = p_is_hemisphere; - _queue_update(); + _queue_update(true); //last property set, force update mesh } bool SphereMesh::get_is_hemisphere() const { diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index 91d1af2ee1..5e1387e864 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -51,6 +51,7 @@ private: Ref<Material> material; + bool first_mesh; bool cache_is_dirty; void _update(); @@ -60,7 +61,7 @@ protected: static void _bind_methods(); virtual void _create_mesh_array(Array &p_arr) = 0; - void _queue_update(); + void _queue_update(bool p_first_mesh = false); //pretty bad hack to have the mesh built firt time parameters are set without delay void set_aabb(Rect3 p_aabb); diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 5b60a46ade..69fd097ee8 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -612,6 +612,7 @@ public: enum Type { TYPE_LINE, + TYPE_POLYLINE, TYPE_RECT, TYPE_NINEPATCH, TYPE_PRIMITIVE, @@ -636,6 +637,18 @@ public: bool antialiased; CommandLine() { type = TYPE_LINE; } }; + struct CommandPolyLine : public Command { + + bool antialiased; + Vector<Point2> triangles; + Vector<Color> triangle_colors; + Vector<Point2> lines; + Vector<Color> line_colors; + CommandPolyLine() { + type = TYPE_POLYLINE; + antialiased = false; + } + }; struct CommandRect : public Command { @@ -815,6 +828,31 @@ public: r.position = line->from; r.expand_to(line->to); } break; + case Item::Command::TYPE_POLYLINE: { + + const Item::CommandPolyLine *pline = static_cast<const Item::CommandPolyLine *>(c); + if (pline->triangles.size()) { + for (int j = 0; j < pline->triangles.size(); j++) { + + if (j == 0) { + r.position = pline->triangles[j]; + } else { + r.expand_to(pline->triangles[j]); + } + } + } else { + + for (int j = 0; j < pline->lines.size(); j++) { + + if (j == 0) { + r.position = pline->lines[j]; + } else { + r.expand_to(pline->lines[j]); + } + } + } + + } break; case Item::Command::TYPE_RECT: { const Item::CommandRect *crect = static_cast<const Item::CommandRect *>(c); diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index 1227863b72..584f45412e 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -392,14 +392,14 @@ void VisualServerCanvas::canvas_item_set_draw_behind_parent(RID p_item, bool p_e canvas_item->behind = p_enable; } -void VisualServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width, bool p_antialiased) { +void VisualServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_colors, float p_width, bool p_antialiased) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); Item::CommandLine *line = memnew(Item::CommandLine); ERR_FAIL_COND(!line); - line->color = p_color; + line->color = p_colors; line->from = p_from; line->to = p_to; line->width = p_width; @@ -409,6 +409,86 @@ void VisualServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_from, canvas_item->commands.push_back(line); } +void VisualServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) { + + ERR_FAIL_COND(p_points.size() < 2); + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandPolyLine *pline = memnew(Item::CommandPolyLine); + ERR_FAIL_COND(!pline); + + pline->antialiased = p_antialiased; + + if (p_width <= 1) { + pline->lines = p_points; + pline->line_colors = p_colors; + if (pline->line_colors.size() == 0) { + pline->line_colors.push_back(Color(1, 1, 1, 1)); + } else if (pline->line_colors.size() > 1 && pline->line_colors.size() != pline->lines.size()) { + pline->line_colors.resize(1); + } + } else { + //make a trianglestrip for drawing the line... + Vector2 prev_t; + pline->triangles.resize(p_points.size() * 2); + if (p_antialiased) { + pline->lines.resize(p_points.size() * 2); + } + + if (p_colors.size() == 0) { + pline->triangle_colors.push_back(Color(1, 1, 1, 1)); + if (p_antialiased) { + pline->line_colors.push_back(Color(1, 1, 1, 1)); + } + } + if (p_colors.size() == 1) { + pline->triangle_colors = p_colors; + pline->line_colors = p_colors; + } else { + pline->triangle_colors.resize(pline->triangles.size()); + pline->line_colors.resize(pline->lines.size()); + } + + for (int i = 0; i < p_points.size(); i++) { + + Vector2 t; + if (i == p_points.size() - 1) { + t = prev_t; + } else { + t = (p_points[i + 1] - p_points[i]).normalized().tangent(); + if (i == 0) { + prev_t = t; + } + } + + Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5; + + if (p_antialiased) { + pline->lines[i] = p_points[i] + tangent; + pline->lines[p_points.size() * 2 - i - 1] = p_points[i] - tangent; + if (pline->line_colors.size() > 1) { + pline->line_colors[i] = p_colors[i]; + pline->line_colors[p_points.size() * 2 - i - 1] = p_colors[i]; + } + } + + pline->triangles[i * 2 + 0] = p_points[i] + tangent; + pline->triangles[i * 2 + 1] = p_points[i] - tangent; + + if (pline->triangle_colors.size() > 1) { + + pline->triangle_colors[i * 2 + 0] = p_colors[i]; + pline->triangle_colors[i * 2 + 1] = p_colors[i]; + } + + prev_t = t; + } + } + canvas_item->rect_dirty = true; + canvas_item->commands.push_back(pline); +} + void VisualServerCanvas::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) { Item *canvas_item = canvas_item_owner.getornull(p_item); diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h index 57c7515367..48e3186ece 100644 --- a/servers/visual/visual_server_canvas.h +++ b/servers/visual/visual_server_canvas.h @@ -171,6 +171,7 @@ public: void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable); void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false); + void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_line, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false); void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color); void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID()); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index e201f6a8c0..448af17478 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -1042,6 +1042,7 @@ public: BIND2(canvas_item_set_draw_behind_parent, RID, bool) BIND6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool) + BIND5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool) BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &) BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) BIND7(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID) diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp index 2c2bd2b167..433b6e945e 100644 --- a/servers/visual/visual_server_viewport.cpp +++ b/servers/visual/visual_server_viewport.cpp @@ -279,6 +279,7 @@ void VisualServerViewport::draw_viewports() { ERR_CONTINUE(!vp->render_target.is_valid()); bool visible = vp->viewport_to_screen_rect != Rect2() || vp->update_mode == VS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == VS::VIEWPORT_UPDATE_ONCE || (vp->update_mode == VS::VIEWPORT_UPDATE_WHEN_VISIBLE && VSG::storage->render_target_was_used(vp->render_target)); + visible = visible && vp->size.x > 0 && vp->size.y > 0; if (!visible) continue; diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 9f49377fa8..c8afc18740 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -469,6 +469,7 @@ public: FUNC2(canvas_item_set_draw_behind_parent, RID, bool) FUNC6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool) + FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool) FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &) FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) FUNC7(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID) diff --git a/servers/visual_server.h b/servers/visual_server.h index 4d2a983751..06ceb2cf4c 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -787,6 +787,7 @@ public: }; virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false) = 0; + virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false) = 0; virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0; virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0; virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID()) = 0; |