diff --git a/synfig-studio/src/gui/app.cpp b/synfig-studio/src/gui/app.cpp
index 23e965b..c8f1a6c 100644
--- a/synfig-studio/src/gui/app.cpp
+++ b/synfig-studio/src/gui/app.cpp
@@ -1,4 +1,4 @@
-// /* === S Y N F I G ========================================================= */
+/* === S Y N F I G ========================================================= */
/*! \file app.cpp
** \brief writeme
**
@@ -954,6 +954,7 @@ DEFINE_ACTION("save-as", Gtk::StockID("synfig-save_as"));
DEFINE_ACTION("save-all", Gtk::StockID("synfig-save_all"));
DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
DEFINE_ACTION("import", _("Import..."));
+DEFINE_ACTION("import-sequence",_("Import Sequence..."));
DEFINE_ACTION("render", _("Render..."));
DEFINE_ACTION("preview", _("Preview..."));
DEFINE_ACTION("close-document", _("Close Document"));
@@ -1092,6 +1093,7 @@ DEFINE_ACTION("keyframe-properties", _("Properties"));
" "
" "
" "
+" "
" "
" "
" "
@@ -2608,7 +2610,6 @@ App::dialog_open_file(const std::string &title, std::string &filename, std::stri
#endif // not USE_WIN32_FILE_DIALOGS
}
-
bool
App::dialog_open_file_spal(const std::string &title, std::string &filename, std::string preference)
{
@@ -2816,6 +2817,66 @@ App::dialog_open_file_audio(const std::string &title, std::string &filename, std
return false;
}
+bool
+App::dialog_open_file_image_sequence(const std::string &title, std::set &filenames, std::string preference)
+{
+ synfig::String prev_path;
+
+ if(!_preferences.get_value(preference, prev_path))
+ prev_path = Glib::get_home_dir();
+
+ prev_path = absolute_path(prev_path);
+
+ Gtk::FileChooserDialog *dialog = new Gtk::FileChooserDialog(*App::main_window,
+ title, Gtk::FILE_CHOOSER_ACTION_OPEN);
+
+ dialog->set_transient_for(*App::main_window);
+ dialog->set_current_folder(prev_path);
+ dialog->set_select_multiple(true);
+ dialog->add_button(_("Cancel"), Gtk::RESPONSE_CANCEL)->set_image_from_icon_name("gtk-cancel", Gtk::ICON_SIZE_BUTTON);
+ dialog->add_button(_("Load"), Gtk::RESPONSE_ACCEPT)->set_image_from_icon_name("gtk-open", Gtk::ICON_SIZE_BUTTON);
+
+ // show only images
+ Glib::RefPtr filter_image = Gtk::FileFilter::create();
+ filter_image->set_name(_("Images files (*.png, *.jpg, *.jpeg, *.bmp)"));
+ filter_image->add_mime_type("image/png");
+ filter_image->add_mime_type("image/jpeg");
+ filter_image->add_mime_type("image/jpg");
+ filter_image->add_mime_type("image/bmp");
+ filter_image->add_mime_type("image/svg+xml");
+ filter_image->add_pattern("*.png");
+ filter_image->add_pattern("*.jpeg");
+ filter_image->add_pattern("*.jpg");
+ filter_image->add_pattern("*.bmp");
+ dialog->add_filter(filter_image);
+
+ // Any files
+ Glib::RefPtr filter_any = Gtk::FileFilter::create();
+ filter_any->set_name(_("Any files"));
+ filter_any->add_pattern("*");
+ dialog->add_filter(filter_any);
+
+ std::string filename = filenames.empty() ? std::string() : *filenames.begin();
+ if (filename.empty())
+ dialog->set_filename(prev_path);
+ else if (is_absolute_path(filename))
+ dialog->set_filename(filename);
+ else
+ dialog->set_filename(prev_path + ETL_DIRECTORY_SEPARATOR + filename);
+
+ filenames.clear();
+ if(dialog->run() == GTK_RESPONSE_ACCEPT) {
+ std::vector files = dialog->get_filenames();
+ filenames.insert(files.begin(), files.end());
+ _preferences.set_value(preference, dirname(dialog->get_filename()));
+ delete dialog;
+ return true;
+ }
+
+ delete dialog;
+ return false;
+}
+
void
on_open_dialog_with_history_selection_changed(Gtk::FileChooserDialog *dialog, Gtk::Button* history_button)
{
diff --git a/synfig-studio/src/gui/app.h b/synfig-studio/src/gui/app.h
index dec1304..44fc661 100644
--- a/synfig-studio/src/gui/app.h
+++ b/synfig-studio/src/gui/app.h
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
#include
@@ -412,6 +413,7 @@ public:
static bool dialog_save_file_spal(const std::string &title, std::string &filename, std::string preference);
static bool dialog_save_file_sketch(const std::string &title, std::string &filename, std::string preference);
static bool dialog_save_file_render(const std::string &title, std::string &filename, std::string preference);
+ static bool dialog_open_file_image_sequence(const std::string &title, std::set &filenames, std::string preference);
static bool dialog_select_list_item(const std::string &title, const std::string &message, const std::list &list, int &item_index);
diff --git a/synfig-studio/src/gui/asyncrenderer.cpp b/synfig-studio/src/gui/asyncrenderer.cpp
index f13c38c..e729954 100644
--- a/synfig-studio/src/gui/asyncrenderer.cpp
+++ b/synfig-studio/src/gui/asyncrenderer.cpp
@@ -124,7 +124,7 @@ public:
ContextParams context_params,
RectInt rect,
RendDesc tile_desc,
- ProgressCallback *cb )
+ ProgressCallback */*cb*/ )
{
if(!alive_flag)
return false;
diff --git a/synfig-studio/src/gui/canvasview.cpp b/synfig-studio/src/gui/canvasview.cpp
index 4b6dc5c..daad0fc 100644
--- a/synfig-studio/src/gui/canvasview.cpp
+++ b/synfig-studio/src/gui/canvasview.cpp
@@ -1437,6 +1437,9 @@ CanvasView::init_menus()
action_group->add( Gtk::Action::create("import", _("Import...")),
sigc::hide_return(sigc::mem_fun(*this, &CanvasView::image_import))
);
+ action_group->add( Gtk::Action::create("import-sequence", _("Import Sequence...")),
+ sigc::hide_return(sigc::mem_fun(*this, &CanvasView::squence_import))
+ );
action_group->add( Gtk::Action::create("render", Gtk::StockID("synfig-render_options"), _("Render...")),
sigc::mem_fun0(render_settings,&RenderSettings::present)
);
@@ -3430,7 +3433,36 @@ CanvasView::image_import()
if(App::dialog_open_file(_("Please select a file"), filename, IMAGE_DIR_PREFERENCE))
{
canvas_interface()->import(filename, errors, warnings, App::resize_imported_images);
- if (warnings != "")
+ if (!errors.empty())
+ App::dialog_message_1b(
+ "ERROR",
+ etl::strprintf("%s:\n\n%s", _("Error"), errors.c_str()),
+ "details",
+ _("Close"));
+ if (!warnings.empty())
+ App::dialog_message_1b(
+ "WARNING",
+ etl::strprintf("%s:\n\n%s", _("Warning"), warnings.c_str()),
+ "details",
+ _("Close"));
+ }
+}
+
+void
+CanvasView::squence_import()
+{
+ std::set filenames;
+ String errors, warnings;
+ if(App::dialog_open_file_image_sequence(_("Please select a files"), filenames, IMAGE_DIR_PREFERENCE))
+ {
+ canvas_interface()->import_sequence(filenames, errors, warnings, App::resize_imported_images);
+ if (!errors.empty())
+ App::dialog_message_1b(
+ "ERROR",
+ etl::strprintf("%s:\n\n%s", _("Error"), errors.c_str()),
+ "details",
+ _("Close"));
+ if (!warnings.empty())
App::dialog_message_1b(
"WARNING",
etl::strprintf("%s:\n\n%s", _("Warning"), warnings.c_str()),
diff --git a/synfig-studio/src/gui/canvasview.h b/synfig-studio/src/gui/canvasview.h
index 2451d4b..4196908 100644
--- a/synfig-studio/src/gui/canvasview.h
+++ b/synfig-studio/src/gui/canvasview.h
@@ -645,6 +645,7 @@ public:
void on_keyframe_description_set();
void image_import();
+ void squence_import();
void on_waypoint_clicked_canvasview(synfigapp::ValueDesc,std::set >, int button);
diff --git a/synfig-studio/src/synfigapp/canvasinterface.cpp b/synfig-studio/src/synfigapp/canvasinterface.cpp
index be5f9c5..6a3447b 100644
--- a/synfig-studio/src/synfigapp/canvasinterface.cpp
+++ b/synfig-studio/src/synfigapp/canvasinterface.cpp
@@ -692,11 +692,15 @@ CanvasInterface::jump_to_prev_keyframe()
}
bool
-CanvasInterface::import(const synfig::String &filename, synfig::String &errors, synfig::String &warnings, bool resize_image)
+CanvasInterface::import(
+ const synfig::String &filename,
+ synfig::String &errors,
+ synfig::String &warnings,
+ bool resize_image )
{
Action::PassiveGrouper group(get_instance().get(),_("Import"));
- synfig::info("Attempting to import " + filename);
+ synfig::info("Attempting to import %s", filename.c_str());
String ext(filename_extension(filename));
//if (filename_extension(filename) == "")
@@ -939,6 +943,197 @@ CanvasInterface::import(const synfig::String &filename, synfig::String &errors,
}
+bool
+CanvasInterface::import_sequence(
+ const std::set &filenames,
+ synfig::String &errors,
+ synfig::String &/*warnings*/,
+ bool resize_image )
+{
+ Action::PassiveGrouper group(get_instance().get(),_("Import sequence"));
+
+ synfig::info("Attempting to import sequence");
+ Layer::Handle layer_switch;
+ try {
+ // add imported layers into switch
+ Action::Handle action(Action::create("LayerEncapsulateSwitch"));
+ if(!action)
+ { get_ui_interface()->error(_("Cannot create action")); throw int(); }
+ action->set_param("canvas",get_canvas());
+ action->set_param("canvas_interface",etl::loose_handle(this));
+
+ Layer::Handle layer;
+ int layers_count = 0;
+ for(std::set::const_iterator i = filenames.begin(); i != filenames.end(); ++i) {
+ const String &filename = *i;
+ synfig::info("Attempting to import '%s' into sequence", filename.c_str());
+
+ String ext(filename_extension(filename));
+ if (!ext.empty()) ext = ext.substr(1); // skip initial '.'
+ std::transform(ext.begin(),ext.end(),ext.begin(),&::tolower);
+
+ if (ext.empty())
+ {
+ errors += etl::strprintf(_("Cannot import file witout extension: %s\n"), filename.c_str());
+ continue;
+ }
+
+ if(!Importer::book().count(ext))
+ {
+ errors += etl::strprintf(_("Cannot import file of type '%s': %s\n"), ext.c_str(), filename.c_str());
+ continue;
+ }
+
+ String short_filename = CanvasFileNaming::make_short_filename(get_canvas()->get_file_name(), filename);
+
+ try {
+ layer = add_layer_to("Import",get_canvas());
+ int w, h;
+ if (!layer)
+ throw int();
+ if (!layer->set_param("filename", ValueBase(short_filename)))
+ throw int();
+ w = layer->get_param("_width").get(int());
+ h = layer->get_param("_height").get(int());
+ layer->monitor(filename);
+ if (w && h) {
+ Vector x, size = get_canvas()->rend_desc().get_br()-get_canvas()->rend_desc().get_tl();
+ // vector from top left of canvas to bottom right
+ if (resize_image) {
+ if(abs(size[0])set_param("tl",ValueBase(-x/2)))
+ throw int();
+ if(!layer->set_param("br",ValueBase(x/2)))
+ throw int();
+ } else {
+ if(!layer->set_param("tl",ValueBase(get_canvas()->rend_desc().get_tl())))
+ throw int();
+ if(!layer->set_param("br",ValueBase(get_canvas()->rend_desc().get_br())))
+ throw int();
+ }
+
+ String desc = etl::basename(filename);
+ layer->set_description(desc);
+ signal_layer_new_description()(layer, desc);
+
+ action->set_param("layer", layer);
+ if (!layers_count)
+ action->set_param("description", desc);
+ ++layers_count;
+ } catch(...) {
+ errors += etl::strprintf(_("Unable to import file: %s"), filename.c_str());
+ group.cancel();
+ return false;
+ }
+ }
+
+ if (!layers_count)
+ { get_ui_interface()->error(_("Nothing imported")); throw int(); }
+ if(!action->is_ready())
+ { get_ui_interface()->error(_("Action Not Ready")); throw int(); }
+ if(!get_instance()->perform_action(action))
+ { get_ui_interface()->error(_("Action Failed.")); throw int(); }
+
+ if (layer) {
+ Layer::Handle layer_switch = layer->get_parent_paste_canvas_layer(); // get parent layer, because image is incapsulated into action switch
+
+ action = Action::create("ValueDescSet");
+ if(!action)
+ { get_ui_interface()->error(_("Cannot create action")); throw int(); }
+ action->set_param("canvas", get_canvas());
+ action->set_param("canvas_interface", etl::loose_handle(this));
+ action->set_param("value_desc", ValueDesc(layer_switch, "layer_name"));
+ action->set_param("new_value", ValueBase(String()));
+ if(!action->is_ready())
+ { get_ui_interface()->error(_("Action Not Ready")); throw int(); }
+ if(!get_instance()->perform_action(action))
+ { get_ui_interface()->error(_("Action Failed.")); throw int(); }
+
+ action = Action::create("ValueDescSet");
+ if(!action)
+ { get_ui_interface()->error(_("Cannot create action")); throw int(); }
+ action->set_param("canvas", get_canvas());
+ action->set_param("canvas_interface", etl::loose_handle(this));
+ action->set_param("value_desc", ValueDesc(layer_switch, "layer_depth"));
+ action->set_param("new_value", ValueBase(int(0)));
+ if(!action->is_ready())
+ { get_ui_interface()->error(_("Action Not Ready")); throw int(); }
+ if(!get_instance()->perform_action(action))
+ { get_ui_interface()->error(_("Action Failed.")); throw int(); }
+
+ action = Action::create("ValueDescConvert");
+ if(!action)
+ { get_ui_interface()->error(_("Cannot create action")); throw int(); }
+ action->set_param("canvas", get_canvas());
+ action->set_param("canvas_interface", etl::loose_handle(this));
+ action->set_param("value_desc", ValueDesc(layer_switch, "layer_depth"));
+ action->set_param("type", "fromreal");
+ action->set_param("time", get_time());
+ if(!action->is_ready())
+ { get_ui_interface()->error(_("Action Not Ready")); throw int(); }
+ if(!get_instance()->perform_action(action))
+ { get_ui_interface()->error(_("Action Failed.")); throw int(); }
+
+ Layer::DynamicParamList::const_iterator i = layer_switch->dynamic_param_list().find("layer_depth");
+ if (i == layer_switch->dynamic_param_list().end())
+ { get_ui_interface()->error(_("Dynamic param not found.")); throw int(); }
+ LinkableValueNode::Handle valuenode_real = LinkableValueNode::Handle::cast_dynamic(i->second);
+
+ action = Action::create("ValueDescConvert");
+ if(!action)
+ { get_ui_interface()->error(_("Cannot create action")); throw int(); }
+ action->set_param("canvas", get_canvas());
+ action->set_param("canvas_interface", etl::loose_handle(this));
+ action->set_param("value_desc", ValueDesc(valuenode_real, valuenode_real->get_link_index_from_name("link")));
+ action->set_param("type", "linear");
+ action->set_param("time", get_time());
+ if(!action->is_ready())
+ { get_ui_interface()->error(_("Action Not Ready")); throw int(); }
+ if(!get_instance()->perform_action(action))
+ { get_ui_interface()->error(_("Action Failed.")); throw int(); }
+
+ LinkableValueNode::Handle valuenode_linear = LinkableValueNode::Handle::cast_dynamic(valuenode_real->get_link("link"));
+
+ action = Action::create("ValueDescSet");
+ if(!action)
+ { get_ui_interface()->error(_("Cannot create action")); throw int(); }
+ action->set_param("canvas", get_canvas());
+ action->set_param("canvas_interface", etl::loose_handle(this));
+ action->set_param("value_desc", ValueDesc(valuenode_linear, valuenode_linear->get_link_index_from_name("slope")));
+ action->set_param("new_value", ValueBase(Real(1)));
+ if(!action->is_ready())
+ { get_ui_interface()->error(_("Action Not Ready")); throw int(); }
+ if(!get_instance()->perform_action(action))
+ { get_ui_interface()->error(_("Action Failed.")); throw int(); }
+ }
+ } catch(...) {
+ get_ui_interface()->error("Unable to import sequence");
+ group.cancel();
+ return false;
+ }
+
+ get_selection_manager()->clear_selected_layers();
+ if (layer_switch)
+ get_selection_manager()->set_selected_layer(layer_switch);
+ return true;
+}
+
+
void
CanvasInterface::waypoint_duplicate(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint)
{
diff --git a/synfig-studio/src/synfigapp/canvasinterface.h b/synfig-studio/src/synfigapp/canvasinterface.h
index 10e130a..43b5928 100644
--- a/synfig-studio/src/synfigapp/canvasinterface.h
+++ b/synfig-studio/src/synfigapp/canvasinterface.h
@@ -28,10 +28,14 @@
/* === H E A D E R S ======================================================= */
+#include
+#include
+
+#include
+
//#include
#include
-#include
-#include
+
#include "selectionmanager.h"
#include "uimanager.h"
#include "value_desc.h"
@@ -298,7 +302,17 @@ public:
void set_rend_desc(const synfig::RendDesc &rend_desc);
- bool import(const synfig::String &filename, synfig::String &errors, synfig::String &warnings, bool resize_image=false);
+ bool import(
+ const synfig::String &filename,
+ synfig::String &errors,
+ synfig::String &warnings,
+ bool resize_image = false );
+
+ bool import_sequence(
+ const std::set &filenames,
+ synfig::String &errors,
+ synfig::String &warnings,
+ bool resize_image = false );
void waypoint_duplicate(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint);