diff options
Diffstat (limited to 'editor')
-rw-r--r-- | editor/editor_node.cpp | 34 | ||||
-rw-r--r-- | editor/plugins/animation_blend_tree_editor_plugin.cpp | 50 | ||||
-rw-r--r-- | editor/plugins/animation_blend_tree_editor_plugin.h | 4 | ||||
-rw-r--r-- | editor/plugins/collision_shape_2d_editor_plugin.cpp | 15 | ||||
-rw-r--r-- | editor/plugins/tile_map_editor_plugin.cpp | 4 | ||||
-rw-r--r-- | editor/plugins/tile_set_editor_plugin.cpp | 114 | ||||
-rw-r--r-- | editor/plugins/tile_set_editor_plugin.h | 2 | ||||
-rw-r--r-- | editor/plugins/visual_shader_editor_plugin.cpp | 804 | ||||
-rw-r--r-- | editor/plugins/visual_shader_editor_plugin.h | 59 |
9 files changed, 978 insertions, 108 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index c1d2a67e36..91e104667e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -5438,7 +5438,7 @@ EditorNode::EditorNode() { p->add_shortcut(ED_SHORTCUT("editor/undo", TTR("Undo"), KEY_MASK_CMD + KEY_Z), EDIT_UNDO, true); p->add_shortcut(ED_SHORTCUT("editor/redo", TTR("Redo"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_Z), EDIT_REDO, true); p->add_separator(); - p->add_item(TTR("Revert Scene"), EDIT_REVERT); + p->add_shortcut(ED_SHORTCUT("editor/revert_scene", TTR("Revert Scene")), EDIT_REVERT); recent_scenes = memnew(PopupMenu); recent_scenes->set_name("RecentScenes"); @@ -5458,10 +5458,10 @@ EditorNode::EditorNode() { p = project_menu->get_popup(); p->set_hide_on_window_lose_focus(true); - p->add_item(TTR("Project Settings"), RUN_SETTINGS); + p->add_shortcut(ED_SHORTCUT("editor/project_settings", TTR("Project Settings")), RUN_SETTINGS); p->add_separator(); p->connect("id_pressed", this, "_menu_option"); - p->add_item(TTR("Export"), FILE_EXPORT_PROJECT); + p->add_shortcut(ED_SHORTCUT("editor/export", TTR("Export")), FILE_EXPORT_PROJECT); plugin_config_dialog = memnew(PluginConfigDialog); plugin_config_dialog->connect("plugin_ready", this, "_on_plugin_ready"); @@ -5472,10 +5472,10 @@ EditorNode::EditorNode() { tool_menu->connect("index_pressed", this, "_tool_menu_option"); p->add_child(tool_menu); p->add_submenu_item(TTR("Tools"), "Tools"); - tool_menu->add_item(TTR("Orphan Resource Explorer"), TOOLS_ORPHAN_RESOURCES); + tool_menu->add_shortcut(ED_SHORTCUT("editor/orphan_resource_explorer", TTR("Orphan Resource Explorer")), TOOLS_ORPHAN_RESOURCES); p->add_separator(); - p->add_item(TTR("Open Project Data Folder"), RUN_PROJECT_DATA_FOLDER); + p->add_shortcut(ED_SHORTCUT("editor/open_project_data_folder", TTR("Open Project Data Folder")), RUN_PROJECT_DATA_FOLDER); p->add_separator(); #ifdef OSX_ENABLED @@ -5499,21 +5499,21 @@ EditorNode::EditorNode() { p = debug_menu->get_popup(); p->set_hide_on_window_lose_focus(true); p->set_hide_on_item_selection(false); - p->add_check_item(TTR("Deploy with Remote Debug"), RUN_DEPLOY_REMOTE_DEBUG); + p->add_check_shortcut(ED_SHORTCUT("editor/deploy_with_remote_debug", TTR("Deploy with Remote Debug")), RUN_DEPLOY_REMOTE_DEBUG); p->set_item_tooltip(p->get_item_count() - 1, TTR("When exporting or deploying, the resulting executable will attempt to connect to the IP of this computer in order to be debugged.")); - p->add_check_item(TTR("Small Deploy with Network FS"), RUN_FILE_SERVER); + p->add_check_shortcut(ED_SHORTCUT("editor/small_deploy_with_network_fs", TTR("Small Deploy with Network FS")), RUN_FILE_SERVER); p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is enabled, export or deploy will produce a minimal executable.\nThe filesystem will be provided from the project by the editor over the network.\nOn Android, deploy will use the USB cable for faster performance. This option speeds up testing for games with a large footprint.")); p->add_separator(); - p->add_check_item(TTR("Visible Collision Shapes"), RUN_DEBUG_COLLISONS); + p->add_check_shortcut(ED_SHORTCUT("editor/visible_collision_shapes", TTR("Visible Collision Shapes")), RUN_DEBUG_COLLISONS); p->set_item_tooltip(p->get_item_count() - 1, TTR("Collision shapes and raycast nodes (for 2D and 3D) will be visible on the running game if this option is turned on.")); - p->add_check_item(TTR("Visible Navigation"), RUN_DEBUG_NAVIGATION); + p->add_check_shortcut(ED_SHORTCUT("editor/visible_navigation", TTR("Visible Navigation")), RUN_DEBUG_NAVIGATION); p->set_item_tooltip(p->get_item_count() - 1, TTR("Navigation meshes and polygons will be visible on the running game if this option is turned on.")); p->add_separator(); //those are now on by default, since they are harmless - p->add_check_item(TTR("Sync Scene Changes"), RUN_LIVE_DEBUG); + p->add_check_shortcut(ED_SHORTCUT("editor/sync_scene_changes", TTR("Sync Scene Changes")), RUN_LIVE_DEBUG); p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is turned on, any changes made to the scene in the editor will be replicated in the running game.\nWhen used remotely on a device, this is more efficient with network filesystem.")); p->set_item_checked(p->get_item_count() - 1, true); - p->add_check_item(TTR("Sync Script Changes"), RUN_RELOAD_SCRIPTS); + p->add_check_shortcut(ED_SHORTCUT("editor/sync_script_changes", TTR("Sync Script Changes")), RUN_RELOAD_SCRIPTS); p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is turned on, any script that is saved will be reloaded on the running game.\nWhen used remotely on a device, this is more efficient with network filesystem.")); p->set_item_checked(p->get_item_count() - 1, true); p->connect("id_pressed", this, "_menu_option"); @@ -5529,7 +5529,7 @@ EditorNode::EditorNode() { p = settings_menu->get_popup(); p->set_hide_on_window_lose_focus(true); - p->add_item(TTR("Editor Settings"), SETTINGS_PREFERENCES); + p->add_shortcut(ED_SHORTCUT("editor/editor_settings", TTR("Editor Settings")), SETTINGS_PREFERENCES); p->add_separator(); editor_layouts = memnew(PopupMenu); @@ -5569,12 +5569,12 @@ EditorNode::EditorNode() { p->connect("id_pressed", this, "_menu_option"); p->add_icon_shortcut(gui_base->get_icon("HelpSearch", "EditorIcons"), ED_SHORTCUT("editor/editor_help", TTR("Search"), KEY_MASK_SHIFT | KEY_F1), HELP_SEARCH); p->add_separator(); - p->add_icon_item(gui_base->get_icon("Instance", "EditorIcons"), TTR("Online Docs"), HELP_DOCS); - p->add_icon_item(gui_base->get_icon("Instance", "EditorIcons"), TTR("Q&A"), HELP_QA); - p->add_icon_item(gui_base->get_icon("Instance", "EditorIcons"), TTR("Issue Tracker"), HELP_ISSUES); - p->add_icon_item(gui_base->get_icon("Instance", "EditorIcons"), TTR("Community"), HELP_COMMUNITY); + p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/online_docs", TTR("Online Docs")), HELP_DOCS); + p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/q&a", TTR("Q&A")), HELP_QA); + p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/issue_tracker", TTR("Issue Tracker")), HELP_ISSUES); + p->add_icon_shortcut(gui_base->get_icon("Instance", "EditorIcons"), ED_SHORTCUT("editor/community", TTR("Community")), HELP_COMMUNITY); p->add_separator(); - p->add_icon_item(gui_base->get_icon("Godot", "EditorIcons"), TTR("About"), HELP_ABOUT); + p->add_icon_shortcut(gui_base->get_icon("Godot", "EditorIcons"), ED_SHORTCUT("editor/about", TTR("About")), HELP_ABOUT); HBoxContainer *play_hb = memnew(HBoxContainer); menu_hb->add_child(play_hb); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index c5dfba6b06..f13c2170ea 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -80,6 +80,7 @@ void AnimationNodeBlendTreeEditor::_update_options_menu() { } add_node->get_popup()->add_separator(); add_node->get_popup()->add_item(TTR("Load..."), MENU_LOAD_FILE); + use_popup_menu_position = false; } Size2 AnimationNodeBlendTreeEditor::get_minimum_size() const { @@ -317,7 +318,15 @@ void AnimationNodeBlendTreeEditor::_add_node(int p_idx) { EditorNode::get_singleton()->show_warning(TTR("Output node can't be added to the blend tree.")); return; } - Point2 instance_pos = graph->get_scroll_ofs() + graph->get_size() * 0.5; + + Point2 instance_pos = graph->get_scroll_ofs(); + if (use_popup_menu_position) { + instance_pos += popup_menu_position; + } else { + instance_pos += graph->get_size() * 0.5; + } + + instance_pos /= graph->get_zoom(); int base = 1; String name = base_name; @@ -412,6 +421,40 @@ void AnimationNodeBlendTreeEditor::_delete_request(const String &p_which) { undo_redo->commit_action(); } +void AnimationNodeBlendTreeEditor::_delete_nodes_request() { + + List<StringName> to_erase; + + for (int i = 0; i < graph->get_child_count(); i++) { + GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); + if (gn) { + if (gn->is_selected() && gn->is_close_button_visible()) { + to_erase.push_back(gn->get_name()); + } + } + } + + if (to_erase.empty()) + return; + + undo_redo->create_action(TTR("Delete Node(s)")); + + for (List<StringName>::Element *F = to_erase.front(); F; F = F->next()) { + _delete_request(F->get()); + } + + undo_redo->commit_action(); +} + +void AnimationNodeBlendTreeEditor::_popup_request(const Vector2 &p_position) { + + _update_options_menu(); + use_popup_menu_position = true; + popup_menu_position = graph->get_local_mouse_position(); + add_node->get_popup()->set_position(p_position); + add_node->get_popup()->popup(); +} + void AnimationNodeBlendTreeEditor::_node_selected(Object *p_node) { GraphNode *gn = Object::cast_to<GraphNode>(p_node); @@ -730,6 +773,8 @@ void AnimationNodeBlendTreeEditor::_bind_methods() { ClassDB::bind_method("_open_in_editor", &AnimationNodeBlendTreeEditor::_open_in_editor); ClassDB::bind_method("_scroll_changed", &AnimationNodeBlendTreeEditor::_scroll_changed); ClassDB::bind_method("_delete_request", &AnimationNodeBlendTreeEditor::_delete_request); + ClassDB::bind_method("_delete_nodes_request", &AnimationNodeBlendTreeEditor::_delete_nodes_request); + ClassDB::bind_method("_popup_request", &AnimationNodeBlendTreeEditor::_popup_request); ClassDB::bind_method("_edit_filters", &AnimationNodeBlendTreeEditor::_edit_filters); ClassDB::bind_method("_update_filters", &AnimationNodeBlendTreeEditor::_update_filters); ClassDB::bind_method("_filter_edited", &AnimationNodeBlendTreeEditor::_filter_edited); @@ -850,6 +895,7 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() { singleton = this; updating = false; + use_popup_menu_position = false; graph = memnew(GraphEdit); add_child(graph); @@ -860,6 +906,8 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() { graph->connect("disconnection_request", this, "_disconnection_request", varray(), CONNECT_DEFERRED); graph->connect("node_selected", this, "_node_selected"); graph->connect("scroll_offset_changed", this, "_scroll_changed"); + graph->connect("delete_nodes_request", this, "_delete_nodes_request"); + graph->connect("popup_request", this, "_popup_request"); VSeparator *vs = memnew(VSeparator); graph->get_zoom_hbox()->add_child(vs); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h index f2a77cecb4..cb40159a40 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.h +++ b/editor/plugins/animation_blend_tree_editor_plugin.h @@ -51,6 +51,8 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { Ref<AnimationNodeBlendTree> blend_tree; GraphEdit *graph; MenuButton *add_node; + Vector2 popup_menu_position; + bool use_popup_menu_position; PanelContainer *error_panel; Label *error_label; @@ -97,6 +99,8 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { void _open_in_editor(const String &p_which); void _anim_selected(int p_index, Array p_options, const String &p_node); void _delete_request(const String &p_which); + void _delete_nodes_request(); + void _popup_request(const Vector2 &p_position); bool _update_filters(const Ref<AnimationNode> &anode); void _edit_filters(const String &p_which); diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index 10023d88bf..c8561d22a4 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -93,7 +93,7 @@ Variant CollisionShape2DEditor::get_handle_value(int idx) const { case RECTANGLE_SHAPE: { Ref<RectangleShape2D> rect = node->get_shape(); - if (idx < 2) { + if (idx < 3) { return rect->get_extents().abs(); } @@ -175,12 +175,15 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { } break; case RECTANGLE_SHAPE: { - if (idx < 2) { + if (idx < 3) { Ref<RectangleShape2D> rect = node->get_shape(); Vector2 extents = rect->get_extents(); - extents[idx] = p_point[idx]; - + if (idx == 2) { + extents = p_point; + } else { + extents[idx] = p_point[idx]; + } rect->set_extents(extents.abs()); canvas_item_editor->update_viewport(); @@ -496,13 +499,15 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla case RECTANGLE_SHAPE: { Ref<RectangleShape2D> shape = node->get_shape(); - handles.resize(2); + handles.resize(3); Vector2 ext = shape->get_extents(); handles.write[0] = Point2(ext.x, 0); handles.write[1] = Point2(0, -ext.y); + handles.write[2] = Point2(ext.x, -ext.y); p_overlay->draw_texture(h, gt.xform(handles[0]) - size); p_overlay->draw_texture(h, gt.xform(handles[1]) - size); + p_overlay->draw_texture(h, gt.xform(handles[2]) - size); } break; diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 8a18af7ae8..33e4bb2336 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -481,10 +481,10 @@ void TileMapEditor::_update_palette() { if (sel_tile != TileMap::INVALID_CELL) { if ((manual_autotile && tileset->tile_get_tile_mode(sel_tile) == TileSet::AUTO_TILE) || tileset->tile_get_tile_mode(sel_tile) == TileSet::ATLAS_TILE) { - const Map<Vector2, uint16_t> &tiles2 = tileset->autotile_get_bitmask_map(sel_tile); + const Map<Vector2, uint32_t> &tiles2 = tileset->autotile_get_bitmask_map(sel_tile); Vector<Vector2> entries2; - for (const Map<Vector2, uint16_t>::Element *E = tiles2.front(); E; E = E->next()) { + for (const Map<Vector2, uint32_t>::Element *E = tiles2.front(); E; E = E->next()) { entries2.push_back(E->key()); } entries2.sort(); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 54e6e5b154..5bc1067718 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -734,7 +734,7 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[SHAPE_KEEP_INSIDE_TILE]->hide(); tools[TOOL_SELECT]->set_pressed(true); - tools[TOOL_SELECT]->set_tooltip(TTR("LMB: Set bit on.\nRMB: Set bit off.\nClick on another Tile to edit it.")); + tools[TOOL_SELECT]->set_tooltip(TTR("LMB: Set bit on.\nRMB: Set bit off.\nShift+LMB: Set wildcard bit.\nClick on another Tile to edit it.")); spin_priority->hide(); } break; case EDITMODE_Z_INDEX: @@ -818,52 +818,92 @@ void TileSetEditor::_on_workspace_draw() { } break; case EDITMODE_BITMASK: { Color c(1, 0, 0, 0.5); + Color ci(0.3, 0.6, 1, 0.5); for (float x = 0; x < region.size.x / (spacing + size.x); x++) { for (float y = 0; y < region.size.y / (spacing + size.y); y++) { Vector2 coord(x, y); Point2 anchor(coord.x * (spacing + size.x), coord.y * (spacing + size.y)); anchor += WORKSPACE_MARGIN; anchor += region.position; - uint16_t mask = tileset->autotile_get_bitmask(get_current_tile(), coord); + uint32_t mask = tileset->autotile_get_bitmask(get_current_tile(), coord); if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { - if (mask & TileSet::BIND_TOPLEFT) { + if (mask & TileSet::BIND_IGNORE_TOPLEFT) { + workspace->draw_rect(Rect2(anchor, size / 4), ci); + workspace->draw_rect(Rect2(anchor + size / 4, size / 4), ci); + } else if (mask & TileSet::BIND_TOPLEFT) { workspace->draw_rect(Rect2(anchor, size / 2), c); } - if (mask & TileSet::BIND_TOPRIGHT) { + if (mask & TileSet::BIND_IGNORE_TOPRIGHT) { + workspace->draw_rect(Rect2(anchor + Vector2(size.x / 2, 0), size / 4), ci); + workspace->draw_rect(Rect2(anchor + Vector2(size.x * 3 / 4, size.y / 4), size / 4), ci); + } else if (mask & TileSet::BIND_TOPRIGHT) { workspace->draw_rect(Rect2(anchor + Vector2(size.x / 2, 0), size / 2), c); } - if (mask & TileSet::BIND_BOTTOMLEFT) { + if (mask & TileSet::BIND_IGNORE_BOTTOMLEFT) { + workspace->draw_rect(Rect2(anchor + Vector2(0, size.y / 2), size / 4), ci); + workspace->draw_rect(Rect2(anchor + Vector2(size.x / 4, size.y * 3 / 4), size / 4), ci); + } else if (mask & TileSet::BIND_BOTTOMLEFT) { workspace->draw_rect(Rect2(anchor + Vector2(0, size.y / 2), size / 2), c); } - if (mask & TileSet::BIND_BOTTOMRIGHT) { + if (mask & TileSet::BIND_IGNORE_BOTTOMRIGHT) { + workspace->draw_rect(Rect2(anchor + size / 2, size / 4), ci); + workspace->draw_rect(Rect2(anchor + size * 3 / 4, size / 4), ci); + } else if (mask & TileSet::BIND_BOTTOMRIGHT) { workspace->draw_rect(Rect2(anchor + size / 2, size / 2), c); } } else { - if (mask & TileSet::BIND_TOPLEFT) { + if (mask & TileSet::BIND_IGNORE_TOPLEFT) { + workspace->draw_rect(Rect2(anchor, size / 6), ci); + workspace->draw_rect(Rect2(anchor + size / 6, size / 6), ci); + } else if (mask & TileSet::BIND_TOPLEFT) { workspace->draw_rect(Rect2(anchor, size / 3), c); } - if (mask & TileSet::BIND_TOP) { + if (mask & TileSet::BIND_IGNORE_TOP) { + workspace->draw_rect(Rect2(anchor + Vector2(size.x / 3, 0), size / 6), ci); + workspace->draw_rect(Rect2(anchor + Vector2(size.x / 2, size.y / 6), size / 6), ci); + } else if (mask & TileSet::BIND_TOP) { workspace->draw_rect(Rect2(anchor + Vector2(size.x / 3, 0), size / 3), c); } - if (mask & TileSet::BIND_TOPRIGHT) { + if (mask & TileSet::BIND_IGNORE_TOPRIGHT) { + workspace->draw_rect(Rect2(anchor + Vector2(size.x * 4 / 6, 0), size / 6), ci); + workspace->draw_rect(Rect2(anchor + Vector2(size.x * 5 / 6, size.y / 6), size / 6), ci); + } else if (mask & TileSet::BIND_TOPRIGHT) { workspace->draw_rect(Rect2(anchor + Vector2((size.x / 3) * 2, 0), size / 3), c); } - if (mask & TileSet::BIND_LEFT) { + if (mask & TileSet::BIND_IGNORE_LEFT) { + workspace->draw_rect(Rect2(anchor + Vector2(0, size.y / 3), size / 6), ci); + workspace->draw_rect(Rect2(anchor + Vector2(size.x / 6, size.y / 2), size / 6), ci); + } else if (mask & TileSet::BIND_LEFT) { workspace->draw_rect(Rect2(anchor + Vector2(0, size.y / 3), size / 3), c); } - if (mask & TileSet::BIND_CENTER) { + if (mask & TileSet::BIND_IGNORE_CENTER) { + workspace->draw_rect(Rect2(anchor + size / 3, size / 6), ci); + workspace->draw_rect(Rect2(anchor + size / 2, size / 6), ci); + } else if (mask & TileSet::BIND_CENTER) { workspace->draw_rect(Rect2(anchor + Vector2(size.x / 3, size.y / 3), size / 3), c); } - if (mask & TileSet::BIND_RIGHT) { + if (mask & TileSet::BIND_IGNORE_RIGHT) { + workspace->draw_rect(Rect2(anchor + Vector2(size.x * 4 / 6, size.y / 3), size / 6), ci); + workspace->draw_rect(Rect2(anchor + Vector2(size.x * 5 / 6, size.y / 2), size / 6), ci); + } else if (mask & TileSet::BIND_RIGHT) { workspace->draw_rect(Rect2(anchor + Vector2((size.x / 3) * 2, size.y / 3), size / 3), c); } - if (mask & TileSet::BIND_BOTTOMLEFT) { + if (mask & TileSet::BIND_IGNORE_BOTTOMLEFT) { + workspace->draw_rect(Rect2(anchor + Vector2(0, size.y * 4 / 6), size / 6), ci); + workspace->draw_rect(Rect2(anchor + Vector2(size.x / 6, size.y * 5 / 6), size / 6), ci); + } else if (mask & TileSet::BIND_BOTTOMLEFT) { workspace->draw_rect(Rect2(anchor + Vector2(0, (size.y / 3) * 2), size / 3), c); } - if (mask & TileSet::BIND_BOTTOM) { + if (mask & TileSet::BIND_IGNORE_BOTTOM) { + workspace->draw_rect(Rect2(anchor + Vector2(size.x / 3, size.y * 4 / 6), size / 6), ci); + workspace->draw_rect(Rect2(anchor + Vector2(size.x / 2, size.y * 5 / 6), size / 6), ci); + } else if (mask & TileSet::BIND_BOTTOM) { workspace->draw_rect(Rect2(anchor + Vector2(size.x / 3, (size.y / 3) * 2), size / 3), c); } - if (mask & TileSet::BIND_BOTTOMRIGHT) { + if (mask & TileSet::BIND_IGNORE_BOTTOMRIGHT) { + workspace->draw_rect(Rect2(anchor + size * 4 / 6, size / 6), ci); + workspace->draw_rect(Rect2(anchor + size * 5 / 6, size / 6), ci); + } else if (mask & TileSet::BIND_BOTTOMRIGHT) { workspace->draw_rect(Rect2(anchor + (size / 3) * 2, size / 3), c); } } @@ -882,10 +922,10 @@ void TileSetEditor::_on_workspace_draw() { } break; case EDITMODE_PRIORITY: { spin_priority->set_value(tileset->autotile_get_subtile_priority(get_current_tile(), edited_shape_coord)); - uint16_t mask = tileset->autotile_get_bitmask(get_current_tile(), edited_shape_coord); + uint32_t mask = tileset->autotile_get_bitmask(get_current_tile(), edited_shape_coord); Vector<Vector2> queue_others; int total = 0; - for (Map<Vector2, uint16_t>::Element *E = tileset->autotile_get_bitmask_map(get_current_tile()).front(); E; E = E->next()) { + for (Map<Vector2, uint32_t>::Element *E = tileset->autotile_get_bitmask_map(get_current_tile()).front(); E; E = E->next()) { if (E->value() == mask) { total += tileset->autotile_get_subtile_priority(get_current_tile(), E->key()); if (E->key() != edited_shape_coord) { @@ -1037,6 +1077,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { static bool dragging; static bool erasing; + static bool alternative; draw_edited_region = false; Rect2 current_tile_region = Rect2(); @@ -1220,10 +1261,11 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { if ((mb->get_button_index() == BUTTON_RIGHT || mb->get_button_index() == BUTTON_LEFT) && current_tile_region.has_point(mb->get_position())) { dragging = true; erasing = (mb->get_button_index() == BUTTON_RIGHT); + alternative = Input::get_singleton()->is_key_pressed(KEY_SHIFT); Vector2 coord((int)((mb->get_position().x - current_tile_region.position.x) / (spacing + size.x)), (int)((mb->get_position().y - current_tile_region.position.y) / (spacing + size.y))); Vector2 pos(coord.x * (spacing + size.x), coord.y * (spacing + size.y)); pos = mb->get_position() - (pos + current_tile_region.position); - uint16_t bit = 0; + uint32_t bit = 0; if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { if (pos.x < size.x / 2) { if (pos.y < size.y / 2) { @@ -1266,13 +1308,19 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } - uint16_t old_mask = tileset->autotile_get_bitmask(get_current_tile(), coord); - uint16_t new_mask = old_mask; - if (erasing) { + uint32_t old_mask = tileset->autotile_get_bitmask(get_current_tile(), coord); + uint32_t new_mask = old_mask; + if (alternative) { new_mask &= ~bit; + new_mask |= (bit << 16); + } else if (erasing) { + new_mask &= ~bit; + new_mask &= ~(bit << 16); } else { new_mask |= bit; + new_mask &= ~(bit << 16); } + if (old_mask != new_mask) { undo_redo->create_action(TTR("Edit Tile Bitmask")); undo_redo->add_do_method(tileset.ptr(), "autotile_set_bitmask", get_current_tile(), coord, new_mask); @@ -1286,6 +1334,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { if ((erasing && mb->get_button_index() == BUTTON_RIGHT) || (!erasing && mb->get_button_index() == BUTTON_LEFT)) { dragging = false; erasing = false; + alternative = false; } } } @@ -1294,7 +1343,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { Vector2 coord((int)((mm->get_position().x - current_tile_region.position.x) / (spacing + size.x)), (int)((mm->get_position().y - current_tile_region.position.y) / (spacing + size.y))); Vector2 pos(coord.x * (spacing + size.x), coord.y * (spacing + size.y)); pos = mm->get_position() - (pos + current_tile_region.position); - uint16_t bit = 0; + uint32_t bit = 0; if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) { if (pos.x < size.x / 2) { if (pos.y < size.y / 2) { @@ -1337,12 +1386,17 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } - uint16_t old_mask = tileset->autotile_get_bitmask(get_current_tile(), coord); - uint16_t new_mask = old_mask; - if (erasing) { + uint32_t old_mask = tileset->autotile_get_bitmask(get_current_tile(), coord); + uint32_t new_mask = old_mask; + if (alternative) { + new_mask &= ~bit; + new_mask |= (bit << 16); + } else if (erasing) { new_mask &= ~bit; + new_mask &= ~(bit << 16); } else { new_mask |= bit; + new_mask &= ~(bit << 16); } if (old_mask != new_mask) { undo_redo->create_action(TTR("Edit Tile Bitmask")); @@ -1529,10 +1583,10 @@ void TileSetEditor::_on_tool_clicked(int p_tool) { undo_redo->create_action(TTR("Paste Tile Bitmask")); undo_redo->add_do_method(tileset.ptr(), "autotile_clear_bitmask_map", get_current_tile()); undo_redo->add_undo_method(tileset.ptr(), "autotile_clear_bitmask_map", get_current_tile()); - for (Map<Vector2, uint16_t>::Element *E = bitmask_map_copy.front(); E; E = E->next()) { + for (Map<Vector2, uint32_t>::Element *E = bitmask_map_copy.front(); E; E = E->next()) { undo_redo->add_do_method(tileset.ptr(), "autotile_set_bitmask", get_current_tile(), E->key(), E->value()); } - for (Map<Vector2, uint16_t>::Element *E = tileset->autotile_get_bitmask_map(get_current_tile()).front(); E; E = E->next()) { + for (Map<Vector2, uint32_t>::Element *E = tileset->autotile_get_bitmask_map(get_current_tile()).front(); E; E = E->next()) { undo_redo->add_undo_method(tileset.ptr(), "autotile_set_bitmask", get_current_tile(), E->key(), E->value()); } undo_redo->add_do_method(workspace, "update"); @@ -1541,7 +1595,7 @@ void TileSetEditor::_on_tool_clicked(int p_tool) { } else if (p_tool == BITMASK_CLEAR) { undo_redo->create_action(TTR("Clear Tile Bitmask")); undo_redo->add_do_method(tileset.ptr(), "autotile_clear_bitmask_map", get_current_tile()); - for (Map<Vector2, uint16_t>::Element *E = tileset->autotile_get_bitmask_map(get_current_tile()).front(); E; E = E->next()) { + for (Map<Vector2, uint32_t>::Element *E = tileset->autotile_get_bitmask_map(get_current_tile()).front(); E; E = E->next()) { undo_redo->add_undo_method(tileset.ptr(), "autotile_set_bitmask", get_current_tile(), E->key(), E->value()); } undo_redo->add_do_method(workspace, "update"); @@ -2139,8 +2193,8 @@ void TileSetEditor::_undo_tile_removal(int p_id) { for (Map<Vector2, Ref<NavigationPolygon> >::Element *E = navigation_map.front(); E; E = E->next()) { undo_redo->add_undo_method(tileset.ptr(), "autotile_set_navigation_polygon", p_id, E->value(), E->key()); } - Map<Vector2, uint16_t> bitmask_map = tileset->autotile_get_bitmask_map(p_id); - for (Map<Vector2, uint16_t>::Element *E = bitmask_map.front(); E; E = E->next()) { + Map<Vector2, uint32_t> bitmask_map = tileset->autotile_get_bitmask_map(p_id); + for (Map<Vector2, uint32_t>::Element *E = bitmask_map.front(); E; E = E->next()) { undo_redo->add_undo_method(tileset.ptr(), "autotile_set_bitmask", p_id, E->key(), E->value()); } Map<Vector2, int> priority_map = tileset->autotile_get_priority_map(p_id); diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 2827964592..1176e1bb92 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -126,7 +126,7 @@ class TileSetEditor : public HSplitContainer { Vector2 edited_shape_coord; PoolVector2Array current_shape; Map<Vector2i, SubtileData> current_tile_data; - Map<Vector2, uint16_t> bitmask_map_copy; + Map<Vector2, uint32_t> bitmask_map_copy; Vector2 snap_step; Vector2 snap_offset; diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 4d8d81fb01..f71ff84bbe 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -39,6 +39,7 @@ #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" #include "scene/main/viewport.h" +#include "scene/resources/visual_shader_nodes.h" Control *VisualShaderNodePlugin::create_editor(const Ref<VisualShaderNode> &p_node) { @@ -107,16 +108,174 @@ void VisualShaderEditor::remove_custom_type(const Ref<Script> &p_script) { _update_options_menu(); } +bool VisualShaderEditor::_is_available(int p_mode) { + + int current_mode = edit_type->get_selected(); + + if (p_mode != -1) { + + switch (current_mode) { + case VisualShader::TYPE_VERTEX: + current_mode = 1; + break; + case VisualShader::TYPE_FRAGMENT: + current_mode = 2; + break; + case VisualShader::TYPE_LIGHT: + current_mode = 4; + break; + default: + break; + } + + int temp_mode = 0; + + if (p_mode & VisualShader::TYPE_FRAGMENT) { + temp_mode |= 2; + } + + if (p_mode & VisualShader::TYPE_LIGHT) { + temp_mode |= 4; + } + + if (temp_mode == 0) { + temp_mode |= 1; + } + + p_mode = temp_mode; + } + + if (p_mode != -1 && ((p_mode & current_mode) == 0)) { + return false; + } + return true; +} + void VisualShaderEditor::_update_options_menu() { + node_desc->set_text(""); + members_dialog->get_ok()->set_disabled(true); + String prev_category; - add_node->get_popup()->clear(); - for (int i = 0; i < add_options.size(); i++) { - if (prev_category != add_options[i].category) { - add_node->get_popup()->add_separator(add_options[i].category); + String prev_sub_category; + + members->clear(); + TreeItem *root = members->create_item(); + TreeItem *category = NULL; + TreeItem *sub_category = NULL; + + String filter = node_filter->get_text().strip_edges(); + bool use_filter = !filter.empty(); + + Vector<String> categories; + Vector<String> sub_categories; + + int item_count = 0; + int item_count2 = 0; + + for (int i = 0; i < add_options.size() + 1; i++) { + + if (i == add_options.size()) { + if (sub_category != NULL && item_count2 == 0) { + memdelete(sub_category); + --item_count; + } + if (category != NULL && item_count == 0) { + memdelete(category); + } + break; + } + + if (!use_filter || add_options[i].name.findn(filter) != -1) { + + if (prev_category != add_options[i].category) { + if (category != NULL && item_count == 0) { + memdelete(category); + } + + item_count = 0; + prev_sub_category = ""; + category = members->create_item(root); + category->set_text(0, add_options[i].category); + if (!use_filter) + category->set_collapsed(true); + } + + if (add_options[i].sub_category != "") { + if (prev_sub_category != add_options[i].sub_category) { + if (category != NULL) { + if (sub_category != NULL && item_count2 == 0) { + memdelete(sub_category); + --item_count; + } + ++item_count; + item_count2 = 0; + sub_category = members->create_item(category); + sub_category->set_text(0, add_options[i].sub_category); + if (!use_filter) + sub_category->set_collapsed(true); + } + } + if (sub_category != NULL) { + if (_is_available(add_options[i].mode)) { + ++item_count2; + TreeItem *item = members->create_item(sub_category); + item->set_text(0, add_options[i].name); + switch (add_options[i].return_type) { + case VisualShaderNode::PORT_TYPE_SCALAR: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("float", "EditorIcons")); + break; + case VisualShaderNode::PORT_TYPE_VECTOR: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Vector3", "EditorIcons")); + break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("bool", "EditorIcons")); + break; + case VisualShaderNode::PORT_TYPE_TRANSFORM: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Transform", "EditorIcons")); + break; + case VisualShaderNode::PORT_TYPE_COLOR: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Color", "EditorIcons")); + break; + default: + break; + } + item->set_meta("id", i); + } + } + } else { + if (category != NULL) { + if (_is_available(add_options[i].mode)) { + ++item_count; + TreeItem *item = members->create_item(category); + item->set_text(0, add_options[i].name); + switch (add_options[i].return_type) { + case VisualShaderNode::PORT_TYPE_SCALAR: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("float", "EditorIcons")); + break; + case VisualShaderNode::PORT_TYPE_VECTOR: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Vector3", "EditorIcons")); + break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("bool", "EditorIcons")); + break; + case VisualShaderNode::PORT_TYPE_TRANSFORM: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Transform", "EditorIcons")); + break; + case VisualShaderNode::PORT_TYPE_COLOR: + item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Color", "EditorIcons")); + break; + default: + break; + } + item->set_meta("id", i); + } + } + } + + prev_sub_category = add_options[i].sub_category; + prev_category = add_options[i].category; } - add_node->get_popup()->add_item(add_options[i].name, i); - prev_category = add_options[i].category; } } @@ -165,10 +324,11 @@ void VisualShaderEditor::_update_graph() { } } - static const Color type_color[3] = { - Color::html("#61daf4"), - Color::html("#d67dee"), - Color::html("#f6a86e") + static const Color type_color[4] = { + Color::html("#61daf4"), // scalar + Color::html("#d67dee"), // vector + Color::html("#8da6f0"), // boolean + Color::html("#f6a86e") // transform }; List<VisualShader::Connection> connections; @@ -462,7 +622,7 @@ void VisualShaderEditor::_edit_port_default_input(Object *p_button, int p_node, editing_port = p_port; } -void VisualShaderEditor::_add_node(int p_idx) { +void VisualShaderEditor::_add_node(int p_idx, int p_op_idx) { ERR_FAIL_INDEX(p_idx, add_options.size()); @@ -471,6 +631,70 @@ void VisualShaderEditor::_add_node(int p_idx) { if (add_options[p_idx].type != String()) { VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instance(add_options[p_idx].type)); ERR_FAIL_COND(!vsn); + + if (p_op_idx != -1) { + + VisualShaderNodeInput *input = Object::cast_to<VisualShaderNodeInput>(vsn); + + if (input) { + input->set_input_name(add_options[p_idx].sub_func_str); + } + + VisualShaderNodeColorOp *colorOp = Object::cast_to<VisualShaderNodeColorOp>(vsn); + + if (colorOp) { + colorOp->set_operator((VisualShaderNodeColorOp::Operator)p_op_idx); + } + + VisualShaderNodeColorFunc *colorFunc = Object::cast_to<VisualShaderNodeColorFunc>(vsn); + + if (colorFunc) { + colorFunc->set_function((VisualShaderNodeColorFunc::Function)p_op_idx); + } + + VisualShaderNodeScalarOp *scalarOp = Object::cast_to<VisualShaderNodeScalarOp>(vsn); + + if (scalarOp) { + scalarOp->set_operator((VisualShaderNodeScalarOp::Operator)p_op_idx); + } + + VisualShaderNodeScalarFunc *scalarFunc = Object::cast_to<VisualShaderNodeScalarFunc>(vsn); + + if (scalarFunc) { + scalarFunc->set_function((VisualShaderNodeScalarFunc::Function)p_op_idx); + } + + VisualShaderNodeVectorOp *vecOp = Object::cast_to<VisualShaderNodeVectorOp>(vsn); + + if (vecOp) { + vecOp->set_operator((VisualShaderNodeVectorOp::Operator)p_op_idx); + } + + VisualShaderNodeVectorFunc *vecFunc = Object::cast_to<VisualShaderNodeVectorFunc>(vsn); + + if (vecFunc) { + vecFunc->set_function((VisualShaderNodeVectorFunc::Function)p_op_idx); + } + + VisualShaderNodeTransformFunc *matFunc = Object::cast_to<VisualShaderNodeTransformFunc>(vsn); + + if (matFunc) { + matFunc->set_function((VisualShaderNodeTransformFunc::Function)p_op_idx); + } + + VisualShaderNodeScalarDerivativeFunc *sderFunc = Object::cast_to<VisualShaderNodeScalarDerivativeFunc>(vsn); + + if (sderFunc) { + sderFunc->set_function((VisualShaderNodeScalarDerivativeFunc::Function)p_op_idx); + } + + VisualShaderNodeVectorDerivativeFunc *vderFunc = Object::cast_to<VisualShaderNodeVectorDerivativeFunc>(vsn); + + if (vderFunc) { + vderFunc->set_function((VisualShaderNodeVectorDerivativeFunc::Function)p_op_idx); + } + } + vsnode = Ref<VisualShaderNode>(vsn); } else { ERR_FAIL_COND(add_options[p_idx].script.is_null()); @@ -481,7 +705,15 @@ void VisualShaderEditor::_add_node(int p_idx) { vsnode->set_script(add_options[p_idx].script.get_ref_ptr()); } - Point2 position = (graph->get_scroll_ofs() + graph->get_size() * 0.5) / EDSCALE; + Point2 position = graph->get_scroll_ofs(); + + if (saved_node_pos_dirty) { + position += saved_node_pos; + } else { + position += graph->get_size() * 0.5; + position /= EDSCALE; + } + saved_node_pos_dirty = false; VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); @@ -600,29 +832,82 @@ void VisualShaderEditor::_node_selected(Object *p_node) { //EditorNode::get_singleton()->push_item(vsnode.ptr(), "", true); } +void VisualShaderEditor::_member_gui_input(const Ref<InputEvent> p_event) { + Ref<InputEventMouseButton> mb = p_event; + Ref<InputEventKey> key = p_event; + + if (mb.is_valid()) { + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && mb->is_doubleclick()) { + _member_create(); + } + } else if (key.is_valid()) { + if (key->is_pressed() && key->get_scancode() == KEY_ENTER) { + _member_create(); + } + } +} + void VisualShaderEditor::_input(const Ref<InputEvent> p_event) { if (graph->has_focus()) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { - add_node->get_popup()->set_position(get_viewport()->get_mouse_position()); - add_node->get_popup()->show_modal(); + saved_node_pos_dirty = true; + saved_node_pos = graph->get_local_mouse_position(); + + Point2 gpos = Input::get_singleton()->get_mouse_position(); + members_dialog->popup(); + members_dialog->set_position(gpos); } } } +void VisualShaderEditor::_show_members_dialog() { + saved_node_pos_dirty = false; + members_dialog->popup(); + members_dialog->set_position(graph->get_global_position() + Point2(5 * EDSCALE, 65 * EDSCALE)); +} + void VisualShaderEditor::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE) { + + node_filter->set_clear_button_enabled(true); + + // collapse tree by default + + TreeItem *category = members->get_root()->get_children(); + while (category) { + category->set_collapsed(true); + TreeItem *sub_category = category->get_children(); + while (sub_category) { + sub_category->set_collapsed(true); + sub_category = sub_category->get_next(); + } + category = category->get_next(); + } + } + + if (p_what == NOTIFICATION_DRAG_BEGIN) { + Dictionary dd = get_viewport()->gui_get_drag_data(); + if (members->is_visible_in_tree() && dd.has("id")) { + members->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM); + } + } else if (p_what == NOTIFICATION_DRAG_END) { + members->set_drop_mode_flags(0); + } if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { error_panel->add_style_override("panel", get_stylebox("bg", "Tree")); error_label->add_color_override("font_color", get_color("error_color", "Editor")); + node_filter->set_right_icon(Control::get_icon("Search", "EditorIcons")); + + tools->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Tools", "EditorIcons")); + if (p_what == NOTIFICATION_THEME_CHANGED && is_visible_in_tree()) _update_graph(); - } - - if (p_what == NOTIFICATION_PROCESS) { + } else if (p_what == NOTIFICATION_PROCESS) { } } @@ -719,6 +1004,7 @@ void VisualShaderEditor::_duplicate_nodes() { } void VisualShaderEditor::_mode_selected(int p_id) { + _update_options_menu(); _update_graph(); } @@ -756,6 +1042,128 @@ void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> input, St undo_redo->commit_action(); } +void VisualShaderEditor::_member_filter_changed(const String &p_text) { + _update_options_menu(); +} + +void VisualShaderEditor::_member_selected() { + TreeItem *item = members->get_selected(); + + if (item != NULL && item->has_meta("id")) { + members_dialog->get_ok()->set_disabled(false); + node_desc->set_text(add_options[item->get_meta("id")].description); + } else { + members_dialog->get_ok()->set_disabled(true); + node_desc->set_text(""); + } +} + +void VisualShaderEditor::_member_unselected() { +} + +void VisualShaderEditor::_member_create() { + TreeItem *item = members->get_selected(); + if (item != NULL && item->has_meta("id")) { + int idx = members->get_selected()->get_meta("id"); + _add_node(idx, add_options[idx].sub_func); + members_dialog->hide(); + } +} + +void VisualShaderEditor::_tools_menu_option(int p_idx) { + + TreeItem *category = members->get_root()->get_children(); + + switch (p_idx) { + case EXPAND_ALL: + + while (category) { + category->set_collapsed(false); + TreeItem *sub_category = category->get_children(); + while (sub_category) { + sub_category->set_collapsed(false); + sub_category = sub_category->get_next(); + } + category = category->get_next(); + } + + break; + + case COLLAPSE_ALL: + + while (category) { + category->set_collapsed(true); + TreeItem *sub_category = category->get_children(); + while (sub_category) { + sub_category->set_collapsed(true); + sub_category = sub_category->get_next(); + } + category = category->get_next(); + } + + break; + default: + break; + } +} + +Variant VisualShaderEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { + + if (p_from == members) { + TreeItem *it = members->get_item_at_position(p_point); + if (!it) + return Variant(); + if (!it->has_meta("id")) + return Variant(); + + int id = it->get_meta("id"); + AddOption op = add_options[id]; + + Dictionary d; + d["id"] = id; + if (op.sub_func == -1) { + d["sub_func"] = op.sub_func_str; + } else { + d["sub_func"] = op.sub_func; + } + + Label *label = memnew(Label); + label->set_text(it->get_text(0)); + set_drag_preview(label); + return d; + } + return Variant(); +} + +bool VisualShaderEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + + if (p_from == graph) { + + Dictionary d = p_data; + + if (d.has("id")) { + return true; + } + } + + return false; +} + +void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + + if (p_from == graph) { + + Dictionary d = p_data; + + if (d.has("id")) { + int idx = d["id"]; + saved_node_pos = p_point; + saved_node_pos_dirty = true; + _add_node(idx, add_options[idx].sub_func); + } + } +} + void VisualShaderEditor::_bind_methods() { ClassDB::bind_method("_update_graph", &VisualShaderEditor::_update_graph); @@ -777,6 +1185,19 @@ void VisualShaderEditor::_bind_methods() { ClassDB::bind_method("_input_select_item", &VisualShaderEditor::_input_select_item); ClassDB::bind_method("_preview_select_port", &VisualShaderEditor::_preview_select_port); ClassDB::bind_method("_input", &VisualShaderEditor::_input); + + ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &VisualShaderEditor::get_drag_data_fw); + ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &VisualShaderEditor::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("drop_data_fw"), &VisualShaderEditor::drop_data_fw); + + ClassDB::bind_method("_is_available", &VisualShaderEditor::_is_available); + ClassDB::bind_method("_tools_menu_option", &VisualShaderEditor::_tools_menu_option); + ClassDB::bind_method("_show_members_dialog", &VisualShaderEditor::_show_members_dialog); + ClassDB::bind_method("_member_gui_input", &VisualShaderEditor::_member_gui_input); + ClassDB::bind_method("_member_filter_changed", &VisualShaderEditor::_member_filter_changed); + ClassDB::bind_method("_member_selected", &VisualShaderEditor::_member_selected); + ClassDB::bind_method("_member_unselected", &VisualShaderEditor::_member_unselected); + ClassDB::bind_method("_member_create", &VisualShaderEditor::_member_create); } VisualShaderEditor *VisualShaderEditor::singleton = NULL; @@ -785,10 +1206,14 @@ VisualShaderEditor::VisualShaderEditor() { singleton = this; updating = false; + saved_node_pos_dirty = false; + saved_node_pos = Point2(0, 0); graph = memnew(GraphEdit); add_child(graph); + graph->set_drag_forwarding(this); graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SCALAR); + graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_BOOLEAN); graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR); graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_TRANSFORM); //graph->add_valid_left_disconnect_type(0); @@ -800,8 +1225,13 @@ VisualShaderEditor::VisualShaderEditor() { graph->connect("duplicate_nodes_request", this, "_duplicate_nodes"); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_BOOLEAN); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR, VisualShaderNode::PORT_TYPE_SCALAR); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR, VisualShaderNode::PORT_TYPE_VECTOR); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR, VisualShaderNode::PORT_TYPE_BOOLEAN); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_SCALAR); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR); + graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_BOOLEAN); graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShaderNode::PORT_TYPE_TRANSFORM); VSeparator *vs = memnew(VSeparator); @@ -817,40 +1247,315 @@ VisualShaderEditor::VisualShaderEditor() { graph->get_zoom_hbox()->add_child(edit_type); graph->get_zoom_hbox()->move_child(edit_type, 0); - add_node = memnew(MenuButton); + add_node = memnew(ToolButton); graph->get_zoom_hbox()->add_child(add_node); add_node->set_text(TTR("Add Node...")); graph->get_zoom_hbox()->move_child(add_node, 0); - add_node->get_popup()->connect("id_pressed", this, "_add_node"); - - add_options.push_back(AddOption("Scalar", "Constants", "VisualShaderNodeScalarConstant")); - add_options.push_back(AddOption("Vector", "Constants", "VisualShaderNodeVec3Constant")); - add_options.push_back(AddOption("Color", "Constants", "VisualShaderNodeColorConstant")); - add_options.push_back(AddOption("Transform", "Constants", "VisualShaderNodeTransformConstant")); - add_options.push_back(AddOption("Texture", "Constants", "VisualShaderNodeTexture")); - add_options.push_back(AddOption("CubeMap", "Constants", "VisualShaderNodeCubeMap")); - add_options.push_back(AddOption("ScalarOp", "Operators", "VisualShaderNodeScalarOp")); - add_options.push_back(AddOption("VectorOp", "Operators", "VisualShaderNodeVectorOp")); - add_options.push_back(AddOption("ColorOp", "Operators", "VisualShaderNodeColorOp")); - add_options.push_back(AddOption("TransformMult", "Operators", "VisualShaderNodeTransformMult")); - add_options.push_back(AddOption("TransformVectorMult", "Operators", "VisualShaderNodeTransformVecMult")); - add_options.push_back(AddOption("ScalarFunc", "Functions", "VisualShaderNodeScalarFunc")); - add_options.push_back(AddOption("VectorFunc", "Functions", "VisualShaderNodeVectorFunc")); - add_options.push_back(AddOption("DotProduct", "Functions", "VisualShaderNodeDotProduct")); - add_options.push_back(AddOption("VectorLen", "Functions", "VisualShaderNodeVectorLen")); - add_options.push_back(AddOption("ScalarInterp", "Interpolation", "VisualShaderNodeScalarInterp")); - add_options.push_back(AddOption("VectorInterp", "Interpolation", "VisualShaderNodeVectorInterp")); - add_options.push_back(AddOption("VectorCompose", "Compose", "VisualShaderNodeVectorCompose")); - add_options.push_back(AddOption("TransformCompose", "Compose", "VisualShaderNodeTransformCompose")); - add_options.push_back(AddOption("VectorDecompose", "Decompose", "VisualShaderNodeVectorDecompose")); - add_options.push_back(AddOption("TransformDecompose", "Decompose", "VisualShaderNodeTransformDecompose")); - add_options.push_back(AddOption("Scalar", "Uniforms", "VisualShaderNodeScalarUniform")); - add_options.push_back(AddOption("Vector", "Uniforms", "VisualShaderNodeVec3Uniform")); - add_options.push_back(AddOption("Color", "Uniforms", "VisualShaderNodeColorUniform")); - add_options.push_back(AddOption("Transform", "Uniforms", "VisualShaderNodeTransformUniform")); - add_options.push_back(AddOption("Texture", "Uniforms", "VisualShaderNodeTextureUniform")); - add_options.push_back(AddOption("CubeMap", "Uniforms", "VisualShaderNodeCubeMapUniform")); - add_options.push_back(AddOption("Input", "Inputs", "VisualShaderNodeInput")); + add_node->connect("pressed", this, "_show_members_dialog"); + + /////////////////////////////////////// + // SHADER NODES TREE + /////////////////////////////////////// + + VBoxContainer *members_vb = memnew(VBoxContainer); + members_vb->set_v_size_flags(SIZE_EXPAND_FILL); + + HBoxContainer *filter_hb = memnew(HBoxContainer); + members_vb->add_child(filter_hb); + + node_filter = memnew(LineEdit); + filter_hb->add_child(node_filter); + node_filter->connect("text_changed", this, "_member_filter_changed"); + node_filter->set_h_size_flags(SIZE_EXPAND_FILL); + node_filter->set_placeholder(TTR("Search")); + + tools = memnew(MenuButton); + filter_hb->add_child(tools); + tools->set_tooltip(TTR("Options")); + tools->get_popup()->connect("id_pressed", this, "_tools_menu_option"); + tools->get_popup()->add_item(TTR("Expand All"), EXPAND_ALL); + tools->get_popup()->add_item(TTR("Collapse All"), COLLAPSE_ALL); + + members = memnew(Tree); + members_vb->add_child(members); + members->set_drag_forwarding(this); + members->set_h_size_flags(SIZE_EXPAND_FILL); + members->set_v_size_flags(SIZE_EXPAND_FILL); + members->set_hide_root(true); + members->set_allow_reselect(true); + members->set_hide_folding(false); + members->set_custom_minimum_size(Size2(180 * EDSCALE, 200 * EDSCALE)); + members->connect("item_selected", this, "_member_selected"); + members->connect("nothing_selected", this, "_member_unselected"); + members->connect("gui_input", this, "_member_gui_input"); + + Label *desc_label = memnew(Label); + members_vb->add_child(desc_label); + desc_label->set_text(TTR("Description:")); + + node_desc = memnew(RichTextLabel); + members_vb->add_child(node_desc); + node_desc->set_h_size_flags(SIZE_EXPAND_FILL); + node_desc->set_v_size_flags(SIZE_FILL); + node_desc->set_custom_minimum_size(Size2(0, 70 * EDSCALE)); + + members_dialog = memnew(ConfirmationDialog); + members_dialog->set_title(TTR("Create Shader Node")); + members_dialog->add_child(members_vb); + members_dialog->get_ok()->set_text(TTR("Create")); + members_dialog->get_ok()->connect("pressed", this, "_member_create"); + members_dialog->get_ok()->set_disabled(true); + members_dialog->set_resizable(true); + members_dialog->set_as_minsize(); + add_child(members_dialog); + + alert = memnew(AcceptDialog); + alert->set_as_minsize(); + alert->get_label()->set_autowrap(true); + alert->get_label()->set_align(Label::ALIGN_CENTER); + alert->get_label()->set_valign(Label::VALIGN_CENTER); + alert->get_label()->set_custom_minimum_size(Size2(400, 60) * EDSCALE); + add_child(alert); + + /////////////////////////////////////// + // SHADER NODES TREE OPTIONS + /////////////////////////////////////// + + // COLOR + + add_options.push_back(AddOption("ColorFunc", "Color", "Common", "VisualShaderNodeColorFunc", TTR("Color function."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ColorOp", "Color", "Common", "VisualShaderNodeColorOp", TTR("Color operator."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + + add_options.push_back(AddOption("Grayscale", "Color", "Functions", "VisualShaderNodeColorFunc", TTR("Grayscale function."), VisualShaderNodeColorFunc::FUNC_GRAYSCALE, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("HSV2RGB", "Color", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts HSV vector to RGB equivalent."), VisualShaderNodeVectorFunc::FUNC_HSV2RGB, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("RGB2HSV", "Color", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts RGB vector to HSV equivalent."), VisualShaderNodeVectorFunc::FUNC_RGB2HSV, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Sepia", "Color", "Functions", "VisualShaderNodeColorFunc", TTR("Sepia function."), VisualShaderNodeColorFunc::FUNC_SEPIA, VisualShaderNode::PORT_TYPE_VECTOR)); + + add_options.push_back(AddOption("Burn", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Burn operator."), VisualShaderNodeColorOp::OP_BURN, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Darken", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Darken operator."), VisualShaderNodeColorOp::OP_DARKEN, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Difference", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Difference operator."), VisualShaderNodeColorOp::OP_DIFFERENCE, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Dodge", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Dodge operator."), VisualShaderNodeColorOp::OP_DODGE, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("HardLight", "Color", "Operators", "VisualShaderNodeColorOp", TTR("HardLight operator"), VisualShaderNodeColorOp::OP_HARD_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Lighten", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Lighten operator."), VisualShaderNodeColorOp::OP_LIGHTEN, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Overlay", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Overlay operator."), VisualShaderNodeColorOp::OP_OVERLAY, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Screen", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Screen operator."), VisualShaderNodeColorOp::OP_SCREEN, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("SoftLight", "Color", "Operators", "VisualShaderNodeColorOp", TTR("SoftLight operator."), VisualShaderNodeColorOp::OP_SOFT_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR)); + + add_options.push_back(AddOption("ColorConstant", "Color", "Variables", "VisualShaderNodeColorConstant", TTR("Color constant."), -1, VisualShaderNode::PORT_TYPE_COLOR)); + add_options.push_back(AddOption("ColorUniform", "Color", "Variables", "VisualShaderNodeColorUniform", TTR("Color uniform."), -1, VisualShaderNode::PORT_TYPE_COLOR)); + + // BOOLEAN + + add_options.push_back(AddOption("BooleanConstant", "Boolean", "Variables", "VisualShaderNodeBooleanConstant", TTR("Boolean constant."), -1, VisualShaderNode::PORT_TYPE_BOOLEAN)); + add_options.push_back(AddOption("BooleanUniform", "Boolean", "Variables", "VisualShaderNodeBooleanUniform", TTR("Boolean uniform."), -1, VisualShaderNode::PORT_TYPE_BOOLEAN)); + + // INPUT + + add_options.push_back(AddOption("Camera", "Input", "All", "VisualShaderNodeInput", TTR("'camera' input parameter for all shader modes."), "camera", VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("InvCamera", "Input", "All", "VisualShaderNodeInput", TTR("'inv_camera' input parameter for all shader modes."), "inv_camera", VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("InvProjection", "Input", "All", "VisualShaderNodeInput", TTR("'inv_projection' input parameter for all shader modes."), "inv_projection", VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("Normal", "Input", "All", "VisualShaderNodeInput", TTR("'normal' input parameter for all shader modes."), "normal", VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Projection", "Input", "All", "VisualShaderNodeInput", TTR("'projection' input parameter for all shader modes."), "projection", VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", TTR("'time' input parameter for all shader modes."), "time", VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("ViewportSize", "Input", "All", "VisualShaderNodeInput", TTR("'viewport_size' input parameter for all shader modes."), "viewport_size", VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("World", "Input", "All", "VisualShaderNodeInput", TTR("'world' input parameter for all shader modes."), "world", VisualShaderNode::PORT_TYPE_TRANSFORM)); + + add_options.push_back(AddOption("Input", "Input", "Common", "VisualShaderNodeInput", TTR("Input parameter."))); + + add_options.push_back(AddOption("Alpha", "Input", "Fragment", "VisualShaderNodeInput", TTR("'alpha' input parameter for fragment shader mode."), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT)); + add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", TTR("'binormal' input parameter for fragment shader mode."), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT)); + add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", TTR("'color' input parameter for fragment shader mode."), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT)); + add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", TTR("'fragcoord' input parameter for fragment shader mode."), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT)); + add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", TTR("'point_coord' input parameter for fragment shader mode."), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT)); + add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", TTR("'screen_uv' input parameter for fragment shader mode."), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT)); + add_options.push_back(AddOption("Side", "Input", "Fragment", "VisualShaderNodeInput", TTR("'side' input parameter for fragment shader mode."), "side", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT)); + add_options.push_back(AddOption("Tangent", "Input", "Fragment", "VisualShaderNodeInput", TTR("'tangent' input parameter for fragment shader mode."), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT)); + add_options.push_back(AddOption("UV", "Input", "Fragment", "VisualShaderNodeInput", TTR("'uv' input parameter for fragment shader mode."), "uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT)); + add_options.push_back(AddOption("UV2", "Input", "Fragment", "VisualShaderNodeInput", TTR("'uv2' input parameter for fragment shader mode."), "uv2", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT)); + add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", TTR("'vertex' input parameter for fragment shader mode."), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT)); + add_options.push_back(AddOption("View", "Input", "Fragment", "VisualShaderNodeInput", TTR("'view' input parameter for fragment shader mode."), "view", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT)); + + add_options.push_back(AddOption("Albedo", "Input", "Light", "VisualShaderNodeInput", TTR("'albedo' input parameter for light shader mode."), "albedo", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("Attenuation", "Input", "Light", "VisualShaderNodeInput", TTR("'attenuation' input parameter for light shader mode."), "attenuation", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("Diffuse", "Input", "Light", "VisualShaderNodeInput", TTR("'diffuse' input parameter for light shader mode."), "diffuse", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", TTR("'fragcoord' input parameter for light shader mode."), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", TTR("'light' input parameter for light shader mode."), "light", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", TTR("'light_color' input parameter for light shader mode."), "light_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("Roughness", "Input", "Light", "VisualShaderNodeInput", TTR("'roughness' input parameter for light shader mode."), "roughness", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("Specular", "Input", "Light", "VisualShaderNodeInput", TTR("'specular' input parameter for light shader mode."), "specular", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("Transmission", "Input", "Light", "VisualShaderNodeInput", TTR("'transmission' input parameter for light shader mode."), "transmission", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("View", "Input", "Light", "VisualShaderNodeInput", TTR("'view' input parameter for light shader mode."), "view", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT)); + + add_options.push_back(AddOption("Alpha", "Input", "Vertex", "VisualShaderNodeInput", TTR("'alpha' input parameter for vertex shader mode."), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX)); + add_options.push_back(AddOption("Binormal", "Input", "Vertex", "VisualShaderNodeInput", TTR("'binormal' input parameter for vertex shader mode."), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX)); + add_options.push_back(AddOption("Color", "Input", "Vertex", "VisualShaderNodeInput", TTR("'color' input parameter for vertex shader mode."), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX)); + add_options.push_back(AddOption("ModelView", "Input", "Vertex", "VisualShaderNodeInput", TTR("'modelview' input parameter for vertex shader mode."), "modelview", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX)); + add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", TTR("'point_size' input parameter for vertex shader mode."), "point_size", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX)); + add_options.push_back(AddOption("Tangent", "Input", "Vertex", "VisualShaderNodeInput", TTR("'tangent' input parameter for vertex shader mode."), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX)); + add_options.push_back(AddOption("UV", "Input", "Vertex", "VisualShaderNodeInput", TTR("'uv' input parameter for vertex shader mode."), "uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX)); + add_options.push_back(AddOption("UV2", "Input", "Vertex", "VisualShaderNodeInput", TTR("'uv2' input parameter for vertex shader mode."), "uv2", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX)); + add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", TTR("'vertex' input parameter for vertex shader mode."), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX)); + + // SCALAR + + add_options.push_back(AddOption("ScalarFunc", "Scalar", "Common", "VisualShaderNodeScalarFunc", TTR("Scalar function."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("ScalarOp", "Scalar", "Common", "VisualShaderNodeScalarOp", TTR("Scalar operator."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + + add_options.push_back(AddOption("Abs", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the absolute value of the parameter."), VisualShaderNodeScalarFunc::FUNC_ABS, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("ACos", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the arc-cosine of the parameter."), VisualShaderNodeScalarFunc::FUNC_ACOS, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("ACosH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("(GLES3 only) Returns the inverse hyperbolic cosine of the parameter."), VisualShaderNodeScalarFunc::FUNC_ACOSH, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("ASin", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the arc-sine of the parameter."), VisualShaderNodeScalarFunc::FUNC_ASIN, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("ASinH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("(GLES3 only) Returns the inverse hyperbolic sine of the parameter."), VisualShaderNodeScalarFunc::FUNC_ASINH, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("ATan", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the arc-tangent of the parameter."), VisualShaderNodeScalarFunc::FUNC_ATAN, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("ATan2", "Scalar", "Functions", "VisualShaderNodeScalarOp", TTR("Returns the arc-tangent of the parameters."), VisualShaderNodeScalarOp::OP_ATAN2, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("ATanH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("(GLES3 only) Returns the inverse hyperbolic tangent of the parameter."), VisualShaderNodeScalarFunc::FUNC_ATANH, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Ceil", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), VisualShaderNodeScalarFunc::FUNC_CEIL, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Clamp", "Scalar", "Functions", "VisualShaderNodeScalarClamp", TTR("Constrains a value to lie between two further values."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Cos", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the cosine of the parameter."), VisualShaderNodeScalarFunc::FUNC_COS, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("CosH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("(GLES3 only) Returns the hyperbolic cosine of the parameter."), VisualShaderNodeScalarFunc::FUNC_COSH, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Degrees", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Converts a quantity in radians to degrees."), VisualShaderNodeScalarFunc::FUNC_DEGREES, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Exp", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Base-e Exponential."), VisualShaderNodeScalarFunc::FUNC_EXP, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Exp2", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Base-2 Exponential."), VisualShaderNodeScalarFunc::FUNC_EXP2, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Floor", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Finds the nearest integer less than or equal to the parameter."), VisualShaderNodeScalarFunc::FUNC_FLOOR, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Fract", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Computes the fractional part of the argument."), VisualShaderNodeScalarFunc::FUNC_FRAC, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("InverseSqrt", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the inverse of the square root of the parameter."), VisualShaderNodeScalarFunc::FUNC_INVERSE_SQRT, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Log", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Natural logarithm."), VisualShaderNodeScalarFunc::FUNC_LOG, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Log2", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Base-2 logarithm."), VisualShaderNodeScalarFunc::FUNC_LOG2, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Max", "Scalar", "Functions", "VisualShaderNodeScalarOp", TTR("Returns the greater of two values."), VisualShaderNodeScalarOp::OP_MAX, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Min", "Scalar", "Functions", "VisualShaderNodeScalarOp", TTR("Returns the lesser of two values."), VisualShaderNodeScalarOp::OP_MIN, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Mix", "Scalar", "Functions", "VisualShaderNodeScalarInterp", TTR("Linear interpolation between two scalars."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Negate", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the opposite value of the parameter."), VisualShaderNodeScalarFunc::FUNC_NEGATE, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Pow", "Scalar", "Functions", "VisualShaderNodeScalarOp", TTR("Returns the value of the first parameter raised to the power of the second."), VisualShaderNodeScalarOp::OP_POW, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Radians", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Converts a quantity in degrees to radians."), VisualShaderNodeScalarFunc::FUNC_RADIANS, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Reciprocal", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("1.0 / scalar"), VisualShaderNodeScalarFunc::FUNC_RECIPROCAL, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Round", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("(GLES3 only) Finds the nearest integer to the parameter."), VisualShaderNodeScalarFunc::FUNC_ROUND, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("RoundEven", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("(GLES3 only) Finds the nearest even integer to the parameter."), VisualShaderNodeScalarFunc::FUNC_ROUNDEVEN, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Saturate", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Clamps the value between 0.0 and 1.0."), VisualShaderNodeScalarFunc::FUNC_SATURATE, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Sign", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Extracts the sign of the parameter."), VisualShaderNodeScalarFunc::FUNC_SIGN, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Sin", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the sine of the parameter."), VisualShaderNodeScalarFunc::FUNC_SIN, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("SinH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("(GLES3 only) Returns the hyperbolic sine of the parameter."), VisualShaderNodeScalarFunc::FUNC_SINH, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Sqrt", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the square root of the parameter."), VisualShaderNodeScalarFunc::FUNC_SQRT, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("SmoothStep", "Scalar", "Functions", "VisualShaderNodeScalarSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), scalar(x) ).\n\nReturns 0.0 if 'x' is smaller then 'edge0' and 1.0 if x is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Step", "Scalar", "Functions", "VisualShaderNodeScalarOp", TTR("Step function( scalar(edge), scalar(x) ).\n\nReturns 0.0 if 'x' is smaller then 'edge' and otherwise 1.0."), VisualShaderNodeScalarOp::OP_STEP, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Tan", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the tangent of the parameter."), VisualShaderNodeScalarFunc::FUNC_TAN, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("TanH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("(GLES3 only) Returns the hyperbolic tangent of the parameter."), VisualShaderNodeScalarFunc::FUNC_TANH, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Trunc", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("(GLES3 only) Finds the truncated value of the parameter."), VisualShaderNodeScalarFunc::FUNC_TRUNC, VisualShaderNode::PORT_TYPE_SCALAR)); + + add_options.push_back(AddOption("Add", "Scalar", "Operators", "VisualShaderNodeScalarOp", TTR("Adds scalar to scalar."), VisualShaderNodeScalarOp::OP_ADD, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Divide", "Scalar", "Operators", "VisualShaderNodeScalarOp", TTR("Divides scalar by scalar."), VisualShaderNodeScalarOp::OP_DIV, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Multiply", "Scalar", "Operators", "VisualShaderNodeScalarOp", TTR("Multiplies scalar by scalar."), VisualShaderNodeScalarOp::OP_MUL, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Remainder", "Scalar", "Operators", "VisualShaderNodeScalarOp", TTR("Returns the remainder of the two scalars."), VisualShaderNodeScalarOp::OP_MOD, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Subtract", "Scalar", "Operators", "VisualShaderNodeScalarOp", TTR("Subtracts scalar from scalar."), VisualShaderNodeScalarOp::OP_SUB, VisualShaderNode::PORT_TYPE_SCALAR)); + + add_options.push_back(AddOption("ScalarConstant", "Scalar", "Variables", "VisualShaderNodeScalarConstant", TTR("Scalar constant."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("ScalarUniform", "Scalar", "Variables", "VisualShaderNodeScalarUniform", TTR("Scalar uniform."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + + // TEXTURES + + add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubeMap", TTR("Perform the cubic texture lookup."), -1, VisualShaderNode::PORT_TYPE_COLOR)); + add_options.push_back(AddOption("Texture", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the texture lookup."), -1, VisualShaderNode::PORT_TYPE_COLOR)); + + add_options.push_back(AddOption("CubeMapUniform", "Textures", "Variables", "VisualShaderNodeCubeMapUniform", TTR("Cubic texture uniform."), -1, VisualShaderNode::PORT_TYPE_COLOR)); + add_options.push_back(AddOption("TextureUniform", "Textures", "Variables", "VisualShaderNodeTextureUniform", TTR("2D texture uniform."), -1, VisualShaderNode::PORT_TYPE_COLOR)); + + // TRANSFORM + + add_options.push_back(AddOption("TransformFunc", "Transform", "Common", "VisualShaderNodeTransformFunc", TTR("Transform function."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); + + add_options.push_back(AddOption("OuterProduct", "Transform", "Composition", "VisualShaderNodeOuterProduct", TTR("(GLES3 only) Calculate the outer product of a pair of vectors.\n\nOuterProduct treats the first parameter 'c' as a column vector (matrix with one column) and the second parameter 'r' as a row vector (matrix with one row) and does a linear algebraic matrix multiply 'c * r', yielding a matrix whose number of rows is the number of components in 'c' and whose number of columns is the number of components in 'r'."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("TransformCompose", "Transform", "Composition", "VisualShaderNodeTransformCompose", TTR("Composes transform from four vectors."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("TransformDecompose", "Transform", "Composition", "VisualShaderNodeTransformDecompose", TTR("Decomposes transform to four vectors."))); + + add_options.push_back(AddOption("Determinant", "Transform", "Functions", "VisualShaderNodeDeterminant", TTR("(GLES3 only) Calculates the determinant of a transform."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Inverse", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("(GLES3 only) Calculates the inverse of a transform."), VisualShaderNodeTransformFunc::FUNC_INVERSE, VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("Transpose", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("(GLES3 only) Calculates the transpose of a transform."), VisualShaderNodeTransformFunc::FUNC_TRANSPOSE, VisualShaderNode::PORT_TYPE_TRANSFORM)); + + add_options.push_back(AddOption("TransformMult", "Transform", "Operators", "VisualShaderNodeTransformMult", TTR("Multiplies transform by transform."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("TransformVectorMult", "Transform", "Operators", "VisualShaderNodeTransformVecMult", TTR("Multiplies vector by transform."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + + add_options.push_back(AddOption("TransformConstant", "Transform", "Variables", "VisualShaderNodeTransformConstant", TTR("Transform constant."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("TransformUniform", "Transform", "Variables", "VisualShaderNodeTransformUniform", TTR("Transform uniform."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); + + // VECTOR + + add_options.push_back(AddOption("VectorFunc", "Vector", "Common", "VisualShaderNodeVectorFunc", TTR("Vector function."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("VectorOp", "Vector", "Common", "VisualShaderNodeVectorOp", TTR("Vector operator."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + + add_options.push_back(AddOption("VectorCompose", "Vector", "Composition", "VisualShaderNodeVectorCompose", TTR("Composes vector from three scalars."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("VectorDecompose", "Vector", "Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes vector to three scalars."))); + + add_options.push_back(AddOption("Abs", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the absolute value of the parameter."), VisualShaderNodeVectorFunc::FUNC_ABS, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ACos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-cosine of the parameter."), VisualShaderNodeVectorFunc::FUNC_ACOS, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ACosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("(GLES3 only) Returns the inverse hyperbolic cosine of the parameter."), VisualShaderNodeVectorFunc::FUNC_ACOSH, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ASin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-sine of the parameter."), VisualShaderNodeVectorFunc::FUNC_ASIN, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ASinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("(GLES3 only) Returns the inverse hyperbolic sine of the parameter."), VisualShaderNodeVectorFunc::FUNC_ASINH, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ATan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-tangent of the parameter."), VisualShaderNodeVectorFunc::FUNC_ATAN, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ATan2", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the arc-tangent of the parameters."), VisualShaderNodeVectorOp::OP_ATAN2, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("ATanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("(GLES3 only) Returns the inverse hyperbolic tangent of the parameter."), VisualShaderNodeVectorFunc::FUNC_ATANH, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Ceil", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), VisualShaderNodeVectorFunc::FUNC_CEIL, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Clamp", "Vector", "Functions", "VisualShaderNodeVectorClamp", TTR("Constrains a value to lie between two further values."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Cos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the cosine of the parameter."), VisualShaderNodeVectorFunc::FUNC_COS, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("CosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("(GLES3 only) Returns the hyperbolic cosine of the parameter."), VisualShaderNodeVectorFunc::FUNC_COSH, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Cross", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Calculates the cross product of two vectors."), VisualShaderNodeVectorOp::OP_CROSS, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Degrees", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in radians to degrees."), VisualShaderNodeVectorFunc::FUNC_DEGREES, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Distance", "Vector", "Functions", "VisualShaderNodeVectorDistance", TTR("Returns the distance between two points."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Dot", "Vector", "Functions", "VisualShaderNodeDotProduct", TTR("Calculates the dot product of two vectors."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Exp", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-e Exponential."), VisualShaderNodeVectorFunc::FUNC_EXP, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Exp2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 Exponential."), VisualShaderNodeVectorFunc::FUNC_EXP2, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("FaceForward", "Vector", "Functions", "VisualShaderNodeFaceForward", TTR("Returns a vector that points in the same direction as a reference vector. The function has three vector parameters : N, the vector to orient, I, the incident vector, and Nref, the reference vector. If the dot product of I and Nref is smaller than zero the return value is N. Otherwise -N is returned."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Floor", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer less than or equal to the parameter."), VisualShaderNodeVectorFunc::FUNC_FLOOR, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Fract", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Computes the fractional part of the argument."), VisualShaderNodeVectorFunc::FUNC_FRAC, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("InverseSqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse of the square root of the parameter."), VisualShaderNodeVectorFunc::FUNC_INVERSE_SQRT, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Length", "Vector", "Functions", "VisualShaderNodeVectorLen", TTR("Calculates the length of a vector."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Log", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Natural logarithm."), VisualShaderNodeVectorFunc::FUNC_LOG, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Log2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 logarithm."), VisualShaderNodeVectorFunc::FUNC_LOG2, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Max", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the greater of two values."), VisualShaderNodeVectorOp::OP_MAX, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Min", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), VisualShaderNodeVectorOp::OP_MIN, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Mix", "Vector", "Functions", "VisualShaderNodeVectorInterp", TTR("Linear interpolation between two vectors."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Negate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), VisualShaderNodeVectorFunc::FUNC_NEGATE, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Normalize", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), VisualShaderNodeVectorFunc::FUNC_NORMALIZE, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Pow", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the value of the first parameter raised to the power of the second."), VisualShaderNodeVectorOp::OP_POW, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Radians", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in degrees to radians."), VisualShaderNodeVectorFunc::FUNC_RADIANS, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Reflect", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns a vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Refract", "Vector", "Functions", "VisualShaderNodeVectorRefract", TTR("Returns a vector that points in the direction of refraction."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("(GLES3 only) Finds the nearest integer to the parameter."), VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("RoundEven", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("(GLES3 only) Finds the nearest even integer to the parameter."), VisualShaderNodeVectorFunc::FUNC_ROUNDEVEN, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Saturate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Clamps the value between 0.0 and 1.0."), VisualShaderNodeVectorFunc::FUNC_SATURATE, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Sign", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Extracts the sign of the parameter."), VisualShaderNodeVectorFunc::FUNC_SIGN, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Sin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the sine of the parameter."), VisualShaderNodeVectorFunc::FUNC_SIN, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("SinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("(GLES3 only) Returns the hyperbolic sine of the parameter."), VisualShaderNodeVectorFunc::FUNC_SINH, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Sqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the square root of the parameter."), VisualShaderNodeVectorFunc::FUNC_SQRT, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("SmoothStep", "Vector", "Functions", "VisualShaderNodeVectorSmoothStep", TTR("SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller then 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("SmoothStepS", "Vector", "Functions", "VisualShaderNodeVectorScalarSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller then 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Step", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Step function( vector(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller then 'edge' and otherwise 1.0."), VisualShaderNodeVectorOp::OP_STEP, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("StepS", "Vector", "Functions", "VisualShaderNodeVectorScalarStep", TTR("Step function( scalar(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller then 'edge' and otherwise 1.0."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Tan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the tangent of the parameter."), VisualShaderNodeVectorFunc::FUNC_TAN, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("TanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("(GLES3 only) Returns the hyperbolic tangent of the parameter."), VisualShaderNodeVectorFunc::FUNC_TANH, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Trunc", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("(GLES3 only) Finds the truncated value of the parameter."), VisualShaderNodeVectorFunc::FUNC_TRUNC, VisualShaderNode::PORT_TYPE_VECTOR)); + + add_options.push_back(AddOption("Add", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Adds vector to vector."), VisualShaderNodeVectorOp::OP_ADD, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Divide", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Divides vector by vector."), VisualShaderNodeVectorOp::OP_DIV, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Multiply", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Multiplies vector by vector."), VisualShaderNodeVectorOp::OP_MUL, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Remainder", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Returns the remainder of the two vectors."), VisualShaderNodeVectorOp::OP_MOD, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("Subtract", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Subtracts vector from vector."), VisualShaderNodeVectorOp::OP_SUB, VisualShaderNode::PORT_TYPE_VECTOR)); + + add_options.push_back(AddOption("VectorConstant", "Vector", "Variables", "VisualShaderNodeVec3Constant", TTR("Vector constant."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("VectorUniform", "Vector", "Variables", "VisualShaderNodeVec3Uniform", TTR("Vector uniform."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); + + // SPECIAL + + add_options.push_back(AddOption("ScalarDerivativeFunc", "Special", "Common", "VisualShaderNodeScalarDerivativeFunc", TTR("(GLES3 only) (Fragment/Light mode only) Scalar derivative function."), -1, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("VectorDerivativeFunc", "Special", "Common", "VisualShaderNodeVectorDerivativeFunc", TTR("(GLES3 only) (Fragment/Light mode only) Vector derivative function."), -1, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT)); + + add_options.push_back(AddOption("DdX", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(GLES3 only) (Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), VisualShaderNodeVectorDerivativeFunc::FUNC_X, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("DdXS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(GLES3 only) (Fragment/Light mode only) (Scalar) Derivative in 'x' using local differencing."), VisualShaderNodeScalarDerivativeFunc::FUNC_X, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("DdY", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(GLES3 only) (Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), VisualShaderNodeVectorDerivativeFunc::FUNC_Y, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("DdYS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(GLES3 only) (Fragment/Light mode only) (Scalar) Derivative in 'y' using local differencing."), VisualShaderNodeScalarDerivativeFunc::FUNC_Y, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("Sum", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(GLES3 only) (Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), VisualShaderNodeVectorDerivativeFunc::FUNC_SUM, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT)); + add_options.push_back(AddOption("SumS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(GLES3 only) (Fragment/Light mode only) (Scalar) Sum of absolute derivative in 'x' and 'y'."), VisualShaderNodeScalarDerivativeFunc::FUNC_SUM, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT)); + + ///////////////////////////////////////////////////////////////////// _update_options_menu(); @@ -940,9 +1645,10 @@ public: void setup(const Ref<VisualShaderNodeInput> &p_input) { input = p_input; - Ref<Texture> type_icon[3] = { + Ref<Texture> type_icon[4] = { EditorNode::get_singleton()->get_gui_base()->get_icon("float", "EditorIcons"), EditorNode::get_singleton()->get_gui_base()->get_icon("Vector3", "EditorIcons"), + EditorNode::get_singleton()->get_gui_base()->get_icon("bool", "EditorIcons"), EditorNode::get_singleton()->get_gui_base()->get_icon("Transform", "EditorIcons"), }; diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 2fb8a85d5b..2709d72931 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -60,7 +60,7 @@ class VisualShaderEditor : public VBoxContainer { Ref<VisualShader> visual_shader; GraphEdit *graph; - MenuButton *add_node; + ToolButton *add_node; OptionButton *edit_type; @@ -68,18 +68,59 @@ class VisualShaderEditor : public VBoxContainer { Label *error_label; UndoRedo *undo_redo; + Point2 saved_node_pos; + bool saved_node_pos_dirty; + + ConfirmationDialog *members_dialog; + MenuButton *tools; + + enum ToolsMenuOptions { + EXPAND_ALL, + COLLAPSE_ALL + }; + + Tree *members; + AcceptDialog *alert; + LineEdit *node_filter; + RichTextLabel *node_desc; + + void _tools_menu_option(int p_idx); + void _show_members_dialog(); void _update_graph(); struct AddOption { String name; String category; + String sub_category; String type; + String description; + int sub_func; + String sub_func_str; Ref<Script> script; - AddOption(const String &p_name = String(), const String &p_category = String(), const String &p_type = String()) { + int mode; + int return_type; + + AddOption(const String &p_name = String(), const String &p_category = String(), const String &p_sub_category = String(), const String &p_type = String(), const String &p_description = String(), int p_sub_func = -1, int p_return_type = -1, int p_mode = -1) { + name = p_name; + type = p_type; + category = p_category; + sub_category = p_sub_category; + description = p_description; + sub_func = p_sub_func; + return_type = p_return_type; + mode = p_mode; + } + + AddOption(const String &p_name, const String &p_category, const String &p_sub_category, const String &p_type, const String &p_description, const String &p_sub_func, int p_return_type = -1, int p_mode = -1) { name = p_name; type = p_type; category = p_category; + sub_category = p_sub_category; + description = p_description; + sub_func_str = p_sub_func; + return_type = p_return_type; + mode = p_mode; } }; @@ -87,7 +128,7 @@ class VisualShaderEditor : public VBoxContainer { void _draw_color_over_button(Object *obj, Color p_color); - void _add_node(int p_idx); + void _add_node(int p_idx, int p_op_idx = -1); void _update_options_menu(); static VisualShaderEditor *singleton; @@ -126,6 +167,18 @@ class VisualShaderEditor : public VBoxContainer { void _preview_select_port(int p_node, int p_port); void _input(const Ref<InputEvent> p_event); + void _member_gui_input(const Ref<InputEvent> p_event); + void _member_filter_changed(const String &p_text); + void _member_selected(); + void _member_unselected(); + void _member_create(); + + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); + bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; + void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); + + bool _is_available(int p_flags); + protected: void _notification(int p_what); static void _bind_methods(); |