* Tablet support fixup

This commit should hopefully fix some of the problems some people were
having with tablet support in sculpt mode, and also the problems I made
visible with my previous commit related to number field dragging.

Now, all the ghost related stuff is tucked away in ghostwinlay.c and a
simple Blender API, similar to the existing get_mbut() for example, is
provided to access the tablet data. As with the other mouse related data in
Blender, the tablet data is cached upon each mouse move or click, in the
Window struct.

You can now just use:

float get_pressure(void);
void get_tilt(float *xtilt, float *ytilt);
short get_activedevice(void);

to get such data from the tablet. Documentation on the returned data
is in ghostwinlay.c in the _Window struct definition.


Brecht and Nicholas, I've updated the painting and sculpt code and it works
just fine here, you may want to give it a check though to make sure I
haven't done anything silly.
This commit is contained in:
2007-04-05 12:42:07 +00:00
parent 54f57cca08
commit bbceedced0
7 changed files with 104 additions and 45 deletions

View File

@@ -122,7 +122,13 @@ void BIF_wait_for_statechange(void);
short get_mbut(void); short get_mbut(void);
short get_qual(void); short get_qual(void);
void getmouse(short *mval); void getmouse(short *mval);
const struct GHOST_TabletData* get_tablet_data();
float get_pressure(void);
void get_tilt(float *xtilt, float *ytilt);
#define DEV_MOUSE 0
#define DEV_STYLUS 1
#define DEV_ERASER 2
short get_activedevice(void);
void warp_pointer(int x, int y); void warp_pointer(int x, int y);

View File

@@ -2119,10 +2119,23 @@ short get_mbut(void)
winlay_process_events(0); winlay_process_events(0);
return window_get_mbut(mainwin); return window_get_mbut(mainwin);
} }
const GHOST_TabletData* get_tablet_data()
/* return values of tablet data related functions are documented
* in the Window struct, ghostwinlay.c */
float get_pressure(void)
{ {
winlay_process_events(0); winlay_process_events(0);
return window_get_tablet_data(mainwin); return window_get_pressure(mainwin);
}
void get_tilt(float *xtilt, float *ytilt)
{
winlay_process_events(0);
window_get_tilt(mainwin, xtilt, ytilt);
}
short get_activedevice(void)
{
winlay_process_events(0);
return window_get_activedevice(mainwin);
} }
void add_to_mainqueue(Window *win, void *user_data, short evt, short val, char ascii) void add_to_mainqueue(Window *win, void *user_data, short evt, short val, char ascii)

View File

