From 4784a8d70bc39f9b7e467f93304d2df3f23fd2df Mon Sep 17 00:00:00 2001 From: Good Guy Date: Tue, 8 Aug 2017 16:10:26 -0600 Subject: [PATCH] crikey rework, KP4 fix, added Shift-KPx, valgrind cleanups, hex eye-dropper, resize asset copy/paste filelist, misc bug fixes --- cinelerra-5.1/cinelerra/assetpopup.C | 65 ++- cinelerra-5.1/cinelerra/assetpopup.h | 2 + cinelerra-5.1/cinelerra/audioalsa.C | 5 +- cinelerra-5.1/cinelerra/commonrender.C | 2 +- cinelerra-5.1/cinelerra/cwindowgui.C | 23 +- cinelerra-5.1/cinelerra/cwindowgui.h | 1 - cinelerra-5.1/cinelerra/cwindowtool.C | 54 ++- cinelerra-5.1/cinelerra/cwindowtool.h | 1 + cinelerra-5.1/cinelerra/playtransport.C | 11 +- cinelerra-5.1/cinelerra/transportque.C | 92 ++-- cinelerra-5.1/cinelerra/transportque.h | 5 +- cinelerra-5.1/guicast/bccapture.C | 2 +- cinelerra-5.1/guicast/bcwindowbase.C | 9 +- cinelerra-5.1/plugins/crikey/crikey.C | 341 +++++++------ cinelerra-5.1/plugins/crikey/crikey.h | 39 +- cinelerra-5.1/plugins/crikey/crikeywindow.C | 510 +++++++++++++++----- cinelerra-5.1/plugins/crikey/crikeywindow.h | 140 +++++- cinelerra-5.1/plugins/titler/titlerwindow.C | 23 +- 18 files changed, 905 insertions(+), 420 deletions(-) diff --git a/cinelerra-5.1/cinelerra/assetpopup.C b/cinelerra-5.1/cinelerra/assetpopup.C index 670e0882..c153e3db 100644 --- a/cinelerra-5.1/cinelerra/assetpopup.C +++ b/cinelerra-5.1/cinelerra/assetpopup.C @@ -432,30 +432,30 @@ int AssetListCopy::handle_event() AssetCopyDialog::AssetCopyDialog(AssetListCopy *copy) : BC_DialogThread() { - this->copy = copy; + this->copy = copy; copy_window = 0; } void AssetCopyDialog::start(char *text, int x, int y) { - close_window(); - this->text = text; + close_window(); + this->text = text; this->x = x; this->y = y; BC_DialogThread::start(); } AssetCopyDialog::~AssetCopyDialog() { - close_window(); + close_window(); } BC_Window* AssetCopyDialog::new_gui() { - BC_DisplayInfo display_info; + BC_DisplayInfo display_info; - copy_window = new AssetCopyWindow(this); - copy_window->create_objects(); - return copy_window; + copy_window = new AssetCopyWindow(this); + copy_window->create_objects(); + return copy_window; } void AssetCopyDialog::handle_done_event(int result) @@ -465,16 +465,16 @@ void AssetCopyDialog::handle_done_event(int result) void AssetCopyDialog::handle_close_event(int result) { - copy_window = 0; + copy_window = 0; } AssetCopyWindow::AssetCopyWindow(AssetCopyDialog *copy_dialog) : BC_Window(_(PROGRAM_NAME ": Copy File List"), copy_dialog->x - 500/2, copy_dialog->y - 200/2, - 500, 200, 500, 200, 0, 0, 1) + 500, 200, 500, 200, 1, 0, 1) { - this->copy_dialog = copy_dialog; + this->copy_dialog = copy_dialog; } AssetCopyWindow::~AssetCopyWindow() @@ -496,9 +496,18 @@ void AssetCopyWindow::create_objects() file_list->create_objects(); add_subwindow(new BC_OKButton(this)); - show_window(); + show_window(); } +int AssetCopyWindow::resize_event(int w, int h) +{ + int fx = file_list->get_x(), fy = file_list->get_y(), pad = 5; + int text_w = w - fx - 10; + int text_h = h - fy - BC_OKButton::calculate_h() - pad; + int text_rows = BC_TextBox::pixels_to_rows(this, MEDIUMFONT, text_h); + file_list->reposition_window(fx, fy, text_w, text_rows); + return 0; +} AssetListPaste::AssetListPaste(MWindow *mwindow, AWindowGUI *gui) : BC_MenuItem(_("Paste file list")) @@ -527,20 +536,20 @@ int AssetListPaste::handle_event() AssetPasteDialog::AssetPasteDialog(AssetListPaste *paste) : BC_DialogThread() { - this->paste = paste; + this->paste = paste; paste_window = 0; } AssetPasteDialog::~AssetPasteDialog() { - close_window(); + close_window(); } BC_Window* AssetPasteDialog::new_gui() { - paste_window = new AssetPasteWindow(this); - paste_window->create_objects(); - return paste_window; + paste_window = new AssetPasteWindow(this); + paste_window->create_objects(); + return paste_window; } void AssetPasteDialog::handle_done_event(int result) @@ -569,14 +578,14 @@ void AssetPasteDialog::handle_done_event(int result) result = mwindow->load_filenames(&path_list, LOADMODE_RESOURCESONLY, 0); mwindow->gui->unlock_window(); path_list.remove_all_objects(); - mwindow->save_backup(); - mwindow->restart_brender(); + mwindow->save_backup(); + mwindow->restart_brender(); mwindow->session->changes_made = 1; } void AssetPasteDialog::handle_close_event(int result) { - paste_window = 0; + paste_window = 0; } void AssetPasteDialog::start(int x, int y) @@ -588,9 +597,9 @@ void AssetPasteDialog::start(int x, int y) AssetPasteWindow::AssetPasteWindow(AssetPasteDialog *paste_dialog) : BC_Window(_(PROGRAM_NAME ": Paste File List"), paste_dialog->x - 500/2, paste_dialog->y - 200/2, - 500, 200, 500, 200, 0, 0, 1) + 500, 200, 500, 200, 1, 0, 1) { - this->paste_dialog = paste_dialog; + this->paste_dialog = paste_dialog; } AssetPasteWindow::~AssetPasteWindow() @@ -610,6 +619,16 @@ void AssetPasteWindow::create_objects() file_list->create_objects(); add_subwindow(new BC_OKButton(this)); add_subwindow(new BC_CancelButton(this)); - show_window(); + show_window(); +} + +int AssetPasteWindow::resize_event(int w, int h) +{ + int fx = file_list->get_x(), fy = file_list->get_y(), pad = 5; + int text_w = w - fx - 10; + int text_h = h - fy - BC_OKButton::calculate_h() - pad; + int text_rows = BC_TextBox::pixels_to_rows(this, MEDIUMFONT, text_h); + file_list->reposition_window(fx, fy, text_w, text_rows); + return 0; } diff --git a/cinelerra-5.1/cinelerra/assetpopup.h b/cinelerra-5.1/cinelerra/assetpopup.h index c070f124..d6c3136e 100644 --- a/cinelerra-5.1/cinelerra/assetpopup.h +++ b/cinelerra-5.1/cinelerra/assetpopup.h @@ -240,6 +240,7 @@ public: ~AssetCopyWindow(); void create_objects(); + int resize_event(int w, int h); AssetCopyDialog *copy_dialog; BC_ScrollTextBox *file_list; @@ -281,6 +282,7 @@ public: ~AssetPasteWindow(); void create_objects(); + int resize_event(int w, int h); AssetPasteDialog *paste_dialog; BC_ScrollTextBox *file_list; diff --git a/cinelerra-5.1/cinelerra/audioalsa.C b/cinelerra-5.1/cinelerra/audioalsa.C index c8a21f6c..7a8d712c 100644 --- a/cinelerra-5.1/cinelerra/audioalsa.C +++ b/cinelerra-5.1/cinelerra/audioalsa.C @@ -567,8 +567,8 @@ int AudioALSA::write_buffer(char *buffer, int size) timer->update(); AudioThread *audio_out = device->audio_out; - while(attempts < 2 && !done && !device->playback_interrupted) - { + while( count > 0 && attempts < 2 && !done ) { + if( device->playback_interrupted ) break; // Buffers written must be equal to period_time audio_out->Thread::enable_cancel(); int ret = snd_pcm_avail_update(get_output()); @@ -586,6 +586,7 @@ int AudioALSA::write_buffer(char *buffer, int size) if( ret > 0 ) ret = 0; } audio_out->Thread::disable_cancel(); + if( device->playback_interrupted ) break; if( ret == 0 ) continue; if( ret > 0 ) { diff --git a/cinelerra-5.1/cinelerra/commonrender.C b/cinelerra-5.1/cinelerra/commonrender.C index 18239788..32358c06 100644 --- a/cinelerra-5.1/cinelerra/commonrender.C +++ b/cinelerra-5.1/cinelerra/commonrender.C @@ -266,7 +266,7 @@ int CommonRender::get_boundaries(int64_t ¤t_render_length) } } - if(renderengine->command->single_frame()) + if(renderengine->command->single_frame() && !renderengine->command->audio_toggle) current_render_length = 1; if(current_render_length < 0) current_render_length = 0; diff --git a/cinelerra-5.1/cinelerra/cwindowgui.C b/cinelerra-5.1/cinelerra/cwindowgui.C index 94887b5b..c3bf4b61 100644 --- a/cinelerra-5.1/cinelerra/cwindowgui.C +++ b/cinelerra-5.1/cinelerra/cwindowgui.C @@ -92,23 +92,28 @@ CWindowGUI::CWindowGUI(MWindow *mwindow, CWindow *cwindow) this->mwindow = mwindow; this->cwindow = cwindow; affected_track = 0; - affected_x = 0; - affected_y = 0; - affected_z = 0; + affected_x = affected_y = affected_z = 0; mask_keyframe = 0; orig_mask_keyframe = new MaskAuto(0, 0); affected_point = 0; - x_offset = 0; - y_offset = 0; - x_origin = 0; - y_origin = 0; + x_offset = y_offset = 0; + x_origin = y_origin = 0; current_operation = CWINDOW_NONE; tool_panel = 0; - translating_zoom = 0; active = 0; inactive = 0; - crop_translate = 0; + crop_handle = -1; crop_translate = 0; + crop_origin_x = crop_origin_y = 0; + crop_origin_x1 = crop_origin_y1 = 0; + crop_origin_x2 = crop_origin_y2 = 0; eyedrop_visible = 0; + eyedrop_x = eyedrop_y = 0; + ruler_origin_x = ruler_origin_y = 0; + ruler_handle = -1; ruler_translate = 0; + center_x = center_y = center_z = 0; + control_in_x = control_in_y = 0; + control_out_x = control_out_y = 0; + translating_zoom = 0; highlighted = 0; } diff --git a/cinelerra-5.1/cinelerra/cwindowgui.h b/cinelerra-5.1/cinelerra/cwindowgui.h index 44a0b607..d08291d1 100644 --- a/cinelerra-5.1/cinelerra/cwindowgui.h +++ b/cinelerra-5.1/cinelerra/cwindowgui.h @@ -148,7 +148,6 @@ public: // Origin for camera and projector operations during last button press float center_x, center_y, center_z; float control_in_x, control_in_y, control_out_x, control_out_y; - int current_tool; // Must recalculate the origin when pressing shift. // Switch toggle on and off to recalculate origin. int translating_zoom; diff --git a/cinelerra-5.1/cinelerra/cwindowtool.C b/cinelerra-5.1/cinelerra/cwindowtool.C index caf0bf82..d73a265b 100644 --- a/cinelerra-5.1/cinelerra/cwindowtool.C +++ b/cinelerra-5.1/cinelerra/cwindowtool.C @@ -461,11 +461,7 @@ void CWindowCropGUI::update() CWindowEyedropGUI::CWindowEyedropGUI(MWindow *mwindow, CWindowTool *thread) - : CWindowToolGUI(mwindow, - thread, - _(PROGRAM_NAME ": Color"), - 200, - 250) + : CWindowToolGUI(mwindow, thread, _(PROGRAM_NAME ": Color"), 220, 250) { } @@ -476,9 +472,9 @@ CWindowEyedropGUI::~CWindowEyedropGUI() void CWindowEyedropGUI::create_objects() { int margin = mwindow->theme->widget_border; - int x = margin; - int y = margin; - int x2 = 70; + int x = 10 + margin; + int y = 10 + margin; + int x2 = 70, x3 = x2 + 60; lock_window("CWindowEyedropGUI::create_objects"); BC_Title *title0, *title1, *title2, *title3, *title4, *title5, *title6, *title7; add_subwindow(title0 = new BC_Title(x, y,_("X,Y:"))); @@ -506,16 +502,17 @@ void CWindowEyedropGUI::create_objects() radius->create_objects(); radius->set_boundaries((int64_t)0, (int64_t)255); - add_subwindow(red = new BC_Title(x2, title1->get_y(), "0")); add_subwindow(green = new BC_Title(x2, title2->get_y(), "0")); add_subwindow(blue = new BC_Title(x2, title3->get_y(), "0")); + add_subwindow(rgb_hex = new BC_Title(x3, red->get_y(), "#000000")); add_subwindow(this->y = new BC_Title(x2, title4->get_y(), "0")); add_subwindow(this->u = new BC_Title(x2, title5->get_y(), "0")); add_subwindow(this->v = new BC_Title(x2, title6->get_y(), "0")); + add_subwindow(yuv_hex = new BC_Title(x3, this->y->get_y(), "#000000")); - y = title6->get_y() + this->v->get_h() + margin; + y = title6->get_y() + this->v->get_h() + 2*margin; add_subwindow(sample = new BC_SubWindow(x, y, 50, 50)); update(); unlock_window(); @@ -531,25 +528,36 @@ void CWindowEyedropGUI::update() radius->update((int64_t)mwindow->edl->session->eyedrop_radius); - red->update(mwindow->edl->local_session->red); - green->update(mwindow->edl->local_session->green); - blue->update(mwindow->edl->local_session->blue); + float r = mwindow->edl->local_session->red; + float g = mwindow->edl->local_session->green; + float b = mwindow->edl->local_session->blue; + red->update(r); + green->update(g); + blue->update(b); + int rx = 255*r + 0.5; bclamp(rx,0,255); + int gx = 255*g + 0.5; bclamp(gx,0,255); + int bx = 255*b + 0.5; bclamp(bx,0,255); + char rgb_text[BCSTRLEN]; + sprintf(rgb_text, "#%02x%02x%02x", rx, gx, bx); + rgb_hex->update(rgb_text); float y, u, v; YUV::rgb_to_yuv_f(mwindow->edl->local_session->red, mwindow->edl->local_session->green, mwindow->edl->local_session->blue, - y, - u, - v); + y, u, v); this->y->update(y); - this->u->update(u); - this->v->update(v); - - int red = (int)(CLIP(mwindow->edl->local_session->red, 0, 1) * 0xff); - int green = (int)(CLIP(mwindow->edl->local_session->green, 0, 1) * 0xff); - int blue = (int)(CLIP(mwindow->edl->local_session->blue, 0, 1) * 0xff); - sample->set_color((red << 16) | (green << 8) | blue); + this->u->update(u); u += 0.5; + this->v->update(v); v += 0.5; + int yx = 255*y + 0.5; bclamp(yx,0,255); + int ux = 255*u + 0.5; bclamp(ux,0,255); + int vx = 255*v + 0.5; bclamp(vx,0,255); + char yuv_text[BCSTRLEN]; + sprintf(yuv_text, "#%02x%02x%02x", yx, ux, vx); + yuv_hex->update(yuv_text); + + int rgb = (rx << 16) | (gx << 8) | (bx << 0); + sample->set_color(rgb); sample->draw_box(0, 0, sample->get_w(), sample->get_h()); sample->set_color(BLACK); sample->draw_rectangle(0, 0, sample->get_w(), sample->get_h()); diff --git a/cinelerra-5.1/cinelerra/cwindowtool.h b/cinelerra-5.1/cinelerra/cwindowtool.h index 5761ae8a..651627e0 100644 --- a/cinelerra-5.1/cinelerra/cwindowtool.h +++ b/cinelerra-5.1/cinelerra/cwindowtool.h @@ -267,6 +267,7 @@ public: BC_Title *current; CWindowCoord *radius; BC_Title *red, *green, *blue, *y, *u, *v; + BC_Title *rgb_hex, *yuv_hex; BC_SubWindow *sample; }; diff --git a/cinelerra-5.1/cinelerra/playtransport.C b/cinelerra-5.1/cinelerra/playtransport.C index 991adb9a..a426ac79 100644 --- a/cinelerra-5.1/cinelerra/playtransport.C +++ b/cinelerra-5.1/cinelerra/playtransport.C @@ -257,6 +257,11 @@ void PlayTransport::handle_transport(int command, int prev_command = engine->command->command; int prev_direction = engine->command->get_direction(); int prev_single_frame = engine->command->single_frame(); + int prev_audio = engine->command->audio_toggle ? + !prev_single_frame : prev_single_frame; + int cur_single_frame = TransportCommand::single_frame(command); + int cur_audio = toggle_audio ? + !cur_single_frame : cur_single_frame; // Dispatch command switch(command) { @@ -268,8 +273,10 @@ void PlayTransport::handle_transport(int command, case SLOW_FWD: case NORMAL_FWD: case FAST_FWD: - if( prev_command == command && !prev_single_frame ) { -// Same direction pressed twice. Stop + if( !prev_single_frame && + prev_command == command && + cur_audio == prev_audio ) { +// Same direction pressed twice and no change in audio state, Stop do_stop = 1; break; } diff --git a/cinelerra-5.1/cinelerra/transportque.C b/cinelerra-5.1/cinelerra/transportque.C index 16aa45fa..61dbdb6d 100644 --- a/cinelerra-5.1/cinelerra/transportque.C +++ b/cinelerra-5.1/cinelerra/transportque.C @@ -95,59 +95,69 @@ TransportCommand& TransportCommand::operator=(TransportCommand &command) return *this; } -int TransportCommand::single_frame() +int TransportCommand::single_frame(int command) { return (command == SINGLE_FRAME_FWD || command == SINGLE_FRAME_REWIND || command == CURRENT_FRAME); } - - -int TransportCommand::get_direction() +int TransportCommand::single_frame() { - switch(command) - { - case SINGLE_FRAME_FWD: - case NORMAL_FWD: - case FAST_FWD: - case SLOW_FWD: - case CURRENT_FRAME: - return PLAY_FORWARD; + return single_frame(command); +} - case SINGLE_FRAME_REWIND: - case NORMAL_REWIND: - case FAST_REWIND: - case SLOW_REWIND: - return PLAY_REVERSE; - default: - break; +int TransportCommand::get_direction(int command) +{ + switch(command) { + case SINGLE_FRAME_FWD: + case NORMAL_FWD: + case FAST_FWD: + case SLOW_FWD: + case CURRENT_FRAME: + return PLAY_FORWARD; + + case SINGLE_FRAME_REWIND: + case NORMAL_REWIND: + case FAST_REWIND: + case SLOW_REWIND: + return PLAY_REVERSE; + + default: + break; } return PLAY_FORWARD; } - -float TransportCommand::get_speed() +int TransportCommand::get_direction() { - switch(command) - { - case SLOW_FWD: - case SLOW_REWIND: - return 0.5; - - case NORMAL_FWD: - case NORMAL_REWIND: - case SINGLE_FRAME_FWD: - case SINGLE_FRAME_REWIND: - case CURRENT_FRAME: - return 1.; + return get_direction(command); +} - case FAST_FWD: - case FAST_REWIND: - return 2.; +float TransportCommand::get_speed(int command) +{ + switch(command) { + case SLOW_FWD: + case SLOW_REWIND: + return 0.5; + + case NORMAL_FWD: + case NORMAL_REWIND: + case SINGLE_FRAME_FWD: + case SINGLE_FRAME_REWIND: + case CURRENT_FRAME: + return 1.; + + case FAST_FWD: + case FAST_REWIND: + return 2.; } return 0.; } +float TransportCommand::get_speed() +{ + return get_speed(command); +} // Assume starting without pause void TransportCommand::set_playback_range(EDL *edl, int use_inout, int toggle_audio) @@ -192,16 +202,12 @@ void TransportCommand::set_playback_range(EDL *edl, int use_inout, int toggle_au case CURRENT_FRAME: case SINGLE_FRAME_FWD: start_position = edl->local_session->get_selectionstart(1); - end_position = start_position + - 1.0 / - edl->session->frame_rate; + end_position = start_position + 1.0 / edl->session->frame_rate; break; case SINGLE_FRAME_REWIND: - start_position = edl->local_session->get_selectionend(1); - end_position = start_position - - 1.0 / - edl->session->frame_rate; + end_position = edl->local_session->get_selectionend(1); + start_position = end_position - 1.0 / edl->session->frame_rate; break; } diff --git a/cinelerra-5.1/cinelerra/transportque.h b/cinelerra-5.1/cinelerra/transportque.h index 1eed30e7..4e9c3635 100644 --- a/cinelerra-5.1/cinelerra/transportque.h +++ b/cinelerra-5.1/cinelerra/transportque.h @@ -35,8 +35,12 @@ public: ~TransportCommand(); void reset(); + static int single_frame(int command); + int single_frame(); // Get the direction based on the command + static int get_direction(int command); int get_direction(); + static float get_speed(int command); float get_speed(); void copy_from(TransportCommand *command); TransportCommand& operator=(TransportCommand &command); @@ -51,7 +55,6 @@ public: void playback_range_project(); void playback_range_1frame(); - int single_frame(); EDL* get_edl(); void delete_edl(); void new_edl(); diff --git a/cinelerra-5.1/guicast/bccapture.C b/cinelerra-5.1/guicast/bccapture.C index 0e32ef05..993cfe14 100644 --- a/cinelerra-5.1/guicast/bccapture.C +++ b/cinelerra-5.1/guicast/bccapture.C @@ -171,7 +171,7 @@ int BC_Capture::delete_data() // data is automatically freed by XDestroyImage data = 0; - delete row_data; + delete [] row_data; } return 0; } diff --git a/cinelerra-5.1/guicast/bcwindowbase.C b/cinelerra-5.1/guicast/bcwindowbase.C index 8654bbe7..f851f384 100644 --- a/cinelerra-5.1/guicast/bcwindowbase.C +++ b/cinelerra-5.1/guicast/bcwindowbase.C @@ -962,12 +962,15 @@ locking_message = event->xclient.message_type; // event_names[event->type] : "Unknown"); //} - if( active_grab && active_grab->grab_event(event) ) { + if( active_grab ) { unlock_window(); - return 0; + active_grab->lock_window("BC_WindowBase::dispatch_event 3"); + result = active_grab->grab_event(event); + active_grab->unlock_window(); + if( result ) return result; + lock_window("BC_WindowBase::dispatch_event 4"); } - switch(event->type) { case ClientMessage: // Clear the resize buffer diff --git a/cinelerra-5.1/plugins/crikey/crikey.C b/cinelerra-5.1/plugins/crikey/crikey.C index ccbb216a..6b942d5d 100644 --- a/cinelerra-5.1/plugins/crikey/crikey.C +++ b/cinelerra-5.1/plugins/crikey/crikey.C @@ -27,6 +27,7 @@ #include "bccmodels.h" #include "cicolors.h" #include "clip.h" +#include "edlsession.h" #include "filexml.h" #include "crikey.h" #include "crikeywindow.h" @@ -48,25 +49,42 @@ void crikey_pgm(const char *fn,VFrame *vfrm) } #endif +CriKeyPoint::CriKeyPoint(int t, int e, float x, float y) +{ + this->t = t; this->e = e; this->x = x; this->y = y; +} +CriKeyPoint::~CriKeyPoint() +{ +} + CriKeyConfig::CriKeyConfig() { color = 0x000000; threshold = 0.5f; draw_mode = DRAW_ALPHA; - key_mode = KEY_SEARCH; - point_x = point_y = 0; drag = 0; + selected = 0; +} +CriKeyConfig::~CriKeyConfig() +{ + points.remove_all_objects(); } int CriKeyConfig::equivalent(CriKeyConfig &that) { - return this->color != that.color || - !EQUIV(this->threshold, that.threshold) || - this->draw_mode != that.draw_mode || - this->key_mode != that.key_mode || - !EQUIV(this->point_x, that.point_x) || - !EQUIV(this->point_y, that.point_y) || - this->drag != that.drag ? 0 : 1; + if( this->color != that.color ) return 0; + if( !EQUIV(this->threshold, that.threshold) ) return 0; + if( this->draw_mode != that.draw_mode ) return 0; + if( this->drag != that.drag ) return 0; + if( this->points.size() != that.points.size() ) return 0; + for( int i=0, n=points.size(); ipoints[i], *bp = that.points[i]; + if( ap->t != bp->t ) return 0; + if( ap->e != bp->e ) return 0; + if( !EQUIV(ap->x, bp->x) ) return 0; + if( !EQUIV(ap->y, bp->y) ) return 0; + } + return 1; } void CriKeyConfig::copy_from(CriKeyConfig &that) @@ -74,33 +92,47 @@ void CriKeyConfig::copy_from(CriKeyConfig &that) this->color = that.color; this->threshold = that.threshold; this->draw_mode = that.draw_mode; - this->key_mode = that.key_mode; - this->point_x = that.point_x; - this->point_y = that.point_y; this->drag = that.drag; + this->selected = that.selected; + + points.remove_all_objects(); + for( int i=0,n=that.points.size(); it, pt->e, pt->x, pt->y); + } } void CriKeyConfig::interpolate(CriKeyConfig &prev, CriKeyConfig &next, long prev_frame, long next_frame, long current_frame) { - copy_from(prev); + this->color = prev.color; + this->draw_mode = prev.draw_mode; + this->drag = prev.drag; + this->selected = prev.selected; + double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame); double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame); this->threshold = prev.threshold * prev_scale + next.threshold * next_scale; - switch( prev.key_mode ) { - case KEY_POINT: { - this->point_x = prev.point_x * prev_scale + next.point_x * next_scale; - this->point_y = prev.point_y * prev_scale + next.point_y * next_scale; - break; } - case KEY_SEARCH: - case KEY_SEARCH_ALL: { - float prev_target[3]; set_target(0, prev.color, prev_target); - float next_target[3]; set_target(0, next.color, next_target); - float target[3]; // interpolates rgb components - for( int i=0; i<3; ++i ) - target[i] = prev_target[i] * prev_scale + next_target[i] * next_scale; - set_color(0, target, this->color); - break; } + // interpolate rgb components + float prev_target[3]; set_target(0, prev.color, prev_target); + float next_target[3]; set_target(0, next.color, next_target); + float target[3]; + for( int i=0; i<3; ++i ) + target[i] = prev_target[i] * prev_scale + next_target[i] * next_scale; + set_color(0, target, this->color); + + points.remove_all_objects(); + int prev_sz = prev.points.size(), next_sz = next.points.size(); + for( int i=0; ix, y = pt->y; + int k = next_sz; // associated by tag id in next + while( --k >= 0 && pt->t != (nt=next.points[k])->t ); + if( k >= 0 ) { + x = x * prev_scale + nt->x * next_scale; + y = y * prev_scale + nt->y * next_scale; + } + add_point(pt->t, pt->e, x, y); } } @@ -108,7 +140,25 @@ void CriKeyConfig::limits() { bclamp(threshold, 0.0f, 1.0f); bclamp(draw_mode, 0, DRAW_MODES-1); - bclamp(key_mode, 0, KEY_MODES-1); +} + +int CriKeyConfig::add_point(int t, int e, float x, float y) +{ + int k = points.size(); + if( t < 0 ) { + t = 0; + for( int i=k; --i>=0; ) { + int n = points[i]->t; + if( n >= t ) t = n + 1; + } + } + points.append(new CriKeyPoint(t, e, x, y)); + return k; +} + +void CriKeyConfig::del_point(int i) +{ + points.remove_object_number(i); } @@ -127,20 +177,19 @@ class FillRegion stack.remove(); } - int w, h, threshold; + int w, h; uint8_t *data, *mask; bool edge_pixel(uint8_t *dp) { return *dp; } public: void fill(int x, int y); - void set_threshold(float v) { threshold = v; } + void run(); FillRegion(VFrame *d, VFrame *m); }; FillRegion::FillRegion(VFrame *d, VFrame *m) { - threshold = 128; w = d->get_w(); h = d->get_h(); data = d->get_data(); @@ -150,27 +199,37 @@ FillRegion::FillRegion(VFrame *d, VFrame *m) void FillRegion::fill(int x, int y) { push(y, x, x); +} - do { - int ilt, irt, lt, rt; +void FillRegion::run() +{ + while( stack.size() > 0 ) { + int y, ilt, irt; pop(y, ilt, irt); int ofs = y*w + ilt; - uint8_t *idp = data + ofs, *dp; - uint8_t *imp = mask + ofs, *mp; + uint8_t *idp = data + ofs; + uint8_t *imp = mask + ofs; for( int x=ilt; x<=irt; ++x,++imp,++idp ) { - if( !*imp || edge_pixel(idp) ) continue; + if( !*imp ) continue; *imp = 0; - lt = rt = x; - dp = idp; mp = imp; - for( int i=lt; --i>=0; lt=i,*mp=0 ) - if( !*--mp || edge_pixel(--dp) ) break; - dp = idp; mp = imp; - for( int i=rt; ++i< w; rt=i,*mp=0 ) - if( !*++mp || edge_pixel(++dp) ) break; + if( edge_pixel(idp) ) continue; + int lt = x, rt = x; + uint8_t *ldp = idp, *lmp = imp; + for( int i=lt; --i>=0; ) { + if( !*--lmp ) break; + *lmp = 0; lt = i; + if( edge_pixel(--ldp) ) break; + } + uint8_t *rdp = idp, *rmp = imp; + for( int i=rt; ++i< w; rt=i,*rmp=0 ) { + if( !*++rmp ) break; + *rmp = 0; rt = i; + if( edge_pixel(++rdp) ) break; + } if( y+1 < h ) push(y+1, lt, rt); if( y-1 >= 0 ) push(y-1, lt, rt); } - } while( stack.size() > 0 ); + } } @@ -180,7 +239,6 @@ CriKey::CriKey(PluginServer *server) engine = 0; msk = 0; dst = 0; - diff_pixel = 0; } CriKey::~CriKey() @@ -241,61 +299,20 @@ void CriKey::get_color(int x, int y) } } -float CriKey::diff_uint8(uint8_t *dp) -{ - float scale = 1./255., v = 0; - for( int i=0; iget_rows(); - for( int y=0; y*diff_pixel)(sp); - if( v >= mv ) continue; - mv = v; ix = x; iy = y; - } - } -} -bool CriKey::find_key(int &ix, int &iy, float thr) -{ - uint8_t **src_rows = src->get_rows(); - uint8_t **msk_rows = msk->get_rows(); - int x = ix, y = iy; - for( ; y*diff_pixel)(sp); - if( v < thr ) { - ix = x; iy = y; - return true; - } - } - x = 0; - } - return false; -} - const char* CriKey::plugin_title() { return _("CriKey"); } int CriKey::is_realtime() { return 1; } NEW_WINDOW_MACRO(CriKey, CriKeyWindow); LOAD_CONFIGURATION_MACRO(CriKey, CriKeyConfig) +int CriKey::new_point() +{ + EDLSession *session = get_edlsession(); + float x = !session ? 0.f : session->output_w / 2.f; + float y = !session ? 0.f : session->output_h / 2.f; + return config.add_point(-1, 0, x, y); +} + void CriKey::save_data(KeyFrame *keyframe) { FileXML output; @@ -307,15 +324,26 @@ void CriKey::save_data(KeyFrame *keyframe) output.tag.set_property("COLOR", config.color); output.tag.set_property("THRESHOLD", config.threshold); output.tag.set_property("DRAW_MODE", config.draw_mode); - output.tag.set_property("KEY_MODE", config.key_mode); - output.tag.set_property("POINT_X", config.point_x); - output.tag.set_property("POINT_Y", config.point_y); output.tag.set_property("DRAG", config.drag); + output.tag.set_property("SELECTED", config.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(); it); + output.tag.set_title(point+1); + output.tag.set_property("E", pt->e); + output.tag.set_property("X", pt->x); + output.tag.set_property("Y", pt->y); + output.append_tag(); + output.tag.set_title(point+0); + output.append_tag(); + output.append_newline(); + } output.terminate_string(); } @@ -323,24 +351,28 @@ void CriKey::read_data(KeyFrame *keyframe) { FileXML input; input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); + config.points.remove_all_objects(); int result = 0; while( !(result=input.read_tag()) ) { - if(input.tag.title_is("CRIKEY")) { + if( input.tag.title_is("CRIKEY") ) { config.color = input.tag.get_property("COLOR", config.color); config.threshold = input.tag.get_property("THRESHOLD", config.threshold); config.draw_mode = input.tag.get_property("DRAW_MODE", config.draw_mode); - config.key_mode = input.tag.get_property("KEY_MODE", config.key_mode); - config.point_x = input.tag.get_property("POINT_X", config.point_x); - config.point_y = input.tag.get_property("POINT_Y", config.point_y); config.drag = input.tag.get_property("DRAG", config.drag); + config.selected = input.tag.get_property("SELECTED", 0); config.limits(); } - else if(input.tag.title_is("/CRIKEY")) { - result = 1; + else if( !strncmp(input.tag.get_title(),"POINT_",6) ) { + int t = atoi(input.tag.get_title() + 6); + int e = input.tag.get_property("E", 0); + float x = input.tag.get_property("X", 0.f); + float y = input.tag.get_property("Y", 0.f); + config.add_point(t, e, x, y); } } + if( !config.points.size() ) new_point(); } void CriKey::update_gui() @@ -488,6 +520,24 @@ void CriKey::draw_mask(VFrame *msk) } } +void CriKey::draw_point(VFrame *src, CriKeyPoint *pt) +{ + int d = bmax(w,h) / 200 + 2; + int r = d/2+1, x = pt->x, y = pt->y; + src->draw_smooth(x-r,y+0, x-r, y-r, x+0,y-r); + src->draw_smooth(x+0,y-r, x+r, y-r, x+r,y+0); + src->draw_smooth(x+r,y+0, x+r, y+r, x+0,y+r); + src->draw_smooth(x+0,y+r, x-r, y+r, x-r,y+0); + if( pt->e ) { + src->set_pixel_color(RED); + src->draw_x(pt->x, pt->y, d); + } + else { + src->set_pixel_color(BLUE); + src->draw_t(pt->x, pt->y, d); + } +} + int CriKey::process_buffer(VFrame *frame, int64_t start_position, double frame_rate) { load_configuration(); @@ -499,26 +549,17 @@ int CriKey::process_buffer(VFrame *frame, int64_t start_position, double frame_r if( comp > 3 ) comp = 3; is_yuv = BC_CModels::is_yuv(color_model); is_float = BC_CModels::is_float(color_model); - diff_pixel = is_float ? &CriKey::diff_float : &CriKey::diff_uint8; read_frame(src, 0, start_position, frame_rate, 0); - switch( config.key_mode ) { - case KEY_SEARCH: - case KEY_SEARCH_ALL: - set_target(is_yuv, config.color, target); - break; - case KEY_POINT: - get_color(config.point_x, config.point_y); - break; - } + set_target(is_yuv, config.color, target); if( dst && ( dst->get_w() != w || src->get_h() != h ) ) { delete dst; dst = 0; } if( !dst ) dst = new VFrame(w, h, BC_A8); - memset(dst->get_data(), 0x00, dst->get_data_size()); + dst->clear_frame(); if( !engine ) engine = new CriKeyEngine(this, @@ -532,47 +573,41 @@ int CriKey::process_buffer(VFrame *frame, int64_t start_position, double frame_r if( h1 > 0 ) for( int x=0; xget_w() != w || msk->get_h() != h ) ) { - delete msk; msk = 0; - } - if( !msk ) - msk = new VFrame(w, h, BC_A8); - memset(msk->get_data(), 0xff, msk->get_data_size()); - - FillRegion fill_region(dst, msk); - fill_region.set_threshold(config.threshold); - - int x = 0, y = 0; - switch( config.key_mode ) { - case KEY_SEARCH: - min_key(x, y); - fill_region.fill(x, y); - break; - case KEY_SEARCH_ALL: - while( find_key(x, y, config.threshold) ) { - fill_region.fill(x, y); - ++x; + if( config.draw_mode != DRAW_EDGE ) { + if( msk && ( msk->get_w() != w || msk->get_h() != h ) ) { + delete msk; msk = 0; } - break; - case KEY_POINT: - x = config.point_x, y = config.point_y; - if( x >= 0 && x < w && y >= 0 && y < h ) - fill_region.fill(x, y); - break; - } + if( !msk ) + msk = new VFrame(w, h, BC_A8); + memset(msk->get_data(), 0xff, msk->get_data_size()); + + FillRegion fill_region(dst, msk); + for( int i=0, n=config.points.size(); ie ) continue; + float x = pt->x, y = pt->y; + if( x >= 0 && x < w && y >= 0 && y < h ) + fill_region.fill(x, y); + } + fill_region.run(); + //crikey_pgm("/tmp/msk.pgm",msk); - if( config.draw_mode == DRAW_MASK ) { - draw_mask(msk); - return 0; + if( config.draw_mode == DRAW_MASK ) + draw_mask(msk); + else + draw_alpha(msk); } + else + draw_mask(dst); - draw_alpha(msk); + if( config.drag ) { + for( int i=0, n=config.points.size(); iset_pixel_color(config.selected == i ? GREEN : WHITE); + draw_point(src, pt); + } + } return 0; } @@ -618,10 +653,10 @@ LoadClient* CriKeyEngine::new_client() } \ v = 0; \ float a = bmin(bmin(a00, a01), bmin(a10, a11)); \ - if( a < threshold ) continue; \ + if( a > threshold ) continue; \ float b = bmax(bmax(a00, a01), bmax(a10, a11)); \ - if( b <= threshold ) continue; \ - v = (b-a)*254 + 1; \ + if( threshold >= b ) continue; \ + v = 255; \ } \ } \ } break diff --git a/cinelerra-5.1/plugins/crikey/crikey.h b/cinelerra-5.1/plugins/crikey/crikey.h index 3b8c1cfc..6747e644 100644 --- a/cinelerra-5.1/plugins/crikey/crikey.h +++ b/cinelerra-5.1/plugins/crikey/crikey.h @@ -20,8 +20,8 @@ -#ifndef EDGE_H -#define EDGE_H +#ifndef __CRIKEY_H__ +#define __CRIKEY_H__ #include "loadbalance.h" #include "pluginvclient.h" @@ -34,15 +34,23 @@ class CriKey; #define DRAW_MASK 2 #define DRAW_MODES 3 -#define KEY_SEARCH 0 -#define KEY_SEARCH_ALL 1 -#define KEY_POINT 2 -#define KEY_MODES 3 +enum { PT_E, PT_X, PT_Y, PT_T, PT_SZ }; // enable, x,y, tag + +class CriKeyPoint +{ +public: + int t, e; + float x, y; + + CriKeyPoint(int t, int e, float x, float y); + ~CriKeyPoint(); +}; class CriKeyConfig { public: CriKeyConfig(); + ~CriKeyConfig(); int equivalent(CriKeyConfig &that); void copy_from(CriKeyConfig &that); @@ -52,11 +60,15 @@ public: static void set_target(int is_yuv, int color, float *target); static void set_color(int is_yuv, float *target, int &color); + ArrayList points; + int add_point(int t, int e, float x, float y); + int add_point(); + void del_point(int i); + int color; float threshold; - int draw_mode, key_mode; - float point_x, point_y; - int drag; + int draw_mode; + int drag, selected; }; class CriKeyPackage : public LoadPackage @@ -102,16 +114,13 @@ public: PLUGIN_CLASS_MEMBERS2(CriKeyConfig) int is_realtime(); void update_gui(); + int new_point(); void save_data(KeyFrame *keyframe); void read_data(KeyFrame *keyframe); int process_buffer(VFrame *frame, int64_t start_position, double frame_rate); void draw_alpha(VFrame *msk); - void draw_mask(VFrame *msk); - float diff_uint8(uint8_t *tp); - float diff_float(uint8_t *tp); - float (CriKey::*diff_pixel)(uint8_t *dp); - void min_key(int &ix, int &iy); - bool find_key(int &ix, int &iy, float threshold); + void draw_mask(VFrame *frm); + void draw_point(VFrame *msk, CriKeyPoint *pt); static void set_target(int is_yuv, int color, float *target) { CriKeyConfig::set_target(is_yuv, color, target); } diff --git a/cinelerra-5.1/plugins/crikey/crikeywindow.C b/cinelerra-5.1/plugins/crikey/crikeywindow.C index 9b7bd82e..3f72f3de 100644 --- a/cinelerra-5.1/plugins/crikey/crikeywindow.C +++ b/cinelerra-5.1/plugins/crikey/crikeywindow.C @@ -23,6 +23,7 @@ #include "clip.h" #include "crikey.h" #include "crikeywindow.h" +#include "cstrdup.h" #include "cwindow.h" #include "cwindowgui.h" #include "edl.h" @@ -37,11 +38,10 @@ #define COLOR_W 50 #define COLOR_H 30 -CriKeyNum::CriKeyNum(CriKeyWindow *gui, int x, int y, float &output) - : BC_TumbleTextBox(gui, output, -32767.0f, 32767.0f, x, y, 80) +CriKeyNum::CriKeyNum(CriKeyWindow *gui, int x, int y, float output) + : BC_TumbleTextBox(gui, output, -32767.0f, 32767.0f, x, y, 120) { this->gui = gui; - this->output = &output; set_increment(1); set_precision(1); } @@ -50,9 +50,31 @@ CriKeyNum::~CriKeyNum() { } -int CriKeyNum::handle_event() +int CriKeyPointX::handle_event() { - *output = atof(get_text()); + if( !CriKeyNum::handle_event() ) return 0; + CriKeyPoints *points = gui->points; + int hot_point = points->get_selection_number(0, 0); + if( hot_point >= 0 && hot_point < gui->plugin->config.points.size() ) { + float v = atof(get_text()); + gui->plugin->config.points[hot_point]->x = v; + points->set_point(hot_point, PT_X, v); + } + points->update_list(); + gui->plugin->send_configure_change(); + return 1; +} +int CriKeyPointY::handle_event() +{ + if( !CriKeyNum::handle_event() ) return 0; + CriKeyPoints *points = gui->points; + int hot_point = points->get_selection_number(0, 0); + if( hot_point >= 0 && hot_point < gui->plugin->config.points.size() ) { + float v = atof(get_text()); + gui->plugin->config.points[hot_point]->y = v; + points->set_point(hot_point, PT_Y, v); + } + points->update_list(); gui->plugin->send_configure_change(); return 1; } @@ -86,35 +108,6 @@ void CriKeyDrawMode::update(int mode, int send) if( send ) gui->plugin->send_configure_change(); } -int CriKeyKeyModeItem::handle_event() -{ - ((CriKeyKeyMode *)get_popup_menu())->update(id); - return 1; -} -CriKeyKeyMode::CriKeyKeyMode(CriKeyWindow *gui, int x, int y) - : BC_PopupMenu(x, y, 100, "", 1) -{ - this->gui = gui; - key_modes[KEY_SEARCH] = _("Search"); - key_modes[KEY_SEARCH_ALL] = _("Search all"); - key_modes[KEY_POINT] = _("Point"); - this->mode = -1; -} -void CriKeyKeyMode::create_objects() -{ - for( int i=0; iplugin->config.key_mode, 0); -} -void CriKeyKeyMode::update(int mode, int send) -{ - if( this->mode == mode ) return; - this->mode = mode; - set_text(key_modes[mode]); - gui->draw_key(mode); - if( send ) gui->plugin->send_configure_change(); -} - CriKeyColorButton::CriKeyColorButton(CriKeyWindow *gui, int x, int y) : BC_GenericButton(x, y, _("Color")) { @@ -134,19 +127,19 @@ CriKeyColorPicker::CriKeyColorPicker(CriKeyColorButton *color_button) void CriKeyColorPicker::start(int color) { - start_window(this->color = color, 0, 1); + orig_color = this->color = color; + start_window(color, 0, 1); } void CriKeyColorPicker::handle_done_event(int result) { - if( !result ) { - CriKeyWindow *gui = color_button->gui; - gui->lock_window("CriKeyColorPicker::handle_done_event"); - gui->update_color(color); - gui->plugin->config.color = color; - gui->plugin->send_configure_change(); - gui->unlock_window(); - } + if( result ) color = orig_color; + CriKeyWindow *gui = color_button->gui; + gui->lock_window("CriKeyColorPicker::handle_done_event"); + gui->update_color(color); + gui->plugin->config.color = color; + gui->plugin->send_configure_change(); + gui->unlock_window(); } int CriKeyColorPicker::handle_new_color(int color, int alpha) @@ -173,19 +166,24 @@ void CriKeyWindow::start_color_thread() CriKeyWindow::CriKeyWindow(CriKey *plugin) - : PluginClientWindow(plugin, 320, 220, 320, 220, 0) + : PluginClientWindow(plugin, 380, 360, 380, 360, 0) { this->plugin = plugin; this->color_button = 0; this->color_picker = 0; - this->title_x = 0; this->point_x = 0; - this->title_y = 0; this->point_y = 0; - this->dragging = 0; this->drag = 0; + this->title_x = 0; this->point_x = 0; + this->title_y = 0; this->point_y = 0; + this->new_point = 0; this->del_point = 0; + this->point_up = 0; this->point_dn = 0; + this->drag = 0; this->dragging = 0; + this->last_x = 0; this->last_y = 0; + this->points = 0; this->cur_point = 0; } CriKeyWindow::~CriKeyWindow() { delete color_picker; + delete points; } void CriKeyWindow::create_objects() @@ -197,46 +195,83 @@ void CriKeyWindow::create_objects() y += title->get_h() + margin; add_subwindow(threshold = new CriKeyThreshold(this, x, y, get_w() - x * 2)); y += threshold->get_h() + margin; + add_subwindow(color_button = new CriKeyColorButton(this, x, y)); + int x1 = x + color_button->get_w() + margin; + color_x = x1; color_y = y; + update_color(plugin->config.color); + y += COLOR_H + 10 + margin ; add_subwindow(title = new BC_Title(x, y+5, _("Draw mode:"))); - int x1 = x + title->get_w() + 10 + margin; + x1 = x + title->get_w() + 10 + margin; add_subwindow(draw_mode = new CriKeyDrawMode(this, x1, y)); draw_mode->create_objects(); - y += draw_mode->get_h() + margin; - add_subwindow(title = new BC_Title(x, y+5, _("Key mode:"))); - add_subwindow(key_mode = new CriKeyKeyMode(this, x1, y)); - y += key_mode->get_h() + margin; - key_x = x + 10 + margin; key_y = y + 10 + margin; - key_mode->create_objects(); + y += draw_mode->get_h() + 10 + margin; + + CriKeyPoint *pt = plugin->config.points[plugin->config.selected]; + add_subwindow(title_x = new BC_Title(x, y, _("X:"))); + x1 = x + title_x->get_w() + margin; + point_x = new CriKeyPointX(this, x1, y, pt->x); + point_x->create_objects(); + x1 += point_x->get_w() + margin; + add_subwindow(new_point = new CriKeyNewPoint(this, plugin, x1, y)); + x1 += new_point->get_w() + margin; + add_subwindow(point_up = new CriKeyPointUp(this, x1, y)); + y += point_x->get_h() + margin; + add_subwindow(title_y = new BC_Title(x, y, _("Y:"))); + x1 = x + title_y->get_w() + margin; + point_y = new CriKeyPointY(this, x1, y, pt->y); + point_y->create_objects(); + x1 += point_y->get_w() + margin; + add_subwindow(del_point = new CriKeyDelPoint(this, plugin, x1, y)); + x1 += del_point->get_w() + margin; + add_subwindow(point_dn = new CriKeyPointDn(this, x1, y)); + y += point_y->get_h() + margin + 10; + add_subwindow(drag = new CriKeyDrag(this, x, y)); + x1 = x + drag->get_w() + margin + 20; + add_subwindow(cur_point = new CriKeyCurPoint(this, plugin, x1, y+3)); + cur_point->update(plugin->config.selected); + y += drag->get_h() + margin; + add_subwindow(points = new CriKeyPoints(this, plugin, x, y)); + points->update(plugin->config.selected); if( plugin->config.drag ) grab(plugin->server->mwindow->cwindow->gui); + show_window(1); } int CriKeyWindow::grab_event(XEvent *event) { - if( key_mode->mode != KEY_POINT ) return 0; + switch( event->type ) { + case ButtonPress: break; + case ButtonRelease: break; + case MotionNotify: break; + default: return 0; + } MWindow *mwindow = plugin->server->mwindow; CWindowGUI *cwindow_gui = mwindow->cwindow->gui; CWindowCanvas *canvas = cwindow_gui->canvas; - int cx, cy; canvas->get_canvas()->get_relative_cursor_xy(cx, cy); - if( cx < mwindow->theme->ccanvas_x ) return 0; - if( cx >= mwindow->theme->ccanvas_x+mwindow->theme->ccanvas_w ) return 0; - if( cy < mwindow->theme->ccanvas_y ) return 0; - if( cy >= mwindow->theme->ccanvas_y+mwindow->theme->ccanvas_h ) return 0; + int cx, cy; cwindow_gui->get_relative_cursor_xy(cx, cy); + cx -= mwindow->theme->ccanvas_x; + cy -= mwindow->theme->ccanvas_y; + + if( !dragging ) { + if( cx < 0 || cx >= mwindow->theme->ccanvas_w ) return 0; + if( cy < 0 || cy >= mwindow->theme->ccanvas_h ) return 0; + } switch( event->type ) { case ButtonPress: if( dragging ) return 0; - dragging = 1; + dragging = event->xbutton.state & ShiftMask ? -1 : 1; break; case ButtonRelease: if( !dragging ) return 0; dragging = 0; return 1; case MotionNotify: - if( dragging ) break; + if( !dragging ) return 0; + break; default: return 0; } @@ -254,8 +289,70 @@ int CriKeyWindow::grab_event(XEvent *event) projector_y += mwindow->edl->session->output_h / 2; float output_x = (cursor_x - projector_x) / projector_z + track_w / 2; float output_y = (cursor_y - projector_y) / projector_z + track_h / 2; - point_x->update((int64_t)(plugin->config.point_x = output_x)); - point_y->update((int64_t)(plugin->config.point_y = output_y)); + point_x->update((int64_t)(output_x)); + point_y->update((int64_t)(output_y)); + + if( dragging > 0 ) { + switch( event->type ) { + case ButtonPress: { + int hot_point = -1; + int n = plugin->config.points.size(); + if( n > 0 ) { + CriKeyPoint *pt = plugin->config.points[hot_point=0]; + double dist = DISTANCE(output_x,output_y, pt->x,pt->y); + for( int i=1; iconfig.points[i]; + double d = DISTANCE(output_x,output_y, pt->x,pt->y); + if( d >= dist ) continue; + dist = d; hot_point = i; + } + } + if( hot_point >= 0 ) { + CriKeyPoint *pt = plugin->config.points[hot_point]; + if( pt->x == output_x && pt->y == output_y ) break; + points->set_point(hot_point, PT_X, pt->x = output_x); + points->set_point(hot_point, PT_Y, pt->y = output_y); + plugin->config.selected = hot_point; + points->set_selected(hot_point); + points->update_list(); + } + break; } + case MotionNotify: { + int hot_point = points->get_selection_number(0, 0); + if( hot_point >= 0 && hot_point < plugin->config.points.size() ) { + CriKeyPoint *pt = plugin->config.points[hot_point]; + if( pt->x == output_x && pt->y == output_y ) break; + points->set_point(hot_point, PT_X, pt->x = output_x); + points->set_point(hot_point, PT_Y, pt->y = output_y); + point_x->update(pt->x); + point_y->update(pt->y); + points->update_list(); + } + break; } + } + } + else { + switch( event->type ) { + case MotionNotify: { + float dx = output_x - last_x, dy = output_y - last_y; + int n = plugin->config.points.size(); + for( int i=0; iconfig.points[i]; + points->set_point(i, PT_X, pt->x += dx); + points->set_point(i, PT_Y, pt->y += dy); + } + int hot_point = points->get_selection_number(0, 0); + if( hot_point >= 0 && hot_point < n ) { + CriKeyPoint *pt = plugin->config.points[hot_point]; + point_x->update(pt->x); + point_y->update(pt->y); + points->update_list(); + } + break; } + } + } + + last_x = output_x; last_y = output_y; plugin->send_configure_change(); return 1; } @@ -266,44 +363,131 @@ void CriKeyWindow::done_event(int result) if( color_picker ) color_picker->close_window(); } -void CriKeyWindow::draw_key(int mode) +CriKeyPoints::CriKeyPoints(CriKeyWindow *gui, CriKey *plugin, int x, int y) + : BC_ListBox(x, y, 360, 130, LISTBOX_TEXT) { - int margin = plugin->get_theme()->widget_border; - int x = key_x, y = key_y; - delete color_picker; color_picker = 0; - delete color_button; color_button = 0; - delete title_x; title_x = 0; - delete point_x; point_x = 0; - delete title_y; title_y = 0; - delete point_y; point_y = 0; - delete drag; drag = 0; - - clear_box(x,y, get_w()-x,get_h()-y); - flash(x,y, get_w()-x,get_h()-y); - - switch( mode ) { - case KEY_SEARCH: - case KEY_SEARCH_ALL: - add_subwindow(color_button = new CriKeyColorButton(this, x, y)); - x += color_button->get_w() + margin; - color_x = x; color_y = y; - update_color(plugin->config.color); - break; - case KEY_POINT: - add_subwindow(title_x = new BC_Title(x, y, _("X:"))); - int x1 = x + title_x->get_w() + margin, y1 = y; - point_x = new CriKeyNum(this, x1, y, plugin->config.point_x); - point_x->create_objects(); - y += point_x->get_h() + margin; - add_subwindow(title_y = new BC_Title(x, y, _("Y:"))); - point_y = new CriKeyNum(this, x1, y, plugin->config.point_y); - point_y->create_objects(); - x1 += point_x->get_w() + margin; - add_subwindow(drag = new CriKeyDrag(this, x1, y1)); - break; + this->gui = gui; + this->plugin = plugin; + titles[PT_E] = _("E"); widths[PT_E] = 40; + titles[PT_X] = _("X"); widths[PT_X] = 120; + titles[PT_Y] = _("Y"); widths[PT_Y] = 120; + titles[PT_T] = _("Tag"); widths[PT_T] = 60; +} +CriKeyPoints::~CriKeyPoints() +{ + clear(); +} +void CriKeyPoints::clear() +{ + for( int i=PT_SZ; --i>=0; ) + cols[i].remove_all_objects(); +} + +int CriKeyPoints::column_resize_event() +{ + for( int i=PT_SZ; --i>=0; ) + widths[i] = get_column_width(i); + return 1; +} + +int CriKeyPoints::handle_event() +{ + int hot_point = get_selection_number(0, 0); + const char *x_text = "", *y_text = ""; + if( hot_point >= 0 && hot_point < plugin->config.points.size() ) { + if( get_cursor_x() < widths[0] ) { + plugin->config.points[hot_point]->e = + !plugin->config.points[hot_point]->e; + } + x_text = gui->points->cols[PT_X].get(hot_point)->get_text(); + y_text = gui->points->cols[PT_Y].get(hot_point)->get_text(); } - plugin->config.key_mode = mode; - show_window(1); + else + hot_point = 0; + gui->point_x->update(x_text); + gui->point_y->update(y_text); + plugin->config.selected = hot_point; + update(hot_point); + gui->plugin->send_configure_change(); + return 1; +} + +int CriKeyPoints::selection_changed() +{ + handle_event(); + return 1; +} + +void CriKeyPoints::new_point(const char *ep, const char *xp, const char *yp, const char *tp) +{ + cols[PT_E].append(new BC_ListBoxItem(ep)); + cols[PT_X].append(new BC_ListBoxItem(xp)); + cols[PT_Y].append(new BC_ListBoxItem(yp)); + cols[PT_T].append(new BC_ListBoxItem(tp)); +} + +void CriKeyPoints::del_point(int i) +{ + for( int n=cols[0].size()-1, c=PT_SZ; --c>=0; ) + cols[c].remove_object_number(n-i); +} + +void CriKeyPoints::set_point(int i, int c, float v) +{ + char s[BCSTRLEN]; sprintf(s,"%0.4f",v); + set_point(i,c,s); +} +void CriKeyPoints::set_point(int i, int c, const char *cp) +{ + cols[c].get(i)->set_text(cp); +} + +int CriKeyPoints::set_selected(int k) +{ + int sz = gui->plugin->config.points.size(); + if( !sz ) return -1; + bclamp(k, 0, sz-1); + int n = gui->points->get_selection_number(0, 0); + if( n >= 0 ) { + for( int i=0; iset_selected(0); + } + for( int i=0; iset_selected(1); + gui->cur_point->update(k); + return k; +} +void CriKeyPoints::update_list() +{ + int xpos = get_xposition(), ypos = get_xposition(); + int k = get_selection_number(0, 0); + BC_ListBox::update(&cols[0], &titles[0],&widths[0],PT_SZ, xpos,ypos,k); +} +void CriKeyPoints::update(int k) +{ + if( k < 0 ) k = get_selection_number(0, 0); + gui->cur_point->update(k); + int xpos = get_xposition(), ypos = get_xposition(); + + clear(); + ArrayList &points = plugin->config.points; + int n = points.size(); + for( int i=0; ie ? "*" : ""); + char xtxt[BCSTRLEN]; sprintf(xtxt,"%0.4f", pt->x); + char ytxt[BCSTRLEN]; sprintf(ytxt,"%0.4f", pt->y); + char ttxt[BCSTRLEN]; sprintf(ttxt,"%d", pt->t); + new_point(etxt, xtxt, ytxt, ttxt); + } + if( k < n ) { + for( int i=PT_SZ; --i>=0; ) + cols[i].get(k)->set_selected(1); + gui->point_x->update(gui->points->cols[PT_X].get(k)->get_text()); + gui->point_y->update(gui->points->cols[PT_Y].get(k)->get_text()); + } + + BC_ListBox::update(&cols[0], &titles[0],&widths[0],PT_SZ, xpos,ypos,k); } void CriKeyWindow::update_color(int color) @@ -317,19 +501,12 @@ void CriKeyWindow::update_color(int color) void CriKeyWindow::update_gui() { - threshold->update(plugin->config.threshold); draw_mode->update(plugin->config.draw_mode); - key_mode->update(plugin->config.key_mode); - switch( plugin->config.key_mode ) { - case KEY_POINT: - point_x->update(plugin->config.point_x); - point_y->update(plugin->config.point_y); - break; - case KEY_SEARCH: - case KEY_SEARCH_ALL: - update_color(plugin->config.color); - break; - } + update_color(plugin->config.color); + threshold->update(plugin->config.threshold); + cur_point->update(plugin->config.selected); + drag->update(plugin->config.drag); + points->update(plugin->config.selected); } @@ -342,11 +519,61 @@ CriKeyThreshold::CriKeyThreshold(CriKeyWindow *gui, int x, int y, int w) int CriKeyThreshold::handle_event() { - gui->plugin->config.threshold = get_value(); + float v = get_value(); + gui->plugin->config.threshold = v; + gui->plugin->send_configure_change(); + return 1; +} + + +CriKeyPointUp::CriKeyPointUp(CriKeyWindow *gui, int x, int y) + : BC_GenericButton(x, y, _("Up")) +{ + this->gui = gui; +} +CriKeyPointUp::~CriKeyPointUp() +{ +} + +int CriKeyPointUp::handle_event() +{ + int n = gui->plugin->config.points.size(); + int hot_point = gui->points->get_selection_number(0, 0); + + if( n > 1 && hot_point > 0 ) { + CriKeyPoint *&pt0 = gui->plugin->config.points[hot_point]; + CriKeyPoint *&pt1 = gui->plugin->config.points[--hot_point]; + CriKeyPoint *t = pt0; pt0 = pt1; pt1 = t; + gui->plugin->config.selected = hot_point; + gui->points->update(hot_point); + } gui->plugin->send_configure_change(); return 1; } +CriKeyPointDn::CriKeyPointDn(CriKeyWindow *gui, int x, int y) + : BC_GenericButton(x, y, _("Dn")) +{ + this->gui = gui; +} +CriKeyPointDn::~CriKeyPointDn() +{ +} + +int CriKeyPointDn::handle_event() +{ + int n = gui->plugin->config.points.size(); + int hot_point = gui->points->get_selection_number(0, 0); + if( n > 1 && hot_point < n-1 ) { + CriKeyPoint *&pt0 = gui->plugin->config.points[hot_point]; + CriKeyPoint *&pt1 = gui->plugin->config.points[++hot_point]; + CriKeyPoint *t = pt0; pt0 = pt1; pt1 = t; + gui->plugin->config.selected = hot_point; + gui->points->update(hot_point); + } + gui->plugin->send_configure_change(); + return 1; +} CriKeyDrag::CriKeyDrag(CriKeyWindow *gui, int x, int y) : BC_CheckBox(x, y, gui->plugin->config.drag, _("Drag")) @@ -366,3 +593,60 @@ int CriKeyDrag::handle_event() return 1; } +CriKeyNewPoint::CriKeyNewPoint(CriKeyWindow *gui, CriKey *plugin, int x, int y) + : BC_GenericButton(x, y, 80, _("New")) +{ + this->gui = gui; + this->plugin = plugin; +} +CriKeyNewPoint::~CriKeyNewPoint() +{ +} +int CriKeyNewPoint::handle_event() +{ + int k = plugin->new_point(); + gui->points->update(k); + gui->plugin->send_configure_change(); + return 1; +} + +CriKeyDelPoint::CriKeyDelPoint(CriKeyWindow *gui, CriKey *plugin, int x, int y) + : BC_GenericButton(x, y, 80, _("Del")) +{ + this->gui = gui; + this->plugin = plugin; +} +CriKeyDelPoint::~CriKeyDelPoint() +{ +} +int CriKeyDelPoint::handle_event() +{ + int hot_point = gui->points->get_selection_number(0, 0); + if( hot_point >= 0 && hot_point < gui->plugin->config.points.size() ) { + plugin->config.del_point(hot_point); + if( !plugin->config.points.size() ) plugin->new_point(); + int n = gui->plugin->config.points.size(); + if( hot_point >= n && hot_point > 0 ) --hot_point; + gui->plugin->config.selected = hot_point; + gui->points->update(hot_point); + gui->plugin->send_configure_change(); + } + return 1; +} + +CriKeyCurPoint::CriKeyCurPoint(CriKeyWindow *gui, CriKey *plugin, int x, int y) + : BC_Title(x, y, "") +{ + this->gui = gui; + this->plugin = plugin; +} +CriKeyCurPoint::~CriKeyCurPoint() +{ +} +void CriKeyCurPoint::update(int n) +{ + char string[BCSTRLEN]; + sprintf(string, _("Selected: %d "), n); + BC_Title::update(string); +} + diff --git a/cinelerra-5.1/plugins/crikey/crikeywindow.h b/cinelerra-5.1/plugins/crikey/crikeywindow.h index 5af60d54..46646fd2 100644 --- a/cinelerra-5.1/plugins/crikey/crikeywindow.h +++ b/cinelerra-5.1/plugins/crikey/crikeywindow.h @@ -27,24 +27,48 @@ class CriKey; class CriKeyWindow; class CriKeyNum; +class CriKeyPointX; +class CriKeyPointY; class CriKeyColorButton; class CriKeyColorPicker; class CriKeyDrawMode; class CriKeyDrawModeItem; -class CriKeyKeyMode; -class CriKeyKeyModeItem; class CriKeyThreshold; +class CriKeyDrag; +class CriKeyPoints; +class CriKeyNewPoint; +class CriKeyDelPoint; +class CriKeyPointUp; +class CriKeyPointDn; +class CriKeyCurPoint; + class CriKeyNum : public BC_TumbleTextBox { public: CriKeyWindow *gui; - float *output; - int handle_event(); - CriKeyNum(CriKeyWindow *gui, int x, int y, float &output); + CriKeyNum(CriKeyWindow *gui, int x, int y, float output); ~CriKeyNum(); }; +class CriKeyPointX : public CriKeyNum +{ +public: + CriKeyPointX(CriKeyWindow *gui, int x, int y, float output) + : CriKeyNum(gui, x, y, output) {} + ~CriKeyPointX() {} + + int handle_event(); +}; +class CriKeyPointY : public CriKeyNum +{ +public: + CriKeyPointY(CriKeyWindow *gui, int x, int y, float output) + : CriKeyNum(gui, x, y, output) {} + ~CriKeyPointY() {} + + int handle_event(); +}; class CriKeyColorButton : public BC_GenericButton { @@ -65,7 +89,7 @@ public: void handle_done_event(int result); CriKeyColorButton *color_button; - int color; + int color, orig_color; }; class CriKeyDrawMode : public BC_PopupMenu @@ -90,42 +114,104 @@ public: int id; }; -class CriKeyKeyMode : public BC_PopupMenu +class CriKeyThreshold : public BC_FSlider +{ +public: + CriKeyThreshold(CriKeyWindow *gui, int x, int y, int w); + int handle_event(); + CriKeyWindow *gui; +}; + +class CriKeyDrag : public BC_CheckBox { - const char *key_modes[KEY_MODES]; public: - CriKeyKeyMode(CriKeyWindow *gui, int x, int y); + CriKeyDrag(CriKeyWindow *gui, int x, int y); - void create_objects(); - void update(int mode, int send=1); + int handle_event(); CriKeyWindow *gui; - int mode; }; -class CriKeyKeyModeItem : public BC_MenuItem + +class CriKeyPoints : public BC_ListBox { public: - CriKeyKeyModeItem(const char *text, int id) - : BC_MenuItem(text) { this->id = id; } + CriKeyPoints(CriKeyWindow *gui, CriKey *plugin, int x, int y); + ~CriKeyPoints(); int handle_event(); + int selection_changed(); + int column_resize_event(); + ArrayList cols[PT_SZ]; + void clear(); + void new_point(const char *ep, const char *xp, const char *yp, const char *tp); + void del_point(int i); + void set_point(int i, int c, float v); + void set_point(int i, int c, const char *cp); + int set_selected(int k); + void update_list(); + void update(int k); + + CriKeyWindow *gui; - int id; + CriKey *plugin; + const char *titles[PT_SZ]; + int widths[PT_SZ]; }; -class CriKeyThreshold : public BC_FSlider +class CriKeyNewPoint : public BC_GenericButton { public: - CriKeyThreshold(CriKeyWindow *gui, int x, int y, int w); + CriKeyNewPoint(CriKeyWindow *gui, CriKey *plugin, int x, int y); + ~CriKeyNewPoint(); + int handle_event(); + CriKeyWindow *gui; + CriKey *plugin; }; -class CriKeyDrag : public BC_CheckBox +class CriKeyDelPoint : public BC_GenericButton { public: - CriKeyDrag(CriKeyWindow *gui, int x, int y); + CriKeyDelPoint(CriKeyWindow *gui, CriKey *plugin, int x, int y); + ~CriKeyDelPoint(); + + int handle_event(); + + CriKey *plugin; + CriKeyWindow *gui; +}; + +class CriKeyPointUp : public BC_GenericButton +{ +public: + CriKeyPointUp(CriKeyWindow *gui, int x, int y); + ~CriKeyPointUp(); + + int handle_event(); + + CriKeyWindow *gui; +}; + +class CriKeyPointDn : public BC_GenericButton +{ +public: + CriKeyPointDn(CriKeyWindow *gui, int x, int y); + ~CriKeyPointDn(); int handle_event(); + + CriKeyWindow *gui; +}; + +class CriKeyCurPoint : public BC_Title +{ +public: + CriKeyCurPoint(CriKeyWindow *gui, CriKey *plugin, int x, int y); + ~CriKeyCurPoint(); + + void update(int n); + + CriKey *plugin; CriKeyWindow *gui; }; @@ -136,7 +222,6 @@ public: ~CriKeyWindow(); void create_objects(); - void draw_key(int mode); void update_color(int color); void update_gui(); void start_color_thread(); @@ -146,15 +231,22 @@ public: CriKey *plugin; CriKeyThreshold *threshold; CriKeyDrawMode *draw_mode; - CriKeyKeyMode *key_mode; CriKeyColorButton *color_button; CriKeyColorPicker *color_picker; - int color_x, color_y, key_x, key_y; + int color_x, color_y; BC_Title *title_x, *title_y; - CriKeyNum *point_x, *point_y; + CriKeyPointX *point_x; + CriKeyPointY *point_y; + CriKeyNewPoint *new_point; + CriKeyDelPoint *del_point; + CriKeyPointUp *point_up; + CriKeyPointDn *point_dn; + CriKeyCurPoint *cur_point; int dragging; + float last_x, last_y; CriKeyDrag *drag; + CriKeyPoints *points; }; #endif diff --git a/cinelerra-5.1/plugins/titler/titlerwindow.C b/cinelerra-5.1/plugins/titler/titlerwindow.C index 01cddf4f..f52d3f21 100644 --- a/cinelerra-5.1/plugins/titler/titlerwindow.C +++ b/cinelerra-5.1/plugins/titler/titlerwindow.C @@ -465,14 +465,24 @@ int TitleWindow::resize_event(int w, int h) int TitleWindow::grab_event(XEvent *event) { + switch( event->type ) { + case ButtonPress: break; + case ButtonRelease: break; + case MotionNotify: break; + default: return 0; + } + MWindow *mwindow = client->server->mwindow; CWindowGUI *cwindow_gui = mwindow->cwindow->gui; CWindowCanvas *canvas = cwindow_gui->canvas; - int cx, cy; canvas->get_canvas()->get_relative_cursor_xy(cx, cy); - if( cx < mwindow->theme->ccanvas_x ) return 0; - if( cx >= mwindow->theme->ccanvas_x+mwindow->theme->ccanvas_w ) return 0; - if( cy < mwindow->theme->ccanvas_y ) return 0; - if( cy >= mwindow->theme->ccanvas_y+mwindow->theme->ccanvas_h ) return 0; + int cx, cy; cwindow_gui->get_relative_cursor_xy(cx, cy); + cx -= mwindow->theme->ccanvas_x; + cy -= mwindow->theme->ccanvas_y; + + if( !dragging ) { + if( cx < 0 || cx >= mwindow->theme->ccanvas_w ) return 0; + if( cy < 0 || cy >= mwindow->theme->ccanvas_h ) return 0; + } switch( event->type ) { case ButtonPress: @@ -483,7 +493,8 @@ int TitleWindow::grab_event(XEvent *event) dragging = 0; return 1; case MotionNotify: - if( dragging ) break; + if( !dragging ) return 0; + break; default: return 0; } -- 2.26.2