Added pinning to voxel graph editor
This commit is contained in:
parent
cff51fbe89
commit
f81e64dd14
@ -28,6 +28,7 @@ Godot 4 is required from this version.
|
||||
- `VoxelGeneratorGraph`: editor: allow to change the axes on preview nodes 3D slices
|
||||
- `VoxelGeneratorGraph`: editor: replace existing connection if dragging from/to an input port having one already
|
||||
- `VoxelGeneratorGraph`: editor: creating noise and curve nodes now auto-create their resource instead of coming up null
|
||||
- `VoxelGeneratorGraph`: editor: added pin button to keep the graph editor shown even after deselecting the terrain.
|
||||
- `VoxelGeneratorGraph`: added `OutputSingleTexture` node for outputting a single texture index per voxel, as an alternative to weights. This is specific to smooth voxels.
|
||||
- `VoxelGeneratorGraph`: added math expression node
|
||||
- `VoxelGeneratorGraph`: added Pow and Powi nodes
|
||||
|
@ -28,6 +28,7 @@ namespace zylann::voxel {
|
||||
const char *VoxelGraphEditor::SIGNAL_NODE_SELECTED = "node_selected";
|
||||
const char *VoxelGraphEditor::SIGNAL_NOTHING_SELECTED = "nothing_selected";
|
||||
const char *VoxelGraphEditor::SIGNAL_NODES_DELETED = "nodes_deleted";
|
||||
const char *VoxelGraphEditor::SIGNAL_REGENERATE_REQUESTED = "regenerate_requested";
|
||||
|
||||
static NodePath to_node_path(StringName sn) {
|
||||
Vector<StringName> path;
|
||||
@ -88,6 +89,17 @@ VoxelGraphEditor::VoxelGraphEditor() {
|
||||
live_update_checkbox->connect("toggled", callable_mp(this, &VoxelGraphEditor::_on_live_update_toggled));
|
||||
toolbar->add_child(live_update_checkbox);
|
||||
|
||||
Control *spacer = memnew(Control);
|
||||
spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
toolbar->add_child(spacer);
|
||||
|
||||
_pin_button = memnew(Button);
|
||||
_pin_button->set_flat(true);
|
||||
_pin_button->set_toggle_mode(true);
|
||||
_pin_button->set_tooltip(TTR("Pin AnimationPlayer"));
|
||||
toolbar->add_child(_pin_button);
|
||||
//_pin_button->connect("pressed", callable_mp(this, &AnimationPlayerEditor::_pin_pressed));
|
||||
|
||||
vbox_container->add_child(toolbar);
|
||||
}
|
||||
|
||||
@ -195,6 +207,10 @@ void VoxelGraphEditor::_notification(int p_what) {
|
||||
case NOTIFICATION_VISIBILITY_CHANGED:
|
||||
set_process_internal(is_visible());
|
||||
break;
|
||||
|
||||
case NOTIFICATION_THEME_CHANGED:
|
||||
_pin_button->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons")));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,6 +387,10 @@ void VoxelGraphEditor::update_node_layout(uint32_t node_id) {
|
||||
}
|
||||
}
|
||||
|
||||
bool VoxelGraphEditor::is_pinned_hint() const {
|
||||
return _pin_button->is_pressed();
|
||||
}
|
||||
|
||||
static bool is_nothing_selected(GraphEdit *graph_edit) {
|
||||
for (int i = 0; i < graph_edit->get_child_count(); ++i) {
|
||||
GraphNode *node = Object::cast_to<GraphNode>(graph_edit->get_child(i));
|
||||
@ -660,12 +680,11 @@ void VoxelGraphEditor::update_previews(bool with_live_update) {
|
||||
if (hash != _last_output_graph_hash) {
|
||||
_last_output_graph_hash = hash;
|
||||
|
||||
// We could be editing the graph standalone with no terrain loaded
|
||||
if (_voxel_node != nullptr) {
|
||||
// Re-generate the terrain.
|
||||
// Only do that if the graph is valid.
|
||||
_voxel_node->restart_stream();
|
||||
}
|
||||
// Not calling into `_voxel_node` directly because the editor could be pinned and the terrain not actually
|
||||
// selected. In this situation the plugin may reset the node to null. But it is desirable for terrains
|
||||
// using the current graph to update if they are in the edited scene, so this may be delegated to the editor
|
||||
// plugin. There isn't enough context from here to do this cleanly.
|
||||
emit_signal(SIGNAL_REGENERATE_REQUESTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -983,6 +1002,7 @@ void VoxelGraphEditor::_bind_methods() {
|
||||
ADD_SIGNAL(MethodInfo(SIGNAL_NODE_SELECTED, PropertyInfo(Variant::INT, "node_id")));
|
||||
ADD_SIGNAL(MethodInfo(SIGNAL_NOTHING_SELECTED));
|
||||
ADD_SIGNAL(MethodInfo(SIGNAL_NODES_DELETED));
|
||||
ADD_SIGNAL(MethodInfo(SIGNAL_REGENERATE_REQUESTED));
|
||||
}
|
||||
|
||||
} // namespace zylann::voxel
|
||||
|
@ -8,6 +8,7 @@ class GraphEdit;
|
||||
class PopupMenu;
|
||||
class AcceptDialog;
|
||||
class UndoRedo;
|
||||
class Button;
|
||||
|
||||
namespace zylann::voxel {
|
||||
|
||||
@ -23,6 +24,7 @@ public:
|
||||
static const char *SIGNAL_NODE_SELECTED;
|
||||
static const char *SIGNAL_NOTHING_SELECTED;
|
||||
static const char *SIGNAL_NODES_DELETED;
|
||||
static const char *SIGNAL_REGENERATE_REQUESTED;
|
||||
|
||||
VoxelGraphEditor();
|
||||
|
||||
@ -38,6 +40,8 @@ public:
|
||||
// Rebuilds the node's internal controls, and updates GUI connections going to it from the graph.
|
||||
void update_node_layout(uint32_t node_id);
|
||||
|
||||
bool is_pinned_hint() const;
|
||||
|
||||
private:
|
||||
void _notification(int p_what);
|
||||
void _process(float delta);
|
||||
@ -95,6 +99,7 @@ private:
|
||||
VoxelGraphEditorShaderDialog *_shader_dialog = nullptr;
|
||||
bool _live_update_enabled = false;
|
||||
uint64_t _last_output_graph_hash = 0;
|
||||
Button *_pin_button = nullptr;
|
||||
|
||||
enum PreviewAxes { //
|
||||
PREVIEW_XY = 0,
|
||||
|
@ -41,6 +41,8 @@ VoxelGraphEditorPlugin::VoxelGraphEditorPlugin() {
|
||||
callable_mp(this, &VoxelGraphEditorPlugin::_on_graph_editor_nothing_selected));
|
||||
_graph_editor->connect(VoxelGraphEditor::SIGNAL_NODES_DELETED,
|
||||
callable_mp(this, &VoxelGraphEditorPlugin::_on_graph_editor_nodes_deleted));
|
||||
_graph_editor->connect(VoxelGraphEditor::SIGNAL_REGENERATE_REQUESTED,
|
||||
callable_mp(this, &VoxelGraphEditorPlugin::_on_graph_editor_regenerate_requested));
|
||||
_bottom_panel_button = add_control_to_bottom_panel(_graph_editor, TTR("Voxel Graph"));
|
||||
_bottom_panel_button->hide();
|
||||
|
||||
@ -87,6 +89,7 @@ void VoxelGraphEditorPlugin::edit(Object *p_object) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_voxel_node = voxel_node;
|
||||
_graph_editor->set_voxel_node(voxel_node);
|
||||
}
|
||||
|
||||
@ -96,13 +99,17 @@ void VoxelGraphEditorPlugin::make_visible(bool visible) {
|
||||
make_bottom_panel_item_visible(_graph_editor);
|
||||
|
||||
} else {
|
||||
_bottom_panel_button->hide();
|
||||
_voxel_node = nullptr;
|
||||
_graph_editor->set_voxel_node(nullptr);
|
||||
|
||||
// TODO Awful hack to handle the nonsense happening in `_on_graph_editor_node_selected`
|
||||
if (!_deferred_visibility_scheduled) {
|
||||
_deferred_visibility_scheduled = true;
|
||||
call_deferred("_hide_deferred");
|
||||
if (!_graph_editor->is_pinned_hint()) {
|
||||
_bottom_panel_button->hide();
|
||||
|
||||
// TODO Awful hack to handle the nonsense happening in `_on_graph_editor_node_selected`
|
||||
if (!_deferred_visibility_scheduled) {
|
||||
_deferred_visibility_scheduled = true;
|
||||
call_deferred("_hide_deferred");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,6 +159,38 @@ void VoxelGraphEditorPlugin::_on_graph_editor_nodes_deleted() {
|
||||
get_editor_interface()->inspect_object(*graph);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void for_each_node(Node *parent, F action) {
|
||||
action(parent);
|
||||
for (int i = 0; i < parent->get_child_count(); ++i) {
|
||||
for_each_node(parent->get_child(i), action);
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelGraphEditorPlugin::_on_graph_editor_regenerate_requested() {
|
||||
// We could be editing the graph standalone with no terrain loaded
|
||||
if (_voxel_node != nullptr) {
|
||||
// Re-generate the selected terrain.
|
||||
_voxel_node->restart_stream();
|
||||
|
||||
} else {
|
||||
// The node is not selected, but it might be in the tree
|
||||
Node *root = get_editor_interface()->get_edited_scene_root();
|
||||
|
||||
if (root != nullptr) {
|
||||
Ref<VoxelGeneratorGraph> generator = _graph_editor->get_graph();
|
||||
ERR_FAIL_COND(generator.is_null());
|
||||
|
||||
for_each_node(root, [&generator](Node *node) {
|
||||
VoxelNode *vnode = Object::cast_to<VoxelNode>(node);
|
||||
if (vnode != nullptr && vnode->get_generator() == generator) {
|
||||
vnode->restart_stream();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelGraphEditorPlugin::_bind_methods() {
|
||||
// ClassDB::bind_method(D_METHOD("_on_graph_editor_node_selected", "node_id"),
|
||||
// &VoxelGraphEditorPlugin::_on_graph_editor_node_selected);
|
||||
|
@ -6,6 +6,7 @@
|
||||
namespace zylann::voxel {
|
||||
|
||||
class VoxelGraphEditor;
|
||||
class VoxelNode;
|
||||
|
||||
class VoxelGraphEditorPlugin : public EditorPlugin {
|
||||
GDCLASS(VoxelGraphEditorPlugin, EditorPlugin)
|
||||
@ -20,6 +21,7 @@ private:
|
||||
void _on_graph_editor_node_selected(uint32_t node_id);
|
||||
void _on_graph_editor_nothing_selected();
|
||||
void _on_graph_editor_nodes_deleted();
|
||||
void _on_graph_editor_regenerate_requested();
|
||||
void _hide_deferred();
|
||||
|
||||
static void _bind_methods();
|
||||
@ -27,6 +29,7 @@ private:
|
||||
VoxelGraphEditor *_graph_editor = nullptr;
|
||||
Button *_bottom_panel_button = nullptr;
|
||||
bool _deferred_visibility_scheduled = false;
|
||||
VoxelNode *_voxel_node = nullptr;
|
||||
};
|
||||
|
||||
} // namespace zylann::voxel
|
||||
|
Loading…
x
Reference in New Issue
Block a user