Enhanced curve editor :
- graphical celan up (surrounding frame deleted, histogram realigned) - a feedback tell what point is going to move - on Button press, the point doesn't move to the cursor anymore. Instead, the cursor is hidden during the drag and reappear in the same place it disappeared - by default, a 0.5 factor is used to move the point during the drag (i.e. you have to move the move of 2 pixel to move the point of one pixel) - keyboard can be used to fine tune the point position (subpixel placement) : - CTRL : factor = 0.1 - SHIFT : factor = 0.02 - CTRL+SHIFT : factor = 0.005 In the mean time, i had to create a new "Empty" cursor to hide it. A new method has been created to easily modify the cursor of the main window.
This commit is contained in:
@@ -30,21 +30,25 @@ void CursorManager::init (Glib::RefPtr<Gdk::Window> mainWin) {
|
||||
cCropMove = new Gdk::Cursor (Gdk::FLEUR);
|
||||
cCropMoving = new Gdk::Cursor (Gdk::HAND2);
|
||||
cCropSelection = new Gdk::Cursor (Gdk::CROSSHAIR);
|
||||
#ifdef _WIN32
|
||||
cNormal = new Gdk::Cursor (Gdk::LAST_CURSOR);
|
||||
#else
|
||||
cAdd = new Gdk::Cursor (Gdk::PLUS);
|
||||
//#ifdef _WIN32
|
||||
// cNormal = new Gdk::Cursor (Gdk::LAST_CURSOR);
|
||||
//#else
|
||||
cNormal = new Gdk::Cursor (Gdk::ARROW);
|
||||
#endif
|
||||
Glib::RefPtr<Gdk::Pixbuf> hand = safe_create_from_file(argv0+"/images/openhand22.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> close_hand = safe_create_from_file(argv0+"/images/closedhand22.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> wbpick = safe_create_from_file(argv0+"/images/wbpicker16.png");
|
||||
cHand = hand ? new Gdk::Cursor (cNormal->get_display(), hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2);
|
||||
//#endif
|
||||
Glib::RefPtr<Gdk::Pixbuf> hand = safe_create_from_file(argv0+"/images/openhand22.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> close_hand = safe_create_from_file(argv0+"/images/closedhand22.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> wbpick = safe_create_from_file(argv0+"/images/wbpicker16.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> empty = safe_create_from_file(argv0+"/images/empty.png");
|
||||
cHand = hand ? new Gdk::Cursor (cNormal->get_display(), hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2);
|
||||
cClosedHand = close_hand ? new Gdk::Cursor (cNormal->get_display(), close_hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2);
|
||||
cWB = wbpick ? new Gdk::Cursor (cNormal->get_display(), wbpick, 1, 12) : new Gdk::Cursor (Gdk::ARROW);
|
||||
cHidden = empty ? new Gdk::Cursor (cNormal->get_display(), empty, 12, 12) : new Gdk::Cursor (Gdk::FLEUR);
|
||||
|
||||
mainWindow = mainWin;
|
||||
}
|
||||
|
||||
/* Set the cursor of the given window */
|
||||
void CursorManager::setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape shape) {
|
||||
|
||||
if (shape==CSArrow)
|
||||
@@ -67,6 +71,14 @@ void CursorManager::setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape sha
|
||||
window->set_cursor (*cCropSelection);
|
||||
else if (shape==CSStraighten)
|
||||
window->set_cursor (*cCropSelection);
|
||||
else if (shape==CSPlus)
|
||||
window->set_cursor (*cAdd);
|
||||
else if (shape==CSEmpty)
|
||||
window->set_cursor (*cHidden);
|
||||
}
|
||||
|
||||
/* Set the cursor of the main window */
|
||||
void CursorManager::setCursor (CursorShape shape) {
|
||||
setCursor(mainWindow, shape);
|
||||
}
|
||||
|
||||
|
@@ -21,7 +21,7 @@
|
||||
|
||||
#include <gtkmm.h>
|
||||
|
||||
enum CursorShape {CSArrow, CSOpenHand, CSClosedHand, CSMove, CSResizeWidth, CSResizeHeight, CSResizeDiagonal, CSSpotWB, CSCropSelect, CSStraighten};
|
||||
enum CursorShape {CSArrow, CSOpenHand, CSClosedHand, CSMove, CSResizeWidth, CSResizeHeight, CSResizeDiagonal, CSSpotWB, CSCropSelect, CSStraighten, CSPlus, CSEmpty};
|
||||
|
||||
class CursorManager {
|
||||
|
||||
@@ -33,14 +33,17 @@ class CursorManager {
|
||||
Gdk::Cursor* cCropMoving;
|
||||
Gdk::Cursor* cNormal;
|
||||
Gdk::Cursor* cCropSelection;
|
||||
Gdk::Cursor* cAdd;
|
||||
Gdk::Cursor* cHand;
|
||||
Gdk::Cursor* cClosedHand;
|
||||
Gdk::Cursor* cWB;
|
||||
Gdk::Cursor* cHidden;
|
||||
Glib::RefPtr<Gdk::Window> mainWindow;
|
||||
|
||||
public:
|
||||
void init (Glib::RefPtr<Gdk::Window> mainWin);
|
||||
void setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape shape);
|
||||
void setCursor (CursorShape shape);
|
||||
};
|
||||
|
||||
extern CursorManager cursorManager;
|
||||
|
@@ -40,13 +40,17 @@ CurveEditor::CurveEditor () : cl(NULL), activeParamControl(-1), realized(false),
|
||||
|
||||
// custom curve
|
||||
customCurveBox = new Gtk::VBox ();
|
||||
Gtk::HBox* tmpa = Gtk::manage (new Gtk::HBox ());
|
||||
customCurve = Gtk::manage (new MyCurve ());
|
||||
Gtk::AspectFrame* af = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
af->add (*customCurve);
|
||||
customCurve->set_size_request (-1, 200);
|
||||
Gtk::Table* cctab = Gtk::manage (new Gtk::Table (2,1));
|
||||
//Gtk::AspectFrame* af = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
//af->add (*customCurve);
|
||||
customCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS);
|
||||
customCurve->setType (Spline);
|
||||
customCurveBox->pack_start (*af, Gtk::PACK_EXPAND_WIDGET);
|
||||
|
||||
tmpa->pack_start (*customCurve, true, false, 4);
|
||||
customCurveBox->pack_start (*tmpa, true, true,4);
|
||||
//customCurveBox->set_size_request (0, -1);
|
||||
|
||||
Gtk::HBox* bbox = Gtk::manage (new Gtk::HBox ());
|
||||
save = Gtk::manage (new Gtk::Button ());
|
||||
save->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)));
|
||||
@@ -55,7 +59,7 @@ CurveEditor::CurveEditor () : cl(NULL), activeParamControl(-1), realized(false),
|
||||
|
||||
bbox->pack_end (*save, Gtk::PACK_EXPAND_WIDGET, 4);
|
||||
bbox->pack_end (*load, Gtk::PACK_EXPAND_WIDGET, 4);
|
||||
|
||||
|
||||
customCurveBox->pack_end (*bbox, Gtk::PACK_SHRINK, 2);
|
||||
customCurveBox->show_all ();
|
||||
|
||||
@@ -66,20 +70,20 @@ CurveEditor::CurveEditor () : cl(NULL), activeParamControl(-1), realized(false),
|
||||
|
||||
// parametric curve
|
||||
paramCurveBox = new Gtk::VBox ();
|
||||
paramCurve = Gtk::manage (new MyCurve ());
|
||||
Gtk::Table* ctab = Gtk::manage (new Gtk::Table (2,1));
|
||||
Gtk::AspectFrame* afp = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
afp->add (*paramCurve);
|
||||
paramCurve->set_size_request (200, 200);
|
||||
paramCurve = Gtk::manage (new MyCurve ());
|
||||
Gtk::Table* paramctab = Gtk::manage (new Gtk::Table (2,1));
|
||||
//Gtk::AspectFrame* afp = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
//afp->add (*paramCurve);
|
||||
paramCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS);
|
||||
paramCurve->setType (Parametric);
|
||||
shcSelector = Gtk::manage (new SHCSelector ());
|
||||
shcSelector->set_size_request (200, 20);
|
||||
shcSelector->set_size_request (GRAPH_SIZE, 20);
|
||||
|
||||
ctab->attach (*afp, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
|
||||
ctab->attach (*shcSelector, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, 2, 2);
|
||||
paramctab->attach (*paramCurve, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, RADIUS+2, RADIUS+2);
|
||||
paramctab->attach (*shcSelector, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, RADIUS+2, 2);
|
||||
|
||||
Gtk::HBox* tmpb = Gtk::manage (new Gtk::HBox ());
|
||||
tmpb->pack_start (*ctab, true, false);
|
||||
tmpb->pack_start (*paramctab, true, false);
|
||||
|
||||
paramCurveBox->pack_start (*tmpb, true, true);
|
||||
|
||||
|
201
rtgui/mycurve.cc
201
rtgui/mycurve.cc
@@ -19,18 +19,17 @@
|
||||
#include <mycurve.h>
|
||||
#include <curves.h>
|
||||
#include <string.h>
|
||||
|
||||
#define RADIUS 3 /* radius of the control points */
|
||||
#define MIN_DISTANCE 8 /* min distance between control points */
|
||||
#include <gdkmm/types.h>
|
||||
|
||||
MyCurve::MyCurve () : listener(NULL), activeParam(-1), bghistvalid(false) {
|
||||
|
||||
cursor_type = Gdk::TOP_LEFT_ARROW;
|
||||
cursor_type = CSArrow;
|
||||
curve.type = Spline;
|
||||
height = 0;
|
||||
grab_point = -1;
|
||||
lit_point = -1;
|
||||
|
||||
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK);
|
||||
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK);
|
||||
signal_event().connect( sigc::mem_fun(*this, &MyCurve::handleEvents) );
|
||||
|
||||
curve.x.push_back(0);
|
||||
@@ -126,7 +125,8 @@ void MyCurve::interpolate (int width, int height) {
|
||||
}
|
||||
}
|
||||
|
||||
void MyCurve::draw (int width, int height) {
|
||||
void MyCurve::draw (int width, int height, int handle) {
|
||||
// width and heigth are the size of the graph
|
||||
|
||||
if (!pixmap)
|
||||
return;
|
||||
@@ -135,7 +135,6 @@ void MyCurve::draw (int width, int height) {
|
||||
if (this->height != height || point.size() != width)
|
||||
interpolate (width, height);
|
||||
|
||||
|
||||
Gtk::StateType state = Gtk::STATE_NORMAL;
|
||||
if (!is_sensitive())
|
||||
state = Gtk::STATE_INSENSITIVE;
|
||||
@@ -159,32 +158,32 @@ void MyCurve::draw (int width, int height) {
|
||||
// draw histogram
|
||||
cr->set_line_width (1.0);
|
||||
double stepSize = (width-1) / 256.0;
|
||||
cr->move_to (0, height-1);
|
||||
cr->move_to (RADIUS, height-1+RADIUS);
|
||||
cr->set_source_rgb (0.75, 0.75, 0.75);
|
||||
for (int i=0; i<256; i++) {
|
||||
double val = bghist[i] * (double)(height-2) / histheight;
|
||||
if (val>height-1)
|
||||
val = height-1;
|
||||
if (i>0)
|
||||
cr->line_to (i*stepSize, height-1-val);
|
||||
cr->line_to (i*stepSize+RADIUS, height-1+RADIUS-val);
|
||||
}
|
||||
cr->line_to (width-1, height-1);
|
||||
cr->line_to (width-1+RADIUS, height-1+RADIUS);
|
||||
cr->fill ();
|
||||
}
|
||||
|
||||
// draw the grid lines:
|
||||
cr->set_line_width (1.0);
|
||||
cr->set_line_width (1.0);
|
||||
c = style->get_dark (state);
|
||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||
cr->set_antialias (Cairo::ANTIALIAS_NONE);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
cr->move_to (RADIUS, i * height / 4 + RADIUS);
|
||||
cr->line_to (width + RADIUS, i * height / 4 + RADIUS);
|
||||
cr->move_to (i * width / 4 + RADIUS, RADIUS);
|
||||
cr->line_to (i * width / 4 + RADIUS, height + RADIUS);
|
||||
cr->move_to (RADIUS, MAX(0,i * height / 4 - 1) + RADIUS);
|
||||
cr->line_to (width + RADIUS, MAX(0,i * height / 4 - 1) + RADIUS);
|
||||
cr->move_to (MAX(0,i * width / 4 - 1) + RADIUS, RADIUS);
|
||||
cr->line_to (MAX(0,i * width / 4 - 1) + RADIUS, height + RADIUS);
|
||||
}
|
||||
cr->stroke ();
|
||||
|
||||
|
||||
// draw f(x)=x line
|
||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||
std::valarray<double> ds (1);
|
||||
@@ -195,6 +194,7 @@ void MyCurve::draw (int width, int height) {
|
||||
cr->stroke ();
|
||||
cr->unset_dash ();
|
||||
|
||||
|
||||
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||
cr->set_line_width (1.0);
|
||||
|
||||
@@ -221,10 +221,11 @@ void MyCurve::draw (int width, int height) {
|
||||
// draw bullets
|
||||
if (curve.type!=Parametric)
|
||||
for (int i = 0; i < curve.x.size(); ++i) {
|
||||
cr->set_source_rgb ((i == handle ? 1.0 : 0.0), 0.0, 0.0);
|
||||
double x = ((width-1) * curve.x[i] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, width);
|
||||
double y = height - ((height-1) * curve.y[i] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, height);
|
||||
|
||||
cr->arc (x, y, RADIUS, 0, 2*M_PI);
|
||||
cr->arc (x, y, RADIUS+0.5, 0, 2*M_PI);
|
||||
cr->fill ();
|
||||
}
|
||||
|
||||
@@ -233,13 +234,17 @@ void MyCurve::draw (int width, int height) {
|
||||
|
||||
bool MyCurve::handleEvents (GdkEvent* event) {
|
||||
|
||||
Gdk::CursorType new_type = cursor_type;
|
||||
CursorShape new_type = cursor_type;
|
||||
int src, dst;
|
||||
GdkEventMotion *mevent;
|
||||
std::vector<double>::iterator itx, ity;
|
||||
|
||||
Glib::RefPtr<Gdk::Display> rt_display = Gtk::Widget::get_display();
|
||||
Glib::RefPtr<Gdk::Screen> rt_screen = Gtk::Widget::get_screen();
|
||||
|
||||
bool retval = false;
|
||||
|
||||
/* width and height are the size of the graph */
|
||||
int width = get_allocation().get_width() - RADIUS * 2;
|
||||
int height = get_allocation().get_height() - RADIUS * 2;
|
||||
|
||||
@@ -250,13 +255,13 @@ bool MyCurve::handleEvents (GdkEvent* event) {
|
||||
int tx, ty;
|
||||
Gdk::ModifierType gm;
|
||||
get_window()->get_pointer (tx, ty, gm);
|
||||
int x = CLAMP ((tx - RADIUS), 0, width-1);
|
||||
int y = CLAMP ((ty - RADIUS), 0, height-1);
|
||||
int x = CLAMP ((tx - RADIUS), 0, width-1); // X position of the pointer from the origin of the graph
|
||||
int y = height-1 - CLAMP ((ty - RADIUS), 0, height-1); // Y position of the pointer from the origin of the graph
|
||||
|
||||
unsigned int distance = ~0U;
|
||||
int num = curve.x.size();
|
||||
int closest_point = 0;
|
||||
|
||||
int closest_point = -1;
|
||||
|
||||
if (curve.type!=Parametric) {
|
||||
for (int i = 0; i < num; ++i) {
|
||||
int cx = (int)((width-1) * curve.x[i] + 0.5); //project (c->ctlpoint[i][0], min_x, c->max_x, width);
|
||||
@@ -266,24 +271,30 @@ bool MyCurve::handleEvents (GdkEvent* event) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case Gdk::CONFIGURE:
|
||||
if (pixmap)
|
||||
pixmap.clear ();
|
||||
|
||||
case Gdk::EXPOSE:
|
||||
// When does this event occurs ???
|
||||
if (!pixmap) {
|
||||
pixmap = Gdk::Pixmap::create (get_window(), get_allocation().get_width(), get_allocation().get_height());
|
||||
interpolate (width, height);
|
||||
}
|
||||
draw (width, height);
|
||||
draw (width, height, lit_point);
|
||||
break;
|
||||
|
||||
case Gdk::BUTTON_PRESS:
|
||||
if (curve.type!=Parametric) {
|
||||
add_modal_grab ();
|
||||
new_type = Gdk::PLUS;
|
||||
|
||||
// get cursor position
|
||||
Gdk::ModifierType mod_type;
|
||||
rt_display->get_pointer(cursor_x, cursor_y, mod_type);
|
||||
|
||||
new_type = CSEmpty;
|
||||
if (distance > MIN_DISTANCE) {
|
||||
/* insert a new control point */
|
||||
if (num > 0) {
|
||||
@@ -294,24 +305,30 @@ bool MyCurve::handleEvents (GdkEvent* event) {
|
||||
itx = curve.x.begin();
|
||||
ity = curve.y.begin();
|
||||
for (int i=0; i<closest_point; i++) { itx++; ity++; }
|
||||
curve.x.insert (itx, 0);
|
||||
curve.y.insert (ity, 0);
|
||||
num++;
|
||||
}
|
||||
grab_point = closest_point;
|
||||
curve.x[grab_point] = (double) x / (width-1);
|
||||
curve.y[grab_point] = (double) (height-y) / (height-1);
|
||||
interpolate (width, height);
|
||||
notifyListener ();
|
||||
break;
|
||||
curve.x.insert (itx, 0);
|
||||
curve.y.insert (ity, 0);
|
||||
num++;
|
||||
|
||||
// the graph is refreshed only if a new point is created (snaped to a pixel)
|
||||
curve.x[closest_point] = (double) x / (width-1);
|
||||
curve.y[closest_point] = (double) y / (height-1);
|
||||
interpolate (width, height);
|
||||
draw (width, height, closest_point);
|
||||
}
|
||||
grab_point = closest_point;
|
||||
lit_point = closest_point;
|
||||
ugp_x = curve.x[closest_point];
|
||||
ugp_y = curve.y[closest_point];
|
||||
notifyListener ();
|
||||
break;
|
||||
}
|
||||
draw (width, height);
|
||||
retval = true;
|
||||
break;
|
||||
|
||||
case Gdk::BUTTON_RELEASE:
|
||||
if (curve.type!=Parametric) {
|
||||
remove_modal_grab ();
|
||||
int previous_lit_point = lit_point;
|
||||
/* delete inactive points: */
|
||||
itx = curve.x.begin();
|
||||
ity = curve.y.begin();
|
||||
@@ -330,61 +347,115 @@ bool MyCurve::handleEvents (GdkEvent* event) {
|
||||
curve.x.push_back (0);
|
||||
curve.y.push_back (0);
|
||||
interpolate (width, height);
|
||||
draw (width, height);
|
||||
draw (width, height, lit_point);
|
||||
}
|
||||
}
|
||||
new_type = Gdk::FLEUR;
|
||||
if (distance <= MIN_DISTANCE) {
|
||||
new_type = CSMove;
|
||||
lit_point = closest_point;
|
||||
}
|
||||
else {
|
||||
new_type = CSPlus;
|
||||
lit_point = -1;
|
||||
}
|
||||
if (lit_point != previous_lit_point)
|
||||
draw (width, height, lit_point);
|
||||
grab_point = -1;
|
||||
retval = true;
|
||||
notifyListener ();
|
||||
}
|
||||
break;
|
||||
|
||||
case Gdk::LEAVE_NOTIFY:
|
||||
// Pointer can LEAVE even when dragging the point, so we don't modify the cursor in this case
|
||||
// The cursor will have to LEAVE another time after the drag...
|
||||
if (grab_point == -1)
|
||||
new_type = CSArrow;
|
||||
break;
|
||||
|
||||
case Gdk::MOTION_NOTIFY:
|
||||
mevent = (GdkEventMotion *) event;
|
||||
|
||||
if (curve.type == Linear || curve.type == Spline) {
|
||||
if (grab_point == -1) {
|
||||
int previous_lit_point = lit_point;
|
||||
/* if no point is grabbed... */
|
||||
if (distance <= MIN_DISTANCE)
|
||||
new_type = Gdk::FLEUR;
|
||||
else
|
||||
new_type = Gdk::PLUS;
|
||||
if (distance <= MIN_DISTANCE) {
|
||||
new_type = CSMove;
|
||||
lit_point = closest_point;
|
||||
}
|
||||
else {
|
||||
new_type = CSPlus;
|
||||
lit_point = -1;
|
||||
}
|
||||
if ((new_type != cursor_type) || (lit_point != previous_lit_point))
|
||||
draw (width, height, lit_point);
|
||||
}
|
||||
else {
|
||||
/* drag the grabbed point */
|
||||
new_type = Gdk::FLEUR;
|
||||
int leftbound = -MIN_DISTANCE;
|
||||
if (grab_point > 0)
|
||||
leftbound = (int)((width-1)*curve.x[grab_point-1]+0.5);
|
||||
|
||||
int rightbound = width + RADIUS * 2 + MIN_DISTANCE;
|
||||
if (grab_point + 1 < num)
|
||||
rightbound = (int)((width-1)*curve.x[grab_point+1]+0.5);
|
||||
|
||||
if (tx <= leftbound || tx >= rightbound || ty > height + RADIUS * 2 + MIN_DISTANCE || ty < -MIN_DISTANCE)
|
||||
curve.x[grab_point] = -1.0;
|
||||
else {
|
||||
curve.x[grab_point] = (double) x / (width-1);
|
||||
curve.y[grab_point] = (double) (height-y) / (height-1);
|
||||
int new_cursor_x, new_cursor_y;
|
||||
double factor = 0.5;
|
||||
|
||||
// get cursor position
|
||||
Gdk::ModifierType mod_type;
|
||||
rt_display->get_pointer(new_cursor_x, new_cursor_y, mod_type);
|
||||
|
||||
// set the dragging factor
|
||||
int control_key = gm & GDK_CONTROL_MASK;
|
||||
int shift_key = gm & GDK_SHIFT_MASK;
|
||||
|
||||
// what is the speed factor
|
||||
if (control_key && shift_key) factor = 0.005;
|
||||
else if (shift_key) factor = 0.02;
|
||||
else if (control_key) factor = 0.1;
|
||||
|
||||
// calculate the delta in [0.0 ; 1.0] range
|
||||
double delta_x = (double)(new_cursor_x - cursor_x) * factor / (double)(width-1);
|
||||
double delta_y = (double)(cursor_y - new_cursor_y) * factor / (double)(height-1);
|
||||
|
||||
// modification of the unclamped grabed point
|
||||
ugp_x += delta_x;
|
||||
ugp_y += delta_y;
|
||||
|
||||
// first and last point cannot be deleted anymore (there's no point to do it)
|
||||
// for intermediate points, we look if the point must be deleted
|
||||
if (grab_point > 0 && grab_point < num-1) {
|
||||
double leftbound = curve.x[grab_point-1];
|
||||
double rightbound = curve.x[grab_point+1];
|
||||
double bottombound = (double)(-MIN_DISTANCE) * factor / (double)(height-1);
|
||||
double topbound = (double)1.0 + (double)(MIN_DISTANCE) * factor / (double)(height-1);
|
||||
|
||||
if (ugp_x <= leftbound || ugp_x >= rightbound || ugp_y > topbound || ugp_y < bottombound) {
|
||||
curve.x[grab_point] = -1.0;
|
||||
}
|
||||
}
|
||||
// first and last points are clamped to the [0.0 ; 1.0] range
|
||||
if (curve.x[grab_point] != -1.0) {
|
||||
double new_curve_x = curve.x[grab_point] + delta_x;
|
||||
double new_curve_y = curve.y[grab_point] + delta_y;
|
||||
curve.x[grab_point] = CLAMP(new_curve_x,0.0,1.0);
|
||||
curve.y[grab_point] = CLAMP(new_curve_y,0.0,1.0);
|
||||
}
|
||||
|
||||
interpolate (width, height);
|
||||
draw (width, height);
|
||||
|
||||
// move the cursor back (to avoid being limited by the screen)
|
||||
rt_display->warp_pointer(rt_screen, cursor_x, cursor_y);
|
||||
|
||||
draw (width, height, lit_point);
|
||||
notifyListener ();
|
||||
}
|
||||
}
|
||||
|
||||
if (new_type != cursor_type) {
|
||||
cursor_type = new_type;
|
||||
Gdk::Cursor* cursor = new Gdk::Cursor (get_display(), cursor_type);
|
||||
get_window ()->set_cursor (*cursor);
|
||||
delete cursor;
|
||||
}
|
||||
|
||||
retval = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (new_type != cursor_type) {
|
||||
cursor_type = new_type;
|
||||
cursorManager.setCursor(cursor_type);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@@ -22,6 +22,11 @@
|
||||
#include <gtkmm.h>
|
||||
#include <vector>
|
||||
#include <curvelistener.h>
|
||||
#include <cursormanager.h>
|
||||
|
||||
#define RADIUS 3 /* radius of the control points. Assuming that the center of the spot is in the center of the pixel, the real RADIUS will be this value +0.5 */
|
||||
#define MIN_DISTANCE 8 /* min distance between control points */
|
||||
#define GRAPH_SIZE 200 /* size of the curve editor graphic */
|
||||
|
||||
enum CurveType {Linear, Spline, Parametric};
|
||||
|
||||
@@ -46,10 +51,11 @@ class MyCurve : public Gtk::DrawingArea {
|
||||
protected:
|
||||
CurveListener* listener;
|
||||
CurveDescr curve;
|
||||
Gdk::CursorType cursor_type;
|
||||
CursorShape cursor_type;
|
||||
Glib::RefPtr<Gdk::Pixmap> pixmap;
|
||||
int height;
|
||||
int grab_point;
|
||||
int height;
|
||||
int grab_point;
|
||||
int lit_point;
|
||||
int last;
|
||||
std::vector<Gdk::Point> point;
|
||||
std::vector<Gdk::Point> upoint;
|
||||
@@ -58,8 +64,10 @@ class MyCurve : public Gtk::DrawingArea {
|
||||
unsigned int bghist[256];
|
||||
bool bghistvalid;
|
||||
MyCurveIdleHelper* mcih;
|
||||
int cursor_x, cursor_y;
|
||||
double ugp_x, ugp_y; // unclamped grabed point coordinates
|
||||
|
||||
void draw (int width, int height);
|
||||
void draw (int width, int height, int handle);
|
||||
void interpolate (int width, int height);
|
||||
std::vector<double> get_vector (int veclen);
|
||||
|
||||
|
Reference in New Issue
Block a user