fit keyframe spanning for sketcher,tracer,crikey, rework keyframegui preset, tweak...
authorGood Guy <[email protected]>
Wed, 10 Jun 2020 01:06:16 +0000 (19:06 -0600)
committerGood Guy <[email protected]>
Wed, 10 Jun 2020 01:06:16 +0000 (19:06 -0600)
25 files changed:
cinelerra-5.1/Cinelerra_factory
cinelerra-5.1/cinelerra/cache.C
cinelerra-5.1/cinelerra/filexml.C
cinelerra-5.1/cinelerra/keyframe.C
cinelerra-5.1/cinelerra/keyframe.h
cinelerra-5.1/cinelerra/keyframegui.C
cinelerra-5.1/cinelerra/keyframes.C
cinelerra-5.1/cinelerra/keyframes.h
cinelerra-5.1/cinelerra/plugin.C
cinelerra-5.1/cinelerra/pluginclient.C
cinelerra-5.1/cinelerra/pluginclient.h
cinelerra-5.1/cinelerra/pluginserver.C
cinelerra-5.1/cinelerra/pluginserver.h
cinelerra-5.1/cinelerra/presets.C
cinelerra-5.1/guicast/linklist.h
cinelerra-5.1/plugins/crikey/crikey.C
cinelerra-5.1/plugins/crikey/crikey.h
cinelerra-5.1/plugins/perspective/perspective.C
cinelerra-5.1/plugins/perspective/perspective.h
cinelerra-5.1/plugins/rotate/rotate.C
cinelerra-5.1/plugins/rotate/rotate.h
cinelerra-5.1/plugins/sketcher/sketcher.C
cinelerra-5.1/plugins/sketcher/sketcher.h
cinelerra-5.1/plugins/tracer/tracer.C
cinelerra-5.1/plugins/tracer/tracer.h

index 4a4c0e5849c5e407d399d990291220de4ab27190..ee236e3479b72e05621d5c68f2dac14007520f3c 100644 (file)
@@ -94,5 +94,5 @@
 <KEYFRAME TITLE="gear360 sideways, 7k"><SPHERECAM ENABLED_0=1 FOV_0=194 CENTER_X_0=2.520000e+01 CENTER_Y_0=5.139998e+01 ROTATE_X_0=50 ROTATE_Y_0=50 ROTATE_Z_0=90 ENABLED_1=1 FOV_1=1.946000e+02 CENTER_X_1=7.499999e+01 CENTER_Y_1=5.079997e+01 ROTATE_X_1=0 ROTATE_Y_1=4.990000e+01 ROTATE_Z_1=-8.900002e+01 FEATHER=1 DRAW_GUIDES=0 MODE=1></KEYFRAME>
 </PLUGIN>
 <PLUGIN TITLE=F_drawgrid>
-<KEYFRAME TITLE=rule_of_3rds>&lt;F_DRAWGRID x=-1 y=-1 width=iw/3 w=iw/3 height=ih/3 h=ih/3 color=invert c=invert thickness=2 t=2&gt;</KEYFRAME>
+<KEYFRAME TITLE=rule_of_3rds><F_DRAWGRID x=-1 y=-1 width=iw/3 w=iw/3 height=ih/3 h=ih/3 color=invert c=invert thickness=2 t=2></KEYFRAME>
 </PLUGIN>
index b8e2326dbc823d01aff508590875f8fb0ff420b3..4c94adbfe78ba4f6a0616cd21094155b53a3df02 100644 (file)
@@ -82,8 +82,8 @@ File* CICache::check_out(Asset *asset, EDL *edl, int block)
                        current = new CICacheItem(this, edl, asset);
                        append(current);  current->checked_out = tid;
                        file = current->file;
-                       total_lock->unlock();
                        int result = file->open_file(preferences, asset, 1, 0);
+                       total_lock->unlock();
                        if( result ) {
 SET_TRACE
                                delete file;
index e045a5321b27cec19568cca901113662ebb0d181..fe0ec15fa082e247f3f48cf3a04108303dc91dc5 100644 (file)
@@ -452,8 +452,9 @@ int FileXML::append_text(const char *text, long len)
 
 char* FileXML::get_data()
 {
+       char *data = (char *)buffer->cstr();
        long ofs = buffer->itell();
-       return (char *)buffer->pos(ofs);
+       return data + ofs;
 }
 char* FileXML::string()
 {
@@ -470,18 +471,34 @@ char* FileXML::read_text()
        int ch = buffer->next();
 // filter out first char is new line
        if( ch == '\n' ) ch = buffer->next();
-       long ipos = buffer->itell()-1;
+       long ipos = buffer->itell();
+       if( ch >= 0 ) --ipos;
+       long pos = ipos;
 // scan for delimiter
-       while( ch >= 0 && ch != left_delm ) ch = buffer->next();
-       long pos = buffer->itell()-1;
-       if( ch >= 0 ) buffer->iseek(pos);
+       while( ch >= 0 ) {
+               while( ch >= 0 && ch != left_delm ) ch = buffer->next();
+               if( ch < 0 ) break;
+               pos = buffer->itell()-1;
+               if( (ch = buffer->next()) != '/' ) continue;
+               char *cp = tag.title;
+               while( (ch=buffer->next()) >= 0 && ch == *cp ) ++cp;
+               if( ch < 0 ) break;
+               if( *cp ) continue;
+               while( ch == ' ' ) ch = buffer->next();
+               if( ch == right_delm ) break;
+       }
+       if( ch < 0 )
+               pos = buffer->itell();
+       buffer->iseek(pos);
        long len = pos - ipos;
        if( len >= output_length ) {
                delete [] output;
                output_length = len+1;
                output = new char[output_length];
        }
-       decode(output,(const char *)buffer->pos(ipos), len);
+       if( len > 0 )
+               decode(output,(const char *)buffer->pos(ipos), len);
+       output[len] = 0;
        return output;
 }
 
index 8d6a57557f86f881e8bde110ed4de3d1adb3ef5a..363c72df3ca797ddf3e283507a40f15dec6f0402 100644 (file)
@@ -25,6 +25,8 @@
 #include "cstrdup.h"
 #include "filexml.h"
 #include "keyframe.h"
+#include "keyframes.h"
+#include "transportque.inc"
 
 #include <stdio.h>
 #include <string.h>
@@ -181,7 +183,7 @@ void KeyFrame::update_parameter(BC_Hash *params,
 
                output.append_tag();
 // Write anonymous text & duplicate the rest
-               output.append_text(text ? text : this_text);
+               output.append_data(text ? text : this_text);
                output.append_data(extra ? extra : this_extra);
                output.terminate_string();
 // Move output to input
@@ -232,6 +234,27 @@ void KeyFrame::get_diff(KeyFrame *src,
        delete [] src_extra;
 }
 
+void KeyFrame::span_keyframes(int64_t start, int64_t end)
+{
+       BC_Hash *params = 0;
+       char *text = 0, *extra = 0;
+// The first one determines the changed parameters since it is the one displayed
+       KeyFrames *keyframes = (KeyFrames *)autos;
+       KeyFrame *current = keyframes->get_prev_keyframe(start, PLAY_FORWARD);
+       current->get_diff(this, &params, &text, &extra);
+// Always update the first one
+       current->update_parameter(params, text, extra);
+
+// Replace changed parameter in all selected keyframes.
+       for( current = (KeyFrame*)NEXT; current;  current = (KeyFrame*)NEXT ) {
+               if( current->position >= end ) break;
+               current->update_parameter(params, text, extra);
+       }
+       delete params;
+       delete [] text,
+       delete [] extra;
+}
+
 int KeyFrame::operator==(Auto &that)
 {
        return identical((KeyFrame*)&that);
index d766b915078dd72a382990f9c82e246bda1da386..8118afb8bc9ef79efc92518b697ff226d37527c5 100644 (file)
@@ -66,6 +66,7 @@ public:
        void get_contents(BC_Hash *ptr, char **text, char **extra);
 // Update a single parameter or the anonymous text depending on which argument is nonzero
        void update_parameter(BC_Hash *params, const char *text, const char *extra);
+       void span_keyframes(int64_t start, int64_t end);
 
        XMLBuffer *xbuf;
 };
index 61a0b052aa3cdf34f74eebedfa76984b61dd4a2d..fb7de36f93d32e6f118e52313b2b430235a21c1a 100644 (file)
@@ -363,9 +363,16 @@ void KeyFrameThread::apply_preset(const char *title, int is_factory)
                mwindow->undo->update_undo_before();
 
 #ifdef USE_KEYFRAME_SPANNING
-               KeyFrame keyframe;
-               presets_db->load_preset(plugin_title, title, &keyframe, is_factory);
-               plugin->keyframes->update_parameter(&keyframe);
+               ArrayList<PluginServer*> &plugindb = *mwindow->plugindb;
+               int k = plugindb.size();
+               while( --k>=0 && strcmp(plugindb[k]->title, plugin->title) );
+               if( k >= 0 ) {
+                       PluginServer server(*plugindb[k]);
+                       server.open_plugin(0, mwindow->preferences, mwindow->edl, plugin);
+                       KeyFrame keyframe(mwindow->edl, plugin->keyframes);
+                       presets_db->load_preset(plugin_title, title, &keyframe, is_factory);
+                       server.apply_keyframe(plugin, &keyframe);
+               }
 #else
                KeyFrame *keyframe = plugin->get_keyframe();
                presets_db->load_preset(plugin_title, title, keyframe, is_factory);
index 68d700f4b87b79a3e647b01869c4ed0a0eea2e46..588db9a9f87c11eca468e310873945084ca33dfb 100644 (file)
 #include "keyframe.h"
 #include "keyframes.h"
 #include "localsession.h"
+#include "plugin.h"
 #include "track.h"
 #include "transportque.inc"
 
-KeyFrames::KeyFrames(EDL *edl, Track *track)
- : Autos(edl, track)
+KeyFrames::KeyFrames(EDL *edl, Plugin *plugin)
+ : Autos(edl, plugin->track)
 {
        type = Autos::AUTOMATION_TYPE_PLUGIN;
+       plugin = plugin;
 }
 
 KeyFrames::~KeyFrames()
@@ -92,44 +94,6 @@ KeyFrame* KeyFrames::get_keyframe()
        return result;
 }
 
-
-void KeyFrames::update_parameter(KeyFrame *src)
-{
-// Create new keyframe if auto keyframes or replace entire keyframe.
-       double selection_start = edl->local_session->get_selectionstart(0);
-       double selection_end = edl->local_session->get_selectionend(0);
-       selection_start = edl->align_to_frame(selection_start, 0);
-       selection_end = edl->align_to_frame(selection_end, 0);
-
-       if( !edl->session->span_keyframes ||
-           EQUIV(selection_start, selection_end) ) {
-// Search for keyframe to write
-               KeyFrame *dst = get_keyframe();
-               dst->copy_data(src);
-       }
-       else {
-// Replace changed parameter in all selected keyframes.
-               BC_Hash *params = 0;
-               char *text = 0, *extra = 0;
-// Search all keyframes in selection but don't create a new one.
-               int64_t start = track->to_units(selection_start, 0);
-               int64_t end = track->to_units(selection_end, 0);
-               KeyFrame *current = get_prev_keyframe(start, PLAY_FORWARD);
-// The first one determines the changed parameters since it is the one displayed
-               current->get_diff(src, &params, &text, &extra);
-// Always update the first one
-               current->update_parameter(params, text, extra);
-
-               for( current = (KeyFrame*)NEXT; current;  current = (KeyFrame*)NEXT ) {
-                       if( current->position >= end ) break;
-                       current->update_parameter(params, text, extra);
-               }
-               delete params;
-               delete [] text,
-               delete [] extra;
-       }
-}
-
 Auto* KeyFrames::new_auto()
 {
        return new KeyFrame(edl, this);
index 89fa24353746b998f2ae979b1f9c1bbe13dd7112..45a453338734c1a280bf718ae4d1c4d014214442 100644 (file)
@@ -28,6 +28,7 @@
 #include "autos.h"
 #include "filexml.inc"
 #include "keyframe.inc"
+#include "plugin.inc"
 
 
 // Keyframes inherit from Autos to reuse the editing commands but
@@ -38,7 +39,7 @@
 class KeyFrames : public Autos
 {
 public:
-       KeyFrames(EDL *edl, Track *track);
+       KeyFrames(EDL *edl, Plugin *plugin);
        ~KeyFrames();
 
 // Get keyframes for editing with automatic creation if enabled.
@@ -46,14 +47,7 @@ public:
        virtual KeyFrame* get_keyframe();
 // Get the previous, first, or default keyframe depending on how many keyframes
 // exist.
-       KeyFrame* get_prev_keyframe(int64_t position,
-               int direction);
-
-// Keyframe updates using rules.
-// If a range is selected, the changed parameter is copied to all
-// the keyframes.
-// If no range is selected, a keyframe is created based on auto keyframe rules.
-       void update_parameter(KeyFrame *src);
+       KeyFrame* get_prev_keyframe(int64_t position, int direction);
 
        Auto* new_auto();
        void dump(FILE *fp=stdout);
index 36b10330a52fd7c6010f78fed7f42571f4fc8eb0..dce1f5b7aaadc654b6385d406a0b6cf925893a35 100644 (file)
@@ -49,7 +49,7 @@ Plugin::Plugin(EDL *edl, Track *track, const char *title)
        show = 0;
        on = 1;
        gui_id = -1;
-       keyframes = new KeyFrames(edl, track);
+       keyframes = new KeyFrames(edl, this);
        keyframes->create_objects();
 }
 
@@ -66,7 +66,7 @@ Plugin::Plugin(EDL *edl, PluginSet *plugin_set, const char *title)
        show = 0;
        on = 1;
        gui_id = -1;
-       keyframes = new KeyFrames(edl, track);
+       keyframes = new KeyFrames(edl, this);
        keyframes->create_objects();
 }
 
index 467fa2aa8346bb3909698f9135dc8bde924b9799..94a208844658668db4048770b28b1eefb3044843 100644 (file)
@@ -1083,9 +1083,12 @@ int PluginClient::send_configure_change()
        if(server->mwindow)
                server->mwindow->undo->update_undo_before(_("tweek"), this);
 #ifdef USE_KEYFRAME_SPANNING
-       KeyFrame keyframe;
+       EDL *edl = server->edl;
+        Plugin *plugin = edl->tracks->plugin_exists(server->plugin_id);
+       KeyFrames *keyframes = plugin ? plugin->keyframes : 0;
+       KeyFrame keyframe(edl, keyframes);
        save_data(&keyframe);
-       server->apply_keyframe(&keyframe);
+       server->apply_keyframe(plugin, &keyframe);
 #else
        KeyFrame* keyframe = server->get_keyframe();
 // Call save routine in plugin
@@ -1097,6 +1100,14 @@ int PluginClient::send_configure_change()
        return 0;
 }
 
+// virtual default spanning keyframe update.  If a range is selected,
+// then changed parameters are copied to (prev + selected) keyframes.
+// redefine per client for custom keyframe updates, see tracer, sketcher, crikey
+void PluginClient::span_keyframes(KeyFrame *src, int64_t start, int64_t end)
+{
+       src->span_keyframes(start, end);
+}
+
 
 KeyFrame* PluginClient::get_prev_keyframe(int64_t position, int is_local)
 {
@@ -1164,3 +1175,4 @@ int PluginClient::gui_open()
        return server->gui_open();
 }
 
+
index 8abf7666dbf39ea4877a160dc5605e7045027133..b338debaf09f5f5037aa9fa7ed60e4dc2185d22f 100644 (file)
@@ -381,7 +381,7 @@ public:
 // console.  This gets a keyframe from the EDL, with the position set to the
 // EDL tracking position.
        int send_configure_change();
-
+       virtual void span_keyframes(KeyFrame *src, int64_t start, int64_t end);
 
 // Called from process_buffer
 // Returns 1 if a GUI is open so OpenGL routines can determine if
index f10cec05742a4a1ceb679d3da7b96c183a65388a..18619cc7ad98ff2d88c7f16eabb5df4128de393a 100644 (file)
@@ -1174,16 +1174,28 @@ KeyFrame* PluginServer::get_keyframe()
 }
 
 
