From f673a148c7104b3aaee4b1332a3631ac15f5f769 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 5 Dec 2007 07:31:01 +0000 Subject: Add preliminary mutation to machina (only random edge probability mutation so far). git-svn-id: http://svn.drobilla.net/lad/machina@951 a436a847-0d15-0410-975c-d299462d15a1 --- src/engine/Machine.cpp | 42 +++- src/engine/MachineBuilder.cpp | 14 +- src/engine/MachineMutation.cpp | 55 +++++ src/engine/Makefile.am | 1 + src/engine/Node.cpp | 36 ++- src/engine/machina/Machine.hpp | 5 +- src/engine/machina/MachineMutation.hpp | 37 +++ src/engine/machina/Makefile.am | 1 + src/engine/machina/Node.hpp | 24 +- src/engine/machina/Schrodinbit.hpp | 45 ++++ src/gui/EdgeView.hpp | 2 +- src/gui/MachinaCanvas.cpp | 16 +- src/gui/MachinaCanvas.hpp | 1 + src/gui/MachinaGUI.cpp | 35 +++ src/gui/MachinaGUI.hpp | 10 +- src/gui/machina.glade | 407 +++++++++++++++++++-------------- 16 files changed, 512 insertions(+), 219 deletions(-) create mode 100644 src/engine/MachineMutation.cpp create mode 100644 src/engine/machina/MachineMutation.hpp create mode 100644 src/engine/machina/Schrodinbit.hpp (limited to 'src') diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp index 2033b5e..7a99b58 100644 --- a/src/engine/Machine.cpp +++ b/src/engine/Machine.cpp @@ -53,6 +53,34 @@ Machine::set_sink(SharedPtr sink) { _sink = sink; } + + +/** Always returns a node, unless there are none */ +SharedPtr +Machine::random_node() +{ + size_t i = rand() % _nodes.size(); + + // FIXME: O(n) worst case :( + for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n, --i) + if (i == 0) + return *n; + + return SharedPtr(); +} + + +/** May return NULL even if edges exist (with low probability) */ +SharedPtr +Machine::random_edge() +{ + SharedPtr tail = random_node(); + + for (size_t i = 0; i < _nodes.size() && tail->edges().empty(); ++i) + tail = random_node(); + + return tail->random_edge(); +} void @@ -69,7 +97,7 @@ Machine::remove_node(SharedPtr node) _nodes.erase(_nodes.find(node)); for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) - (*n)->remove_outgoing_edges_to(node); + (*n)->remove_edges_to(node); } @@ -170,8 +198,8 @@ Machine::exit_node(SharedPtr sink, const SharedPtr node) const double rand_normal = rand() / (double)RAND_MAX; // [0, 1] double range_min = 0; - for (Node::Edges::const_iterator s = node->outgoing_edges().begin(); - s != node->outgoing_edges().end(); ++s) { + for (Node::Edges::const_iterator s = node->edges().begin(); + s != node->edges().end(); ++s) { if (!(*s)->head()->is_active() && rand_normal > range_min @@ -187,8 +215,8 @@ Machine::exit_node(SharedPtr sink, const SharedPtr node) } else { - for (Node::Edges::const_iterator s = node->outgoing_edges().begin(); - s != node->outgoing_edges().end(); ++s) { + for (Node::Edges::const_iterator s = node->edges().begin(); + s != node->edges().end(); ++s) { const double rand_normal = rand() / (double)RAND_MAX; // [0, 1] @@ -328,8 +356,8 @@ Machine::write_state(Redland::Model& model) for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) { - for (Node::Edges::const_iterator e = (*n)->outgoing_edges().begin(); - e != (*n)->outgoing_edges().end(); ++e) { + for (Node::Edges::const_iterator e = (*n)->edges().begin(); + e != (*n)->edges().end(); ++e) { (*e)->write_state(model); diff --git a/src/engine/MachineBuilder.cpp b/src/engine/MachineBuilder.cpp index 1830ee6..fd53487 100644 --- a/src/engine/MachineBuilder.cpp +++ b/src/engine/MachineBuilder.cpp @@ -91,7 +91,7 @@ MachineBuilder::connect_nodes(SharedPtr m, SharedPtr delay_node; - if (is_delay_node(tail) && tail->outgoing_edges().size() == 0) { + if (is_delay_node(tail) && tail->edges().size() == 0) { // Tail is a delay node, just accumulate the time difference into it set_node_duration(tail, tail->duration() + head_start_time - tail_end_time); tail->add_outgoing_edge(SharedPtr(new Edge(tail, head))); @@ -133,7 +133,7 @@ MachineBuilder::event(Raul::BeatTime time_offset, // Results in patterns closes to what a human would choose if ( ! _poly_nodes.empty()) { for (PolyList::iterator j = _poly_nodes.begin(); j != _poly_nodes.end(); ++j) { - if (j->second->outgoing_edges().empty()) { + if (j->second->edges().empty()) { this_connect_node = j->second; this_connect_node_end_time = j->first + j->second->duration(); break; @@ -194,7 +194,7 @@ MachineBuilder::event(Raul::BeatTime time_offset, for (PolyList::iterator j = _poly_nodes.begin(); j != _poly_nodes.end(); ++j) { _machine->add_node(j->second); - if (j->second->outgoing_edges().size() == 0) + if (j->second->edges().size() == 0) connect_nodes(_machine, j->second, j->first + j->second->duration(), _connect_node, t); } @@ -207,11 +207,11 @@ MachineBuilder::event(Raul::BeatTime time_offset, // Trim useless delay node if possible (these appear after poly sections) if (is_delay_node(_connect_node) && _connect_node->duration() == 0 - && _connect_node->outgoing_edges().size() == 1 - && (*_connect_node->outgoing_edges().begin())->head() == resolved) { + && _connect_node->edges().size() == 1 + && (*_connect_node->edges().begin())->head() == resolved) { - _connect_node->outgoing_edges().clear(); - assert(_connect_node->outgoing_edges().empty()); + _connect_node->edges().clear(); + assert(_connect_node->edges().empty()); _connect_node->set_enter_action(resolved->enter_action()); _connect_node->set_exit_action(resolved->exit_action()); resolved->set_enter_action(SharedPtr()); diff --git a/src/engine/MachineMutation.cpp b/src/engine/MachineMutation.cpp new file mode 100644 index 0000000..6e98ee0 --- /dev/null +++ b/src/engine/MachineMutation.cpp @@ -0,0 +1,55 @@ +/* This file is part of Machina. + * Copyright (C) 2007 Dave Robillard + * + * Machina is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Machina is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include "machina/Edge.hpp" +#include "machina/Machine.hpp" +#include "machina/MachineMutation.hpp" + +using namespace std; + +namespace Machina { +namespace Mutation { + + +void +AddEdge::mutate(Machine& machine) +{ + cout << "ADD" << endl; +} + + +void +RemoveEdge::mutate(Machine& machine) +{ + cout << "REMOVE" << endl; +} + + +void +AdjustEdge::mutate(Machine& machine) +{ + SharedPtr edge = machine.random_edge(); + if (edge) + edge->set_probability(rand() / (float)RAND_MAX); +} + + +} // namespace Mutation +} // namespace Machina + diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am index 5e291c7..010affa 100644 --- a/src/engine/Makefile.am +++ b/src/engine/Makefile.am @@ -10,6 +10,7 @@ libmachina_la_SOURCES = \ Edge.cpp \ Action.cpp \ Machine.cpp \ + MachineMutation.cpp \ Loader.cpp \ MidiAction.cpp \ ActionFactory.cpp \ diff --git a/src/engine/Node.cpp b/src/engine/Node.cpp index 5a1ca85..fd784e5 100644 --- a/src/engine/Node.cpp +++ b/src/engine/Node.cpp @@ -35,6 +35,28 @@ Node::Node(BeatCount duration, bool initial) } +/** Always returns an edge, unless there are none */ +SharedPtr +Node::random_edge() +{ + SharedPtr ret; + if (_edges.empty()) + return ret; + + size_t i = rand() % _edges.size(); + + // FIXME: O(n) worst case :( + for (Edges::const_iterator e = _edges.begin(); e != _edges.end(); ++e, --i) { + if (i == 0) { + ret = *e; + break; + } + } + + return ret; +} + + void Node::set_selector(bool yn) { @@ -42,10 +64,10 @@ Node::set_selector(bool yn) if (yn) { double prob_sum = 0; - for (Edges::iterator i = _outgoing_edges.begin(); i != _outgoing_edges.end(); ++i) + for (Edges::iterator i = _edges.begin(); i != _edges.end(); ++i) prob_sum += (*i)->probability(); - for (Edges::iterator i = _outgoing_edges.begin(); i != _outgoing_edges.end(); ++i) + for (Edges::iterator i = _edges.begin(); i != _edges.end(); ++i) (*i)->set_probability((*i)->probability() / prob_sum); } _changed = true; @@ -101,26 +123,26 @@ Node::add_outgoing_edge(SharedPtr edge) { assert(edge->tail().lock().get() == this); - _outgoing_edges.push_back(edge); + _edges.push_back(edge); } void Node::remove_outgoing_edge(SharedPtr edge) { - _outgoing_edges.erase(_outgoing_edges.find(edge)); + _edges.erase(_edges.find(edge)); } void -Node::remove_outgoing_edges_to(SharedPtr node) +Node::remove_edges_to(SharedPtr node) { - for (Edges::iterator i = _outgoing_edges.begin(); i != _outgoing_edges.end() ; ) { + for (Edges::iterator i = _edges.begin(); i != _edges.end() ; ) { Edges::iterator next = i; ++next; if ((*i)->head() == node) - _outgoing_edges.erase(i); + _edges.erase(i); i = next; } diff --git a/src/engine/machina/Machine.hpp b/src/engine/machina/Machine.hpp index 626ef10..889dc1a 100644 --- a/src/engine/machina/Machine.hpp +++ b/src/engine/machina/Machine.hpp @@ -61,9 +61,12 @@ public: SharedPtr pending_learn() { return _pending_learn; } void clear_pending_learn() { _pending_learn.reset(); } - typedef Raul::List > Nodes; + typedef Raul::List< SharedPtr > Nodes; Nodes& nodes() { return _nodes; } + SharedPtr random_node(); + SharedPtr random_edge(); + void set_sink(SharedPtr sink); private: diff --git a/src/engine/machina/MachineMutation.hpp b/src/engine/machina/MachineMutation.hpp new file mode 100644 index 0000000..34eda30 --- /dev/null +++ b/src/engine/machina/MachineMutation.hpp @@ -0,0 +1,37 @@ +/* This file is part of Machina. + * Copyright (C) 2007 Dave Robillard + * + * Machina is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Machina is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef MACHINA_MACHINE_MUTATION_HPP +#define MACHINA_MACHINE_MUTATION_HPP + +namespace Machina { + +class Machine; + +namespace Mutation { + +struct Mutation { virtual void mutate(Machine& machine) = 0; }; + +struct AddEdge { static void mutate(Machine& machine); }; +struct RemoveEdge { static void mutate(Machine& machine); }; +struct AdjustEdge { static void mutate(Machine& machine); }; + +} // namespace Mutation + +} // namespace Machina + +#endif // MACHINA_MACHINE_MUTATION_HPP diff --git a/src/engine/machina/Makefile.am b/src/engine/machina/Makefile.am index 65ea295..de99845 100644 --- a/src/engine/machina/Makefile.am +++ b/src/engine/machina/Makefile.am @@ -11,6 +11,7 @@ libmachinainclude_HEADERS = \ Loader.hpp \ Machine.hpp \ MachineBuilder.hpp \ + MachineMutation.hpp \ MidiAction.hpp \ Node.hpp \ Recorder.hpp \ diff --git a/src/engine/machina/Node.hpp b/src/engine/machina/Node.hpp index 041f443..a916eb6 100644 --- a/src/engine/machina/Node.hpp +++ b/src/engine/machina/Node.hpp @@ -24,6 +24,7 @@ #include #include #include "Action.hpp" +#include "Schrodinbit.hpp" namespace Machina { @@ -57,7 +58,7 @@ public: void add_outgoing_edge(SharedPtr edge); void remove_outgoing_edge(SharedPtr edge); - void remove_outgoing_edges_to(SharedPtr node); + void remove_edges_to(SharedPtr node); void write_state(Redland::Model& model); @@ -71,23 +72,16 @@ public: bool is_selector() const { return _is_selector; } void set_selector(bool i); - /// Schroedinger's flag - inline bool changed() { - if (_changed) { - _changed = false; - return true; - } else { - return false; - } - } - - void set_changed() { _changed = true; } + inline bool changed() { return _changed; } + inline void set_changed() { _changed = true; } typedef Raul::List > Edges; - Edges& outgoing_edges() { return _outgoing_edges; } + Edges& edges() { return _edges; } + + SharedPtr random_edge(); private: - bool _changed; + Schrodinbit _changed; bool _is_initial; bool _is_selector; bool _is_active; @@ -95,7 +89,7 @@ private: BeatCount _duration; SharedPtr _enter_action; SharedPtr _exit_action; - Edges _outgoing_edges; + Edges _edges; }; diff --git a/src/engine/machina/Schrodinbit.hpp b/src/engine/machina/Schrodinbit.hpp new file mode 100644 index 0000000..6065cfc --- /dev/null +++ b/src/engine/machina/Schrodinbit.hpp @@ -0,0 +1,45 @@ +/* This file is part of Machina. + * Copyright (C) 2007 Dave Robillard + * + * Machina is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Machina is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef SCHRODINBIT_HPP +#define SCHRODINBIT_HPP + + +/** A flag which becomes false when it's value is observed + */ +class Schrodinbit { +public: + Schrodinbit() : _flag(false) {} + + inline operator bool() { + const bool ret = _flag; + _flag = false; + return ret; + } + + inline bool operator=(bool flag) { + _flag = flag; + return flag; + } + +private: + bool _flag; +}; + + +#endif // SCHRODINBIT_HPP + diff --git a/src/gui/EdgeView.hpp b/src/gui/EdgeView.hpp index 2555e4a..2b04324 100644 --- a/src/gui/EdgeView.hpp +++ b/src/gui/EdgeView.hpp @@ -34,11 +34,11 @@ public: SharedPtr edge() { return _edge; } void show_label(bool show); + void update(); virtual double length_hint() const; private: - void update(); bool on_event(GdkEvent* ev); SharedPtr _edge; diff --git a/src/gui/MachinaCanvas.cpp b/src/gui/MachinaCanvas.cpp index e899a64..8ed9e40 100644 --- a/src/gui/MachinaCanvas.cpp +++ b/src/gui/MachinaCanvas.cpp @@ -131,7 +131,7 @@ void MachinaCanvas::disconnect_node(boost::shared_ptr src, boost::shared_ptr head) { - src->node()->remove_outgoing_edges_to(head->node()); + src->node()->remove_edges_to(head->node()); remove_connection(src, head); } @@ -177,8 +177,8 @@ MachinaCanvas::build(SharedPtr machine) if (!view) continue; - for (Machina::Node::Edges::const_iterator e = view->node()->outgoing_edges().begin(); - e != view->node()->outgoing_edges().end(); ++e) { + for (Machina::Node::Edges::const_iterator e = view->node()->edges().begin(); + e != view->node()->edges().end(); ++e) { SharedPtr head_view = views[(*e)->head()]; if (!head_view) { @@ -201,3 +201,13 @@ MachinaCanvas::build(SharedPtr machine) } +void +MachinaCanvas::update_edges() +{ + for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) { + SharedPtr edge = PtrCast(*i); + if (edge) + edge->update(); + } +} + diff --git a/src/gui/MachinaCanvas.hpp b/src/gui/MachinaCanvas.hpp index 63c88fd..631957e 100644 --- a/src/gui/MachinaCanvas.hpp +++ b/src/gui/MachinaCanvas.hpp @@ -41,6 +41,7 @@ public: SharedPtr port2); void build(SharedPtr machine); + void update_edges(); ArtVpathDash* selector_dash() { return _selector_dash; } diff --git a/src/gui/MachinaGUI.cpp b/src/gui/MachinaGUI.cpp index 2e383ec..6c94211 100644 --- a/src/gui/MachinaGUI.cpp +++ b/src/gui/MachinaGUI.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "GladeXml.hpp" #include "MachinaGUI.hpp" @@ -31,6 +32,8 @@ #include "NodeView.hpp" #include "EdgeView.hpp" +using namespace Machina; + MachinaGUI::MachinaGUI(SharedPtr engine) : _refresh(false), @@ -69,6 +72,9 @@ MachinaGUI::MachinaGUI(SharedPtr engine) xml->get_widget("zoom_normal_but", _zoom_normal_button); xml->get_widget("zoom_full_but", _zoom_full_button); xml->get_widget("arrange_but", _arrange_button); + xml->get_widget("add_edge_but", _add_edge_button); + xml->get_widget("remove_edge_but", _remove_edge_button); + xml->get_widget("adjust_edge_but", _adjust_edge_button); _canvas_scrolledwindow->add(*_canvas); _canvas_scrolledwindow->signal_event().connect(sigc::mem_fun(this, @@ -121,6 +127,13 @@ MachinaGUI::MachinaGUI(SharedPtr engine) sigc::mem_fun(this, &MachinaGUI::quantize_changed)); _quantize_spinbutton->signal_changed().connect( sigc::mem_fun(this, &MachinaGUI::quantize_changed)); + + _add_edge_button->signal_clicked().connect( + sigc::mem_fun(this, &MachinaGUI::add_edge)); + _remove_edge_button->signal_clicked().connect( + sigc::mem_fun(this, &MachinaGUI::remove_edge)); + _adjust_edge_button->signal_clicked().connect( + sigc::mem_fun(this, &MachinaGUI::adjust_edge)); connect_widgets(); @@ -198,6 +211,28 @@ MachinaGUI::arrange() _canvas->arrange(_menu_view_time_edges->get_active()); } + +void +MachinaGUI::add_edge() +{ + Mutation::AddEdge::mutate(*_engine->machine().get()); +} + + +void +MachinaGUI::remove_edge() +{ + Mutation::RemoveEdge::mutate(*_engine->machine().get()); +} + + +void +MachinaGUI::adjust_edge() +{ + Mutation::AdjustEdge::mutate(*_engine->machine().get()); + _canvas->update_edges(); +} + void MachinaGUI::update_toolbar() diff --git a/src/gui/MachinaGUI.hpp b/src/gui/MachinaGUI.hpp index 4b82ff3..cc1eee3 100644 --- a/src/gui/MachinaGUI.hpp +++ b/src/gui/MachinaGUI.hpp @@ -62,10 +62,13 @@ protected: void show_labels_toggled(); void menu_help_about(); void menu_help_help(); + void arrange(); + void add_edge(); + void remove_edge(); + void adjust_edge(); void zoom(double z); - bool idle_callback(); void update_toolbar(); - void arrange(); + bool idle_callback(); bool scrolled_window_event(GdkEvent* ev); void record_toggled(); @@ -116,6 +119,9 @@ protected: Gtk::ToolButton* _zoom_normal_button; Gtk::ToolButton* _zoom_full_button; Gtk::ToolButton* _arrange_button; + Gtk::ToolButton* _add_edge_button; + Gtk::ToolButton* _remove_edge_button; + Gtk::ToolButton* _adjust_edge_button; }; #endif // MACHINA_GUI_H diff --git a/src/gui/machina.glade b/src/gui/machina.glade index f892894..11f3e7c 100644 --- a/src/gui/machina.glade +++ b/src/gui/machina.glade @@ -207,86 +207,72 @@ - + True - GTK_TOOLBAR_BOTH_HORIZ + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - True - Record - gtk-media-record - - - False - - - - - True - Stop playback or recording - gtk-media-stop - - - False - - - - - True - Play - gtk-media-play - True - - - False - - - - - True - - - False - False - - - - + True + GTK_TOOLBAR_BOTH_HORIZ + False - + + True + Record + gtk-media-record + + + False + + + + + True + Stop playback or recording + gtk-media-stop + + + False + + + + + True + Play + gtk-media-play + True + + + False + + + + + True + + + False + False + + + + True - 4 - 6 - - - True - False - True - Slave to JACK transport - Slave - True - 0 - True - - - False - False - - - + True + 4 + 6 - + True + False True - Use internal tempo + Slave to JACK transport + Slave True 0 - True True - slave_radiobutton False @@ -294,135 +280,204 @@ - + True - True - Set internal tempo - 120 1 640 1 10 10 - 1 + + + True + True + Use internal tempo + True + 0 + True + True + slave_radiobutton + + + False + False + + + + + True + True + Set internal tempo + 120 1 640 1 10 10 + 1 + + + 1 + + + + + True + BPM + + + False + False + 2 + + 1 + + + + + False + False + + + + + True + + + False + False + + + + + True + + + True + 4 - + True - BPM + True + Quantize recording + Quantize: 1/ + True + 0 + True False False - 2 + + + + + True + False + True + 1 1 99 1 4 4 + 1 + + + 1 - - 1 - + + False + False + - - - False - False - - - - - True - - - False - False - - - - - True - + True - 4 - - - True - True - Quantize recording - Quantize: 1/ - True - 0 - True - - - False - False - - - - - True - False - True - 1 1 99 1 4 4 - 1 - - - 1 - - + + False + False + + + + + True + Zoom to normal size + gtk-zoom-100 + + + False + + + + + True + Zoom to fit entire machine + gtk-zoom-fit + + + False + + + + + True + Automatically arrange nodes + gtk-refresh + + + False + - - False - False - - - - - True - - - False - False - - - - - True - Zoom to normal size - gtk-zoom-100 - - - False - - - - - True - Zoom to fit entire machine - gtk-zoom-fit - - - False - - + True - Automatically arrange nodes - gtk-refresh + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + GTK_ICON_SIZE_SMALL_TOOLBAR + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Add random edge + Add Edge + gtk-add + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Remove random edge + Remove Edge + gtk-remove + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Adjust random edge probability + Mutate Edge Probabililty + gtk-edit + + + False + + False + 1 False - False 1 @@ -559,58 +614,58 @@ Selector nodes are shown in green. 4 8 - + True True - 60 0 127 1 10 10 + True + 1 0 999999 1 10 10 1 + 2 True 1 2 + 1 + 2 - + True 0 - Note: + Duration: + 1 + 2 GTK_FILL - + True 0 - Duration: + Note: - 1 - 2 GTK_FILL - + True True - True - 1 0 999999 1 10 10 + 60 0 127 1 10 10 1 - 2 True 1 2 - 1 - 2 -- cgit v1.2.1