crikey rework, KP4 fix, added Shift-KPx, valgrind cleanups, hex eye-dropper, resize...
authorGood Guy <good1.2guy@gmail.com>
Tue, 8 Aug 2017 22:10:26 +0000 (16:10 -0600)
committerGood Guy <good1.2guy@gmail.com>
Tue, 8 Aug 2017 22:10:26 +0000 (16:10 -0600)
18 files changed:
cinelerra-5.1/cinelerra/assetpopup.C
cinelerra-5.1/cinelerra/assetpopup.h
cinelerra-5.1/cinelerra/audioalsa.C
cinelerra-5.1/cinelerra/commonrender.C
cinelerra-5.1/cinelerra/cwindowgui.C
cinelerra-5.1/cinelerra/cwindowgui.h
cinelerra-5.1/cinelerra/cwindowtool.C
cinelerra-5.1/cinelerra/cwindowtool.h
cinelerra-5.1/cinelerra/playtransport.C
cinelerra-5.1/cinelerra/transportque.C
cinelerra-5.1/cinelerra/transportque.h
cinelerra-5.1/guicast/bccapture.C
cinelerra-5.1/guicast/bcwindowbase.C
cinelerra-5.1/plugins/crikey/crikey.C
cinelerra-5.1/plugins/crikey/crikey.h
cinelerra-5.1/plugins/crikey/crikeywindow.C
cinelerra-5.1/plugins/crikey/crikeywindow.h
cinelerra-5.1/plugins/titler/titlerwindow.C

index 670e088299dbd96a59081759ed36ad0e673e4922..c153e3db8935ed9ef0e3cc59ed00f04c4ed5c0e5 100644 (file)
@@ -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;
 }
 
index c070f124eb857fa4360f8c410070670df19e538a..d6c3136e5a3c9e873ba85115b2f02c2f23081cf8 100644 (file)
@@ -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;
index c8a21f6cb62053d600043201480be1a5e30538c7..7a8d712c3b8f2687280dd33a9bccfa0925872c12 100644 (file)
@@ -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 ) {
index 18239788c8d73a45cfc79665b5896aecabaef595..32358c06fda1c24e825dbadcf8413afe5ef9eaa7 100644 (file)
@@ -266,7 +266,7 @@ int CommonRender::get_boundaries(int64_t &current_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;
index 94887b5ba6a9c5e2ff29ebf080228f3655f4857d..c3bf4b61b88ddf0a7b491edf3fc4556344853d9f 100644 (file)
@@ -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;
 }
 
index 44a0b607be5f5547c2a18d595fb6215975064b70..d08291d15da1c806e655b3e64e5ced55f286aa3a 100644 (file)
@@ -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;
index caf0bf82d2953b65b9f4eeb2d9917d9a958cdd9b..d73a265b5727d15d3e4391d479ea21845ddc57b4 100644 (file)
@@ -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());
index 5761ae8ae80387a62efe29e5bf0bdf991a8ba391..651627e0860f8206d12aac83fa23f4edbb3b274b 100644 (file)
@@ -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;
 };
 
index 991adb9ada070efb187e43ecfbb42715a0a4d3fa..a426ac79336e6509c098c5ce475413985bffad05 100644 (file)
@@ -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;
                }
index 16aa45faf352aad41e945a99057f41dc1ed50521..61dbdb6d00e3cd7fbe12a37d02d42fedc5f908cf 100644 (file)
@@ -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;
        }
 
index 1eed30e7f0115ca93794d22f511d1380639a40de..4e9c36353ee7b5e6d7ad6a9016d372d149a8b6cb 100644 (file)
@@ -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();
index 0e32ef057a8cbdc3845520f3183411a92b7f3c45..993cfe14fbc3279ee1cbf7c08943608416d5e441 100644 (file)
@@ -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;
 }