-void PluginServer::apply_keyframe(KeyFrame *src)
-{
-       Plugin *plugin = edl->tracks->plugin_exists(plugin_id);
-       if( !plugin )
-               keyframe->copy_data(src);
-       else if( plugin->is_transition() )
-               plugin->get_keyframe()->copy_data(src);
-       else
-// Span keyframes
-               plugin->keyframes->update_parameter(src);
+void PluginServer::apply_keyframe(Plugin *plugin, KeyFrame *src)
+{
+       KeyFrame* dst = !plugin ? keyframe :
+               plugin->is_transition() ? plugin->get_keyframe() : 0;
+       if( !dst ) {
+               if( edl->session->span_keyframes ) {
+                       double selection_start = edl->local_session->get_selectionstart(0);
+                       double selection_end = edl->local_session->get_selectionend(0);
+                       selection_start = edl->align_to_frame(selection_start, 0);
+                       selection_end = edl->align_to_frame(selection_end, 0);
+                       Track *track = plugin->track;
+                       int64_t start = track->to_units(selection_start, 1);
+                       int64_t end = track->to_units(selection_end, 1);
+                       if( start != end ) {
+                               client->span_keyframes(src, start, end);
+                               return;
+                       }
+               }
+               dst = get_keyframe();
+       }
+       if( dst )
+               dst->copy_data(src);
 }
 
 
index f0c8500de5bee094dcebf8bac8671807cfd235ec..1808db7e2435c502795eec3b8f23e113baa1f784 100644 (file)
@@ -170,7 +170,7 @@ public:
        KeyFrame* get_keyframe();
 // Apply new settings from the plugin GUI.  Called by PluginClient::send_configure_change
 // Used in keyframe spanning mode.
-       void apply_keyframe(KeyFrame *src);
+       void apply_keyframe(Plugin *plugin, KeyFrame *src);
 
 // Create new theme object.  Used by theme plugins.
        Theme* new_theme();
index 2dabe6adb092d7b698a01b8759426d6c10029ab1..d9c160f16f8c2c097e4f5309f5f3ca87bc83ed3f 100644 (file)
@@ -329,7 +329,7 @@ void PresetsDBPlugin::load(FileXML *file, int is_factory)
                                const char *keyframe_title = file->tag.get_property("TITLE", string);
                                PresetsDBKeyframe *keyframe = new PresetsDBKeyframe(keyframe_title, is_factory);
                                XMLBuffer data;
-                               file->read_text_until("/KEYFRAME", &data);
+                               file->read_data_until("/KEYFRAME", &data);
                                keyframe->set_data(data.cstr());
                                keyframes.append(keyframe);
                
@@ -352,7 +352,7 @@ void PresetsDBPlugin::save(FileXML *file)
                        file->tag.set_title("KEYFRAME");
                        file->tag.set_property("TITLE", keyframe->title);
                        file->append_tag();
-                       file->append_text(keyframe->data);
+                       file->append_data(keyframe->data);
                        file->tag.set_title("/KEYFRAME");
                        file->append_tag();
                        file->append_newline();
index c92f2d5621e5f6680cb72994f2d61b6e3fcc0e41..b424a2aca5d1f64d9ebe3d79b2683cb8137507b1 100644 (file)
@@ -11,7 +11,7 @@ public:
 
        int get_item_number() { return !list ? -1 : list->number_of((TYPE*)this); }
        ListItem() { list = 0;  previous = next = 0; }
-       ListItem(List<TYPE> &me) { list = me;  previous = next = 0; }
+       ListItem(List<TYPE> *me) { list = me;  previous = next = 0; }
        virtual ~ListItem() { if( list ) list->remove_pointer(this); }
 };
 
index d5a6cd13f4c740dc711adeb03472821c14e5ce0e..8431842294a62fbda76e1535f8ddb8b1d7e893a2 100644 (file)
 #include "filexml.h"
 #include "crikey.h"
 #include "crikeywindow.h"
+#include "keyframe.h"
+#include "keyframes.h"
 #include "language.h"
+#include "transportque.inc"
 #include "vframe.h"
 
 // chroma interpolated key, crikey
@@ -270,7 +273,7 @@ int CriKey::new_point()
        return config.add_point(-1, 0, x, y, 0.5f);
 }
 
