From c6118036bc044bd5f25106dfb0b422ee2310d5ba Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Wed, 16 Jan 2008 07:19:21 +0000 Subject: [PATCH] == Radial Control == * Generalized the interactive brush property control from sculpt mode into a simple API * Modified sculpt mode to take advantage of this (even fixes some minor bugs!) * Added shortcuts in particle edit to set brush size/strength (FKEY/shift+FKEY) Still todo are the other modes that have brushes... --- source/blender/blenkernel/BKE_sculpt.h | 23 +- source/blender/blenkernel/intern/scene.c | 9 +- source/blender/include/BDR_sculptmode.h | 5 +- source/blender/include/BIF_editparticle.h | 3 + source/blender/include/BIF_radialcontrol.h | 62 +++++ source/blender/src/drawview.c | 66 +---- source/blender/src/editparticle.c | 41 +++ source/blender/src/header_view3d.c | 8 +- source/blender/src/radialcontrol.c | 266 +++++++++++++++++++ source/blender/src/sculptmode.c | 283 +++++---------------- source/blender/src/space.c | 27 +- 11 files changed, 476 insertions(+), 317 deletions(-) create mode 100644 source/blender/include/BIF_radialcontrol.h create mode 100644 source/blender/src/radialcontrol.c diff --git a/source/blender/blenkernel/BKE_sculpt.h b/source/blender/blenkernel/BKE_sculpt.h index d539bcf5e8c..e03e38bab75 100644 --- a/source/blender/blenkernel/BKE_sculpt.h +++ b/source/blender/blenkernel/BKE_sculpt.h @@ -31,30 +31,11 @@ #define BKE_SCULPT_H struct NumInput; +struct RadialControl; struct Scene; struct SculptData; struct SculptSession; -typedef enum PropsetMode { - PropsetNone = 0, - PropsetSize, - PropsetStrength, - PropsetTexRot -} PropsetMode; - -typedef struct PropsetData { - PropsetMode mode; - unsigned int tex; - short origloc[2]; - float *texdata; - - short origsize; - char origstrength; - float origtexrot; - - struct NumInput *num; -} PropsetData; - typedef struct SculptSession { struct ProjVert *projverts; @@ -76,7 +57,7 @@ typedef struct SculptSession { /* Used to cache the render of the active texture */ unsigned int texcache_w, texcache_h, *texcache; - struct PropsetData *propset; + struct RadialControl *radialcontrol; /* For rotating around a pivot point */ vec3f pivot; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 357b3c1bf54..94dfa705dc2 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -661,13 +661,8 @@ void sculptsession_free(Scene *sce) if(ss->mats) MEM_freeN(ss->mats); - if(ss->propset) { - if(ss->propset->texdata) - MEM_freeN(ss->propset->texdata); - if(ss->propset->num) - MEM_freeN(ss->propset->num); - MEM_freeN(ss->propset); - } + if(ss->radialcontrol) + MEM_freeN(ss->radialcontrol); sculpt_vertexusers_free(ss); if(ss->texcache) diff --git a/source/blender/include/BDR_sculptmode.h b/source/blender/include/BDR_sculptmode.h index e15c1fb7063..8b0b65be4de 100644 --- a/source/blender/include/BDR_sculptmode.h +++ b/source/blender/include/BDR_sculptmode.h @@ -33,7 +33,6 @@ #include "DNA_listBase.h" #include "DNA_vec_types.h" #include "BKE_sculpt.h" -#include "transform.h" struct uiBlock; struct BrushData; @@ -59,15 +58,13 @@ void sculptmode_draw_interface_tools(struct uiBlock *block,unsigned short cx, un void sculptmode_draw_interface_brush(struct uiBlock *block,unsigned short cx, unsigned short cy); void sculptmode_draw_interface_textures(struct uiBlock *block,unsigned short cx, unsigned short cy); void sculptmode_rem_tex(void*,void*); -void sculptmode_propset_init(PropsetMode mode); -void sculptmode_propset(const unsigned short event); void sculptmode_selectbrush_menu(void); void sculptmode_draw_mesh(int); void sculpt_paint_brush(char clear); void sculpt_stroke_draw(); +void sculpt_radialcontrol_start(int mode); struct BrushData *sculptmode_brush(void); -float tex_angle(void); void do_symmetrical_brush_actions(struct EditData *e, short *, short *); void sculptmode_update_tex(void); diff --git a/source/blender/include/BIF_editparticle.h b/source/blender/include/BIF_editparticle.h index 77fb091de37..6074dcd4fec 100644 --- a/source/blender/include/BIF_editparticle.h +++ b/source/blender/include/BIF_editparticle.h @@ -38,6 +38,7 @@ struct Object; struct ParticleSystem; struct ParticleEditSettings; +struct RadialControl; /* particle edit mode */ void PE_set_particle_edit(void); @@ -53,6 +54,7 @@ short PE_get_current_num(struct Object *ob); int PE_minmax(float *min, float *max); void PE_get_colors(char sel[4], char nosel[4]); struct ParticleEditSettings *PE_settings(void); +struct RadialControl **PE_radialcontrol(); /* update calls */ void PE_hide_keys_time(struct ParticleSystem *psys, float cfra); @@ -83,6 +85,7 @@ void PE_remove_doubles(void); void PE_mirror_x(int tagged); void PE_selectbrush_menu(void); void PE_remove_doubles(void); +void PE_radialcontrol_start(const int mode); /* undo */ void PE_undo_push(char *str); diff --git a/source/blender/include/BIF_radialcontrol.h b/source/blender/include/BIF_radialcontrol.h new file mode 100644 index 00000000000..81181a3a91e --- /dev/null +++ b/source/blender/include/BIF_radialcontrol.h @@ -0,0 +1,62 @@ +/* + * $Id: multires.h 13015 2007-12-27 07:27:03Z nicholasbishop $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2008 by Nicholas Bishop + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef RADIALCONTROL_H +#define RADIALCONTROL_H + +struct NumInput; + +#define RADIALCONTROL_NONE 0 +#define RADIALCONTROL_SIZE 1 +#define RADIALCONTROL_STRENGTH 2 +#define RADIALCONTROL_ROTATION 3 + +typedef void (*RadialControlCallback)(const int, const int); + +typedef struct RadialControl { + int mode; + short origloc[2]; + + unsigned int tex; + + int new_value; + int original_value; + int max_value; + RadialControlCallback callback; + + struct NumInput *num; +} RadialControl; + +RadialControl *radialcontrol_start(const int mode, RadialControlCallback callback, + const int original_value, const int max_value, + const unsigned int tex); +void radialcontrol_do_events(RadialControl *rc, const unsigned short event); +void radialcontrol_draw(RadialControl *rc); + +#endif diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index fd23761c82c..e3d73f4cda3 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -125,6 +125,7 @@ #include "BIF_mywindow.h" #include "BIF_poseobject.h" #include "BIF_previewrender.h" +#include "BIF_radialcontrol.h" #include "BIF_resources.h" #include "BIF_retopo.h" #include "BIF_screen.h" @@ -3061,68 +3062,13 @@ void drawview3dspace(ScrArea *sa, void *spacedata) /* Draw Sculpt Mode brush */ if(!G.obedit && (G.f & G_SCULPTMODE) && area_is_active_area(v3d->area) && sculpt_session()) { - PropsetData *pd= sculpt_session()->propset; - short r1=100, r2=100, r3=100; - short mouse[2]; + RadialControl *rc= sculpt_session()->radialcontrol; if(sculpt_data()->flags & SCULPT_INPUT_SMOOTH) sculpt_stroke_draw(); - if(pd) { - if(pd->mode == PropsetSize) { - r1= sculptmode_brush()->size; - r2= pd->origsize; - r3= r1; - } else if(pd->mode == PropsetStrength) { - r1= 200 - sculptmode_brush()->strength * 2; - r2= 200; - r3= 200; - } else if(pd->mode == PropsetTexRot) { - r1= r2= 200; - r3= 200; - } - - /* Draw brush with texture */ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glBindTexture(GL_TEXTURE_2D, pd->tex); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glPushMatrix(); - glTranslatef(pd->origloc[0], pd->origloc[1], 0); - glRotatef(tex_angle(), 0, 0, 1); - - glEnable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - glColor4f(0,0,0,1); - glTexCoord2f(0,0); - glVertex2f(-r3, -r3); - glTexCoord2f(1,0); - glVertex2f(r3, -r3); - glTexCoord2f(1,1); - glVertex2f(r3, r3); - glTexCoord2f(0,1); - glVertex2f(-r3, r3); - glEnd(); - glDisable(GL_TEXTURE_2D); - - glPopMatrix(); - - if(r1 != r2) - fdrawXORcirc(pd->origloc[0], pd->origloc[1], r1); - fdrawXORcirc(pd->origloc[0], pd->origloc[1], r2); - - if(pd->mode == PropsetTexRot) { - const float ang= pd->origtexrot * (M_PI/180.0f); - getmouseco_areawin(mouse); - sdrawXORline(pd->origloc[0], pd->origloc[1], - pd->origloc[0]+200*cos(ang), pd->origloc[1]+200*sin(ang)); - sdrawXORline(pd->origloc[0], pd->origloc[1], mouse[0], mouse[1]); - } - } + if(rc) + radialcontrol_draw(rc); else if(sculpt_data()->flags & SCULPT_DRAW_BRUSH) { short csc[2], car[2]; getmouseco_sc(csc); @@ -3143,7 +3089,9 @@ void drawview3dspace(ScrArea *sa, void *spacedata) ParticleEditSettings *pset = PE_settings(); short c[2]; - if(psys && psys->edit && pset->brushtype>=0){ + if(*PE_radialcontrol()) + radialcontrol_draw(*PE_radialcontrol()); + else if(psys && psys->edit && pset->brushtype>=0) { getmouseco_areawin(c); fdrawXORcirc((float)c[0], (float)c[1], (float)pset->brush[pset->brushtype].size); } diff --git a/source/blender/src/editparticle.c b/source/blender/src/editparticle.c index 0a2158faf33..ea93ba7a090 100644 --- a/source/blender/src/editparticle.c +++ b/source/blender/src/editparticle.c @@ -80,6 +80,7 @@ #include "BIF_interface.h" #include "BIF_meshtools.h" #include "BIF_mywindow.h" +#include "BIF_radialcontrol.h" #include "BIF_resources.h" #include "BIF_screen.h" #include "BIF_space.h" @@ -1989,6 +1990,46 @@ void PE_remove_doubles(void) BIF_undo_push("Remove double particles"); } +static void PE_radialcontrol_callback(const int mode, const int val) +{ + ParticleEditSettings *pset = PE_settings(); + + if(pset->brushtype>=0) { + ParticleBrushData *brush= &pset->brush[pset->brushtype]; + + if(mode == RADIALCONTROL_SIZE) + brush->size = val; + else if(mode == RADIALCONTROL_STRENGTH) + brush->strength = val; + } + + (*PE_radialcontrol()) = NULL; +} + +RadialControl **PE_radialcontrol() +{ + static RadialControl *rc = NULL; + return &rc; +} + +void PE_radialcontrol_start(const int mode) +{ + ParticleEditSettings *pset = PE_settings(); + int orig; + + if(pset->brushtype>=0) { + ParticleBrushData *brush= &pset->brush[pset->brushtype]; + + if(mode == RADIALCONTROL_SIZE) + orig = brush->size; + else if(mode == RADIALCONTROL_STRENGTH) + orig = brush->strength; + + if(mode != RADIALCONTROL_NONE) + (*PE_radialcontrol())= radialcontrol_start(mode, PE_radialcontrol_callback, orig, 100, 0); + } +} + /************************************************/ /* Edit Brushes */ /************************************************/ diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 8102e60c7fb..b476bb6c944 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -113,6 +113,7 @@ #include "BIF_meshtools.h" #include "BIF_poselib.h" #include "BIF_poseobject.h" +#include "BIF_radialcontrol.h" #include "BIF_renderwin.h" #include "BIF_resources.h" #include "BIF_retopo.h" @@ -4402,6 +4403,7 @@ void do_view3d_sculptmenu(void *arg, int event) { SculptData *sd= &G.scene->sculptdata; BrushData *br= sculptmode_brush(); + switch(event) { case 0: case 1: @@ -4445,13 +4447,13 @@ void do_view3d_sculptmenu(void *arg, int event) add_blockhandler(curarea, VIEW3D_HANDLER_OBJECT, UI_PNL_UNSTOW); break; case 15: - sculptmode_propset_init(PropsetTexRot); + sculpt_radialcontrol_start(RADIALCONTROL_ROTATION); break; case 16: - sculptmode_propset_init(PropsetStrength); + sculpt_radialcontrol_start(RADIALCONTROL_STRENGTH); break; case 17: - sculptmode_propset_init(PropsetSize); + sculpt_radialcontrol_start(RADIALCONTROL_SIZE); break; case 18: br->dir= br->dir==1 ? 2 : 1; diff --git a/source/blender/src/radialcontrol.c b/source/blender/src/radialcontrol.c new file mode 100644 index 00000000000..9911062f3df --- /dev/null +++ b/source/blender/src/radialcontrol.c @@ -0,0 +1,266 @@ +/* + * $Id: multires.c 13015 2007-12-27 07:27:03Z nicholasbishop $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2006 by Nicholas Bishop + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + * + * Implements the multiresolution modeling tools. + * + * multires.h + * + */ + +#include "MEM_guardedalloc.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" +#include "BIF_mywindow.h" +#include "BIF_screen.h" +#include "BIF_space.h" +#include "BIF_radialcontrol.h" + +#include "BKE_global.h" + +#include "mydevice.h" +#include "transform.h" + +#include "math.h" + +/* Prints the value being edited in the view header */ +static void radialcontrol_header(const RadialControl *rc) +{ + if(rc) { + char str[512]; + const char *name= ""; + + if(rc->mode == RADIALCONTROL_SIZE) + name= "Size"; + else if(rc->mode == RADIALCONTROL_STRENGTH) + name= "Strength"; + else if(rc->mode == RADIALCONTROL_ROTATION) + name= "Angle"; + + sprintf(str, "%s: %d", name, (int)(rc->new_value)); + headerprint(str); + } +} + +/* Creates, initializes, and returns the control */ +RadialControl *radialcontrol_start(const int mode, RadialControlCallback callback, + const int original_value, const int max_value, + const unsigned int tex) +{ + RadialControl *rc= MEM_callocN(sizeof(RadialControl), "radial control"); + short mouse[2]; + + getmouseco_areawin(mouse); + rc->origloc[0]= mouse[0]; + rc->origloc[1]= mouse[1]; + + if(mode == RADIALCONTROL_SIZE) + rc->origloc[0]-= original_value; + else if(mode == RADIALCONTROL_STRENGTH) + rc->origloc[0]-= 200 - 2*original_value; + else if(mode == RADIALCONTROL_ROTATION) { + rc->origloc[0]-= 200 * cos(original_value * M_PI / 180.0); + rc->origloc[1]-= 200 * sin(original_value * M_PI / 180.0); + } + + rc->callback = callback; + rc->original_value = original_value; + rc->max_value = max_value; + + rc->tex = tex; + + /* NumInput is used for keyboard input */ + rc->num = MEM_callocN(sizeof(NumInput), "radialcontrol numinput"); + rc->num->idx_max= 0; + + rc->mode= mode; + radialcontrol_header(rc); + + allqueue(REDRAWVIEW3D, 0); + + return rc; +} + + +static void radialcontrol_end(RadialControl *rc) +{ + if(rc) { + rc->callback(rc->mode, rc->new_value); + BIF_undo_push("Brush property set"); + + /* Free everything */ + glDeleteTextures(1, (GLuint*)(&rc->tex)); + MEM_freeN(rc->num); + MEM_freeN(rc); + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWHEADERS, 0); + } +} + +void radialcontrol_do_events(RadialControl *rc, unsigned short event) +{ + short mouse[2]; + short tmp[2]; + float dist; + char valset= 0; + + if(!rc) + return; + + handleNumInput(rc->num, event); + + if(hasNumInput(rc->num)) { + float val; + applyNumInput(rc->num, &val); + rc->new_value = val; + valset= 1; + allqueue(REDRAWVIEW3D, 0); + } + + switch(event) { + case MOUSEX: + case MOUSEY: + if(!hasNumInput(rc->num)) { + char ctrl= G.qual & LR_CTRLKEY; + getmouseco_areawin(mouse); + tmp[0]= rc->origloc[0]-mouse[0]; + tmp[1]= rc->origloc[1]-mouse[1]; + dist= sqrt(tmp[0]*tmp[0]+tmp[1]*tmp[1]); + if(rc->mode == RADIALCONTROL_SIZE) + rc->new_value = dist; + else if(rc->mode == RADIALCONTROL_STRENGTH) { + float fin= (200.0f - dist) * 0.5f; + rc->new_value= fin>=0 ? fin : 0; + } else if(rc->mode == RADIALCONTROL_ROTATION) + rc->new_value= ((int)(atan2(tmp[1], tmp[0]) * (180.0 / M_PI)) + 180); + + if(ctrl) + rc->new_value= (rc->new_value + 5) / 10*10; + + valset= 1; + allqueue(REDRAWVIEW3D, 0); + } + break; + case ESCKEY: + case RIGHTMOUSE: + rc->new_value = rc->original_value; + case LEFTMOUSE: + while(get_mbut()==L_MOUSE); + case RETKEY: + case PADENTER: + radialcontrol_end(rc); + return; + default: + break; + }; + + if(valset) { + if(rc->new_value > rc->max_value) + rc->new_value = rc->max_value; + } + + radialcontrol_header(rc); +} + +static void rot_line(const short o[2], const float ang) +{ + sdrawXORline(o[0], o[1], o[0] + 200*cos(ang), o[1] + 200*sin(ang)); +} + +void radialcontrol_draw(RadialControl *rc) +{ + short r1, r2, r3; + float angle = 0; + + if(rc && rc->mode) { + if(rc->mode == RADIALCONTROL_SIZE) { + r1= rc->new_value; + r2= rc->original_value; + r3= r1; + } else if(rc->mode == RADIALCONTROL_STRENGTH) { + r1= 200 - rc->new_value * 2; + r2= 200; + r3= 200; + } else if(rc->mode == RADIALCONTROL_ROTATION) { + r1= r2= 200; + r3= 200; + angle = rc->new_value; + } + + /* Draw brush with texture */ + glPushMatrix(); + glTranslatef(rc->origloc[0], rc->origloc[1], 0); + glRotatef(angle, 0, 0, 1); + + if(rc->tex) { + const float str = rc->mode == RADIALCONTROL_STRENGTH ? (rc->new_value / 200.0 + 0.5) : 1; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glBindTexture(GL_TEXTURE_2D, rc->tex); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glEnable(GL_TEXTURE_2D); + glBegin(GL_QUADS); + glColor4f(0,0,0, str); + glTexCoord2f(0,0); + glVertex2f(-r3, -r3); + glTexCoord2f(1,0); + glVertex2f(r3, -r3); + glTexCoord2f(1,1); + glVertex2f(r3, r3); + glTexCoord2f(0,1); + glVertex2f(-r3, r3); + glEnd(); + glDisable(GL_TEXTURE_2D); + } + + glPopMatrix(); + + if(r1 != r2) + fdrawXORcirc(rc->origloc[0], rc->origloc[1], r1); + fdrawXORcirc(rc->origloc[0], rc->origloc[1], r2); + + if(rc->mode == RADIALCONTROL_ROTATION) { + float ang1= rc->original_value * (M_PI/180.0f); + float ang2= rc->new_value * (M_PI/180.0f); + + if(rc->new_value > 359) + ang2 = 0; + + rot_line(rc->origloc, ang1); + if(ang1 != ang2) + rot_line(rc->origloc, ang2); + } + } +} diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c index a1341fd60c3..79a40fdb607 100644 --- a/source/blender/src/sculptmode.c +++ b/source/blender/src/sculptmode.c @@ -76,6 +76,7 @@ #include "BIF_gl.h" #include "BIF_interface.h" #include "BIF_mywindow.h" +#include "BIF_radialcontrol.h" #include "BIF_resources.h" #include "BIF_screen.h" #include "BIF_space.h" @@ -672,7 +673,7 @@ void flip_coord(float co[3], const char symm) } /* Use the warpfac field in MTex to store a rotation value for sculpt textures. Value is in degrees */ -float tex_angle(void) +float sculpt_tex_angle(void) { SculptData *sd= sculpt_data(); if(sd->texact!=-1 && sd->mtex[sd->texact]) @@ -737,7 +738,7 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin else if(ss->texcache) { const short bsize= sculptmode_brush()->size * 2; const short half= sculptmode_brush()->size; - const float rot= to_rad(tex_angle()); + const float rot= to_rad(sculpt_tex_angle()); const unsigned tcw = ss->texcache_w, tch = ss->texcache_h; int px, py; unsigned i, *p; @@ -1224,147 +1225,85 @@ void sculptmode_set_strength(const int delta) sculptmode_brush()->strength= val; } -void sculptmode_propset_calctex() +static void sculpt_radialcontrol_callback(const int mode, const int val) +{ + SculptSession *ss = sculpt_session(); + BrushData *br = sculptmode_brush(); + + if(mode == RADIALCONTROL_SIZE) + br->size = val; + else if(mode == RADIALCONTROL_STRENGTH) + br->strength = val; + else if(mode == RADIALCONTROL_ROTATION) + set_tex_angle(val); + + ss->radialcontrol = NULL; +} + +/* Returns GL handle to brush texture */ +static GLuint sculpt_radialcontrol_calctex() { SculptData *sd= sculpt_data(); SculptSession *ss= sculpt_session(); - PropsetData *pd= sculpt_session()->propset; - if(pd) { - int i, j; - const int tsz = 128; - float *d; - if(!pd->texdata) { - pd->texdata= MEM_mallocN(sizeof(float)*tsz*tsz, "Brush preview"); - if(sd->texrept!=SCULPTREPT_3D) - sculptmode_update_tex(); - for(i=0; itexfade) - pd->texdata[i*tsz+j]= curve_strength(magn,tsz/2); - else - pd->texdata[i*tsz+j]= magn < tsz/2 ? 1 : 0; - } - if(sd->texact != -1 && ss->texcache) { - for(i=0; itexcache[i*tsz+j]; - pd->texdata[i*tsz+j]*= (((char*)&col)[0]+((char*)&col)[1]+((char*)&col)[2])/3.0f/255.0f; - } - } + int i, j; + const int tsz = 128; + float *texdata= MEM_mallocN(sizeof(float)*tsz*tsz, "Brush preview"); + GLuint tex; + + if(sd->texrept!=SCULPTREPT_3D) + sculptmode_update_tex(); + for(i=0; itexfade) + texdata[i*tsz+j]= curve_strength(magn,tsz/2); + else + texdata[i*tsz+j]= magn < tsz/2 ? 1 : 0; } - - /* Adjust alpha with brush strength */ - d= MEM_dupallocN(pd->texdata); + if(sd->texact != -1 && ss->texcache) { for(i=0; istrength/200.0f+0.5f; - - - if(!pd->tex) - glGenTextures(1, (GLuint *)&pd->tex); - glBindTexture(GL_TEXTURE_2D, pd->tex); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tsz, tsz, 0, GL_ALPHA, GL_FLOAT, d); - MEM_freeN(d); + for(j=0; jtexcache[i*tsz+j]; + texdata[i*tsz+j]*= (((char*)&col)[0]+((char*)&col)[1]+((char*)&col)[2])/3.0f/255.0f; + } } + + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tsz, tsz, 0, GL_ALPHA, GL_FLOAT, texdata); + MEM_freeN(texdata); + + return tex; } -void sculptmode_propset_header() +void sculpt_radialcontrol_start(int mode) { - SculptSession *ss= sculpt_session(); - PropsetData *pd= ss ? ss->propset : NULL; - if(pd) { - char str[512]; - const char *name= ""; - int val= 0; - if(pd->mode == PropsetSize) { - name= "Size"; - val= sculptmode_brush()->size; - } - else if(pd->mode == PropsetStrength) { - name= "Strength"; - val= sculptmode_brush()->strength; - } - else if(pd->mode == PropsetTexRot) { - name= "Texture Angle"; - val= tex_angle(); - } - sprintf(str, "Brush %s: %d", name, val); - headerprint(str); + SculptData *sd = sculpt_data(); + SculptSession *ss = sculpt_session(); + BrushData *br = sculptmode_brush(); + int orig, max; + + if(mode == RADIALCONTROL_SIZE) { + orig = br->size; + max = 200; } -} - -void sculptmode_propset_end(SculptSession *ss, int cancel) -{ - if(ss && ss->propset) { - PropsetData *pd= ss->propset; - - if(cancel) { - sculptmode_brush()->size= pd->origsize; - sculptmode_brush()->strength= pd->origstrength; - set_tex_angle(pd->origtexrot); - } else { - if(pd->mode != PropsetSize) - sculptmode_brush()->size= pd->origsize; - if(pd->mode != PropsetStrength) - sculptmode_brush()->strength= pd->origstrength; - if(pd->mode != PropsetTexRot) - set_tex_angle(pd->origtexrot); - - BIF_undo_push("Brush property set"); - } - glDeleteTextures(1, &pd->tex); - MEM_freeN(pd->num); - MEM_freeN(pd->texdata); - MEM_freeN(pd); - ss->propset= NULL; - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWBUTSEDIT, 0); - allqueue(REDRAWHEADERS, 0); + else if(mode == RADIALCONTROL_STRENGTH) { + orig = br->strength; + max = 100; } -} - -void sculptmode_propset_init(PropsetMode mode) -{ - SculptSession *ss= sculpt_session(); - PropsetData *pd= ss->propset; - const float ang= tex_angle(); - - if(!pd) { - short mouse[2]; - - pd= MEM_callocN(sizeof(PropsetData),"PropsetSize"); - ss->propset= pd; - - getmouseco_areawin(mouse); - pd->origloc[0]= mouse[0]; - pd->origloc[1]= mouse[1]; - - if(mode == PropsetSize) - pd->origloc[0]-= sculptmode_brush()->size; - else if(mode == PropsetStrength) - pd->origloc[0]-= 200 - 2*sculptmode_brush()->strength; - else if(mode == PropsetTexRot) { - pd->origloc[0]-= 200 * cos(to_rad(ang)); - pd->origloc[1]-= 200 * sin(to_rad(ang)); + else if(mode == RADIALCONTROL_ROTATION) { + if(sd->texact!=-1 && sd->mtex[sd->texact]) { + orig = sculpt_tex_angle(); + max = 360; } - - pd->origsize= sculptmode_brush()->size; - pd->origstrength= sculptmode_brush()->strength; - pd->origtexrot= ang; - - sculptmode_propset_calctex(); - - if(!pd->num) - pd->num = MEM_callocN(sizeof(NumInput), "propset numinput"); - pd->num->idx_max= 0; + else + mode = RADIALCONTROL_NONE; } - pd->mode= mode; - sculptmode_propset_header(); - - allqueue(REDRAWVIEW3D, 0); + if(mode != RADIALCONTROL_NONE) { + ss->radialcontrol= radialcontrol_start(mode, sculpt_radialcontrol_callback, orig, max, + sculpt_radialcontrol_calctex()); + } } void sculpt_paint_brush(char clear) @@ -1387,90 +1326,6 @@ void sculpt_paint_brush(char clear) } } -void sculptmode_propset(unsigned short event) -{ - PropsetData *pd= sculpt_session()->propset; - short mouse[2]; - short tmp[2]; - float dist; - BrushData *brush= sculptmode_brush(); - char valset= 0; - - handleNumInput(pd->num, event); - - if(hasNumInput(pd->num)) { - float val; - applyNumInput(pd->num, &val); - if(pd->mode==PropsetSize) - brush->size= val; - else if(pd->mode==PropsetStrength) - brush->strength= val; - else if(pd->mode==PropsetTexRot) - set_tex_angle(val); - valset= 1; - allqueue(REDRAWVIEW3D, 0); - } - - switch(event) { - case MOUSEX: - case MOUSEY: - if(!hasNumInput(pd->num)) { - char ctrl= G.qual & LR_CTRLKEY; - getmouseco_areawin(mouse); - tmp[0]= pd->origloc[0]-mouse[0]; - tmp[1]= pd->origloc[1]-mouse[1]; - dist= sqrt(tmp[0]*tmp[0]+tmp[1]*tmp[1]); - if(pd->mode == PropsetSize) { - brush->size= dist; - if(ctrl) brush->size= (brush->size+5)/10*10; - } else if(pd->mode == PropsetStrength) { - float fin= (200.0f - dist) * 0.5f; - brush->strength= fin>=0 ? fin : 0; - if(ctrl) brush->strength= (brush->strength+5)/10*10; - } else if(pd->mode == PropsetTexRot) { - set_tex_angle((int)to_deg(atan2(tmp[1], tmp[0])) + 180); - if(ctrl) - set_tex_angle(((int)(tex_angle())+5)/10*10); - } - valset= 1; - allqueue(REDRAWVIEW3D, 0); - } - break; - case ESCKEY: - case RIGHTMOUSE: - brush->size= pd->origsize; - brush->strength= pd->origstrength; - set_tex_angle(pd->origtexrot); - case LEFTMOUSE: - while(get_mbut()==L_MOUSE); - case RETKEY: - case PADENTER: - sculptmode_propset_end(sculpt_session(), 0); - break; - default: - break; - }; - - if(valset) { - if(pd->mode == PropsetSize) { - if(brush->size<1) brush->size= 1; - if(brush->size>200) brush->size= 200; - } - else if(pd->mode == PropsetStrength) { - if(brush->strength > 100) brush->strength= 100; - sculptmode_propset_calctex(); - } - else if(pd->mode == PropsetTexRot) { - if(tex_angle() < 0) - set_tex_angle(0); - else if(tex_angle() > 360) - set_tex_angle(360); - } - } - - sculptmode_propset_header(); -} - void sculptmode_selectbrush_menu(void) { SculptData *sd= sculpt_data(); @@ -1699,7 +1554,7 @@ void sculpt(void) glGetIntegerv(GL_SCISSOR_BOX, scissor_box); /* For raking, get the original angle*/ - offsetRot=tex_angle(); + offsetRot=sculpt_tex_angle(); while (get_mbut() & mousebut) { getmouseco_areawin(mouse); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 9f3754f32da..e09da2b4a3b 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -129,6 +129,7 @@ #include "BIF_poselib.h" #include "BIF_poseobject.h" #include "BIF_outliner.h" +#include "BIF_radialcontrol.h" #include "BIF_resources.h" #include "BIF_retopo.h" #include "BIF_screen.h" @@ -1199,8 +1200,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(!mouse_in_header(sa)) { if(!G.obedit && (G.f & G_SCULPTMODE)) { SculptSession *ss= sculpt_session(); - if(ss && ss->propset) { - sculptmode_propset(event); + if(ss && ss->radialcontrol) { + radialcontrol_do_events(ss->radialcontrol, event); return; } else if(event!=LEFTMOUSE && event!=MIDDLEMOUSE && (event==MOUSEY || event==MOUSEX)) { @@ -1211,6 +1212,10 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if(!G.obedit && OBACT && G.f&G_PARTICLEEDIT){ ParticleSystem *psys=PE_get_current(OBACT); ParticleEditSettings *pset=PE_settings(); + if(*PE_radialcontrol()) { + radialcontrol_do_events(*PE_radialcontrol(), event); + return; + } if(psys && psys->edit){ if(pset->brushtype>=0 && event!=LEFTMOUSE && event!=RIGHTMOUSE && event!=MIDDLEMOUSE && @@ -1366,7 +1371,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case LEFTMOUSE: if(G.qual==LR_SHIFTKEY+LR_CTRLKEY) sculptmode_pmv(0); - else if(!(ss && ss->propset)) + else if(!(ss && ss->radialcontrol)) sculpt(); break; /* View */ @@ -1444,12 +1449,12 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) br->airbrush= !br->airbrush; update_prop= 1; break; case FKEY: - if(G.qual==0) - sculptmode_propset_init(PropsetSize); - if(G.qual==LR_SHIFTKEY) - sculptmode_propset_init(PropsetStrength); - if(G.qual==LR_CTRLKEY) - sculptmode_propset_init(PropsetTexRot); + if(ss) { + sculpt_radialcontrol_start(G.qual == 0 ? RADIALCONTROL_SIZE : + G.qual == LR_SHIFTKEY ? RADIALCONTROL_STRENGTH : + G.qual == LR_CTRLKEY ? RADIALCONTROL_ROTATION : + RADIALCONTROL_NONE); + } break; case VKEY: br->dir= br->dir==1 ? 2 : 1; @@ -1914,6 +1919,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) pose_activate_flipped_bone(); else if(G.f & G_WEIGHTPAINT) pose_activate_flipped_bone(); + else if(G.f & G_PARTICLEEDIT) + PE_radialcontrol_start(RADIALCONTROL_STRENGTH); else fly(); } @@ -1922,6 +1929,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) G.f ^= G_FACESELECT; allqueue(REDRAWVIEW3D, 1); } + else if(G.f & G_PARTICLEEDIT) + PE_radialcontrol_start(RADIALCONTROL_SIZE); } break;