index 8654bbe7238bb6ed66d66e201c3e3a10bb05d238..f851f384de0b916e6bb25faa297e7cb8fd5fe169 100644 (file)
@@ -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
index ccbb216a34ca180373edfe4a14050e0e2ca1743b..6b942d5d95d13bc4f52b069260db568adfe8791f 100644 (file)
@@ -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(); i<n; ++i ) {
+               CriKeyPoint *ap = this->points[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(); i<n; ++i ) {
+               CriKeyPoint *pt = that.points[i];
+               add_point(pt->t, 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; i<prev_sz; ++i ) {
+               CriKeyPoint *pt = prev.points[i], *nt = 0;
+               float x = pt->x, 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; i<comp; ++i,++dp )
-               v += fabs(*dp * scale - target[i]);
-       return v / comp;
-}
-float CriKey::diff_float(uint8_t *dp)
-{
-       float *fp = (float *)dp, v = 0;
-       for( int i=0; i<comp; ++i,++fp )
-               v += fabs(*fp - target[i]);
-       return v / comp;
-}
-
-void CriKey::min_key(int &ix, int &iy)
-{
-       float mv = 1;
-       uint8_t **src_rows = src->get_rows();
-       for( int y=0; y<h; ++y ) {
-               uint8_t *sp = src_rows[y];
-               for( int x=0; x<w; ++x,sp+=bpp ) {
-                       float v = (this->*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<h; ++y ) {
-               uint8_t *sp = src_rows[y] + x*bpp;
-               uint8_t *mp = msk_rows[y] + x;
-               for( ; x<w; ++x,++mp,sp+=bpp ) {
-                       if( !*mp ) continue;
-                       float v = (this->*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(); i<n; ++i ) {
+               CriKeyPoint *pt = config.points[i];
+               char point[BCSTRLEN];
+               sprintf(point,"/POINT_%d",pt->t);
+               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; x<w; ++x ) dp[x] = dp[x-w];
 //crikey_pgm("/tmp/dst.pgm",dst);
 
-       if( config.draw_mode == DRAW_EDGE ) {
-               draw_mask(dst);
-               return 0;
-       }
-
-       if( msk && ( msk->get_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(); i<n; ++i ) {
+                       CriKeyPoint *pt = config.points[i];
+                       if( !pt->e ) 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(); i<n; ++i ) {
+                       CriKeyPoint *pt = config.points[i];
+                       src->set_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
index 3b8c1cfc532819eb73076b5e1ce82c431ec67148..6747e6449f18eb4e4f9126f7619ef00d87e3e9e1 100644 (file)
@@ -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<CriKeyPoint *> 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);
        }
index 9b7bd82e69463275397080f9f2534eea48af5686..3f72f3ded74ccf5aa1f3b56189a6e6661ab1ca98 100644 (file)
@@ -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"
 #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; i<KEY_MODES; ++i )
-               add_item(new CriKeyKeyModeItem(key_modes[i], i));
-       update(gui->plugin->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; i<n; ++i ) {
+                                       pt = plugin->config.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; i<n; ++i ) {
+                               CriKeyPoint *pt = plugin->config.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; i<PT_SZ; ++i )
+                       cols[i].get(n)->set_selected(0);
+       }
+       for( int i=0; i<PT_SZ; ++i )
+               cols[i].get(k)->set_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<CriKeyPoint*> &points = plugin->config.points;
+       int n = points.size();
+       for( int i=0; i<n; ++i ) {
+               CriKeyPoint *pt = points[i];
+               char etxt[BCSTRLEN];  sprintf(etxt,"%s", pt->e ? "*" : "");
+               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);
+}
+
index 5af60d541c86f398d29edb6e432ce5a5fc52edad..46646fd29524204735c8ab2f45cd1a22edf59d9a 100644 (file)
 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<BC_ListBoxItem*> 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
index 01cddf4f7d7c468b1d82a5bfc22ce295b2a67936..f52d3f21adf8411457259c22cb4e495bf2c7b0b0 100644 (file)
@@ -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;
        }