-void CriKey::save_data(KeyFrame *keyframe)
+void CriKeyConfig::save_data(KeyFrame *keyframe)
 {
        FileXML output;
 
@@ -278,17 +281,17 @@ void CriKey::save_data(KeyFrame *keyframe)
        output.set_shared_output(keyframe->xbuf);
 
        output.tag.set_title("CRIKEY");
-       output.tag.set_property("THRESHOLD", config.threshold);
-       output.tag.set_property("DRAW_MODE", config.draw_mode);
-       output.tag.set_property("DRAG", config.drag);
-       output.tag.set_property("SELECTED", config.selected);
+       output.tag.set_property("THRESHOLD", threshold);
+       output.tag.set_property("DRAW_MODE", draw_mode);
+       output.tag.set_property("DRAG", drag);
+       output.tag.set_property("SELECTED", selected);
        output.append_tag();
        output.append_newline();
        output.tag.set_title("/CRIKEY");
        output.append_tag();
        output.append_newline();
-       for( int i=0, n = config.points.size(); i<n; ++i ) {
-               CriKeyPoint *pt = config.points[i];
+       for( int i=0, n = points.size(); i<n; ++i ) {
+               CriKeyPoint *pt = points[i];
                char point[BCSTRLEN];
                sprintf(point,"/POINT_%d",pt->tag);
                output.tag.set_title(point+1);
@@ -304,20 +307,25 @@ void CriKey::save_data(KeyFrame *keyframe)
        output.terminate_string();
 }
 
-void CriKey::read_data(KeyFrame *keyframe)
+void CriKey::save_data(KeyFrame *keyframe)
+{
+       config.save_data(keyframe);
+}
+
+void CriKeyConfig::read_data(KeyFrame *keyframe)
 {
        FileXML input;
        input.set_shared_input(keyframe->xbuf);
-       config.points.remove_all_objects();
+       points.remove_all_objects();
        int result = 0;
 
        while( !(result=input.read_tag()) ) {
                if( input.tag.title_is("CRIKEY") ) {
-                       config.threshold = input.tag.get_property("THRESHOLD", config.threshold);
-                       config.draw_mode = input.tag.get_property("DRAW_MODE", config.draw_mode);
-                       config.drag = input.tag.get_property("DRAG", config.drag);
-                       config.selected = input.tag.get_property("SELECTED", 0);
-                       config.limits();
+                       threshold = input.tag.get_property("THRESHOLD", threshold);
+                       draw_mode = input.tag.get_property("DRAW_MODE", draw_mode);
+                       drag = input.tag.get_property("DRAG", drag);
+                       selected = input.tag.get_property("SELECTED", 0);
+                       limits();
                }
                else if( !strncmp(input.tag.get_title(),"POINT_",6) ) {
                        int tag = atoi(input.tag.get_title() + 6);
@@ -325,13 +333,72 @@ void CriKey::read_data(KeyFrame *keyframe)
                        float x = input.tag.get_property("X", 0.f);
                        float y = input.tag.get_property("Y", 0.f);
                        float t = input.tag.get_property("T", .5f);
-                       config.add_point(tag, e, x, y, t);
+                       add_point(tag, e, x, y, t);
                }
        }
+}
 
+void CriKey::read_data(KeyFrame *keyframe)
+{
+       config.read_data(keyframe);
        if( !config.points.size() ) new_point();
 }
 
+void CriKey::span_keyframes(KeyFrame *src, int64_t start, int64_t end)
+{
+       CriKeyConfig src_config;
+       src_config.read_data(src);
+       KeyFrames *keyframes = (KeyFrames *)src->autos;
+       KeyFrame *prev = keyframes->get_prev_keyframe(start, PLAY_FORWARD);
+       CriKeyConfig prev_config;
+       prev_config.read_data(prev);
+// Always update the first one
+       update_parameter(prev_config, src_config, prev);
+       KeyFrame *curr = (KeyFrame*)prev->next;
+       while( curr && curr->position < end ) {
+               update_parameter(prev_config, src_config, curr);
+               curr = (KeyFrame*)curr->next;
+       }
+}
+
+void CriKeyPoint::update_parameter(CriKeyPoint *prev, CriKeyPoint *src)
+{
+       if( prev->e != src->e ) e = src->e;
+       if( prev->x != src->x ) x = src->x;
+       if( prev->y != src->y ) y = src->y;
+       if( prev->t != src->t ) t = src->t;
+}
+
+void CriKey::update_parameter(CriKeyConfig &prev_config, CriKeyConfig &src_config,
+               KeyFrame *keyframe)
+{
+       CriKeyConfig dst_config;
+       dst_config.read_data(keyframe);
+       if( !EQUIV(prev_config.threshold, src_config.threshold) )
+               dst_config.threshold = src_config.threshold;
+       if( prev_config.draw_mode != src_config.draw_mode )
+               dst_config.draw_mode = src_config.draw_mode;
+       if( prev_config.drag != src_config.drag )
+               dst_config.drag = src_config.drag;
+       int src_points = src_config.points.size();
+       int dst_points = dst_config.points.size();
+       int prev_points = prev_config.points.size();
+       int npoints = bmin(prev_points, bmin(src_points, dst_points));
+       for( int i=0; i<npoints; ++i ) {
+               CriKeyPoint *src_point = src_config.points[i];
+               int tag = src_point->tag, k = prev_points;
+               while( --k >= 0 && tag != prev_config.points[k]->tag );
+               if( k < 0 ) continue;
+               CriKeyPoint *prev_point = prev_config.points[k];
+               k = dst_points;
+               while( --k >= 0 && tag != dst_config.points[k]->tag );
+               if( k < 0 ) continue;
+               CriKeyPoint *dst_point = dst_config.points[k];
+               dst_point->update_parameter(prev_point, src_point);
+       }
+       dst_config.save_data(keyframe);
+}
+
 void CriKey::update_gui()
 {
        if( !thread ) return;
@@ -666,14 +733,14 @@ LoadClient* CriKeyEngine::new_client()
                        float a00 = 0, a01 = 0, a10 = 0, a11 = 0; \
                        for( int c=0; c<comps; ++c,++r0,++r1 ) { \
                                float t = target_color[c]; \
-                                a00 += fabs(t - r0[0]); \
+                               a00 += fabs(t - r0[0]); \
                                a01 += fabs(t - r0[components]); \
                                a10 += fabs(t - r1[0]); \
                                a11 += fabs(t - r1[components]); \
                        } \
                        float mx = scale * bmax(bmax(a00, a01), bmax(a10, a11)); \
                        if( mx < threshold ) continue; \
-                        float mn = scale * bmin(bmin(a00, a01), bmin(a10, a11)); \
+                       float mn = scale * bmin(bmin(a00, a01), bmin(a10, a11)); \
                        if( mn >= threshold ) continue; \
                        *edgp += (mx - mn); \
                } \
index 21e602e7c669ff534484b5a21eaceb62f1469306..ca452b04de462a65c7f9c623719bb41bd43f3c23 100644 (file)
@@ -44,6 +44,7 @@ public:
 
        CriKeyPoint(int tag, int e, float x, float y, float t);
        ~CriKeyPoint();
+       void update_parameter(CriKeyPoint *prev, CriKeyPoint *src);
 };
 class CriKeyPoints : public ArrayList<CriKeyPoint *>
 {
@@ -58,6 +59,8 @@ public:
        CriKeyConfig();
        ~CriKeyConfig();
 
+       void save_data(KeyFrame *keyframe);
+       void read_data(KeyFrame *keyframe);
        int equivalent(CriKeyConfig &that);
        void copy_from(CriKeyConfig &that);
        void interpolate(CriKeyConfig &prev, CriKeyConfig &next,
@@ -128,6 +131,9 @@ public:
        void draw_edge(VFrame *frm);
        void draw_mask(VFrame *frm);
        void draw_point(VFrame *msk, CriKeyPoint *pt);
+       void span_keyframes(KeyFrame *src, int64_t start, int64_t end);
+       void update_parameter(CriKeyConfig &prev_config, CriKeyConfig &src_config,
+                KeyFrame *keyframe);
 
        CriKeyEngine *engine;
        VFrame *src, *edg, *msk;
index 3bfa66fe7f13e7164fa7d2c53b725082074b41d1..39c63d43ce407a42865ef3e829bacc01f533dc64 100644 (file)
@@ -120,7 +120,7 @@ PerspectiveWindow::~PerspectiveWindow()
 
 void PerspectiveWindow::create_objects()
 {
-       int xs10 = xS(10), xs20 = xS(20), xs80 = xS(80), xs100 = xS(100), xs120 = xS(120);
+       int xs10 = xS(10), xs20 = xS(20), xs100 = xS(100), xs120 = xS(120);
        int ys5 = yS(5), ys10 = yS(10), ys30 = yS(30), ys40 = yS(40);
        int x = xs10, y = ys10;
 
@@ -128,16 +128,24 @@ void PerspectiveWindow::create_objects()
                x, y, get_w() - xs20, get_h() - yS(290)));
        canvas->set_cursor(CROSS_CURSOR, 0, 0);
        y += canvas->get_h() + ys10;
-       add_subwindow(new BC_Title(x, y, _("Current X:")));
-       x += xs80;
+       int x1 = x;
+       BC_Title *title;
+       add_subwindow(title = new BC_Title(x1, y, _("Current: ")));
+       x1 += title->get_w() + xs10;
+       char string[BCSTRLEN];
+       sprintf(string, "%d", plugin->config.current_point+1);
+       add_subwindow(curr_point = new BC_Title(x1, y, string));
+       x1 += xs20;
+       add_subwindow(title = new BC_Title(x1, y, _("X:")));
+       x1 += title->get_w() + xs10;
        this->x = new PerspectiveCoord(this,
-               x, y, plugin->get_current_x(), 1);
+               x1, y, plugin->get_current_x(), 1);
        this->x->create_objects();
-       x += xS(140);
-       add_subwindow(new BC_Title(x, y, _("Y:")));
-       x += xs20;
+       x1 += this->x->get_w() + xs20;
+       add_subwindow(new BC_Title(x1, y, _("Y:")));
+       x1 += title->get_w() + xs10;
        this->y = new PerspectiveCoord(this,
-               x, y, plugin->get_current_y(), 0);
+               x1, y, plugin->get_current_y(), 0);
        this->y->create_objects();
        x = xs10;   y += ys30;
        add_subwindow(mode_perspective = new PerspectiveMode(this,
@@ -156,9 +164,9 @@ void PerspectiveWindow::create_objects()
        update_canvas();
 
        x = xs10;   y += ys30;
-       BC_Title *title;
        add_subwindow(title = new BC_Title(x, y, _("Zoom view:")));
-       int x1 = x + title->get_w() + xs10, w1 = get_w() - x1 - xs10;
+       x1 = x + title->get_w() + xs10;
+       int w1 = get_w() - x1 - xs10;
        add_subwindow(zoom_view = new PerspectiveZoomView(this, x1, y, w1));
        y += ys30;
 
@@ -266,6 +274,12 @@ void PerspectiveWindow::update_canvas()
        canvas->draw_line(vx2, vy2, vx1, vy2);
        canvas->draw_line(vx1, vy2, vx1, vy1);
 
+       canvas->set_color(YELLOW);
+       canvas->draw_text(x1, y1,"1");
+       canvas->draw_text(x2, y2,"2");
+       canvas->draw_text(x3, y3,"3");
+       canvas->draw_text(x4, y4,"4");
+
 //printf("PerspectiveWindow::update_canvas %d,%d %d,%d %d,%d %d,%d\n",
 // x1, y1, x2, y2, x3, y3, x4, y4);
 // Draw divisions
@@ -321,6 +335,9 @@ void PerspectiveWindow::update_mode()
 
 void PerspectiveWindow::update_coord()
 {
+       char string[BCSTRLEN];
+       sprintf(string, "%d", plugin->config.current_point+1);
+       curr_point->update(string);
        x->update(plugin->get_current_x());
        y->update(plugin->get_current_y());
 }
index 074e20ba043e156ed2481b49102f5663d07007a5..dcabb265da3d6bcfaffb428b916d2665f1d14454 100644 (file)
@@ -185,6 +185,7 @@ public:
                int &x3, int &y3, int &x4, int &y4);
 
        PerspectiveCanvas *canvas;
+       BC_Title *curr_point;
        PerspectiveCoord *x, *y;
        PerspectiveReset *reset;
        PerspectiveZoomView *zoom_view;
index 15471ced939482dc717a7f112f7dbe986052663f..cc78511f4158bd25d3e494801653eb9d444ae89c 100644 (file)
 
 
 #include "rotate.h"
+#include "theme.h"
+
+#define MAXANGLE 360.00
+#define MINPIVOT   0.00
+#define MAXPIVOT 100.00
 
-#define MAXANGLE 360
 
 REGISTER_PLUGIN(RotateEffect)
 
@@ -31,15 +35,30 @@ REGISTER_PLUGIN(RotateEffect)
 
 RotateConfig::RotateConfig()
 {
-       reset();
-}
-
-void RotateConfig::reset()
-{
-       angle = 0.0;
-       pivot_x = 50.0;
-       pivot_y = 50.0;
-       draw_pivot = 0;
+       reset(RESET_DEFAULT_SETTINGS);
+}
+
+void RotateConfig::reset(int clear)
+{
+       switch(clear) {
+               case RESET_ANGLE :
+                       angle = 0.0;
+                       break;
+               case RESET_PIVOT_X :
+                       pivot_x = 50.0;
+                       break;
+               case RESET_PIVOT_Y :
+                       pivot_y = 50.0;
+                       break;
+               case RESET_ALL :
+               case RESET_DEFAULT_SETTINGS :
+               default:
+                       angle = 0.0;
+                       pivot_x = 50.0;
+                       pivot_y = 50.0;
+                       draw_pivot = 0;
+                       break;
+       }
 }
 
 int RotateConfig::equivalent(RotateConfig &that)
@@ -149,97 +168,138 @@ int RotateDrawPivot::handle_event()
 
 
 
-RotateFine::RotateFine(RotateWindow *window, RotateEffect *plugin, int x, int y)
- : BC_FPot(x,
-       y,
-       (float)plugin->config.angle,
-       (float)-360,
-       (float)360)
+RotateAngleText::RotateAngleText(RotateWindow *window, RotateEffect *plugin, int x, int y)
+ : BC_TumbleTextBox(window, (float)plugin->config.angle,
+       (float)-MAXANGLE, (float)MAXANGLE, x, y, xS(60), 2)
 {
        this->window = window;
        this->plugin = plugin;
+}
+
+int RotateAngleText::handle_event()
+{
+       plugin->config.angle = atof(get_text());
+       window->update_toggles();
+       window->update_sliders();
+       plugin->send_configure_change();
+       return 1;
+}
+
+
+RotateAngleSlider::RotateAngleSlider(RotateWindow *window, RotateEffect *plugin, int x, int y, int w)
+ : BC_FSlider(x, y, 0, w, w, (float)-MAXANGLE, (float)MAXANGLE, (float)plugin->config.angle)
+{
+       this->window = window;
+       this->plugin = plugin;
+       enable_show_value(0); // Hide caption
        set_precision(0.1);
-       set_use_caption(0);
 }
 
-int RotateFine::handle_event()
+int RotateAngleSlider::handle_event()
 {
        plugin->config.angle = get_value();
        window->update_toggles();
-       window->update_text();
+       window->update_texts();
        plugin->send_configure_change();
        return 1;
 }
 
 
 
-RotateText::RotateText(RotateWindow *window,
-       RotateEffect *plugin,
-       int x,
-       int y)
- : BC_TextBox(x,
-       y,
-       xS(90),
-       1,
-       (float)plugin->config.angle)
+RotatePivotXText::RotatePivotXText(RotateWindow *window, RotateEffect *plugin, int x, int y)
+ : BC_TumbleTextBox(window, (float)plugin->config.pivot_x,
+       (float)MINPIVOT, (float)MAXPIVOT, x, y, xS(60), 2)
 {
        this->window = window;
        this->plugin = plugin;
-       set_precision(4);
 }
 
-int RotateText::handle_event()
+int RotatePivotXText::handle_event()
 {
-       plugin->config.angle = atof(get_text());
-       window->update_toggles();
-       window->update_fine();
+       plugin->config.pivot_x = atof(get_text());
+       window->update_sliders();
        plugin->send_configure_change();
        return 1;
 }
 
 
-
-RotateX::RotateX(RotateWindow *window, RotateEffect *plugin, int x, int y)
- : BC_FPot(x,
-       y,
-       (float)plugin->config.pivot_x,
-       (float)0,
-       (float)100)
+RotatePivotXSlider::RotatePivotXSlider(RotateWindow *window, RotateEffect *plugin, int x, int y, int w)
+ : BC_FSlider(x, y, 0, w, w, (float)MINPIVOT, (float)MAXPIVOT, (float)plugin->config.pivot_x)
 {
        this->window = window;
        this->plugin = plugin;
-       set_precision(0.01);
-       set_use_caption(1);
+       enable_show_value(0); // Hide caption
+       set_precision(0.1);
 }
 
-int RotateX::handle_event()
+int RotatePivotXSlider::handle_event()
 {
        plugin->config.pivot_x = get_value();
+       window->update_toggles();
+       window->update_texts();
        plugin->send_configure_change();
        return 1;
 }
 
-RotateY::RotateY(RotateWindow *window, RotateEffect *plugin, int x, int y)
- : BC_FPot(x,
-       y,
-       (float)plugin->config.pivot_y,
-       (float)0,
-       (float)100)
+
+RotatePivotYText::RotatePivotYText(RotateWindow *window, RotateEffect *plugin, int x, int y)
+ : BC_TumbleTextBox(window, (float)plugin->config.pivot_y,
+       (float)MINPIVOT, (float)MAXPIVOT, x, y, xS(60), 2)
 {
        this->window = window;
        this->plugin = plugin;
-       set_precision(0.01);
-       set_use_caption(1);
 }
 
-int RotateY::handle_event()
+int RotatePivotYText::handle_event()
+{
+       plugin->config.pivot_y = atof(get_text());
+       plugin->send_configure_change();
+       return 1;
+}
+
+
+RotatePivotYSlider::RotatePivotYSlider(RotateWindow *window, RotateEffect *plugin, int x, int y, int w)
+ : BC_FSlider(x, y, 0, w, w, (float)MINPIVOT, (float)MAXPIVOT, (float)plugin->config.pivot_y)
+{
+       this->window = window;
+       this->plugin = plugin;
+       enable_show_value(0); // Hide caption
+       set_precision(0.1);
+}
+
+int RotatePivotYSlider::handle_event()
 {
        plugin->config.pivot_y = get_value();
+       window->update_toggles();
+       window->update_texts();
+       plugin->send_configure_change();
+       return 1;
+}
+
+
+
+RotateClr::RotateClr(RotateWindow *window, RotateEffect *plugin, int x, int y, int clear)
+ : BC_Button(x, y, plugin->get_theme()->get_image_set("reset_button"))
+{
+       this->window = window;
+       this->plugin = plugin;
+       this->clear = clear;
+}
+
+RotateClr::~RotateClr()
+{
+}
+
+int RotateClr::handle_event()
+{
+       plugin->config.reset(clear);
+       window->update();
        plugin->send_configure_change();
        return 1;
 }
 
 
+
 RotateReset::RotateReset(RotateEffect *plugin, RotateWindow *window, int x, int y)
  : BC_GenericButton(x, y, _("Reset"))
 {
@@ -251,7 +311,7 @@ RotateReset::~RotateReset()
 }
 int RotateReset::handle_event()
 {
-       plugin->config.reset();
+       plugin->config.reset(RESET_ALL);
        window->update();
        plugin->send_configure_change();
        return 1;
@@ -263,7 +323,7 @@ int RotateReset::handle_event()
 
 
 RotateWindow::RotateWindow(RotateEffect *plugin)
- : PluginClientWindow(plugin, xS(300), yS(230), xS(300), yS(230), 0)
+ : PluginClientWindow(plugin, xS(420), yS(260), xS(420), yS(260), 0)
 {
        this->plugin = plugin;
 }
@@ -272,42 +332,69 @@ RotateWindow::RotateWindow(RotateEffect *plugin)
 
 void RotateWindow::create_objects()
 {
-       int xs10 = xS(10), xs50 = xS(50), xs150 = xS(150);
-       int ys10 = yS(10), ys20 = yS(20), ys25 = yS(25), ys50 = yS(50), ys60 = yS(60);
+       int xs10 = xS(10), xs20 = xS(20), xs64 = xS(64), xs200 = xS(200);
+       int ys10 = yS(10), ys20 = yS(20), ys30 = yS(30), ys40 = yS(40);
+       int x2 = xS(80), x3 = xS(180);
        int x = xs10, y = ys10;
-       BC_Title *title;
-       add_tool(new BC_Title(x, y, _("Rotate")));
-       x += xs50;  y += ys20;
+       int clr_x = get_w()-x - xS(22); // note: clrBtn_w = 22
+
+       BC_TitleBar *title_bar;
+       BC_Bar *bar;
+
+// Angle section
+       add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, xs20, xs10, _("Rotation")));
+       x = xs10;  y += ys20;
+       add_tool(new BC_Title(x, y, _("Preset:")));
+       x = x + x2; 
+       add_tool(toggle180neg = new RotateToggle(this, plugin,
+               plugin->config.angle == -180, x, y, -180, "-180°"));
+       x += xs64;
+       add_tool(toggle90neg = new RotateToggle(this, plugin,
+               plugin->config.angle == -90, x, y, -90, "-90°"));
+       x += xs64;
        add_tool(toggle0 = new RotateToggle(this, plugin,
-               plugin->config.angle == 0, x, y, 0, "0"));
-    x += RADIUS;  y += RADIUS;
+               plugin->config.angle == 0, x, y, 0, "0°"));
+       x += xs64;
        add_tool(toggle90 = new RotateToggle(this, plugin,
-               plugin->config.angle == 90, x, y, 90, "90"));
-    x -= RADIUS;  y += RADIUS;
+               plugin->config.angle == 90, x, y, 90, "+90°"));
+       x += xs64;
        add_tool(toggle180 = new RotateToggle(this, plugin,
-               plugin->config.angle == 180, x, y, 180, "180"));
-    x -= RADIUS;  y -= RADIUS;
-       add_tool(toggle270 = new RotateToggle(this, plugin,
-               plugin->config.angle == 270, x, y, 270, "270"));
+               plugin->config.angle == 180, x, y, 180, "+180°"));
 //     add_subwindow(bilinear = new RotateInterpolate(plugin, xs10, y + ys60));
