From 096e197a21d85fa8c60547cd54944fb379c08bb9 Mon Sep 17 00:00:00 2001 From: Good Guy Date: Tue, 9 Jun 2020 19:06:16 -0600 Subject: [PATCH] fit keyframe spanning for sketcher,tracer,crikey, rework keyframegui preset, tweak cache for deadlocks on open_file errors, change keyframe data from text to raw data, fix mask init in tracer, tweak perspective for gui corner points, add contrib rotate plugin upgrades --- cinelerra-5.1/Cinelerra_factory | 2 +- cinelerra-5.1/cinelerra/cache.C | 2 +- cinelerra-5.1/cinelerra/filexml.C | 29 +- cinelerra-5.1/cinelerra/keyframe.C | 25 +- cinelerra-5.1/cinelerra/keyframe.h | 1 + cinelerra-5.1/cinelerra/keyframegui.C | 13 +- cinelerra-5.1/cinelerra/keyframes.C | 44 +-- cinelerra-5.1/cinelerra/keyframes.h | 12 +- cinelerra-5.1/cinelerra/plugin.C | 4 +- cinelerra-5.1/cinelerra/pluginclient.C | 16 +- cinelerra-5.1/cinelerra/pluginclient.h | 2 +- cinelerra-5.1/cinelerra/pluginserver.C | 32 +- cinelerra-5.1/cinelerra/pluginserver.h | 2 +- cinelerra-5.1/cinelerra/presets.C | 4 +- cinelerra-5.1/guicast/linklist.h | 2 +- cinelerra-5.1/plugins/crikey/crikey.C | 101 +++++-- cinelerra-5.1/plugins/crikey/crikey.h | 6 + .../plugins/perspective/perspective.C | 37 ++- .../plugins/perspective/perspective.h | 1 + cinelerra-5.1/plugins/rotate/rotate.C | 276 ++++++++++++------ cinelerra-5.1/plugins/rotate/rotate.h | 110 +++++-- cinelerra-5.1/plugins/sketcher/sketcher.C | 112 ++++++- cinelerra-5.1/plugins/sketcher/sketcher.h | 7 + cinelerra-5.1/plugins/tracer/tracer.C | 112 +++++-- cinelerra-5.1/plugins/tracer/tracer.h | 7 + 25 files changed, 701 insertions(+), 258 deletions(-) diff --git a/cinelerra-5.1/Cinelerra_factory b/cinelerra-5.1/Cinelerra_factory index 4a4c0e58..ee236e34 100644 --- a/cinelerra-5.1/Cinelerra_factory +++ b/cinelerra-5.1/Cinelerra_factory @@ -94,5 +94,5 @@ -<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> + diff --git a/cinelerra-5.1/cinelerra/cache.C b/cinelerra-5.1/cinelerra/cache.C index b8e2326d..4c94adbf 100644 --- a/cinelerra-5.1/cinelerra/cache.C +++ b/cinelerra-5.1/cinelerra/cache.C @@ -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; diff --git a/cinelerra-5.1/cinelerra/filexml.C b/cinelerra-5.1/cinelerra/filexml.C index e045a532..fe0ec15f 100644 --- a/cinelerra-5.1/cinelerra/filexml.C +++ b/cinelerra-5.1/cinelerra/filexml.C @@ -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; } diff --git a/cinelerra-5.1/cinelerra/keyframe.C b/cinelerra-5.1/cinelerra/keyframe.C index 8d6a5755..363c72df 100644 --- a/cinelerra-5.1/cinelerra/keyframe.C +++ b/cinelerra-5.1/cinelerra/keyframe.C @@ -25,6 +25,8 @@ #include "cstrdup.h" #include "filexml.h" #include "keyframe.h" +#include "keyframes.h" +#include "transportque.inc" #include #include @@ -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, ¶ms, &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); diff --git a/cinelerra-5.1/cinelerra/keyframe.h b/cinelerra-5.1/cinelerra/keyframe.h index d766b915..8118afb8 100644 --- a/cinelerra-5.1/cinelerra/keyframe.h +++ b/cinelerra-5.1/cinelerra/keyframe.h @@ -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; }; diff --git a/cinelerra-5.1/cinelerra/keyframegui.C b/cinelerra-5.1/cinelerra/keyframegui.C index 61a0b052..fb7de36f 100644 --- a/cinelerra-5.1/cinelerra/keyframegui.C +++ b/cinelerra-5.1/cinelerra/keyframegui.C @@ -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 &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); diff --git a/cinelerra-5.1/cinelerra/keyframes.C b/cinelerra-5.1/cinelerra/keyframes.C index 68d700f4..588db9a9 100644 --- a/cinelerra-5.1/cinelerra/keyframes.C +++ b/cinelerra-5.1/cinelerra/keyframes.C @@ -27,13 +27,15 @@ #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, ¶ms, &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); diff --git a/cinelerra-5.1/cinelerra/keyframes.h b/cinelerra-5.1/cinelerra/keyframes.h index 89fa2435..45a45333 100644 --- a/cinelerra-5.1/cinelerra/keyframes.h +++ b/cinelerra-5.1/cinelerra/keyframes.h @@ -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); diff --git a/cinelerra-5.1/cinelerra/plugin.C b/cinelerra-5.1/cinelerra/plugin.C index 36b10330..dce1f5b7 100644 --- a/cinelerra-5.1/cinelerra/plugin.C +++ b/cinelerra-5.1/cinelerra/plugin.C @@ -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(); } diff --git a/cinelerra-5.1/cinelerra/pluginclient.C b/cinelerra-5.1/cinelerra/pluginclient.C index 467fa2aa..94a20884 100644 --- a/cinelerra-5.1/cinelerra/pluginclient.C +++ b/cinelerra-5.1/cinelerra/pluginclient.C @@ -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(); } + diff --git a/cinelerra-5.1/cinelerra/pluginclient.h b/cinelerra-5.1/cinelerra/pluginclient.h index 8abf7666..b338deba 100644 --- a/cinelerra-5.1/cinelerra/pluginclient.h +++ b/cinelerra-5.1/cinelerra/pluginclient.h @@ -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 diff --git a/cinelerra-5.1/cinelerra/pluginserver.C b/cinelerra-5.1/cinelerra/pluginserver.C index f10cec05..18619cc7 100644 --- a/cinelerra-5.1/cinelerra/pluginserver.C +++ b/cinelerra-5.1/cinelerra/pluginserver.C @@ -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); } diff --git a/cinelerra-5.1/cinelerra/pluginserver.h b/cinelerra-5.1/cinelerra/pluginserver.h index f0c8500d..1808db7e 100644 --- a/cinelerra-5.1/cinelerra/pluginserver.h +++ b/cinelerra-5.1/cinelerra/pluginserver.h @@ -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(); diff --git a/cinelerra-5.1/cinelerra/presets.C b/cinelerra-5.1/cinelerra/presets.C index 2dabe6ad..d9c160f1 100644 --- a/cinelerra-5.1/cinelerra/presets.C +++ b/cinelerra-5.1/cinelerra/presets.C @@ -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(); diff --git a/cinelerra-5.1/guicast/linklist.h b/cinelerra-5.1/guicast/linklist.h index c92f2d56..b424a2ac 100644 --- a/cinelerra-5.1/guicast/linklist.h +++ b/cinelerra-5.1/guicast/linklist.h @@ -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 &me) { list = me; previous = next = 0; } + ListItem(List *me) { list = me; previous = next = 0; } virtual ~ListItem() { if( list ) list->remove_pointer(this); } }; diff --git a/cinelerra-5.1/plugins/crikey/crikey.C b/cinelerra-5.1/plugins/crikey/crikey.C index d5a6cd13..84318422 100644 --- a/cinelerra-5.1/plugins/crikey/crikey.C +++ b/cinelerra-5.1/plugins/crikey/crikey.C @@ -32,7 +32,10 @@ #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(); itag); 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; itag, 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= threshold ) continue; \ *edgp += (mx - mn); \ } \ diff --git a/cinelerra-5.1/plugins/crikey/crikey.h b/cinelerra-5.1/plugins/crikey/crikey.h index 21e602e7..ca452b04 100644 --- a/cinelerra-5.1/plugins/crikey/crikey.h +++ b/cinelerra-5.1/plugins/crikey/crikey.h @@ -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 { @@ -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; diff --git a/cinelerra-5.1/plugins/perspective/perspective.C b/cinelerra-5.1/plugins/perspective/perspective.C index 3bfa66fe..39c63d43 100644 --- a/cinelerra-5.1/plugins/perspective/perspective.C +++ b/cinelerra-5.1/plugins/perspective/perspective.C @@ -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()); } diff --git a/cinelerra-5.1/plugins/perspective/perspective.h b/cinelerra-5.1/plugins/perspective/perspective.h index 074e20ba..dcabb265 100644 --- a/cinelerra-5.1/plugins/perspective/perspective.h +++ b/cinelerra-5.1/plugins/perspective/perspective.h @@ -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; diff --git a/cinelerra-5.1/plugins/rotate/rotate.C b/cinelerra-5.1/plugins/rotate/rotate.C index 15471ced..cc78511f 100644 --- a/cinelerra-5.1/plugins/rotate/rotate.C +++ b/cinelerra-5.1/plugins/rotate/rotate.C @@ -21,8 +21,12 @@ #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; } diff --git a/cinelerra-5.1/plugins/rotate/rotate.h b/cinelerra-5.1/plugins/rotate/rotate.h index 4a8870b1..296e7326 100644 --- a/cinelerra-5.1/plugins/rotate/rotate.h +++ b/cinelerra-5.1/plugins/rotate/rotate.h @@ -41,6 +41,24 @@ 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; }; diff --git a/cinelerra-5.1/plugins/sketcher/sketcher.C b/cinelerra-5.1/plugins/sketcher/sketcher.C index 2b392327..c57bfc0b 100644 --- a/cinelerra-5.1/plugins/sketcher/sketcher.C +++ b/cinelerra-5.1/plugins/sketcher/sketcher.C @@ -30,11 +30,13 @@ #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(); isave_data(output); + for( int i=0,n=curves.size(); isave_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; ipoints[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; iupdate_parameter(prev_curve, src_curve); + } + dst_config.save_data(keyframe); } void Sketcher::update_gui() diff --git a/cinelerra-5.1/plugins/sketcher/sketcher.h b/cinelerra-5.1/plugins/sketcher/sketcher.h index dcf7a6ba..c8f3be5f 100644 --- a/cinelerra-5.1/plugins/sketcher/sketcher.h +++ b/cinelerra-5.1/plugins/sketcher/sketcher.h @@ -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 { @@ -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 { @@ -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); diff --git a/cinelerra-5.1/plugins/tracer/tracer.C b/cinelerra-5.1/plugins/tracer/tracer.C index 604a3824..822b5d78 100644 --- a/cinelerra-5.1/plugins/tracer/tracer.C +++ b/cinelerra-5.1/plugins/tracer/tracer.C @@ -31,7 +31,10 @@ #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(); ixbuf); - 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; iupdate_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); diff --git a/cinelerra-5.1/plugins/tracer/tracer.h b/cinelerra-5.1/plugins/tracer/tracer.h index e9918719..fdca6d16 100644 --- a/cinelerra-5.1/plugins/tracer/tracer.h +++ b/cinelerra-5.1/plugins/tracer/tracer.h @@ -37,6 +37,7 @@ public: TracerPoint(float x, float y); ~TracerPoint(); + void update_parameter(TracerPoint *prev, TracerPoint *src); }; class TracerPoints : public ArrayList { @@ -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; -- 2.26.2