== 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...
This commit is contained in:
Nicholas Bishop 2008-01-16 07:19:21 +00:00
parent f41c3340be
commit c6118036bc
11 changed files with 476 additions and 317 deletions

@ -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;

@ -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)

@ -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);

@ -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);

@ -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

@ -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);
}

@ -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 */
/************************************************/

@ -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;

@ -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);
}
}
}

@ -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; i<tsz; ++i)
for(j=0; j<tsz; ++j) {
float magn= sqrt(pow(i-tsz/2,2)+pow(j-tsz/2,2));
if(sd->texfade)
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; i<tsz; ++i)
for(j=0; j<tsz; ++j) {
const int col= ss->texcache[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; i<tsz; ++i)
for(j=0; j<tsz; ++j) {
float magn= sqrt(pow(i-tsz/2,2)+pow(j-tsz/2,2));
if(sd->texfade)
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; i<tsz; ++i)
for(j=0; j<tsz; ++j)
d[i*tsz+j]*= sculptmode_brush()->strength/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; j<tsz; ++j) {
const int col= ss->texcache[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);

@ -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;