-       x += xs150;  y -= ys50;
-       add_tool(fine = new RotateFine(this, plugin, x, y));
-       y += fine->get_h() + ys10;
-       add_tool(text = new RotateText(this, plugin, x, y));
-       y += ys25;
-       add_tool(new BC_Title(x, y, _("Degrees")));
-
-       y += text->get_h() + ys10;
-       add_subwindow(title = new BC_Title(x, y, _("Pivot (x,y):")));
-       y += title->get_h() + ys10;
-       add_subwindow(this->x = new RotateX(this, plugin, x, y));
-       x += this->x->get_w() + xs10;
-       add_subwindow(this->y = new RotateY(this, plugin, x, y));
-
-//     y += this->y->get_h() + ys10;
-       x = xs10;
+       x = xs10;  y += ys30;
+       add_tool(new BC_Title(x, y, _("Angle:")));
+       rotate_angle_text = new RotateAngleText(this, plugin, (x + x2), y);
+       rotate_angle_text->create_objects();
+       add_tool(rotate_angle_slider = new RotateAngleSlider(this, plugin, x3, y, xs200));
+       add_tool(rotate_angle_clr = new RotateClr(this, plugin,
+               clr_x, y, RESET_ANGLE));
+       y += ys40;
+
+// Pivot section
+       add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, xs20, xs10, _("Pivot")));
+       y += ys20;
        add_subwindow(draw_pivot = new RotateDrawPivot(this, plugin, x, y));
