Merge branch 'nikitakit_smoothbline' into nikitakit_ducks
[synfig.git] / synfig-studio / src / gtkmm / canvasview.cpp
index 7ffc505..95fe556 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <ETL/clock>
 #include <sstream>
+#include <math.h>
 
 #include <gtkmm/paned.h>
 #include <gtkmm/scale.h>
@@ -52,6 +53,7 @@
 #include <synfig/valuenode_linear.h>
 #include <synfig/valuenode_timedswap.h>
 #include <synfig/valuenode_scale.h>
+#include <synfig/valuenode_range.h>
 #include <synfig/valuenode_dynamiclist.h>
 #include <synfig/valuenode_twotone.h>
 #include <synfig/valuenode_stripes.h>
@@ -684,10 +686,10 @@ CanvasView::CanvasView(etl::loose_handle<Instance> instance,etl::handle<synfigap
        //keyframe_tree_store_  (KeyframeTreeStore::create(canvas_interface_)),
        time_adjustment_                (0,0,25,0,0,0),
        time_window_adjustment_ (0,0,25,0,0,0),
+       statusbar                               (manage(new class Gtk::Statusbar())),
        quality_adjustment_             (8,1,10,1,1,0),
        future_onion_adjustment_ (0,0,2,1,1,0),
        past_onion_adjustment_  (0,0,2,1,1,0),
-       statusbar                               (manage(new class Gtk::Statusbar())),
 
        timeslider                              (new Widget_Timeslider),
        widget_kf_list                  (new Widget_Keyframe_List),
@@ -1123,10 +1125,10 @@ CanvasView::create_status_bar()
 Gtk::Widget*
 CanvasView::create_display_bar()
 {
-       displaybar = manage(new class Gtk::Table(1, 7, false));
-
+       displaybar = manage(new class Gtk::Table(16, 1, false));
+       Gtk::IconSize iconsize=Gtk::IconSize::from_name("synfig-small_icon_16x16");
        // Setup the ToggleDuckDial widget
-       toggleducksdial = Gtk::manage(new class ToggleDucksDial());
+       toggleducksdial = Gtk::manage(new class ToggleDucksDial(iconsize));
 
        Duck::Type m = work_area->get_type_mask();
        toggleducksdial->update_toggles(m);
@@ -1152,7 +1154,7 @@ CanvasView::create_display_bar()
        toggleducksdial->show();
 
        // Set up the ResolutionDial widget
-       resolutiondial=Gtk::manage(new class ResolutionDial());
+       resolutiondial=Gtk::manage(new class ResolutionDial(iconsize));
 
        resolutiondial->update_lowres(work_area->get_low_resolution_flag());
        resolutiondial->signal_increase_resolution().connect(
@@ -1163,11 +1165,17 @@ CanvasView::create_display_bar()
                        sigc::mem_fun(*this, &studio::CanvasView::toggle_low_res_pixel_flag));
        resolutiondial->show();
 
-       // Set up a separator
+       // Set up some separators
        Gtk::VSeparator *separator1 = Gtk::manage(new class Gtk::VSeparator());
        separator1->show();
        Gtk::VSeparator *separator2 = Gtk::manage(new class Gtk::VSeparator());
        separator2->show();
+       Gtk::VSeparator *separator3 = Gtk::manage(new class Gtk::VSeparator());
+       separator3->show();
+       Gtk::VSeparator *separator4 = Gtk::manage(new class Gtk::VSeparator());
+       separator4->show();
+       Gtk::VSeparator *separator5 = Gtk::manage(new class Gtk::VSeparator());
+       separator5->show();
 
        // Set up quality spin button
        quality_spin=Gtk::manage(new class Gtk::SpinButton(quality_adjustment_));
@@ -1179,7 +1187,7 @@ CanvasView::create_display_bar()
        // Set up the show grid toggle button
        show_grid = Gtk::manage(new class Gtk::ToggleButton());
        show_grid->set_active(work_area->grid_status());
-       Gtk::Image *icon = manage(new Gtk::Image(Gtk::StockID("synfig-toggle_show_grid"), Gtk::IconSize::from_name("synfig-small_icon")));
+       Gtk::Image *icon = manage(new Gtk::Image(Gtk::StockID("synfig-toggle_show_grid"), iconsize));
        icon->set_padding(0, 0);
        icon->show();
        show_grid->add(*icon);
@@ -1192,7 +1200,7 @@ CanvasView::create_display_bar()
        // Set up the snap to grid toggle button
        snap_grid = Gtk::manage(new class Gtk::ToggleButton());
        snap_grid->set_active(work_area->grid_status());
-       Gtk::Image *icon2 = manage(new Gtk::Image(Gtk::StockID("synfig-toggle_snap_grid"), Gtk::IconSize::from_name("synfig-small_icon")));
+       Gtk::Image *icon2 = manage(new Gtk::Image(Gtk::StockID("synfig-toggle_snap_grid"), iconsize));
        icon2->set_padding(0, 0);
        icon2->show();
        snap_grid->add(*icon2);
@@ -1205,7 +1213,7 @@ CanvasView::create_display_bar()
        // Set up the onion skin toggle button
        onion_skin = Gtk::manage(new class Gtk::ToggleButton());
        onion_skin->set_active(work_area->get_onion_skin());
-       Gtk::Image *icon3 = manage(new Gtk::Image(Gtk::StockID("synfig-toggle_onion_skin"), Gtk::IconSize::from_name("synfig-small_icon")));
+       Gtk::Image *icon3 = manage(new Gtk::Image(Gtk::StockID("synfig-toggle_onion_skin"), iconsize));
        icon3->set_padding(0, 0);
        icon3->show();
        onion_skin->add(*icon3);
@@ -1229,17 +1237,46 @@ CanvasView::create_display_bar()
        tooltips.set_tip(*future_onion_spin, _("Future onion skins"));
        future_onion_spin->show();
 
+       // Setup render options dialog button
+       render_options_button = Gtk::manage(new class Gtk::Button());
+       Gtk::Image *icon4 = manage(new Gtk::Image(Gtk::StockID("synfig-render_options"), iconsize));
+       icon4->set_padding(0, 0);
+       icon4->show();
+       render_options_button->add(*icon4);
+       render_options_button->signal_clicked().connect(
+                       sigc::mem_fun0(render_settings,&studio::RenderSettings::present));
+       tooltips.set_tip(*render_options_button, _("Shows the Render Settings Dialog"));
+       render_options_button->set_relief(Gtk::RELIEF_NONE);
+       render_options_button->show();
+
+       // Setup preview options dialog button
+       preview_options_button = Gtk::manage(new class Gtk::Button());
+       Gtk::Image *icon5 = manage(new Gtk::Image(Gtk::StockID("synfig-preview_options"), iconsize));
+       icon5->set_padding(0, 0);
+       icon5->show();
+       preview_options_button->add(*icon5);
+       preview_options_button->signal_clicked().connect(
+                       sigc::mem_fun(*this,&CanvasView::on_preview_option));
+       tooltips.set_tip(*preview_options_button, _("Shows the Preview Settings Dialog"));
+       preview_options_button->set_relief(Gtk::RELIEF_NONE);
+       preview_options_button->show();
+
 
        displaybar->attach(*toggleducksdial, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
        displaybar->attach(*separator1, 1, 2, 0, 1, Gtk::FILL, Gtk::FILL);
        displaybar->attach(*resolutiondial, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
        displaybar->attach(*separator2, 3, 4, 0, 1, Gtk::FILL, Gtk::FILL);
        displaybar->attach(*quality_spin, 4, 5, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
-       displaybar->attach(*show_grid, 5, 6, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
-       displaybar->attach(*snap_grid, 6, 7, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
-       displaybar->attach(*past_onion_spin, 7, 8, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
-       displaybar->attach(*onion_skin, 8, 9, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
-       displaybar->attach(*future_onion_spin, 9, 10, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+       displaybar->attach(*separator3, 5, 6, 0, 1, Gtk::FILL, Gtk::FILL);
+       displaybar->attach(*show_grid, 6, 7, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+       displaybar->attach(*snap_grid, 7, 8, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+       displaybar->attach(*separator4, 8, 9, 0, 1, Gtk::FILL, Gtk::FILL);
+       displaybar->attach(*past_onion_spin, 9, 10, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+       displaybar->attach(*onion_skin, 10, 11, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+       displaybar->attach(*future_onion_spin, 11, 12, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+       displaybar->attach(*separator5, 12, 13, 0, 1, Gtk::FILL, Gtk::FILL);
+       displaybar->attach(*render_options_button, 13, 14, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+       displaybar->attach(*preview_options_button, 14, 15, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
 
        displaybar->show();
 
@@ -1390,7 +1427,7 @@ CanvasView::init_menus()
        - canvasmenu
        - viewmenu
        */
-       action_group = Gtk::ActionGroup::create();
+       action_group = Gtk::ActionGroup::create("canvasview");
 
        //action_group->add( Gtk::Action::create("MenuFile", _("_File")) );
        action_group->add( Gtk::Action::create("new", Gtk::Stock::NEW),
@@ -2846,10 +2883,20 @@ CanvasView::on_duck_changed(const synfig::Point &value,const synfigapp::ValueDes
 
        if (ValueNode_BLineCalcVertex::Handle bline_vertex = ValueNode_BLineCalcVertex::Handle::cast_dynamic(value_desc.get_value_node()))
        {
-               ValueNode_BLine::Handle bline = ValueNode_BLine::Handle::cast_dynamic(bline_vertex->get_link(bline_vertex->get_link_index_from_name("bline")));
+               ValueNode_BLine::Handle bline = ValueNode_BLine::Handle::cast_dynamic(bline_vertex->get_link("bline"));
                Real radius = 0.0;
-               Real amount = synfig::find_closest_point((*bline)(get_time()), value, radius, bline->get_loop());
-               return canvas_interface()->change_value(synfigapp::ValueDesc(bline_vertex,bline_vertex->get_link_index_from_name("amount")), amount);
+               if (((*(bline_vertex->get_link("loop")))(get_time()).get(bool()))){
+                       Real amount_old((*(bline_vertex->get_link("amount")))(get_time()).get(Real()));
+                       Real amount_new = synfig::find_closest_point((*bline)(get_time()), value, radius, bline->get_loop());
+                       Real difference = fmod( fmod(amount_new - amount_old, 1.0) + 1.0 , 1.0);
+                                                       //fmod is called twice to avoid negative values
+                       if (difference > 0.5) difference=difference-1.0;
+                       return canvas_interface()->change_value(synfigapp::ValueDesc(bline_vertex,bline_vertex->get_link_index_from_name("amount")), amount_old+difference);
+
+               } else {
+                       Real amount = synfig::find_closest_point((*bline)(get_time()), value, radius, bline->get_loop());
+                       return canvas_interface()->change_value(synfigapp::ValueDesc(bline_vertex,bline_vertex->get_link_index_from_name("amount")), amount);
+               }
        }
 
        if (ValueNode_BLineCalcTangent::Handle bline_tangent = ValueNode_BLineCalcTangent::Handle::cast_dynamic(value_desc.get_value_node()))
@@ -2914,6 +2961,15 @@ CanvasView::on_duck_changed(const synfig::Point &value,const synfigapp::ValueDes
                        return false;
        }
 
+       if (ValueNode_Range::Handle range_value_node = ValueNode_Range::Handle::cast_dynamic(value_desc.get_value_node()))
+       {
+               int link_index(range_value_node->get_link_index_from_name("link"));
+               return canvas_interface()->change_value(
+                       synfigapp::ValueDesc(range_value_node,link_index),
+                               range_value_node->get_inverse(get_time(), value)
+                               );
+       }
+
        switch(value_desc.get_value_type())
        {
        case ValueBase::TYPE_REAL:
@@ -2947,6 +3003,14 @@ CanvasView::on_duck_angle_changed(const synfig::Angle &rotation,const synfigapp:
                        return false;
 
        }
+       if (ValueNode_Range::Handle range_value_node = ValueNode_Range::Handle::cast_dynamic(value_desc.get_value_node()))
+       {
+               int link_index(range_value_node->get_link_index_from_name("link"));
+               return canvas_interface()->change_value(
+                       synfigapp::ValueDesc(range_value_node,link_index),
+                               range_value_node->get_inverse(get_time(), rotation)
+                               );
+       }
        // \todo will this really always be the case?
        assert(value_desc.get_value_type() == ValueBase::TYPE_ANGLE);
        return canvas_interface()->change_value(value_desc, value_desc.get_value(get_time()).get(Angle()) + rotation);