@@ -75,22 +75,36 @@ void getMacAvailableBounds(short *, short *, short *, short *);
struct _Window { struct _Window {
GHOST_WindowHandle ghostwin; GHOST_WindowHandle ghostwin;
/* Handler and private data for handler */ /* Handler and private data for handler */
WindowHandlerFP handler; WindowHandlerFP handler;
void *user_data; void *user_data;
/* Window state */ /* Window state */
int size[2], position[2]; int size[2], position[2];
int active, visible; int active, visible;
/* Last known mouse/button/qualifier state */ /* Last known mouse/button/qualifier state */
int lmouse[2]; int lmouse[2];
int lqual; /* (LR_SHFTKEY, LR_CTRLKEY, LR_ALTKEY, LR_COMMANDKEY) */ int lqual; /* (LR_SHFTKEY, LR_CTRLKEY, LR_ALTKEY, LR_COMMANDKEY) */
int lmbut; /* (L_MOUSE, M_MOUSE, R_MOUSE) */ int lmbut; /* (L_MOUSE, M_MOUSE, R_MOUSE) */
/* Tracks the faked mouse button, if non-zero it is /* xtilt and ytilt represent how much the pen is tilted away from
* the event number of the last faked button. * vertically upright in either the X or Y direction, with X and Y the
*/ * axes of the tablet surface.
* In other words, Xtilt and Ytilt are components of a vector created by projecting
* the pen's angle in 3D space vertically downwards on to the XY plane
* --Matt
*/
float pressure; /* tablet pressure - 0.0 (no pressure) to 1.0 (full pressure) */
/* mouse clicks and non-contacting stylus buttons generate pressure of 0.0. */
float xtilt, ytilt; /* tablet tilt value - x and y components of 3D angle
* ranging from 0.0 (pen upright) to 1.0 (pen fully leaning over) */
short activedevice; /* Active input device currently in use (DEV_MOUSE, DEV_STYLUS, DEV_ERASER) */
/* Tracks the faked mouse button, if non-zero it is
* the event number of the last faked button.
*/
int faked_mbut; int faked_mbut;
GHOST_TimerTaskHandle timer; GHOST_TimerTaskHandle timer;
@@ -488,6 +502,24 @@ static int change_bit(int val, int bit, int to_on) {
return to_on?(val|bit):(val&~bit); return to_on?(val|bit):(val&~bit);
} }
static void update_tablet_data(Window *win, Window *ghostwin) {
const GHOST_TabletData *td= GHOST_GetTabletData(ghostwin);
/* if there's tablet data from an active tablet device then use it,
* otherwise set all tablet related data to default */
if ((td != NULL) && ELEM(td->Active, DEV_STYLUS, DEV_ERASER)) {
win->activedevice = (short)td->Active;
win->pressure = td->Pressure;
win->xtilt = td->Xtilt;
win->ytilt = td->Ytilt;
} else {
win->activedevice = DEV_MOUSE;
win->pressure = 0.0;
win->xtilt = win->ytilt = 0.0;
}
}
static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
{ {
GHOST_TEventType type= GHOST_GetEventType(evt); GHOST_TEventType type= GHOST_GetEventType(evt);
@@ -517,12 +549,14 @@ static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
case GHOST_kEventCursorMove: { case GHOST_kEventCursorMove: {
if(win->active == 1) { if(win->active == 1) {
GHOST_TEventCursorData *cd= data; GHOST_TEventCursorData *cd= data;
int cx, cy; int cx, cy;
GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy); GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy);
win->lmouse[0]= cx; win->lmouse[0]= cx;
win->lmouse[1]= (win->size[1]-1) - cy; win->lmouse[1]= (win->size[1]-1) - cy;
update_tablet_data(win, ghostwin);
window_handle(win, MOUSEX, win->lmouse[0]); window_handle(win, MOUSEX, win->lmouse[0]);
window_handle(win, MOUSEY, win->lmouse[1]); window_handle(win, MOUSEY, win->lmouse[1]);
} }
@@ -557,6 +591,8 @@ static int event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
} else { } else {
win->lmbut= change_bit(win->lmbut, R_MOUSE, val); win->lmbut= change_bit(win->lmbut, R_MOUSE, val);
} }
update_tablet_data(win, ghostwin);
window_handle(win, bbut, val); window_handle(win, bbut, val);
break; break;
@@ -709,16 +745,24 @@ void window_get_mouse(Window *win, short *mval) {
mval[1]= win->lmouse[1]; mval[1]= win->lmouse[1];
} }
float window_get_pressure(Window *win) {
return win->pressure;
}
void window_get_tilt(Window *win, float *xtilt, float *ytilt) {
*xtilt= win->xtilt;
*ytilt= win->ytilt;
}
short window_get_activedevice(Window *win) {
return win->activedevice;
}
void window_get_position(Window *win, int *posx_r, int *posy_r) { void window_get_position(Window *win, int *posx_r, int *posy_r) {
*posx_r= win->position[0]; *posx_r= win->position[0];
*posy_r= win->position[1]; *posy_r= win->position[1];
} }
const GHOST_TabletData* window_get_tablet_data(Window *win)
{
return GHOST_GetTabletData(win->ghostwin);
}
void window_get_size(Window *win, int *width_r, int *height_r) { void window_get_size(Window *win, int *width_r, int *height_r) {
*width_r= win->size[0]; *width_r= win->size[0];
*height_r= win->size[1]; *height_r= win->size[1];

View File

@@ -657,7 +657,6 @@ void imagepaint_paint(short mousebutton, short texpaint)
short prevmval[2], mval[2]; short prevmval[2], mval[2];
double time; double time;
float pressure; float pressure;
const GHOST_TabletData *td;
if(!settings->imapaint.brush) if(!settings->imapaint.brush)
return; return;
@@ -697,27 +696,27 @@ void imagepaint_paint(short mousebutton, short texpaint)
painter= brush_painter_new(s.brush); painter= brush_painter_new(s.brush);
getmouseco_areawin(mval); getmouseco_areawin(mval);
td= get_tablet_data();
pressure= (td)? td->Pressure: 1.0f; pressure = get_pressure();
s.blend = (get_activedevice() == 2)? BRUSH_BLEND_ERASE_ALPHA: s.brush->blend;
time= PIL_check_seconds_timer(); time= PIL_check_seconds_timer();
prevmval[0]= mval[0]; prevmval[0]= mval[0];
prevmval[1]= mval[1]; prevmval[1]= mval[1];
s.blend = (td && td->Active == 2)? BRUSH_BLEND_ERASE_ALPHA: s.brush->blend;
/* special exception here for too high pressure values on first touch in /* special exception here for too high pressure values on first touch in
windows for some tablets */ windows for some tablets */
if (!((s.brush->flag & (BRUSH_ALPHA_PRESSURE|BRUSH_SIZE_PRESSURE| if (!((s.brush->flag & (BRUSH_ALPHA_PRESSURE|BRUSH_SIZE_PRESSURE|
BRUSH_SPACING_PRESSURE|BRUSH_RAD_PRESSURE)) && td && pressure >= 0.99f)) BRUSH_SPACING_PRESSURE|BRUSH_RAD_PRESSURE)) && (get_activedevice() != 0) && (pressure >= 0.99f)))
imapaint_paint_stroke(&s, painter, texpaint, prevmval, mval, time, pressure); imapaint_paint_stroke(&s, painter, texpaint, prevmval, mval, time, pressure);
/* paint loop */ /* paint loop */
do { do {
getmouseco_areawin(mval); getmouseco_areawin(mval);
if(td) {
td= get_tablet_data(); pressure = get_pressure();
pressure= (td)? td->Pressure: 1.0f; s.blend = (get_activedevice() == 2)? BRUSH_BLEND_ERASE_ALPHA: s.brush->blend;
s.blend = (td && td->Active == 2)? BRUSH_BLEND_ERASE_ALPHA: s.brush->blend;
}
time= PIL_check_seconds_timer(); time= PIL_check_seconds_timer();
if((mval[0] != prevmval[0]) || (mval[1] != prevmval[1])) { if((mval[0] != prevmval[0]) || (mval[1] != prevmval[1])) {

View File

@@ -2100,8 +2100,6 @@ static int ui_act_as_text_but(uiBut *but)
static int ui_do_but_NUM(uiBut *but) static int ui_do_but_NUM(uiBut *but)
{ {
const GHOST_TabletData *td;
float pressure;
double value; double value;
float deler, fstart, f, tempf; float deler, fstart, f, tempf;
int lvalue, temp, orig_x; /* , firsttime=1; */ int lvalue, temp, orig_x; /* , firsttime=1; */
@@ -2137,9 +2135,6 @@ static int ui_do_but_NUM(uiBut *but)
sx = mval[0]; /* ignore mouse movement within drag-lock */ sx = mval[0]; /* ignore mouse movement within drag-lock */
while (get_mbut() & L_MOUSE) { while (get_mbut() & L_MOUSE) {
td= get_tablet_data();
pressure= (td)? td->Pressure: 1.0f;
qual= get_qual(); qual= get_qual();
uiGetMouse(mywinget(), mval); uiGetMouse(mywinget(), mval);

View File

@@ -395,13 +395,14 @@ char brush_size()
{ {
const BrushData *b= sculptmode_brush(); const BrushData *b= sculptmode_brush();
float size= b->size; float size= b->size;
const GHOST_TabletData *td= get_tablet_data(); float pressure= get_pressure();
short activedevice= get_activedevice();
if(td && sculpt_data()->brush_type!=GRAB_BRUSH) { if(sculpt_data()->brush_type!=GRAB_BRUSH) {
const float size_factor= G.scene->sculptdata.tablet_size / 10.0f; const float size_factor= G.scene->sculptdata.tablet_size / 10.0f;
if(td->Active==1 || td->Active==2) if(ELEM(activedevice, DEV_STYLUS, DEV_ERASER))
size*= G.scene->sculptdata.tablet_size==0?1: size*= G.scene->sculptdata.tablet_size==0?1:
(1-size_factor) + td->Pressure*size_factor; (1-size_factor) + pressure*size_factor;
} }
return size; return size;
@@ -415,19 +416,17 @@ float brush_strength(EditData *e)
const BrushData* b= sculptmode_brush(); const BrushData* b= sculptmode_brush();
float dir= b->dir==1 ? 1 : -1; float dir= b->dir==1 ? 1 : -1;
float pressure= 1; float pressure= 1;
const GHOST_TabletData *td= get_tablet_data(); short activedevice= get_activedevice();
float flip= e->flip ? -1:1; float flip= e->flip ? -1:1;
if(td) { const float strength_factor= G.scene->sculptdata.tablet_strength / 10.0f;
const float strength_factor= G.scene->sculptdata.tablet_strength / 10.0f; if(ELEM(activedevice, DEV_STYLUS, DEV_ERASER))
if(td->Active==1 || td->Active==2) pressure= G.scene->sculptdata.tablet_strength==0?1:
pressure= G.scene->sculptdata.tablet_strength==0?1: (1-strength_factor) + get_pressure()*strength_factor;
(1-strength_factor) + td->Pressure*strength_factor;
/* Flip direction for eraser */
/* Flip direction for eraser */ if(activedevice==DEV_ERASER)
if(td->Active==2) dir= -dir;
dir= -dir;
}
switch(G.scene->sculptdata.brush_type){ switch(G.scene->sculptdata.brush_type){
case DRAW_BRUSH: case DRAW_BRUSH:

View File

@@ -57,7 +57,10 @@ void window_lower (Window *win);
short window_get_qual (Window *win); short window_get_qual (Window *win);
short window_get_mbut (Window *win); short window_get_mbut (Window *win);
void window_get_mouse (Window *win, short *mval); void window_get_mouse (Window *win, short *mval);
const struct GHOST_TabletData* window_get_tablet_data(Window *win);
float window_get_pressure(Window *win);
void window_get_tilt(Window *win, float *xtilt, float *ytilt);
short window_get_activedevice(Window *win);
void window_get_position (Window *win, int *posx_r, int *poxy_r); void window_get_position (Window *win, int *posx_r, int *poxy_r);