-       y += ys60;
+       y += ys30;
+       add_tool(new BC_Title(x, y, _("X:")));
+       add_tool(new BC_Title((x2-x), y, _("%")));
+       rotate_pivot_x_text = new RotatePivotXText(this, plugin, (x + x2), y);
+       rotate_pivot_x_text->create_objects();
+       add_tool(rotate_pivot_x_slider = new RotatePivotXSlider(this, plugin, x3, y, xs200));
+       add_tool(rotate_pivot_x_clr = new RotateClr(this, plugin,
+               clr_x, y, RESET_PIVOT_X));
+       y += ys30;
+       add_tool(new BC_Title(x, y, _("Y:")));
+       add_tool(new BC_Title((x2-x), y, _("%")));
+       rotate_pivot_y_text = new RotatePivotYText(this, plugin, (x + x2), y);
+       rotate_pivot_y_text->create_objects();
+       add_tool(rotate_pivot_y_slider = new RotatePivotYSlider(this, plugin, x3, y, xs200));
+       add_tool(rotate_pivot_y_clr = new RotateClr(this, plugin,
+               clr_x, y, RESET_PIVOT_Y));
+       y += ys40;
+
+// Reset section
+       add_subwindow(bar = new BC_Bar(x, y, get_w()-2*x));
+       y += ys10;
        add_subwindow(reset = new RotateReset(plugin, this, x, y));
 
        show_window();
@@ -317,33 +404,36 @@ void RotateWindow::create_objects()
 
 int RotateWindow::update()
 {
-       update_fine();
+       update_sliders();
        update_toggles();
-       update_text();
+       update_texts();
 //     bilinear->update(plugin->config.bilinear);
        return 0;
 }
 
-int RotateWindow::update_fine()
+int RotateWindow::update_sliders()
 {
-       fine->update(plugin->config.angle);
-       x->update(plugin->config.pivot_x);
-       y->update(plugin->config.pivot_y);
+       rotate_angle_slider->update(plugin->config.angle);
+       rotate_pivot_x_slider->update(plugin->config.pivot_x);
+       rotate_pivot_y_slider->update(plugin->config.pivot_y);
        return 0;
 }
 
-int RotateWindow::update_text()
+int RotateWindow::update_texts()
 {
-       text->update(plugin->config.angle);
+       rotate_angle_text->update(plugin->config.angle);
+       rotate_pivot_x_text->update(plugin->config.pivot_x);
+       rotate_pivot_y_text->update(plugin->config.pivot_y);
        return 0;
 }
 
 int RotateWindow::update_toggles()
 {
+       toggle180neg->update(EQUIV(plugin->config.angle, -180));
+       toggle90neg->update(EQUIV(plugin->config.angle, -90));
        toggle0->update(EQUIV(plugin->config.angle, 0));
        toggle90->update(EQUIV(plugin->config.angle, 90));
        toggle180->update(EQUIV(plugin->config.angle, 180));
-       toggle270->update(EQUIV(plugin->config.angle, 270));
        draw_pivot->update(plugin->config.draw_pivot);
        return 0;
 }
index 4a8870b124ebde66706c18d13f92a7c707b3ec97..296e732625e8881cea24a47a97df42a8886c7df9 100644 (file)
 
 class RotateEffect;
 class RotateWindow;
+class RotateToggle;
+class RotateDrawPivot;
+class RotateInterpolate;
+class RotateAngleText;
+class RotateAngleSlider;
+class RotatePivotXText;
+class RotatePivotXSlider;
+class RotatePivotYText;
+class RotatePivotYSlider;
+class RotateClr;
+class RotateReset;
+
+
+#define RESET_DEFAULT_SETTINGS 10
+#define RESET_ALL     0
+#define RESET_ANGLE   1
+#define RESET_PIVOT_X 2
+#define RESET_PIVOT_Y 3
 
 
 class RotateConfig
@@ -48,7 +66,7 @@ class RotateConfig
 public:
        RotateConfig();
 
-       void reset();
+       void reset(int clear);
        int equivalent(RotateConfig &that);
        void copy_from(RotateConfig &that);
        void interpolate(RotateConfig &prev,
@@ -102,10 +120,10 @@ public:
        RotateEffect *plugin;
 };
 
-class RotateFine : public BC_FPot
+class RotateAngleText : public BC_TumbleTextBox
 {
 public:
-       RotateFine(RotateWindow *window,
+       RotateAngleText(RotateWindow *window,
                RotateEffect *plugin,
                int x,
                int y);
@@ -115,35 +133,49 @@ public:
        RotateWindow *window;
 };
 
-class RotateX : public BC_FPot
+class RotateAngleSlider : public BC_FSlider
 {
 public:
-       RotateX(RotateWindow *window,
+       RotateAngleSlider(RotateWindow *window,
                RotateEffect *plugin,
-               int x,
-               int y);
+               int x, int y, int w);
        int handle_event();
+
        RotateEffect *plugin;
        RotateWindow *window;
 };
 
-class RotateY : public BC_FPot
+
+class RotatePivotXText : public BC_TumbleTextBox
 {
 public:
-       RotateY(RotateWindow *window,
+       RotatePivotXText(RotateWindow *window,
                RotateEffect *plugin,
                int x,
                int y);
        int handle_event();
+
+       RotateEffect *plugin;
+       RotateWindow *window;
+};
+
+class RotatePivotXSlider : public BC_FSlider
+{
+public:
+       RotatePivotXSlider(RotateWindow *window,
+               RotateEffect *plugin,
+               int x, int y, int w);
+       int handle_event();
+
        RotateEffect *plugin;
        RotateWindow *window;
 };
 
 
-class RotateText : public BC_TextBox
+class RotatePivotYText : public BC_TumbleTextBox
 {
 public:
-       RotateText(RotateWindow *window,
+       RotatePivotYText(RotateWindow *window,
                RotateEffect *plugin,
                int x,
                int y);
@@ -153,10 +185,39 @@ public:
        RotateWindow *window;
 };
 
+class RotatePivotYSlider : public BC_FSlider
+{
+public:
+       RotatePivotYSlider(RotateWindow *window,
+               RotateEffect *plugin,
+               int x, int y, int w);
+       int handle_event();
+
+       RotateEffect *plugin;
+       RotateWindow *window;
+};
+
+
+
+
+class RotateClr : public BC_Button
+{
+public:
+       RotateClr(RotateWindow *window, RotateEffect *plugin,
+               int x, int y, int clear);
+       ~RotateClr();
+       int handle_event();
+       RotateEffect *plugin;
+       RotateWindow *window;
+       int clear;
+};
+
+
 class RotateReset : public BC_GenericButton
 {
 public:
-       RotateReset(RotateEffect *plugin, RotateWindow *window, int x, int y);
+       RotateReset(RotateEffect *plugin, RotateWindow *window,
+       int x, int y);
        ~RotateReset();
        int handle_event();
        RotateEffect *plugin;
@@ -172,20 +233,31 @@ public:
        void create_objects();
 
        int update();
-       int update_fine();
-       int update_text();
+       int update_sliders();
+       int update_texts();
        int update_toggles();
 
        RotateEffect *plugin;
+       RotateToggle *toggle180neg;
+       RotateToggle *toggle90neg;
        RotateToggle *toggle0;
        RotateToggle *toggle90;
        RotateToggle *toggle180;
-       RotateToggle *toggle270;
+
+       RotateAngleText *rotate_angle_text;
+       RotateAngleSlider *rotate_angle_slider;
+       RotateClr *rotate_angle_clr;
+
        RotateDrawPivot *draw_pivot;
-       RotateFine *fine;
-       RotateText *text;
-       RotateX *x;
-       RotateY *y;
+
+       RotatePivotXText *rotate_pivot_x_text;
+       RotatePivotXSlider *rotate_pivot_x_slider;
+       RotateClr *rotate_pivot_x_clr;
+
+       RotatePivotYText *rotate_pivot_y_text;
+       RotatePivotYSlider *rotate_pivot_y_slider;
+       RotateClr *rotate_pivot_y_clr;
+
 //     RotateInterpolate *bilinear;
        RotateReset *reset;
 };
index 2b392327176b85cdb35e3a22cd8283dd6ff85d3c..c57bfc0bda5888c22f69b0663bafa8f90135c9e5 100644 (file)
 #include "edl.h"
 #include "edlsession.h"
 #include "filexml.h"
+#include "keyframes.h"
 #include "overlayframe.h"
 #include "pluginserver.h"
 #include "preferences.h"
 #include "sketcher.h"
 #include "sketcherwindow.h"
+#include "transportque.inc"
 #include "language.h"
 #include "vframe.h"
 
@@ -356,21 +358,21 @@ int Sketcher::is_synthesis() { return 1; }
 NEW_WINDOW_MACRO(Sketcher, SketcherWindow);
 LOAD_CONFIGURATION_MACRO(Sketcher, SketcherConfig)
 
-void Sketcher::save_data(KeyFrame *keyframe)
+void SketcherConfig::save_data(KeyFrame *keyframe)
 {
        FileXML output;
 // cause data to be stored directly in text
        output.set_shared_output(keyframe->xbuf);
 
        output.tag.set_title("SKETCHER");
-       output.tag.set_property("DRAG", config.drag);
-       output.tag.set_property("ALIASING", config.aliasing);
-       output.tag.set_property("CV_SELECTED", config.cv_selected);
-       output.tag.set_property("PT_SELECTED", config.pt_selected);
+       output.tag.set_property("DRAG", drag);
+       output.tag.set_property("ALIASING", aliasing);
+       output.tag.set_property("CV_SELECTED", cv_selected);
+       output.tag.set_property("PT_SELECTED", pt_selected);
        output.append_tag();
        output.append_newline();
-       for( int i=0,n=config.curves.size(); i<n; ++i ) {
-               config.curves[i]->save_data(output);
+       for( int i=0,n=curves.size(); i<n; ++i ) {
+               curves[i]->save_data(output);
        }
        output.tag.set_title("/SKETCHER");
        output.append_tag();
@@ -378,25 +380,30 @@ void Sketcher::save_data(KeyFrame *keyframe)
        output.terminate_string();
 }
 
-void Sketcher::read_data(KeyFrame *keyframe)
+void Sketcher::save_data(KeyFrame *keyframe)
+{
+       config.save_data(keyframe);
+}
+
+void SketcherConfig::read_data(KeyFrame *keyframe)
 {
        FileXML input;
        input.set_shared_input(keyframe->xbuf);
-       config.curves.remove_all_objects();
+       curves.remove_all_objects();
        int result = 0;
        SketcherCurve *cv = 0;
 
        while( !(result=input.read_tag()) ) {
                if( input.tag.title_is("SKETCHER") ) {
-                       config.drag = input.tag.get_property("DRAG", config.drag);
-                       config.aliasing = input.tag.get_property("ALIASING", config.aliasing);
-                       config.cv_selected = input.tag.get_property("CV_SELECTED", 0);
-                       config.pt_selected = input.tag.get_property("PT_SELECTED", 0);
+                       drag = input.tag.get_property("DRAG", drag);
+                       aliasing = input.tag.get_property("ALIASING", aliasing);
+                       cv_selected = input.tag.get_property("CV_SELECTED", 0);
+                       pt_selected = input.tag.get_property("PT_SELECTED", 0);
                }
                else if( !strncmp(input.tag.get_title(),"CURVE_",6) ) {
                        cv = new SketcherCurve();
                        cv->read_data(input);
-                       config.curves.append(cv);
+                       curves.append(cv);
                }
                else if( !strncmp(input.tag.get_title(),"/CURVE_",7) )
                        cv = 0;
@@ -407,13 +414,86 @@ void Sketcher::read_data(KeyFrame *keyframe)
                                cv->points.append(pt);
                        }
                        else
-                               printf("Sketcher::read_data: no curve for point\n");
+                               printf("SketcherConfig::read_data: no curve for point\n");
                }
        }
 
+       limits();
+}
+
+void Sketcher::read_data(KeyFrame *keyframe)
+{
+       config.read_data(keyframe);
        if( !config.curves.size() )
                new_curve();
-       config.limits();
+}
+
+
+void SketcherPoint::update_parameter(SketcherPoint *prev, SketcherPoint *src)
+{
+       if( prev->arc != src->arc ) arc = src->arc;
+       if( prev->x != src->x ) x = src->x;
+       if( prev->y != src->y ) y = src->y;
+}
+
+void SketcherCurve::update_parameter(SketcherCurve *prev, SketcherCurve *src)
+{
+       if( prev->pen != src->pen ) pen = src->pen;
+       if( prev->width != src->width ) width = src->width;
+       if( prev->color != src->color ) color = src->color;
+       int prev_points = prev->points.size();
+       int src_points = src->points.size();
+       int dst_points = this->points.size();
+       int npoints = bmin(prev_points, bmin(src_points, dst_points));
+       for( int i=0; i<npoints; ++i ) {
+               SketcherPoint *prev_point = prev->points[i];
+               SketcherPoint *src_point = src->points[i];
+               SketcherPoint *dst_point = this->points[i];
+               dst_point->update_parameter(prev_point, src_point);
+       }
+}
+
+void Sketcher::span_keyframes(KeyFrame *src, int64_t start, int64_t end)
+{
+       SketcherConfig src_config;
+       src_config.read_data(src);
+       KeyFrames *keyframes = (KeyFrames *)src->autos;
+       KeyFrame *prev = keyframes->get_prev_keyframe(start, PLAY_FORWARD);
+       SketcherConfig prev_config;
+       prev_config.read_data(prev);
+// Always update the first one
+       update_parameter(prev_config, src_config, prev);
+       KeyFrame *curr = (KeyFrame*)prev->next;
+       while( curr && curr->position < end ) {
+               update_parameter(prev_config, src_config, curr);
+               curr = (KeyFrame*)curr->next;
+       }
+}
+
+void Sketcher::update_parameter(SketcherConfig &prev_config, SketcherConfig &src_config,
+               KeyFrame *keyframe)
+{
+       SketcherConfig dst_config;
+       dst_config.read_data(keyframe);
+       if( prev_config.drag != src_config.drag )
+               dst_config.drag = src_config.drag;
+       if( prev_config.aliasing != src_config.aliasing )
+               dst_config.aliasing = src_config.aliasing;
+       if( prev_config.cv_selected != src_config.cv_selected )
+               dst_config.cv_selected = src_config.cv_selected;
+       if( prev_config.pt_selected != src_config.pt_selected )
+               dst_config.pt_selected = src_config.pt_selected;
+       int src_curves = src_config.curves.size();
+       int dst_curves = dst_config.curves.size();
+       int prev_curves = prev_config.curves.size();
+       int ncurves = bmin(prev_curves, bmin(src_curves, dst_curves));
+       for( int i=0; i<ncurves; ++i ) {
+               SketcherCurve *prev_curve = prev_config.curves[i];
+               SketcherCurve *src_curve = src_config.curves[i];
+               SketcherCurve *dst_curve = dst_config.curves[i];
+               dst_curve->update_parameter(prev_curve, src_curve);
+       }
+       dst_config.save_data(keyframe);
 }
 
 void Sketcher::update_gui()
index dcf7a6ba34772c08e92312ed311c23ce4e43e4f0..c8f3be5fda3ea5d15db5195397935491a3815a1d 100644 (file)
@@ -109,6 +109,7 @@ public:
        void save_data(FileXML &output);
        void read_data(FileXML &input);
        static const char *types[ARC_SZ];
+       void update_parameter(SketcherPoint *the, SketcherPoint *src);
 };
 class SketcherPoints : public ArrayList<SketcherPoint *>
 {
@@ -140,6 +141,7 @@ public:
 
        SketcherVPen *new_vpen(VFrame *out);
        void draw(VFrame *img, int flags);
+       void update_parameter(SketcherCurve *the, SketcherCurve *src);
 };
 class SketcherCurves : public ArrayList<SketcherCurve *>
 {
@@ -154,6 +156,8 @@ class SketcherConfig
 public:
        SketcherConfig();
        ~SketcherConfig();
+       void read_data(KeyFrame *keyframe);
+       void save_data(KeyFrame *keyframe);
 
        SketcherCurves curves;
        int equivalent(SketcherConfig &that);
@@ -180,6 +184,9 @@ public:
        void update_gui();
        void save_data(KeyFrame *keyframe);
        void read_data(KeyFrame *keyframe);
+       void span_keyframes(KeyFrame *src, int64_t start, int64_t end);
+       void update_parameter(SketcherConfig &prev_config, SketcherConfig &src_config,
+               KeyFrame *keyframe);
        int new_curve(int pen, int width, int color);
        int new_curve();
        int new_point(SketcherCurve *cv, int arc, coord x, coord y, int idx=-1);
index 604a382403ff0e48e91455aada9fee69e57a77f6..822b5d78b99cbf93ca8b3b5d17acf703a8c80343 100644 (file)
 #include "edl.h"
 #include "edlsession.h"
 #include "filexml.h"
+#include "keyframe.h"
+#include "keyframes.h"
 #include "tracer.h"
+#include "transportque.inc"
 #include "tracerwindow.h"
 #include "language.h"
 #include "vframe.h"
@@ -167,7 +170,7 @@ int Tracer::new_point()
        return config.add_point(x, y);
 }
 
-void Tracer::save_data(KeyFrame *keyframe)
+void TracerConfig::save_data(KeyFrame *keyframe)
 {
        FileXML output;
 
@@ -175,20 +178,20 @@ void Tracer::save_data(KeyFrame *keyframe)
        output.set_shared_output(keyframe->xbuf);
 
        output.tag.set_title("TRACER");
-       output.tag.set_property("DRAG", config.drag);
-       output.tag.set_property("DRAW", config.draw);
-       output.tag.set_property("FILL", config.fill);
-       output.tag.set_property("FEATHER", config.feather);
-       output.tag.set_property("RADIUS", config.radius);
-       output.tag.set_property("INVERT", config.invert);
-       output.tag.set_property("SELECTED", config.selected);
+       output.tag.set_property("DRAG", drag);
+       output.tag.set_property("DRAW", draw);
+       output.tag.set_property("FILL", fill);
+       output.tag.set_property("FEATHER", feather);
+       output.tag.set_property("RADIUS", radius);
+       output.tag.set_property("INVERT", invert);
+       output.tag.set_property("SELECTED", selected);
        output.append_tag();
        output.append_newline();
        output.tag.set_title("/TRACER");
        output.append_tag();
        output.append_newline();
-       for( int i=0, n=config.points.size(); i<n; ++i ) {
-               TracerPoint *pt = config.points[i];
+       for( int i=0, n=points.size(); i<n; ++i ) {
+               TracerPoint *pt = points[i];
                char point[BCSTRLEN];
                sprintf(point,"/POINT_%d",i+1);
                output.tag.set_title(point+1);
@@ -202,32 +205,95 @@ void Tracer::save_data(KeyFrame *keyframe)
        output.terminate_string();
 }
 
-void Tracer::read_data(KeyFrame *keyframe)
+void Tracer::save_data(KeyFrame *keyframe)
+{
+       config.save_data(keyframe);
+}
+
+void TracerConfig::read_data(KeyFrame *keyframe)
 {
        FileXML input;
        input.set_shared_input(keyframe->xbuf);
-       config.points.remove_all_objects();
+       points.remove_all_objects();
        int result = 0;
 
        while( !(result=input.read_tag()) ) {
                if( input.tag.title_is("TRACER") ) {
-                       config.drag = input.tag.get_property("DRAG", config.drag);
-                       config.draw = input.tag.get_property("DRAW", config.draw);
-                       config.fill = input.tag.get_property("FILL", config.fill);
-                       config.feather = input.tag.get_property("FEATHER", config.feather);
-                       config.radius = input.tag.get_property("RADIUS", config.radius);
-                       config.invert = input.tag.get_property("INVERT", config.invert);
-                       config.selected = input.tag.get_property("SELECTED", 0);
-                       config.limits();
+                       drag = input.tag.get_property("DRAG", drag);
+                       draw = input.tag.get_property("DRAW", draw);
+                       fill = input.tag.get_property("FILL", fill);
+                       feather = input.tag.get_property("FEATHER", feather);
+                       radius = input.tag.get_property("RADIUS", radius);
+                       invert = input.tag.get_property("INVERT", invert);
+                       selected = input.tag.get_property("SELECTED", 0);
+                       limits();
                }
                else if( !strncmp(input.tag.get_title(),"POINT_",6) ) {
                        float x = input.tag.get_property("X", 0.f);
                        float y = input.tag.get_property("Y", 0.f);
-                       config.add_point(x, y);
+                       add_point(x, y);
                }
        }
 }
 
+void Tracer::read_data(KeyFrame *keyframe)
+{
+       config.read_data(keyframe);
+}
+
+void Tracer::span_keyframes(KeyFrame *src, int64_t start, int64_t end)
+{
+       TracerConfig src_config;
+       src_config.read_data(src);
+       KeyFrames *keyframes = (KeyFrames *)src->autos;
+       KeyFrame *prev = keyframes->get_prev_keyframe(start, PLAY_FORWARD);
+       TracerConfig prev_config;
+       prev_config.read_data(prev);
+// Always update the first one
+       update_parameter(prev_config, src_config, prev);
+       KeyFrame *curr = (KeyFrame*)prev->next;
+       while( curr && curr->position < end ) {
+               update_parameter(prev_config, src_config, curr);
+               curr = (KeyFrame*)curr->next;
+       }
+}
+
+void TracerPoint::update_parameter(TracerPoint *prev, TracerPoint *src)
+{
+       if( prev->x != src->x ) x = src->x;
+       if( prev->y != src->y ) y = src->y;
+}
+
+void Tracer::update_parameter(TracerConfig &prev_config, TracerConfig &src_config,
+                KeyFrame *keyframe)
+{
+        TracerConfig dst_config;
+        dst_config.read_data(keyframe);
+       if( prev_config.drag != src_config.drag )
+               dst_config.drag = src_config.drag;
+       if( prev_config.draw != src_config.draw )
+               dst_config.draw = src_config.draw;
+       if( prev_config.fill != src_config.fill )
+               dst_config.fill = src_config.fill;
+       if( prev_config.feather != src_config.feather )
+               dst_config.feather = src_config.feather;
+       if( prev_config.invert != src_config.invert )
+               dst_config.invert = src_config.invert;
+       if( prev_config.radius != src_config.radius )
+               dst_config.radius = src_config.radius;
+       int src_points = src_config.points.size();
+       int dst_points = dst_config.points.size();
+       int prev_points = prev_config.points.size();
+       int npoints = bmin(prev_points, bmin(src_points, dst_points));
+       for( int i=0; i<npoints; ++i ) {
+               TracerPoint *prev_point = prev_config.points[i];
+               TracerPoint *src_point = src_config.points[i];
+               TracerPoint *dst_point = dst_config.points[i];
+               dst_point->update_parameter(prev_point, src_point);
+       }
+        dst_config.save_data(keyframe);
+}
+
 void Tracer::update_gui()
 {
        if( !thread ) return;
@@ -652,7 +718,7 @@ int Tracer::process_buffer(VFrame *frame, int64_t start_position, double frame_r
        if( !edg ) redraw = 1;
        VFrame::get_temp(edg, w, h, BC_GREY8);
        if( redraw ) {
-               edg->clear_frame();
+               edg->black_frame();
                edg_rows = edg->get_rows();
 
                int n = config.points.size()-1;
@@ -668,7 +734,7 @@ int Tracer::process_buffer(VFrame *frame, int64_t start_position, double frame_r
                        TracePoint *pt0 = &points[0], *pt1 = &points[l2];
                        int cx = (pt0->x+pt1->x)/2, cy = (pt0->y+pt1->y)/2;
                        VFrame::get_temp(msk, w, h, BC_GREY8);
-                       msk->clear_frame();
+                       msk->black_frame();
                        msk_rows = msk->get_rows();
 
                        FillRegion fill_region(edg, msk);
index e9918719cdefd365b162eb066ad4be1cf8df7c22..fdca6d16b8e4c5c3cc838c917451246fa924a39a 100644 (file)
@@ -37,6 +37,7 @@ public:
 
        TracerPoint(float x, float y);
        ~TracerPoint();
+       void update_parameter(TracerPoint *prev, TracerPoint *src);
 };
 class TracerPoints : public ArrayList<TracerPoint *>
 {
@@ -51,6 +52,8 @@ public:
        TracerConfig();
        ~TracerConfig();
 
+       void save_data(KeyFrame *keyframe);
+       void read_data(KeyFrame *keyframe);
        int equivalent(TracerConfig &that);
        void copy_from(TracerConfig &that);
        void interpolate(TracerConfig &prev, TracerConfig &next,
@@ -113,6 +116,10 @@ public:
        int smooth();
        void feather(int r, double s);
        int load_configuration1();
+       void span_keyframes(KeyFrame *src, int64_t start, int64_t end);
+       void update_parameter(TracerPoint *prev, TracerPoint *src);
+       void update_parameter(TracerConfig &prev_config, TracerConfig &src_config,
+                KeyFrame *keyframe);
 
        VFrame *edg, *msk, *frm;
        uint8_t **edg_rows;