2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2009-01-07 19:23:22 +00:00
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* ***** 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-01-07 19:23:22 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
*
|
|
|
|
* Contributor(s): none yet.
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2011-02-27 20:29:51 +00:00
|
|
|
/** \file blender/editors/sculpt_paint/paint_vertex.c
|
|
|
|
* \ingroup edsculpt
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2009-01-07 19:23:22 +00:00
|
|
|
#include <math.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
#include <io.h>
|
|
|
|
#else
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
2009-11-10 20:43:45 +00:00
|
|
|
#include "BLI_math.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2009-10-30 02:09:52 +00:00
|
|
|
#include "BLI_ghash.h"
|
2009-09-06 00:36:26 +00:00
|
|
|
|
2010-08-16 05:46:10 +00:00
|
|
|
#include "IMB_imbuf.h"
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
|
2009-01-07 19:23:22 +00:00
|
|
|
#include "DNA_armature_types.h"
|
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_particle_types.h"
|
2010-08-10 05:41:51 +00:00
|
|
|
#include "DNA_scene_types.h"
|
2010-08-04 04:01:27 +00:00
|
|
|
#include "DNA_brush_types.h"
|
2010-08-10 05:41:51 +00:00
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-01-25 21:02:52 +00:00
|
|
|
#include "RNA_access.h"
|
2009-08-20 05:13:07 +00:00
|
|
|
#include "RNA_define.h"
|
2011-05-25 10:07:59 +00:00
|
|
|
#include "RNA_enum_types.h"
|
2009-01-25 21:02:52 +00:00
|
|
|
|
2010-08-10 05:41:51 +00:00
|
|
|
#include "BKE_DerivedMesh.h"
|
2011-09-14 02:04:26 +00:00
|
|
|
#include "BKE_armature.h"
|
2010-01-18 16:21:23 +00:00
|
|
|
#include "BKE_action.h"
|
2009-03-11 00:43:08 +00:00
|
|
|
#include "BKE_brush.h"
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
#include "BKE_context.h"
|
2009-01-07 19:23:22 +00:00
|
|
|
#include "BKE_depsgraph.h"
|
|
|
|
#include "BKE_deform.h"
|
|
|
|
#include "BKE_mesh.h"
|
|
|
|
#include "BKE_modifier.h"
|
|
|
|
#include "BKE_object.h"
|
2009-08-17 02:49:31 +00:00
|
|
|
#include "BKE_paint.h"
|
2011-05-25 10:07:59 +00:00
|
|
|
#include "BKE_report.h"
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
#include "WM_api.h"
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
#include "WM_types.h"
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
|
2010-01-26 11:11:53 +00:00
|
|
|
#include "ED_armature.h"
|
2009-01-07 19:23:22 +00:00
|
|
|
#include "ED_mesh.h"
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
#include "ED_screen.h"
|
2009-01-07 19:23:22 +00:00
|
|
|
#include "ED_view3d.h"
|
|
|
|
|
2009-08-20 05:13:07 +00:00
|
|
|
#include "paint_intern.h"
|
|
|
|
|
2010-01-20 08:30:40 +00:00
|
|
|
/* brush->vertexpaint_tool */
|
2009-01-07 19:23:22 +00:00
|
|
|
#define VP_MIX 0
|
|
|
|
#define VP_ADD 1
|
|
|
|
#define VP_SUB 2
|
|
|
|
#define VP_MUL 3
|
|
|
|
#define VP_BLUR 4
|
|
|
|
#define VP_LIGHTEN 5
|
|
|
|
#define VP_DARKEN 6
|
|
|
|
|
2009-01-25 21:02:52 +00:00
|
|
|
/* polling - retrieve whether cursor should be set or operator should be done */
|
|
|
|
|
2009-08-22 02:27:37 +00:00
|
|
|
|
|
|
|
/* Returns true if vertex paint mode is active */
|
|
|
|
int vertex_paint_mode_poll(bContext *C)
|
2009-01-25 21:02:52 +00:00
|
|
|
{
|
2009-08-15 20:36:15 +00:00
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
|
2010-08-22 06:31:26 +00:00
|
|
|
return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totface;
|
2009-08-22 02:27:37 +00:00
|
|
|
}
|
|
|
|
|
2009-09-18 15:48:49 +00:00
|
|
|
int vertex_paint_poll(bContext *C)
|
2009-08-22 02:27:37 +00:00
|
|
|
{
|
|
|
|
if(vertex_paint_mode_poll(C) &&
|
2009-08-17 02:49:31 +00:00
|
|
|
paint_brush(&CTX_data_tool_settings(C)->vpaint->paint)) {
|
2009-01-25 21:02:52 +00:00
|
|
|
ScrArea *sa= CTX_wm_area(C);
|
|
|
|
if(sa->spacetype==SPACE_VIEW3D) {
|
|
|
|
ARegion *ar= CTX_wm_region(C);
|
|
|
|
if(ar->regiontype==RGN_TYPE_WINDOW)
|
|
|
|
return 1;
|
2010-08-22 06:31:26 +00:00
|
|
|
}
|
2009-01-25 21:02:52 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-01-26 11:11:53 +00:00
|
|
|
int weight_paint_mode_poll(bContext *C)
|
|
|
|
{
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
|
2010-08-22 06:31:26 +00:00
|
|
|
return ob && ob->mode == OB_MODE_WEIGHT_PAINT && ((Mesh *)ob->data)->totface;
|
2010-01-26 11:11:53 +00:00
|
|
|
}
|
|
|
|
|
2009-09-18 15:48:49 +00:00
|
|
|
int weight_paint_poll(bContext *C)
|
2009-01-25 21:02:52 +00:00
|
|
|
{
|
2011-03-22 14:04:47 +00:00
|
|
|
Object *ob= CTX_data_active_object(C);
|
|
|
|
ScrArea *sa;
|
|
|
|
|
|
|
|
if( (ob != NULL) &&
|
|
|
|
(ob->mode & OB_MODE_WEIGHT_PAINT) &&
|
|
|
|
(paint_brush(&CTX_data_tool_settings(C)->wpaint->paint) != NULL) &&
|
|
|
|
(sa= CTX_wm_area(C)) &&
|
|
|
|
(sa->spacetype == SPACE_VIEW3D)
|
|
|
|
) {
|
|
|
|
ARegion *ar= CTX_wm_region(C);
|
|
|
|
if(ar->regiontype==RGN_TYPE_WINDOW) {
|
|
|
|
return 1;
|
2009-01-25 21:02:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
static VPaint *new_vpaint(int wpaint)
|
|
|
|
{
|
|
|
|
VPaint *vp= MEM_callocN(sizeof(VPaint), "VPaint");
|
|
|
|
|
2009-11-20 01:39:27 +00:00
|
|
|
vp->flag= VP_AREA+VP_SPRAY;
|
2009-01-10 14:19:14 +00:00
|
|
|
|
2009-03-11 00:43:08 +00:00
|
|
|
if(wpaint)
|
2009-11-20 01:39:27 +00:00
|
|
|
vp->flag= VP_AREA;
|
2009-03-11 00:43:08 +00:00
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
return vp;
|
|
|
|
}
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2010-02-06 15:50:53 +00:00
|
|
|
static int *get_indexarray(Mesh *me)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
2010-02-06 15:50:53 +00:00
|
|
|
return MEM_mallocN(sizeof(int)*(me->totface+1), "vertexpaint");
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* in contradiction to cpack drawing colors, the MCOL colors (vpaint colors) are per byte!
|
|
|
|
so not endian sensitive. Mcol = ABGR!!! so be cautious with cpack calls */
|
|
|
|
|
2011-02-14 17:55:27 +00:00
|
|
|
static unsigned int rgba_to_mcol(float r, float g, float b, float a)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
|
|
|
int ir, ig, ib, ia;
|
|
|
|
unsigned int col;
|
|
|
|
char *cp;
|
|
|
|
|
2011-03-27 14:59:55 +00:00
|
|
|
ir= floor(255.0f * r);
|
2009-01-07 19:23:22 +00:00
|
|
|
if(ir<0) ir= 0; else if(ir>255) ir= 255;
|
2011-03-27 14:59:55 +00:00
|
|
|
ig= floor(255.0f * g);
|
2009-01-07 19:23:22 +00:00
|
|
|
if(ig<0) ig= 0; else if(ig>255) ig= 255;
|
2011-03-27 14:59:55 +00:00
|
|
|
ib= floor(255.0f * b);
|
2009-01-07 19:23:22 +00:00
|
|
|
if(ib<0) ib= 0; else if(ib>255) ib= 255;
|
2011-03-27 14:59:55 +00:00
|
|
|
ia= floor(255.0f * a);
|
2009-01-07 19:23:22 +00:00
|
|
|
if(ia<0) ia= 0; else if(ia>255) ia= 255;
|
|
|
|
|
|
|
|
cp= (char *)&col;
|
|
|
|
cp[0]= ia;
|
|
|
|
cp[1]= ib;
|
|
|
|
cp[2]= ig;
|
|
|
|
cp[3]= ir;
|
|
|
|
|
|
|
|
return col;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-10-22 12:59:14 +00:00
|
|
|
unsigned int vpaint_get_current_col(VPaint *vp)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
2009-08-17 02:49:31 +00:00
|
|
|
Brush *brush = paint_brush(&vp->paint);
|
|
|
|
return rgba_to_mcol(brush->rgb[0], brush->rgb[1], brush->rgb[2], 1.0f);
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
2009-10-20 19:27:27 +00:00
|
|
|
static void do_shared_vertexcol(Mesh *me)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
|
|
|
/* if no mcol: do not do */
|
|
|
|
/* if tface: only the involved faces, otherwise all */
|
|
|
|
MFace *mface;
|
|
|
|
MTFace *tface;
|
|
|
|
int a;
|
|
|
|
short *scolmain, *scol;
|
|
|
|
char *mcol;
|
|
|
|
|
2011-03-05 10:29:10 +00:00
|
|
|
if(me->mcol==NULL || me->totvert==0 || me->totface==0) return;
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
scolmain= MEM_callocN(4*sizeof(short)*me->totvert, "colmain");
|
|
|
|
|
|
|
|
tface= me->mtface;
|
|
|
|
mface= me->mface;
|
|
|
|
mcol= (char *)me->mcol;
|
|
|
|
for(a=me->totface; a>0; a--, mface++, mcol+=16) {
|
2009-10-20 19:27:27 +00:00
|
|
|
if((tface && tface->mode & TF_SHAREDCOL) || (me->editflag & ME_EDIT_PAINT_MASK)==0) {
|
2009-01-07 19:23:22 +00:00
|
|
|
scol= scolmain+4*mface->v1;
|
|
|
|
scol[0]++; scol[1]+= mcol[1]; scol[2]+= mcol[2]; scol[3]+= mcol[3];
|
|
|
|
scol= scolmain+4*mface->v2;
|
|
|
|
scol[0]++; scol[1]+= mcol[5]; scol[2]+= mcol[6]; scol[3]+= mcol[7];
|
|
|
|
scol= scolmain+4*mface->v3;
|
|
|
|
scol[0]++; scol[1]+= mcol[9]; scol[2]+= mcol[10]; scol[3]+= mcol[11];
|
|
|
|
if(mface->v4) {
|
|
|
|
scol= scolmain+4*mface->v4;
|
|
|
|
scol[0]++; scol[1]+= mcol[13]; scol[2]+= mcol[14]; scol[3]+= mcol[15];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(tface) tface++;
|
|
|
|
}
|
|
|
|
|
|
|
|
a= me->totvert;
|
|
|
|
scol= scolmain;
|
|
|
|
while(a--) {
|
|
|
|
if(scol[0]>1) {
|
|
|
|
scol[1]/= scol[0];
|
|
|
|
scol[2]/= scol[0];
|
|
|
|
scol[3]/= scol[0];
|
|
|
|
}
|
|
|
|
scol+= 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
tface= me->mtface;
|
|
|
|
mface= me->mface;
|
|
|
|
mcol= (char *)me->mcol;
|
|
|
|
for(a=me->totface; a>0; a--, mface++, mcol+=16) {
|
2009-10-20 19:27:27 +00:00
|
|
|
if((tface && tface->mode & TF_SHAREDCOL) || (me->editflag & ME_EDIT_PAINT_MASK)==0) {
|
2009-01-07 19:23:22 +00:00
|
|
|
scol= scolmain+4*mface->v1;
|
|
|
|
mcol[1]= scol[1]; mcol[2]= scol[2]; mcol[3]= scol[3];
|
|
|
|
scol= scolmain+4*mface->v2;
|
|
|
|
mcol[5]= scol[1]; mcol[6]= scol[2]; mcol[7]= scol[3];
|
|
|
|
scol= scolmain+4*mface->v3;
|
|
|
|
mcol[9]= scol[1]; mcol[10]= scol[2]; mcol[11]= scol[3];
|
|
|
|
if(mface->v4) {
|
|
|
|
scol= scolmain+4*mface->v4;
|
|
|
|
mcol[13]= scol[1]; mcol[14]= scol[2]; mcol[15]= scol[3];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(tface) tface++;
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(scolmain);
|
|
|
|
}
|
|
|
|
|
2009-10-22 12:59:14 +00:00
|
|
|
static void make_vertexcol(Object *ob) /* single ob */
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
|
|
|
Mesh *me;
|
|
|
|
if(!ob || ob->id.lib) return;
|
|
|
|
me= get_mesh(ob);
|
2011-03-05 10:29:10 +00:00
|
|
|
if(me==NULL) return;
|
2009-10-22 12:59:14 +00:00
|
|
|
if(me->edit_mesh) return;
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
/* copies from shadedisplist to mcol */
|
|
|
|
if(!me->mcol) {
|
|
|
|
CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
|
|
|
|
mesh_update_customdata_pointers(me);
|
|
|
|
}
|
|
|
|
|
2009-10-22 12:59:14 +00:00
|
|
|
//if(shade)
|
|
|
|
// shadeMeshMCol(scene, ob, me);
|
|
|
|
//else
|
|
|
|
|
|
|
|
memset(me->mcol, 255, 4*sizeof(MCol)*me->totface);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2011-01-03 12:41:16 +00:00
|
|
|
DAG_id_tag_update(&me->id, 0);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-05-26 22:20:29 +00:00
|
|
|
/* mirror_vgroup is set to -1 when invalid */
|
|
|
|
static void wpaint_mirror_vgroup_ensure(Object *ob, int *vgroup_mirror)
|
|
|
|
{
|
|
|
|
bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef - 1);
|
|
|
|
|
|
|
|
if(defgroup) {
|
|
|
|
bDeformGroup *curdef;
|
|
|
|
int mirrdef;
|
|
|
|
char name[MAXBONENAME];
|
|
|
|
|
|
|
|
flip_side_name(name, defgroup->name, FALSE);
|
|
|
|
|
|
|
|
if(strcmp(name, defgroup->name) != 0) {
|
2011-06-01 23:55:49 +00:00
|
|
|
for (curdef= ob->defbase.first, mirrdef= 0; curdef; curdef=curdef->next, mirrdef++) {
|
2011-05-26 22:20:29 +00:00
|
|
|
if (!strcmp(curdef->name, name)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(curdef==NULL) {
|
|
|
|
int olddef= ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */
|
|
|
|
curdef= ED_vgroup_add_name(ob, name);
|
|
|
|
ob->actdef= olddef;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* curdef should never be NULL unless this is
|
|
|
|
* a lamp and ED_vgroup_add_name fails */
|
|
|
|
if(curdef) {
|
|
|
|
*vgroup_mirror= mirrdef;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*vgroup_mirror= -1;
|
|
|
|
}
|
|
|
|
|
2009-01-07 19:23:22 +00:00
|
|
|
static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
|
|
|
|
{
|
|
|
|
if(vp->vpaint_prev) {
|
|
|
|
MEM_freeN(vp->vpaint_prev);
|
|
|
|
vp->vpaint_prev= NULL;
|
|
|
|
}
|
|
|
|
vp->tot= tot;
|
|
|
|
|
|
|
|
if(mcol==NULL || tot==0) return;
|
|
|
|
|
|
|
|
vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev");
|
|
|
|
memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
static void copy_wpaint_prev (VPaint *wp, MDeformVert *dverts, int dcount)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
2009-01-10 14:19:14 +00:00
|
|
|
if (wp->wpaint_prev) {
|
|
|
|
free_dverts(wp->wpaint_prev, wp->tot);
|
|
|
|
wp->wpaint_prev= NULL;
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(dverts && dcount) {
|
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
wp->wpaint_prev = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaint prev");
|
|
|
|
wp->tot = dcount;
|
|
|
|
copy_dverts (wp->wpaint_prev, dverts, dcount);
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-22 12:59:14 +00:00
|
|
|
void vpaint_fill(Object *ob, unsigned int paintcol)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
|
|
|
Mesh *me;
|
|
|
|
MFace *mf;
|
2009-10-22 12:59:14 +00:00
|
|
|
unsigned int *mcol;
|
2011-07-21 18:46:59 +00:00
|
|
|
int i, selected;
|
2011-07-20 15:56:35 +00:00
|
|
|
|
2009-01-07 19:23:22 +00:00
|
|
|
me= get_mesh(ob);
|
2011-03-05 10:29:10 +00:00
|
|
|
if(me==NULL || me->totface==0) return;
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
if(!me->mcol)
|
2009-10-22 12:59:14 +00:00
|
|
|
make_vertexcol(ob);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-10-22 12:59:14 +00:00
|
|
|
selected= (me->editflag & ME_EDIT_PAINT_MASK);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
mf = me->mface;
|
|
|
|
mcol = (unsigned int*)me->mcol;
|
|
|
|
for (i = 0; i < me->totface; i++, mf++, mcol+=4) {
|
2011-07-21 18:46:59 +00:00
|
|
|
if (!selected || mf->flag & ME_FACE_SEL) {
|
|
|
|
mcol[0] = paintcol;
|
|
|
|
mcol[1] = paintcol;
|
|
|
|
mcol[2] = paintcol;
|
|
|
|
mcol[3] = paintcol;
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-03 12:41:16 +00:00
|
|
|
DAG_id_tag_update(&me->id, 0);
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
2011-07-18 15:05:50 +00:00
|
|
|
|
2009-01-07 19:23:22 +00:00
|
|
|
/* fills in the selected faces with the current weight and vertex group */
|
2009-10-22 12:59:14 +00:00
|
|
|
void wpaint_fill(VPaint *wp, Object *ob, float paintweight)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
|
|
|
Mesh *me;
|
|
|
|
MFace *mface;
|
|
|
|
MDeformWeight *dw, *uw;
|
|
|
|
int *indexar;
|
|
|
|
int index, vgroup;
|
|
|
|
unsigned int faceverts[5]={0,0,0,0,0};
|
|
|
|
unsigned char i;
|
|
|
|
int vgroup_mirror= -1;
|
2009-10-22 12:59:14 +00:00
|
|
|
int selected;
|
2011-07-18 17:38:17 +00:00
|
|
|
// Jason
|
|
|
|
int selectedVerts;
|
|
|
|
|
2009-01-07 19:23:22 +00:00
|
|
|
me= ob->data;
|
2011-03-05 10:29:10 +00:00
|
|
|
if(me==NULL || me->totface==0 || me->dvert==NULL || !me->mface) return;
|
2011-07-18 15:05:50 +00:00
|
|
|
|
2009-10-22 12:59:14 +00:00
|
|
|
selected= (me->editflag & ME_EDIT_PAINT_MASK);
|
2011-07-18 17:38:17 +00:00
|
|
|
// Jason
|
|
|
|
selectedVerts = (me->editflag & ME_EDIT_VERT_SEL);
|
2009-10-22 12:59:14 +00:00
|
|
|
|
2010-02-06 15:50:53 +00:00
|
|
|
indexar= get_indexarray(me);
|
|
|
|
|
2009-10-22 12:59:14 +00:00
|
|
|
if(selected) {
|
|
|
|
for(index=0, mface=me->mface; index<me->totface; index++, mface++) {
|
|
|
|
if((mface->flag & ME_FACE_SEL)==0)
|
|
|
|
indexar[index]= 0;
|
|
|
|
else
|
|
|
|
indexar[index]= index+1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for(index=0; index<me->totface; index++)
|
2009-01-07 19:23:22 +00:00
|
|
|
indexar[index]= index+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
vgroup= ob->actdef-1;
|
2011-05-26 22:20:29 +00:00
|
|
|
|
2009-01-07 19:23:22 +00:00
|
|
|
/* if mirror painting, find the other group */
|
2009-10-19 13:09:13 +00:00
|
|
|
if(me->editflag & ME_EDIT_MIRROR_X) {
|
2011-05-26 22:20:29 +00:00
|
|
|
wpaint_mirror_vgroup_ensure(ob, &vgroup_mirror);
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
copy_wpaint_prev(wp, me->dvert, me->totvert);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
for(index=0; index<me->totface; index++) {
|
|
|
|
if(indexar[index] && indexar[index]<=me->totface) {
|
|
|
|
mface= me->mface + (indexar[index]-1);
|
|
|
|
/* just so we can loop through the verts */
|
|
|
|
faceverts[0]= mface->v1;
|
|
|
|
faceverts[1]= mface->v2;
|
|
|
|
faceverts[2]= mface->v3;
|
|
|
|
faceverts[3]= mface->v4;
|
|
|
|
for (i=0; i<3 || faceverts[i]; i++) {
|
|
|
|
if(!((me->dvert+faceverts[i])->flag)) {
|
2011-07-18 17:38:17 +00:00
|
|
|
// Jason
|
2011-07-20 15:56:35 +00:00
|
|
|
if(selectedVerts && !((me->mvert+faceverts[i])->flag & SELECT)) {
|
2011-07-18 17:38:17 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-01-26 17:07:47 +00:00
|
|
|
dw= defvert_verify_index(me->dvert+faceverts[i], vgroup);
|
2009-01-07 19:23:22 +00:00
|
|
|
if(dw) {
|
2010-01-26 17:07:47 +00:00
|
|
|
uw= defvert_verify_index(wp->wpaint_prev+faceverts[i], vgroup);
|
2009-01-10 17:20:34 +00:00
|
|
|
uw->weight= dw->weight; /* set the undo weight */
|
2009-01-07 19:23:22 +00:00
|
|
|
dw->weight= paintweight;
|
|
|
|
|
2009-10-19 13:09:13 +00:00
|
|
|
if(me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */
|
2009-01-07 19:23:22 +00:00
|
|
|
int j= mesh_get_x_mirror_vert(ob, faceverts[i]);
|
|
|
|
if(j>=0) {
|
|
|
|
/* copy, not paint again */
|
|
|
|
if(vgroup_mirror != -1) {
|
2010-01-26 17:07:47 +00:00
|
|
|
dw= defvert_verify_index(me->dvert+j, vgroup_mirror);
|
|
|
|
uw= defvert_verify_index(wp->wpaint_prev+j, vgroup_mirror);
|
2009-01-07 19:23:22 +00:00
|
|
|
} else {
|
2010-01-26 17:07:47 +00:00
|
|
|
dw= defvert_verify_index(me->dvert+j, vgroup);
|
|
|
|
uw= defvert_verify_index(wp->wpaint_prev+j, vgroup);
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
uw->weight= dw->weight; /* set the undo weight */
|
|
|
|
dw->weight= paintweight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(me->dvert+faceverts[i])->flag= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
index=0;
|
|
|
|
while (index<me->totvert) {
|
|
|
|
(me->dvert+index)->flag= 0;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(indexar);
|
2009-01-10 14:19:14 +00:00
|
|
|
copy_wpaint_prev(wp, NULL, 0);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2011-01-03 12:41:16 +00:00
|
|
|
DAG_id_tag_update(&me->id, 0);
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
2010-12-03 12:30:59 +00:00
|
|
|
/* XXX: should be re-implemented as a vertex/weight paint 'color correct' operator
|
2009-11-20 01:39:27 +00:00
|
|
|
|
2009-01-07 19:23:22 +00:00
|
|
|
void vpaint_dogamma(Scene *scene)
|
|
|
|
{
|
2009-01-10 14:19:14 +00:00
|
|
|
VPaint *vp= scene->toolsettings->vpaint;
|
2009-01-07 19:23:22 +00:00
|
|
|
Mesh *me;
|
|
|
|
Object *ob;
|
|
|
|
float igam, fac;
|
|
|
|
int a, temp;
|
2009-01-26 09:13:15 +00:00
|
|
|
unsigned char *cp, gamtab[256];
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
ob= OBACT;
|
|
|
|
me= get_mesh(ob);
|
2009-08-15 20:36:15 +00:00
|
|
|
|
|
|
|
if(!(ob->mode & OB_MODE_VERTEX_PAINT)) return;
|
2009-01-07 19:23:22 +00:00
|
|
|
if(me==0 || me->mcol==0 || me->totface==0) return;
|
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
igam= 1.0/vp->gamma;
|
2009-01-07 19:23:22 +00:00
|
|
|
for(a=0; a<256; a++) {
|
|
|
|
|
|
|
|
fac= ((float)a)/255.0;
|
2009-01-10 14:19:14 +00:00
|
|
|
fac= vp->mul*pow( fac, igam);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
temp= 255.9*fac;
|
|
|
|
|
|
|
|
if(temp<=0) gamtab[a]= 0;
|
|
|
|
else if(temp>=255) gamtab[a]= 255;
|
|
|
|
else gamtab[a]= temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
a= 4*me->totface;
|
2009-01-26 09:13:15 +00:00
|
|
|
cp= (unsigned char *)me->mcol;
|
2009-01-07 19:23:22 +00:00
|
|
|
while(a--) {
|
|
|
|
|
|
|
|
cp[1]= gamtab[ cp[1] ];
|
|
|
|
cp[2]= gamtab[ cp[2] ];
|
|
|
|
cp[3]= gamtab[ cp[3] ];
|
|
|
|
|
|
|
|
cp+= 4;
|
|
|
|
}
|
|
|
|
}
|
2009-11-20 01:39:27 +00:00
|
|
|
*/
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
static unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac)
|
|
|
|
{
|
|
|
|
char *cp1, *cp2, *cp;
|
|
|
|
int mfac;
|
|
|
|
unsigned int col=0;
|
|
|
|
|
|
|
|
if(fac==0) return col1;
|
|
|
|
if(fac>=255) return col2;
|
|
|
|
|
|
|
|
mfac= 255-fac;
|
|
|
|
|
|
|
|
cp1= (char *)&col1;
|
|
|
|
cp2= (char *)&col2;
|
|
|
|
cp= (char *)&col;
|
|
|
|
|
|
|
|
cp[0]= 255;
|
|
|
|
cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
|
|
|
|
cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
|
|
|
|
cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
|
|
|
|
|
|
|
|
return col;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int mcol_add(unsigned int col1, unsigned int col2, int fac)
|
|
|
|
{
|
|
|
|
char *cp1, *cp2, *cp;
|
|
|
|
int temp;
|
|
|
|
unsigned int col=0;
|
|
|
|
|
|
|
|
if(fac==0) return col1;
|
|
|
|
|
|
|
|
cp1= (char *)&col1;
|
|
|
|
cp2= (char *)&col2;
|
|
|
|
cp= (char *)&col;
|
|
|
|
|
|
|
|
cp[0]= 255;
|
|
|
|
temp= cp1[1] + ((fac*cp2[1])/255);
|
|
|
|
if(temp>254) cp[1]= 255; else cp[1]= temp;
|
|
|
|
temp= cp1[2] + ((fac*cp2[2])/255);
|
|
|
|
if(temp>254) cp[2]= 255; else cp[2]= temp;
|
|
|
|
temp= cp1[3] + ((fac*cp2[3])/255);
|
|
|
|
if(temp>254) cp[3]= 255; else cp[3]= temp;
|
|
|
|
|
|
|
|
return col;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac)
|
|
|
|
{
|
|
|
|
char *cp1, *cp2, *cp;
|
|
|
|
int temp;
|
|
|
|
unsigned int col=0;
|
|
|
|
|
|
|
|
if(fac==0) return col1;
|
|
|
|
|
|
|
|
cp1= (char *)&col1;
|
|
|
|
cp2= (char *)&col2;
|
|
|
|
cp= (char *)&col;
|
|
|
|
|
|
|
|
cp[0]= 255;
|
|
|
|
temp= cp1[1] - ((fac*cp2[1])/255);
|
|
|
|
if(temp<0) cp[1]= 0; else cp[1]= temp;
|
|
|
|
temp= cp1[2] - ((fac*cp2[2])/255);
|
|
|
|
if(temp<0) cp[2]= 0; else cp[2]= temp;
|
|
|
|
temp= cp1[3] - ((fac*cp2[3])/255);
|
|
|
|
if(temp<0) cp[3]= 0; else cp[3]= temp;
|
|
|
|
|
|
|
|
return col;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int mcol_mul(unsigned int col1, unsigned int col2, int fac)
|
|
|
|
{
|
|
|
|
char *cp1, *cp2, *cp;
|
|
|
|
int mfac;
|
|
|
|
unsigned int col=0;
|
|
|
|
|
|
|
|
if(fac==0) return col1;
|
|
|
|
|
|
|
|
mfac= 255-fac;
|
|
|
|
|
|
|
|
cp1= (char *)&col1;
|
|
|
|
cp2= (char *)&col2;
|
|
|
|
cp= (char *)&col;
|
|
|
|
|
|
|
|
/* first mul, then blend the fac */
|
|
|
|
cp[0]= 255;
|
|
|
|
cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])/255) )/255;
|
|
|
|
cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])/255) )/255;
|
|
|
|
cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])/255) )/255;
|
|
|
|
|
|
|
|
|
|
|
|
return col;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int mcol_lighten(unsigned int col1, unsigned int col2, int fac)
|
|
|
|
{
|
|
|
|
char *cp1, *cp2, *cp;
|
|
|
|
int mfac;
|
|
|
|
unsigned int col=0;
|
|
|
|
|
|
|
|
if(fac==0) return col1;
|
|
|
|
if(fac>=255) return col2;
|
|
|
|
|
|
|
|
mfac= 255-fac;
|
|
|
|
|
|
|
|
cp1= (char *)&col1;
|
|
|
|
cp2= (char *)&col2;
|
|
|
|
cp= (char *)&col;
|
|
|
|
|
|
|
|
/* See if are lighter, if so mix, else dont do anything.
|
|
|
|
if the paint col is darker then the original, then ignore */
|
|
|
|
if (cp1[1]+cp1[2]+cp1[3] > cp2[1]+cp2[2]+cp2[3])
|
|
|
|
return col1;
|
|
|
|
|
|
|
|
cp[0]= 255;
|
|
|
|
cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
|
|
|
|
cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
|
|
|
|
cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
|
|
|
|
|
|
|
|
return col;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int mcol_darken(unsigned int col1, unsigned int col2, int fac)
|
|
|
|
{
|
|
|
|
char *cp1, *cp2, *cp;
|
|
|
|
int mfac;
|
|
|
|
unsigned int col=0;
|
|
|
|
|
|
|
|
if(fac==0) return col1;
|
|
|
|
if(fac>=255) return col2;
|
|
|
|
|
|
|
|
mfac= 255-fac;
|
|
|
|
|
|
|
|
cp1= (char *)&col1;
|
|
|
|
cp2= (char *)&col2;
|
|
|
|
cp= (char *)&col;
|
|
|
|
|
|
|
|
/* See if were darker, if so mix, else dont do anything.
|
|
|
|
if the paint col is brighter then the original, then ignore */
|
|
|
|
if (cp1[1]+cp1[2]+cp1[3] < cp2[1]+cp2[2]+cp2[3])
|
|
|
|
return col1;
|
|
|
|
|
|
|
|
cp[0]= 255;
|
|
|
|
cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
|
|
|
|
cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
|
|
|
|
cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
|
|
|
|
return col;
|
|
|
|
}
|
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
static void vpaint_blend(VPaint *vp, unsigned int *col, unsigned int *colorig, unsigned int paintcol, int alpha)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
2009-08-17 02:49:31 +00:00
|
|
|
Brush *brush = paint_brush(&vp->paint);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2010-01-20 08:30:40 +00:00
|
|
|
if(brush->vertexpaint_tool==VP_MIX || brush->vertexpaint_tool==VP_BLUR) *col= mcol_blend( *col, paintcol, alpha);
|
|
|
|
else if(brush->vertexpaint_tool==VP_ADD) *col= mcol_add( *col, paintcol, alpha);
|
|
|
|
else if(brush->vertexpaint_tool==VP_SUB) *col= mcol_sub( *col, paintcol, alpha);
|
|
|
|
else if(brush->vertexpaint_tool==VP_MUL) *col= mcol_mul( *col, paintcol, alpha);
|
|
|
|
else if(brush->vertexpaint_tool==VP_LIGHTEN) *col= mcol_lighten( *col, paintcol, alpha);
|
|
|
|
else if(brush->vertexpaint_tool==VP_DARKEN) *col= mcol_darken( *col, paintcol, alpha);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
/* if no spray, clip color adding with colorig & orig alpha */
|
2009-01-10 14:19:14 +00:00
|
|
|
if((vp->flag & VP_SPRAY)==0) {
|
2009-01-07 19:23:22 +00:00
|
|
|
unsigned int testcol=0, a;
|
|
|
|
char *cp, *ct, *co;
|
|
|
|
|
2011-03-27 14:59:55 +00:00
|
|
|
alpha= (int)(255.0f*brush_alpha(brush));
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2010-01-20 08:30:40 +00:00
|
|
|
if(brush->vertexpaint_tool==VP_MIX || brush->vertexpaint_tool==VP_BLUR) testcol= mcol_blend( *colorig, paintcol, alpha);
|
|
|
|
else if(brush->vertexpaint_tool==VP_ADD) testcol= mcol_add( *colorig, paintcol, alpha);
|
|
|
|
else if(brush->vertexpaint_tool==VP_SUB) testcol= mcol_sub( *colorig, paintcol, alpha);
|
|
|
|
else if(brush->vertexpaint_tool==VP_MUL) testcol= mcol_mul( *colorig, paintcol, alpha);
|
|
|
|
else if(brush->vertexpaint_tool==VP_LIGHTEN) testcol= mcol_lighten( *colorig, paintcol, alpha);
|
|
|
|
else if(brush->vertexpaint_tool==VP_DARKEN) testcol= mcol_darken( *colorig, paintcol, alpha);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
cp= (char *)col;
|
|
|
|
ct= (char *)&testcol;
|
|
|
|
co= (char *)colorig;
|
|
|
|
|
|
|
|
for(a=0; a<4; a++) {
|
|
|
|
if( ct[a]<co[a] ) {
|
|
|
|
if( cp[a]<ct[a] ) cp[a]= ct[a];
|
|
|
|
else if( cp[a]>co[a] ) cp[a]= co[a];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if( cp[a]<co[a] ) cp[a]= co[a];
|
|
|
|
else if( cp[a]>ct[a] ) cp[a]= ct[a];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x, int y, float size)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
|
|
|
struct ImBuf *ibuf;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
int a, tot=0, index;
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-09-14 19:49:40 +00:00
|
|
|
/* brecht: disabled this because it obviously failes for
|
|
|
|
brushes with size > 64, why is this here? */
|
|
|
|
/*if(size>64.0) size= 64.0;*/
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
ibuf= view3d_read_backbuf(vc, x-size, y-size, x+size, y+size);
|
|
|
|
if(ibuf) {
|
|
|
|
unsigned int *rt= ibuf->rect;
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2010-02-06 15:50:53 +00:00
|
|
|
memset(indexar, 0, sizeof(int)*(totface+1));
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
|
|
|
size= ibuf->x*ibuf->y;
|
|
|
|
while(size--) {
|
|
|
|
|
|
|
|
if(*rt) {
|
|
|
|
index= WM_framebuffer_to_index(*rt);
|
|
|
|
if(index>0 && index<=totface)
|
|
|
|
indexar[index] = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(a=1; a<=totface; a++) {
|
|
|
|
if(indexar[a]) indexar[tot++]= a;
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
}
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
return tot;
|
|
|
|
}
|
|
|
|
|
2011-05-20 14:11:05 +00:00
|
|
|
static float calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, float vpimat[][3], float *vert_nor, const float mval[2], float pressure)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
2009-08-17 02:49:31 +00:00
|
|
|
Brush *brush = paint_brush(&vp->paint);
|
2009-11-20 01:39:27 +00:00
|
|
|
float fac, fac_2, size, dx, dy;
|
|
|
|
float alpha;
|
2011-05-12 16:47:36 +00:00
|
|
|
int vertco[2];
|
2010-07-22 18:56:46 +00:00
|
|
|
const int radius= brush_size(brush);
|
|
|
|
|
2011-05-12 16:47:36 +00:00
|
|
|
project_int_noclip(vc->ar, vert_nor, vertco);
|
2009-11-20 01:39:27 +00:00
|
|
|
dx= mval[0]-vertco[0];
|
|
|
|
dy= mval[1]-vertco[1];
|
|
|
|
|
2010-07-22 18:56:46 +00:00
|
|
|
if (brush_use_size_pressure(brush))
|
|
|
|
size = pressure * radius;
|
2009-11-20 01:39:27 +00:00
|
|
|
else
|
2010-07-22 18:56:46 +00:00
|
|
|
size = radius;
|
2009-11-20 01:39:27 +00:00
|
|
|
|
|
|
|
fac_2= dx*dx + dy*dy;
|
|
|
|
if(fac_2 > size*size) return 0.f;
|
|
|
|
fac = sqrtf(fac_2);
|
|
|
|
|
2010-07-22 18:56:46 +00:00
|
|
|
alpha= brush_alpha(brush) * brush_curve_strength_clamp(brush, fac, size);
|
2009-11-20 01:39:27 +00:00
|
|
|
|
2010-07-22 18:56:46 +00:00
|
|
|
if (brush_use_alpha_pressure(brush))
|
2009-11-20 01:39:27 +00:00
|
|
|
alpha *= pressure;
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
if(vp->flag & VP_NORMALS) {
|
|
|
|
float *no= vert_nor+3;
|
|
|
|
|
2009-11-20 01:39:27 +00:00
|
|
|
/* transpose ! */
|
2009-01-07 19:23:22 +00:00
|
|
|
fac= vpimat[2][0]*no[0]+vpimat[2][1]*no[1]+vpimat[2][2]*no[2];
|
2011-03-27 14:59:55 +00:00
|
|
|
if(fac > 0.0f) {
|
2009-01-07 19:23:22 +00:00
|
|
|
dx= vpimat[0][0]*no[0]+vpimat[0][1]*no[1]+vpimat[0][2]*no[2];
|
|
|
|
dy= vpimat[1][0]*no[0]+vpimat[1][1]*no[1]+vpimat[1][2]*no[2];
|
|
|
|
|
2009-11-20 01:39:27 +00:00
|
|
|
alpha*= fac/sqrtf(dx*dx + dy*dy + fac*fac);
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
2009-11-20 01:39:27 +00:00
|
|
|
else return 0.f;
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return alpha;
|
|
|
|
}
|
|
|
|
|
2011-06-29 18:20:39 +00:00
|
|
|
static void wpaint_blend(VPaint *wp, MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval, int flip, int multipaint)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
2009-08-17 02:49:31 +00:00
|
|
|
Brush *brush = paint_brush(&wp->paint);
|
2010-01-20 08:30:40 +00:00
|
|
|
int tool = brush->vertexpaint_tool;
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
if(dw==NULL || uw==NULL) return;
|
|
|
|
|
2009-11-20 01:39:27 +00:00
|
|
|
if (flip) {
|
2010-01-20 08:30:40 +00:00
|
|
|
switch(tool) {
|
2009-11-20 01:39:27 +00:00
|
|
|
case VP_MIX:
|
|
|
|
paintval = 1.f - paintval; break;
|
|
|
|
case VP_ADD:
|
2010-01-20 08:30:40 +00:00
|
|
|
tool= VP_SUB; break;
|
2009-11-20 01:39:27 +00:00
|
|
|
case VP_SUB:
|
2010-01-20 08:30:40 +00:00
|
|
|
tool= VP_ADD; break;
|
2009-11-20 01:39:27 +00:00
|
|
|
case VP_LIGHTEN:
|
2010-01-20 08:30:40 +00:00
|
|
|
tool= VP_DARKEN; break;
|
2009-11-20 01:39:27 +00:00
|
|
|
case VP_DARKEN:
|
2010-01-20 08:30:40 +00:00
|
|
|
tool= VP_LIGHTEN; break;
|
2009-11-20 01:39:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-20 08:30:40 +00:00
|
|
|
if(tool==VP_MIX || tool==VP_BLUR)
|
2011-03-27 14:59:55 +00:00
|
|
|
dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
|
2010-01-20 08:30:40 +00:00
|
|
|
else if(tool==VP_ADD)
|
2009-01-07 19:23:22 +00:00
|
|
|
dw->weight += paintval*alpha;
|
2010-01-20 08:30:40 +00:00
|
|
|
else if(tool==VP_SUB)
|
2009-01-07 19:23:22 +00:00
|
|
|
dw->weight -= paintval*alpha;
|
2010-01-20 08:30:40 +00:00
|
|
|
else if(tool==VP_MUL)
|
2009-01-07 19:23:22 +00:00
|
|
|
/* first mul, then blend the fac */
|
2011-03-27 14:59:55 +00:00
|
|
|
dw->weight = ((1.0f-alpha) + alpha*paintval)*dw->weight;
|
2010-01-20 08:30:40 +00:00
|
|
|
else if(tool==VP_LIGHTEN) {
|
2009-01-07 19:23:22 +00:00
|
|
|
if (dw->weight < paintval)
|
2011-03-27 14:59:55 +00:00
|
|
|
dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
|
2010-01-20 08:30:40 +00:00
|
|
|
} else if(tool==VP_DARKEN) {
|
2009-01-07 19:23:22 +00:00
|
|
|
if (dw->weight > paintval)
|
2011-03-27 14:59:55 +00:00
|
|
|
dw->weight = paintval*alpha + dw->weight*(1.0f-alpha);
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
2011-06-21 19:20:42 +00:00
|
|
|
// Jason delay clamping until the end so multi-paint can function when the active group is at the limits
|
|
|
|
//CLAMP(dw->weight, 0.0f, 1.0f);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
/* if no spray, clip result with orig weight & orig alpha */
|
2009-01-10 14:19:14 +00:00
|
|
|
if((wp->flag & VP_SPRAY)==0) {
|
2009-01-07 19:23:22 +00:00
|
|
|
float testw=0.0f;
|
|
|
|
|
2010-07-22 18:56:46 +00:00
|
|
|
alpha= brush_alpha(brush);
|
2010-01-20 08:30:40 +00:00
|
|
|
if(tool==VP_MIX || tool==VP_BLUR)
|
2011-03-27 14:59:55 +00:00
|
|
|
testw = paintval*alpha + uw->weight*(1.0f-alpha);
|
2010-01-20 08:30:40 +00:00
|
|
|
else if(tool==VP_ADD)
|
2009-01-07 19:23:22 +00:00
|
|
|
testw = uw->weight + paintval*alpha;
|
2010-01-20 08:30:40 +00:00
|
|
|
else if(tool==VP_SUB)
|
2009-01-07 19:23:22 +00:00
|
|
|
testw = uw->weight - paintval*alpha;
|
2010-01-20 08:30:40 +00:00
|
|
|
else if(tool==VP_MUL)
|
2009-01-07 19:23:22 +00:00
|
|
|
/* first mul, then blend the fac */
|
2011-03-27 14:59:55 +00:00
|
|
|
testw = ((1.0f-alpha) + alpha*paintval)*uw->weight;
|
2010-01-20 08:30:40 +00:00
|
|
|
else if(tool==VP_LIGHTEN) {
|
2009-01-07 19:23:22 +00:00
|
|
|
if (uw->weight < paintval)
|
2011-03-27 14:59:55 +00:00
|
|
|
testw = paintval*alpha + uw->weight*(1.0f-alpha);
|
2009-01-07 19:23:22 +00:00
|
|
|
else
|
|
|
|
testw = uw->weight;
|
2010-01-20 08:30:40 +00:00
|
|
|
} else if(tool==VP_DARKEN) {
|
2009-01-07 19:23:22 +00:00
|
|
|
if (uw->weight > paintval)
|
2011-03-27 14:59:55 +00:00
|
|
|
testw = paintval*alpha + uw->weight*(1.0f-alpha);
|
2009-01-07 19:23:22 +00:00
|
|
|
else
|
|
|
|
testw = uw->weight;
|
|
|
|
}
|
2011-06-21 19:20:42 +00:00
|
|
|
//CLAMP(testw, 0.0f, 1.0f);
|
2011-06-29 18:20:39 +00:00
|
|
|
if(!multipaint) {
|
|
|
|
if( testw<uw->weight ) {
|
|
|
|
if(dw->weight < testw) dw->weight= testw;
|
|
|
|
else if(dw->weight > uw->weight) dw->weight= uw->weight;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(dw->weight > testw) dw->weight= testw;
|
|
|
|
else if(dw->weight < uw->weight) dw->weight= uw->weight;
|
|
|
|
}
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------- */
|
|
|
|
|
2011-05-25 10:07:59 +00:00
|
|
|
|
|
|
|
/* sets wp->weight to the closest weight value to vertex */
|
|
|
|
/* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
|
|
|
|
static int weight_sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
|
|
|
ViewContext vc;
|
2011-05-25 10:07:59 +00:00
|
|
|
Mesh *me;
|
|
|
|
short change= FALSE;
|
|
|
|
|
|
|
|
view3d_set_viewcontext(C, &vc);
|
|
|
|
me= get_mesh(vc.obact);
|
|
|
|
|
|
|
|
if (me && me->dvert && vc.v3d && vc.rv3d) {
|
|
|
|
int index;
|
|
|
|
|
|
|
|
view3d_operator_needs_opengl(C);
|
|
|
|
|
|
|
|
index= view3d_sample_backbuf(&vc, event->mval[0], event->mval[1]);
|
|
|
|
|
|
|
|
if(index && index<=me->totface) {
|
|
|
|
DerivedMesh *dm= mesh_get_derived_final(vc.scene, vc.obact, CD_MASK_BAREMESH);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
if(dm->getVertCo==NULL) {
|
2011-05-25 10:07:59 +00:00
|
|
|
BKE_report(op->reports, RPT_WARNING, "The modifier used does not support deformed locations");
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-05-25 10:07:59 +00:00
|
|
|
MFace *mf= ((MFace *)me->mface) + index-1;
|
|
|
|
const int vgroup= vc.obact->actdef - 1;
|
|
|
|
ToolSettings *ts= vc.scene->toolsettings;
|
|
|
|
float mval_f[2];
|
|
|
|
int v_idx_best= -1;
|
|
|
|
int fidx;
|
|
|
|
float len_best= FLT_MAX;
|
|
|
|
|
|
|
|
mval_f[0]= (float)event->mval[0];
|
|
|
|
mval_f[1]= (float)event->mval[1];
|
|
|
|
|
|
|
|
fidx= mf->v4 ? 3:2;
|
|
|
|
do {
|
|
|
|
float co[3], sco[3], len;
|
|
|
|
const int v_idx= (*(&mf->v1 + fidx));
|
|
|
|
dm->getVertCo(dm, v_idx, co);
|
|
|
|
project_float_noclip(vc.ar, co, sco);
|
|
|
|
len= len_squared_v2v2(mval_f, sco);
|
|
|
|
if(len < len_best) {
|
|
|
|
len_best= len;
|
|
|
|
v_idx_best= v_idx;
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
2011-05-25 10:07:59 +00:00
|
|
|
} while (fidx--);
|
|
|
|
|
|
|
|
if(v_idx_best != -1) { /* should always be valid */
|
|
|
|
ts->vgroup_weight= defvert_find_weight(&me->dvert[v_idx_best], vgroup);
|
|
|
|
change= TRUE;
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
dm->release(dm);
|
2011-05-25 10:07:59 +00:00
|
|
|
}
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
2011-05-25 10:07:59 +00:00
|
|
|
|
|
|
|
if(change) {
|
|
|
|
/* not really correct since the brush didnt change, but redraws the toolbar */
|
|
|
|
WM_main_add_notifier(NC_BRUSH|NA_EDITED, NULL); /* ts->wpaint->paint.brush */
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PAINT_OT_weight_sample(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Weight Paint Sample Weight";
|
|
|
|
ot->idname= "PAINT_OT_weight_sample";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= weight_sample_invoke;
|
|
|
|
ot->poll= weight_paint_mode_poll;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_UNDO;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* samples cursor location, and gives menu with vertex groups to activate */
|
2011-05-26 13:38:16 +00:00
|
|
|
static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
|
2011-05-25 10:07:59 +00:00
|
|
|
{
|
|
|
|
if (C) {
|
|
|
|
wmWindow *win= CTX_wm_window(C);
|
|
|
|
if(win && win->eventstate) {
|
|
|
|
ViewContext vc;
|
|
|
|
Mesh *me;
|
|
|
|
|
|
|
|
view3d_set_viewcontext(C, &vc);
|
|
|
|
me= get_mesh(vc.obact);
|
|
|
|
|
|
|
|
if (me && me->dvert && vc.v3d && vc.rv3d) {
|
|
|
|
int index;
|
|
|
|
|
|
|
|
view3d_operator_needs_opengl(C);
|
|
|
|
|
|
|
|
index= view3d_sample_backbuf(&vc, win->eventstate->x - vc.ar->winrct.xmin, win->eventstate->y - vc.ar->winrct.ymin);
|
|
|
|
|
|
|
|
if(index && index<=me->totface) {
|
|
|
|
const int totgroup= BLI_countlist(&vc.obact->defbase);
|
|
|
|
if(totgroup) {
|
|
|
|
MFace *mf= ((MFace *)me->mface) + index-1;
|
|
|
|
int fidx= mf->v4 ? 3:2;
|
|
|
|
int *groups= MEM_callocN(totgroup*sizeof(int), "groups");
|
|
|
|
int found= FALSE;
|
|
|
|
|
|
|
|
do {
|
|
|
|
MDeformVert *dvert= me->dvert + (*(&mf->v1 + fidx));
|
|
|
|
int i= dvert->totweight;
|
|
|
|
MDeformWeight *dw;
|
|
|
|
for(dw= dvert->dw; i > 0; dw++, i--) {
|
|
|
|
groups[dw->def_nr]= TRUE;
|
|
|
|
found= TRUE;
|
|
|
|
}
|
|
|
|
} while (fidx--);
|
|
|
|
|
|
|
|
if(found==FALSE) {
|
|
|
|
MEM_freeN(groups);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
EnumPropertyItem *item= NULL, item_tmp= {0};
|
|
|
|
int totitem= 0;
|
2011-05-26 05:40:00 +00:00
|
|
|
int i= 0;
|
2011-05-25 10:07:59 +00:00
|
|
|
bDeformGroup *dg;
|
2011-05-26 05:40:00 +00:00
|
|
|
for(dg= vc.obact->defbase.first; dg && i<totgroup; i++, dg= dg->next) {
|
|
|
|
if(groups[i]) {
|
2011-05-25 10:07:59 +00:00
|
|
|
item_tmp.identifier= item_tmp.name= dg->name;
|
2011-05-26 05:40:00 +00:00
|
|
|
item_tmp.value= i;
|
2011-05-25 10:07:59 +00:00
|
|
|
RNA_enum_item_add(&item, &totitem, &item_tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RNA_enum_item_end(&item, &totitem);
|
|
|
|
*free= 1;
|
|
|
|
|
|
|
|
MEM_freeN(groups);
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return DummyRNA_NULL_items;
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
2011-05-25 10:07:59 +00:00
|
|
|
static int weight_sample_group_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
int type= RNA_enum_get(op->ptr, "group");
|
|
|
|
ViewContext vc;
|
|
|
|
view3d_set_viewcontext(C, &vc);
|
|
|
|
|
|
|
|
vc.obact->actdef= type + 1;
|
|
|
|
|
|
|
|
DAG_id_tag_update(&vc.obact->id, OB_RECALC_DATA);
|
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, vc.obact);
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2011-05-28 13:11:24 +00:00
|
|
|
/* TODO, we could make this a menu into OBJECT_OT_vertex_group_set_active rather than its own operator */
|
2011-05-25 10:07:59 +00:00
|
|
|
void PAINT_OT_weight_sample_group(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop= NULL;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Weight Paint Sample Group";
|
|
|
|
ot->idname= "PAINT_OT_weight_sample_group";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->exec= weight_sample_group_exec;
|
|
|
|
ot->invoke= WM_menu_invoke;
|
|
|
|
ot->poll= weight_paint_mode_poll;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_UNDO;
|
|
|
|
|
|
|
|
/* keyingset to use (dynamic enum) */
|
|
|
|
prop= RNA_def_enum(ot->srna, "group", DummyRNA_DEFAULT_items, 0, "Keying Set", "The Keying Set to use");
|
|
|
|
RNA_def_enum_funcs(prop, weight_paint_sample_enum_itemf);
|
|
|
|
ot->prop= prop;
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
2011-05-25 10:07:59 +00:00
|
|
|
|
2011-09-14 05:25:43 +00:00
|
|
|
#if 0 /* UNUSED */
|
2009-10-30 02:09:52 +00:00
|
|
|
static void do_weight_paint_auto_normalize(MDeformVert *dvert,
|
|
|
|
int paint_nr, char *map)
|
|
|
|
{
|
2009-11-02 17:25:15 +00:00
|
|
|
// MDeformWeight *dw = dvert->dw;
|
2009-10-30 02:09:52 +00:00
|
|
|
float sum=0.0f, fac=0.0f, paintw=0.0f;
|
|
|
|
int i, tot=0;
|
|
|
|
|
|
|
|
if (!map)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i=0; i<dvert->totweight; i++) {
|
|
|
|
if (dvert->dw[i].def_nr == paint_nr)
|
|
|
|
paintw = dvert->dw[i].weight;
|
|
|
|
|
|
|
|
if (map[dvert->dw[i].def_nr]) {
|
|
|
|
tot += 1;
|
|
|
|
if (dvert->dw[i].def_nr != paint_nr)
|
|
|
|
sum += dvert->dw[i].weight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!tot || sum <= (1.0f - paintw))
|
|
|
|
return;
|
|
|
|
|
|
|
|
fac = sum / (1.0f - paintw);
|
|
|
|
fac = fac==0.0f ? 1.0f : 1.0f / fac;
|
|
|
|
|
|
|
|
for (i=0; i<dvert->totweight; i++) {
|
|
|
|
if (map[dvert->dw[i].def_nr]) {
|
|
|
|
if (dvert->dw[i].def_nr != paint_nr)
|
|
|
|
dvert->dw[i].weight *= fac;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-09-14 05:25:43 +00:00
|
|
|
#endif
|
|
|
|
|
2011-06-07 17:59:38 +00:00
|
|
|
// Jason was here: the active group should be involved in auto normalize
|
2011-06-16 19:05:05 +00:00
|
|
|
static void do_weight_paint_auto_normalize_all_groups(MDeformVert *dvert, char *map)
|
2011-06-07 17:59:38 +00:00
|
|
|
{
|
|
|
|
// MDeformWeight *dw = dvert->dw;
|
|
|
|
float sum=0.0f, fac=0.0f;
|
|
|
|
int i, tot=0;
|
|
|
|
|
|
|
|
if (!map)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i=0; i<dvert->totweight; i++) {
|
|
|
|
if (map[dvert->dw[i].def_nr]) {
|
|
|
|
tot += 1;
|
|
|
|
sum += dvert->dw[i].weight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!tot || sum == 1.0f)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fac = sum;
|
|
|
|
fac = fac==0.0f ? 1.0f : 1.0f / fac;
|
|
|
|
|
|
|
|
for (i=0; i<dvert->totweight; i++) {
|
|
|
|
if (map[dvert->dw[i].def_nr]) {
|
|
|
|
dvert->dw[i].weight *= fac;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-01 15:45:09 +00:00
|
|
|
/* Jason was here */
|
|
|
|
/*
|
2011-06-07 17:59:38 +00:00
|
|
|
See if the current deform vertex has a locked group
|
2011-06-01 15:45:09 +00:00
|
|
|
*/
|
|
|
|
static char has_locked_group(MDeformVert *dvert, char *flags)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < dvert->totweight; i++) {
|
2011-06-01 17:04:32 +00:00
|
|
|
if(flags[(dvert->dw+i)->def_nr] && (dvert->dw+i)->weight > 0.0f) {
|
2011-06-01 15:45:09 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-09-14 05:25:43 +00:00
|
|
|
/* Jason was here
|
|
|
|
* gen_lck_flags gets the status of "flag" for each bDeformGroup
|
|
|
|
*in ob->defbase and returns an array containing them
|
|
|
|
*/
|
2011-09-14 05:56:25 +00:00
|
|
|
static char *gen_lck_flags(Object* ob, int defbase_len)
|
2011-05-27 19:13:54 +00:00
|
|
|
{
|
2011-06-01 15:45:09 +00:00
|
|
|
char is_locked = FALSE;
|
|
|
|
int i;
|
2011-09-14 05:56:25 +00:00
|
|
|
//int defbase_len = BLI_countlist(&ob->defbase);
|
|
|
|
char *flags = MEM_mallocN(defbase_len*sizeof(char), "defflags");
|
2011-06-07 17:59:38 +00:00
|
|
|
bDeformGroup *defgroup;
|
|
|
|
|
2011-09-14 05:56:25 +00:00
|
|
|
for(i = 0, defgroup = ob->defbase.first; i < defbase_len && defgroup; defgroup = defgroup->next, i++) {
|
2011-06-08 19:05:17 +00:00
|
|
|
flags[i] = defgroup->flag;
|
|
|
|
if(flags[i]) {
|
|
|
|
is_locked = TRUE;
|
2011-05-27 19:13:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(is_locked){
|
|
|
|
return flags;
|
|
|
|
}
|
2011-06-07 17:59:38 +00:00
|
|
|
// don't forget to free it if it is unneeded
|
2011-06-01 15:45:09 +00:00
|
|
|
MEM_freeN(flags);
|
2011-05-27 19:13:54 +00:00
|
|
|
return NULL;
|
2011-06-01 15:45:09 +00:00
|
|
|
}
|
|
|
|
/* Jason was here */
|
2011-09-14 05:56:25 +00:00
|
|
|
static int has_locked_group_selected(int defbase_len, char *defbase_sel, char *flags) {
|
2011-06-14 19:11:01 +00:00
|
|
|
int i;
|
2011-09-14 05:56:25 +00:00
|
|
|
for(i = 0; i < defbase_len; i++) {
|
|
|
|
if(defbase_sel[i] && flags[i]) {
|
2011-06-14 19:11:01 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-06-16 19:05:05 +00:00
|
|
|
|
2011-06-14 19:11:01 +00:00
|
|
|
/* Jason was here */
|
2011-09-14 05:25:43 +00:00
|
|
|
#if 0 /* UNUSED */
|
2011-09-14 05:56:25 +00:00
|
|
|
static int has_unselected_unlocked_bone_group(int defbase_len, char *defbase_sel, int selected, char *flags, char *bone_groups) {
|
2011-06-14 19:11:01 +00:00
|
|
|
int i;
|
2011-09-14 05:56:25 +00:00
|
|
|
if(defbase_len == selected) {
|
2011-06-14 19:11:01 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2011-09-14 05:56:25 +00:00
|
|
|
for(i = 0; i < defbase_len; i++) {
|
|
|
|
if(bone_groups[i] && !defbase_sel[i] && !flags[i]) {
|
2011-06-14 19:11:01 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-09-14 05:25:43 +00:00
|
|
|
#endif
|
2011-06-16 19:05:05 +00:00
|
|
|
|
|
|
|
/*Jason*/
|
2011-09-14 05:56:25 +00:00
|
|
|
static void multipaint_selection(MDeformVert *dvert, float change, char *defbase_sel, int defbase_len) {
|
2011-06-01 15:45:09 +00:00
|
|
|
int i;
|
|
|
|
MDeformWeight *dw;
|
2011-06-21 19:20:42 +00:00
|
|
|
float val;
|
2011-06-16 19:05:05 +00:00
|
|
|
// make sure they are all at most 1 after the change
|
2011-09-14 05:56:25 +00:00
|
|
|
for(i = 0; i < defbase_len; i++) {
|
|
|
|
if(defbase_sel[i]) {
|
2011-06-16 19:05:05 +00:00
|
|
|
dw = defvert_find_index(dvert, i);
|
|
|
|
if(dw && dw->weight) {
|
2011-06-21 19:20:42 +00:00
|
|
|
val = dw->weight * change;
|
|
|
|
if(val > 1) {
|
2011-07-05 18:03:31 +00:00
|
|
|
// Jason TODO: when the change is reduced, you need to recheck the earlier values to make sure they are not 0 (precision error)
|
2011-06-16 19:05:05 +00:00
|
|
|
change = 1.0f/dw->weight;
|
|
|
|
}
|
2011-07-07 17:59:15 +00:00
|
|
|
// the value should never reach zero while multi-painting if it was nonzero beforehand
|
2011-06-29 18:20:39 +00:00
|
|
|
if(val <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
2011-06-16 19:05:05 +00:00
|
|
|
}
|
2011-06-01 15:45:09 +00:00
|
|
|
}
|
|
|
|
}
|
2011-07-07 17:59:15 +00:00
|
|
|
// apply the valid change
|
2011-09-14 05:56:25 +00:00
|
|
|
for(i = 0; i < defbase_len; i++) {
|
|
|
|
if(defbase_sel[i]) {
|
2011-06-16 19:05:05 +00:00
|
|
|
dw = defvert_find_index(dvert, i);
|
|
|
|
if(dw && dw->weight) {
|
|
|
|
dw->weight = dw->weight * change;
|
|
|
|
}
|
2011-06-07 17:59:38 +00:00
|
|
|
}
|
2011-06-16 19:05:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/*Jason*/
|
2011-07-07 17:59:15 +00:00
|
|
|
// move all change onto valid, unchanged groups. If there is change left over, then return it.
|
|
|
|
// assumes there are valid groups to shift weight onto
|
2011-06-16 19:05:05 +00:00
|
|
|
static float redistribute_change(MDeformVert *ndv, char *change_status, int changeme, int changeto, char *validmap, float totchange, float total_valid) {
|
|
|
|
float was_change;
|
|
|
|
float change;
|
|
|
|
float oldval;
|
|
|
|
MDeformWeight *ndw;
|
|
|
|
int i;
|
|
|
|
do {
|
2011-07-07 17:59:15 +00:00
|
|
|
// assume there is no change until you see one
|
2011-06-16 19:05:05 +00:00
|
|
|
was_change = FALSE;
|
2011-07-07 17:59:15 +00:00
|
|
|
// change each group by the same amount each time
|
2011-06-16 19:05:05 +00:00
|
|
|
change = totchange/total_valid;
|
|
|
|
for(i = 0; i < ndv->totweight && total_valid && totchange; i++) {
|
|
|
|
ndw = (ndv->dw+i);
|
2011-07-07 17:59:15 +00:00
|
|
|
// change only the groups with a valid status
|
2011-06-16 19:05:05 +00:00
|
|
|
if(change_status[ndw->def_nr] == changeme) {
|
|
|
|
oldval = ndw->weight;
|
2011-07-07 17:59:15 +00:00
|
|
|
// if auto normalize is active, don't worry about upper bounds
|
2011-06-16 19:05:05 +00:00
|
|
|
if(!validmap && ndw->weight + change > 1) {
|
|
|
|
totchange -= 1-ndw->weight;
|
|
|
|
ndw->weight = 1;
|
2011-07-07 17:59:15 +00:00
|
|
|
// stop the changes to this group
|
2011-06-16 19:05:05 +00:00
|
|
|
change_status[ndw->def_nr] = changeto;
|
|
|
|
total_valid--;
|
2011-07-07 17:59:15 +00:00
|
|
|
} else if(ndw->weight + change < 0) { // check the lower bound
|
2011-06-16 19:05:05 +00:00
|
|
|
totchange -= ndw->weight;
|
|
|
|
ndw->weight = 0;
|
|
|
|
change_status[ndw->def_nr] = changeto;
|
|
|
|
total_valid--;
|
2011-07-07 17:59:15 +00:00
|
|
|
} else {// a perfectly valid change occurred to ndw->weight
|
2011-06-16 19:05:05 +00:00
|
|
|
totchange -= change;
|
|
|
|
ndw->weight += change;
|
2011-06-07 17:59:38 +00:00
|
|
|
}
|
2011-07-07 17:59:15 +00:00
|
|
|
// see if there was a change
|
2011-06-16 19:05:05 +00:00
|
|
|
if(oldval != ndw->weight) {
|
|
|
|
was_change = TRUE;
|
2011-06-14 19:11:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-07-07 17:59:15 +00:00
|
|
|
// don't go again if there was no change, if there is no valid group, or there is no change left
|
2011-06-16 19:05:05 +00:00
|
|
|
}while(was_change && total_valid && totchange);
|
2011-07-07 17:59:15 +00:00
|
|
|
// left overs
|
2011-06-16 19:05:05 +00:00
|
|
|
return totchange;
|
2011-05-27 19:13:54 +00:00
|
|
|
}
|
2011-06-16 19:05:05 +00:00
|
|
|
/*Jason*/
|
2011-07-07 17:59:15 +00:00
|
|
|
// observe the changes made to the weights of groups.
|
|
|
|
// make sure all locked groups on the vertex have the same deformation
|
|
|
|
// by moving the changes made to groups onto other unlocked groups
|
2011-09-14 05:56:25 +00:00
|
|
|
static void enforce_locks(MDeformVert *odv, MDeformVert *ndv, int defbase_len, char *flags, char *bone_groups, char *validmap) {
|
2011-06-16 19:05:05 +00:00
|
|
|
float totchange = 0.0f;
|
|
|
|
float totchange_allowed = 0.0f;
|
|
|
|
float left_over;
|
2011-07-18 17:38:17 +00:00
|
|
|
|
2011-06-16 19:05:05 +00:00
|
|
|
int total_valid = 0;
|
|
|
|
int total_changed = 0;
|
|
|
|
int i;
|
|
|
|
MDeformWeight *ndw;
|
|
|
|
MDeformWeight *odw;
|
|
|
|
MDeformWeight *ndw2;
|
|
|
|
MDeformWeight *odw2;
|
|
|
|
int designatedw = -1;
|
|
|
|
int designatedw_changed = FALSE;
|
|
|
|
float storedw;
|
|
|
|
char *change_status;
|
|
|
|
char new_weight_has_zero = FALSE;
|
|
|
|
|
|
|
|
if(!flags || !has_locked_group(ndv, flags)) {
|
|
|
|
return;
|
2011-06-08 19:05:17 +00:00
|
|
|
}
|
2011-07-07 17:59:15 +00:00
|
|
|
// record if a group was changed, unlocked and not changed, or locked
|
2011-09-14 05:56:25 +00:00
|
|
|
change_status = MEM_callocN(sizeof(char)*defbase_len, "unlocked_unchanged");
|
2011-06-16 19:05:05 +00:00
|
|
|
|
2011-09-14 05:56:25 +00:00
|
|
|
for(i = 0; i < defbase_len; i++) {
|
2011-06-16 19:05:05 +00:00
|
|
|
ndw = defvert_find_index(ndv, i);
|
|
|
|
odw = defvert_find_index(odv, i);
|
2011-07-07 17:59:15 +00:00
|
|
|
// the weights are zero, so we can assume a lot
|
2011-06-16 19:05:05 +00:00
|
|
|
if(!ndw || !odw) {
|
|
|
|
if (!flags[i] && bone_groups[i]){
|
|
|
|
defvert_verify_index(odv, i);
|
|
|
|
defvert_verify_index(ndv, i);
|
|
|
|
total_valid++;
|
|
|
|
change_status[i] = 1; // can be altered while redistributing
|
2011-06-08 19:05:17 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2011-07-07 17:59:15 +00:00
|
|
|
// locked groups should not be changed
|
2011-06-16 19:05:05 +00:00
|
|
|
if(flags[i]) {
|
|
|
|
ndw->weight = odw->weight;
|
2011-07-07 17:59:15 +00:00
|
|
|
} else if(ndw->weight != odw->weight) { // changed groups are handled here
|
2011-06-16 19:05:05 +00:00
|
|
|
totchange += ndw->weight-odw->weight;
|
|
|
|
change_status[i] = 2; // was altered already
|
|
|
|
total_changed++;
|
|
|
|
if(ndw->weight == 0) {
|
|
|
|
new_weight_has_zero = TRUE;
|
2011-07-11 17:27:37 +00:00
|
|
|
} else if(designatedw == -1){
|
2011-06-16 19:05:05 +00:00
|
|
|
designatedw = i;
|
|
|
|
}
|
2011-07-07 17:59:15 +00:00
|
|
|
} // unchanged, unlocked bone groups are handled here
|
|
|
|
else if (bone_groups[i]){
|
2011-06-16 19:05:05 +00:00
|
|
|
totchange_allowed += ndw->weight;
|
|
|
|
total_valid++;
|
|
|
|
change_status[i] = 1; // can be altered while redistributing
|
2011-06-10 19:47:53 +00:00
|
|
|
}
|
|
|
|
}
|
2011-07-07 17:59:15 +00:00
|
|
|
// if there was any change, redistribute it
|
2011-06-16 19:05:05 +00:00
|
|
|
if(total_changed) {
|
2011-06-21 19:20:42 +00:00
|
|
|
// auto normalize will allow weights to temporarily go above 1 in redistribution
|
|
|
|
if(validmap && total_changed < 0 && total_valid) {
|
|
|
|
totchange_allowed = total_valid;
|
|
|
|
}
|
2011-07-07 17:59:15 +00:00
|
|
|
// there needs to be change allowed, or you should not bother
|
2011-06-16 19:05:05 +00:00
|
|
|
if(totchange_allowed) {
|
2011-07-07 17:59:15 +00:00
|
|
|
// the way you modify the unlocked+unchanged groups is different depending
|
|
|
|
// on whether or not you are painting the weight(s) up or down
|
2011-06-16 19:05:05 +00:00
|
|
|
if(totchange < 0) {
|
|
|
|
totchange_allowed = total_valid - totchange_allowed;
|
|
|
|
} else {
|
|
|
|
totchange_allowed *= -1;
|
|
|
|
}
|
|
|
|
left_over = 0;
|
|
|
|
if(fabs(totchange_allowed) < fabs(totchange)) {
|
2011-07-07 17:59:15 +00:00
|
|
|
// this amount goes back onto the changed, unlocked weights
|
2011-06-16 19:05:05 +00:00
|
|
|
left_over = fabs(fabs(totchange)-fabs(totchange_allowed));
|
|
|
|
if(totchange > 0) {
|
|
|
|
left_over *= -1;
|
|
|
|
}
|
|
|
|
}else {
|
2011-07-07 17:59:15 +00:00
|
|
|
// all of the change will be permitted
|
2011-06-16 19:05:05 +00:00
|
|
|
totchange_allowed = -totchange;
|
|
|
|
}
|
|
|
|
// move the weight evenly between the allowed groups, move excess back onto the used groups based on the change
|
|
|
|
totchange_allowed = redistribute_change(ndv, change_status, 1, -1, validmap, totchange_allowed, total_valid);
|
|
|
|
left_over += totchange_allowed;
|
|
|
|
if(left_over) {
|
|
|
|
// more than one nonzero weights were changed with the same ratio, so keep them changed that way!
|
2011-07-11 17:27:37 +00:00
|
|
|
if(total_changed > 1 && !new_weight_has_zero && designatedw >= 0) {
|
2011-07-07 17:59:15 +00:00
|
|
|
// this dw is special, it is used as a base to determine how to change the others
|
2011-06-16 19:05:05 +00:00
|
|
|
ndw = defvert_find_index(ndv, designatedw);
|
|
|
|
odw = defvert_find_index(odv, designatedw);
|
|
|
|
storedw = ndw->weight;
|
|
|
|
for(i = 0; i < ndv->totweight; i++) {
|
|
|
|
if(change_status[ndw->def_nr] == 2) {
|
|
|
|
odw2 = (odv->dw+i);
|
|
|
|
ndw2 = (ndv->dw+i);
|
|
|
|
if(!designatedw_changed) {
|
|
|
|
ndw->weight = (totchange_allowed + odw->weight + odw2->weight)/(1 + ndw2->weight/ndw->weight);
|
|
|
|
designatedw_changed = TRUE;
|
|
|
|
}
|
|
|
|
ndw2->weight = ndw->weight*ndw2->weight/storedw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-07-11 17:27:37 +00:00
|
|
|
// a weight was changed to zero, only one weight was changed, or designatedw is still -1
|
2011-06-16 19:05:05 +00:00
|
|
|
// put weight back as evenly as possible
|
|
|
|
else {
|
|
|
|
redistribute_change(ndv, change_status, 2, -2, validmap, left_over, total_changed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// reset the weights
|
|
|
|
for(i = 0; i < ndv->totweight; i++) {
|
|
|
|
(ndv->dw+i)->weight = (odv->dw+i)->weight;
|
2011-06-14 19:11:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-16 19:05:05 +00:00
|
|
|
|
|
|
|
MEM_freeN(change_status);
|
2011-06-10 19:47:53 +00:00
|
|
|
}
|
2011-06-16 19:05:05 +00:00
|
|
|
/*Jason*/
|
2011-07-07 17:59:15 +00:00
|
|
|
// multi-paint's initial, potential change is computed here based on the user's stroke
|
2011-09-14 05:56:25 +00:00
|
|
|
static float get_mp_change(MDeformVert *odv, char *defbase_sel, float brush_change) {
|
2011-06-29 18:20:39 +00:00
|
|
|
float selwsum = 0.0f;
|
|
|
|
int i;
|
|
|
|
MDeformWeight *dw;
|
|
|
|
for(i=0; i < odv->totweight; i++) {
|
2011-09-14 05:56:25 +00:00
|
|
|
if(defbase_sel[(dw = (odv->dw+i))->def_nr]) {
|
2011-06-29 18:20:39 +00:00
|
|
|
selwsum += dw->weight;
|
|
|
|
}
|
2011-06-16 19:05:05 +00:00
|
|
|
}
|
2011-06-29 18:20:39 +00:00
|
|
|
if(selwsum && selwsum+brush_change > 0) {
|
|
|
|
return (selwsum+brush_change)/selwsum;
|
|
|
|
}
|
|
|
|
return 0.0f;
|
2011-06-21 19:20:42 +00:00
|
|
|
}
|
|
|
|
/*Jason*/
|
2011-07-07 17:59:15 +00:00
|
|
|
// change the weights back to the wv's weights
|
|
|
|
// it assumes you already have the correct pointer index
|
2011-06-29 18:20:39 +00:00
|
|
|
static void reset_to_prev(MDeformVert *wv, MDeformVert *dv) {
|
2011-06-21 19:20:42 +00:00
|
|
|
int i;
|
|
|
|
MDeformWeight *d;
|
|
|
|
MDeformWeight *w;
|
|
|
|
for(i = 0; i < dv->totweight; i++) {
|
|
|
|
d = dv->dw+i;
|
|
|
|
w = defvert_find_index(wv, d->def_nr);
|
2011-07-07 17:59:15 +00:00
|
|
|
// if there was no w when there is a d, then the old weight was 0
|
2011-06-21 19:20:42 +00:00
|
|
|
if(w) {
|
|
|
|
d->weight = w->weight;
|
|
|
|
} else {
|
|
|
|
d->weight = 0;
|
2011-06-08 19:05:17 +00:00
|
|
|
}
|
|
|
|
}
|
2011-06-29 18:20:39 +00:00
|
|
|
}
|
2011-06-21 19:20:42 +00:00
|
|
|
/* Jason */
|
|
|
|
static void clamp_weights(MDeformVert *dvert) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < dvert->totweight; i++) {
|
|
|
|
CLAMP((dvert->dw+i)->weight, 0.0f, 1.0f);
|
|
|
|
}
|
2011-06-08 19:05:17 +00:00
|
|
|
}
|
2011-06-16 19:05:05 +00:00
|
|
|
/*Jason*/
|
|
|
|
/* fresh start to make multi-paint and locking modular */
|
2011-08-12 15:42:16 +00:00
|
|
|
/* returns TRUE if it thinks you need to reset the weights due to normalizing while multi-painting */
|
2011-09-14 05:56:25 +00:00
|
|
|
static int apply_mp_lcks_normalize(Mesh *me, int index, MDeformWeight *dw, MDeformWeight *tdw, int defbase_len, float change, float oldChange, float oldw, float neww, char *defbase_sel, int selected, char *bone_groups, char *validmap, char *flags, int multipaint) {
|
2011-06-16 19:05:05 +00:00
|
|
|
MDeformVert *dvert = me->dvert+index;
|
2011-09-14 05:25:43 +00:00
|
|
|
MDeformVert dv= {NULL};
|
2011-07-07 17:59:15 +00:00
|
|
|
|
2011-09-14 05:25:43 +00:00
|
|
|
dv.dw= MEM_dupallocN(dvert->dw);
|
|
|
|
dv.flag = dvert->flag;
|
|
|
|
dv.totweight = dvert->totweight;
|
2011-07-07 17:59:15 +00:00
|
|
|
// do not multi-paint if a locked group is selected or the active group is locked
|
|
|
|
// !flags[dw->def_nr] helps if nothing is selected, but active group is locked
|
2011-09-14 05:56:25 +00:00
|
|
|
if((flags == NULL) || (has_locked_group_selected(defbase_len, defbase_sel, flags) == FALSE && flags[dw->def_nr] == FALSE)) {
|
2011-06-29 18:20:39 +00:00
|
|
|
if(multipaint && selected > 1) {
|
|
|
|
if(change && change!=1) {
|
2011-09-14 05:56:25 +00:00
|
|
|
multipaint_selection(dvert, change, defbase_sel, defbase_len);
|
2011-06-29 18:20:39 +00:00
|
|
|
}
|
2011-07-07 17:59:15 +00:00
|
|
|
} else {// this lets users paint normally, but don't let them paint locked groups
|
2011-06-14 19:11:01 +00:00
|
|
|
dw->weight = neww;
|
2011-06-08 19:05:17 +00:00
|
|
|
}
|
|
|
|
}
|
2011-07-21 16:25:07 +00:00
|
|
|
clamp_weights(dvert);
|
2011-06-21 19:20:42 +00:00
|
|
|
|
2011-09-14 05:56:25 +00:00
|
|
|
enforce_locks(&dv, dvert, defbase_len, flags, bone_groups, validmap);
|
2011-06-16 19:05:05 +00:00
|
|
|
|
|
|
|
do_weight_paint_auto_normalize_all_groups(dvert, validmap);
|
2011-07-21 16:25:07 +00:00
|
|
|
|
|
|
|
if(oldChange && multipaint && selected > 1) {
|
|
|
|
if(tdw->weight != oldw) {
|
|
|
|
if( neww > oldw ) {
|
2011-08-12 15:42:16 +00:00
|
|
|
if(tdw->weight <= oldw) {
|
2011-09-14 05:25:43 +00:00
|
|
|
MEM_freeN(dv.dw);
|
2011-07-21 16:25:07 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
} else {
|
2011-08-12 15:42:16 +00:00
|
|
|
if(tdw->weight >= oldw) {
|
2011-09-14 05:25:43 +00:00
|
|
|
MEM_freeN(dv.dw);
|
2011-07-21 16:25:07 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-09-14 05:25:43 +00:00
|
|
|
MEM_freeN(dv.dw);
|
2011-07-21 16:25:07 +00:00
|
|
|
return FALSE;
|
2011-06-08 19:05:17 +00:00
|
|
|
}
|
2011-06-16 19:05:05 +00:00
|
|
|
|
2011-07-07 17:59:15 +00:00
|
|
|
// within the current dvert index, get the dw that is selected and has a weight above 0
|
|
|
|
// this helps multi-paint
|
2011-09-14 05:56:25 +00:00
|
|
|
static int get_first_selected_nonzero_weight(MDeformVert *dvert, char *defbase_sel) {
|
2011-06-29 18:20:39 +00:00
|
|
|
int i;
|
|
|
|
MDeformWeight *dw;
|
|
|
|
for(i=0; i< dvert->totweight; i++) {
|
|
|
|
dw = dvert->dw+i;
|
2011-09-14 05:56:25 +00:00
|
|
|
if(defbase_sel[dw->def_nr] && dw->weight > 0) {
|
2011-06-29 18:20:39 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2011-06-01 17:04:32 +00:00
|
|
|
// Jason
|
|
|
|
static char *wpaint_make_validmap(Object *ob);
|
|
|
|
|
2009-10-30 02:09:52 +00:00
|
|
|
static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index,
|
2009-11-20 01:39:27 +00:00
|
|
|
float alpha, float paintweight, int flip,
|
2011-06-08 19:05:17 +00:00
|
|
|
int vgroup_mirror, char *validmap, int multipaint)
|
2009-01-07 19:23:22 +00:00
|
|
|
{
|
|
|
|
Mesh *me= ob->data;
|
2011-07-21 16:25:07 +00:00
|
|
|
// Jason: tdw, tuw
|
|
|
|
MDeformWeight *dw, *uw, *tdw = NULL, *tuw;
|
2009-01-07 19:23:22 +00:00
|
|
|
int vgroup= ob->actdef-1;
|
2011-06-07 17:59:38 +00:00
|
|
|
|
2011-05-27 19:13:54 +00:00
|
|
|
/* Jason was here */
|
2011-06-08 19:05:17 +00:00
|
|
|
char *flags;
|
|
|
|
char *bone_groups;
|
2011-09-14 05:56:25 +00:00
|
|
|
char *defbase_sel;
|
2011-06-10 19:47:53 +00:00
|
|
|
int selected;
|
2011-05-27 19:13:54 +00:00
|
|
|
float oldw;
|
2011-06-21 19:20:42 +00:00
|
|
|
float neww;
|
2011-07-21 16:25:07 +00:00
|
|
|
float testw=0;
|
2011-09-14 05:56:25 +00:00
|
|
|
int defbase_len;
|
2011-06-29 18:20:39 +00:00
|
|
|
float change = 0;
|
2011-07-21 16:25:07 +00:00
|
|
|
float oldChange = 0;
|
2011-06-21 19:20:42 +00:00
|
|
|
int i;
|
2011-07-21 16:25:07 +00:00
|
|
|
MDeformVert *dv = NULL;
|
|
|
|
|
2011-07-07 17:59:15 +00:00
|
|
|
// Need to know which groups are bone groups
|
2011-06-01 17:04:32 +00:00
|
|
|
if(validmap) {
|
|
|
|
bone_groups = validmap;
|
|
|
|
}else {
|
|
|
|
bone_groups = wpaint_make_validmap(ob);
|
|
|
|
}
|
2011-05-27 19:13:54 +00:00
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
if(wp->flag & VP_ONLYVGROUP) {
|
2010-01-26 17:07:47 +00:00
|
|
|
dw= defvert_find_index(me->dvert+index, vgroup);
|
|
|
|
uw= defvert_find_index(wp->wpaint_prev+index, vgroup);
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-01-26 17:07:47 +00:00
|
|
|
dw= defvert_verify_index(me->dvert+index, vgroup);
|
|
|
|
uw= defvert_verify_index(wp->wpaint_prev+index, vgroup);
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
if(dw==NULL || uw==NULL)
|
|
|
|
return;
|
2011-05-27 19:13:54 +00:00
|
|
|
/* Jason was here */
|
2011-09-14 05:56:25 +00:00
|
|
|
flags = gen_lck_flags(ob, defbase_len = BLI_countlist(&ob->defbase));
|
|
|
|
defbase_sel = MEM_mallocN(defbase_len * sizeof(char), "dg_selected_flags");
|
|
|
|
selected = get_selected_defgroups(ob, defbase_sel, defbase_len);
|
2011-06-14 19:11:01 +00:00
|
|
|
if(!selected && ob->actdef) {
|
|
|
|
selected = 1;
|
|
|
|
}
|
2011-06-21 19:20:42 +00:00
|
|
|
|
2011-05-27 19:13:54 +00:00
|
|
|
oldw = dw->weight;
|
2011-06-29 18:20:39 +00:00
|
|
|
wpaint_blend(wp, dw, uw, alpha, paintweight, flip, multipaint && selected >1);
|
2011-06-21 19:20:42 +00:00
|
|
|
neww = dw->weight;
|
2011-06-29 18:20:39 +00:00
|
|
|
dw->weight = oldw;
|
2011-07-21 16:25:07 +00:00
|
|
|
|
2011-07-07 17:59:15 +00:00
|
|
|
// setup multi-paint
|
2011-06-21 19:20:42 +00:00
|
|
|
if(selected > 1 && multipaint) {
|
2011-07-21 16:25:07 +00:00
|
|
|
dv = MEM_mallocN(sizeof (*(me->dvert+index)), "prevMDeformVert");
|
|
|
|
|
|
|
|
dv->dw= MEM_dupallocN((me->dvert+index)->dw);
|
|
|
|
dv->flag = (me->dvert+index)->flag;
|
|
|
|
dv->totweight = (me->dvert+index)->totweight;
|
2011-06-29 18:20:39 +00:00
|
|
|
tdw = dw;
|
|
|
|
tuw = uw;
|
2011-09-14 05:56:25 +00:00
|
|
|
change = get_mp_change(wp->wpaint_prev+index, defbase_sel, neww-oldw);
|
2011-06-29 18:20:39 +00:00
|
|
|
if(change) {
|
|
|
|
if(!tdw->weight) {
|
2011-09-14 05:56:25 +00:00
|
|
|
i = get_first_selected_nonzero_weight(me->dvert+index, defbase_sel);
|
2011-06-29 18:20:39 +00:00
|
|
|
if(i>=0) {
|
|
|
|
tdw = ((me->dvert+index)->dw+i);
|
|
|
|
tuw = defvert_verify_index(wp->wpaint_prev+index, tdw->def_nr);
|
|
|
|
} else {
|
|
|
|
change = 0;
|
|
|
|
}
|
|
|
|
}
|
2011-07-21 16:25:07 +00:00
|
|
|
if(change && tuw->weight && tuw->weight * change) {
|
2011-06-29 18:20:39 +00:00
|
|
|
if(tdw->weight != tuw->weight) {
|
2011-07-21 16:25:07 +00:00
|
|
|
oldChange = tdw->weight/tuw->weight;
|
2011-06-29 18:20:39 +00:00
|
|
|
testw = tuw->weight*change;
|
|
|
|
if( testw > tuw->weight ) {
|
2011-07-21 16:25:07 +00:00
|
|
|
if(change > oldChange) {
|
2011-08-12 15:42:16 +00:00
|
|
|
// reset the weights and use the new change
|
2011-06-29 18:20:39 +00:00
|
|
|
reset_to_prev(wp->wpaint_prev+index, me->dvert+index);
|
|
|
|
} else {
|
2011-08-12 15:42:16 +00:00
|
|
|
// the old change was more significant,
|
|
|
|
// so set the change to 0 so that it will not do another multi-paint
|
2011-06-29 18:20:39 +00:00
|
|
|
change = 0;
|
|
|
|
}
|
|
|
|
} else {
|
2011-07-21 16:25:07 +00:00
|
|
|
if(change < oldChange) {
|
2011-06-29 18:20:39 +00:00
|
|
|
reset_to_prev(wp->wpaint_prev+index, me->dvert+index);
|
|
|
|
} else {
|
|
|
|
change = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
change = 0;
|
|
|
|
}
|
2011-06-21 19:20:42 +00:00
|
|
|
}
|
|
|
|
}
|
2011-05-27 19:13:54 +00:00
|
|
|
/* Jason was here */
|
2011-09-14 05:56:25 +00:00
|
|
|
if(apply_mp_lcks_normalize(me, index, dw, tdw, defbase_len, change, oldChange, oldw, neww, defbase_sel, selected, bone_groups, validmap, flags, multipaint)) {
|
2011-07-21 16:25:07 +00:00
|
|
|
reset_to_prev(dv, me->dvert+index);
|
|
|
|
change = 0;
|
|
|
|
oldChange = 0;
|
|
|
|
}
|
|
|
|
if(dv) {
|
|
|
|
MEM_freeN(dv->dw);
|
|
|
|
MEM_freeN(dv);
|
|
|
|
}
|
2011-06-14 19:11:01 +00:00
|
|
|
// dvert may have been altered greatly
|
|
|
|
dw = defvert_find_index(me->dvert+index, vgroup);
|
2011-06-07 17:59:38 +00:00
|
|
|
|
2009-10-19 13:09:13 +00:00
|
|
|
if(me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */
|
2009-01-07 19:23:22 +00:00
|
|
|
int j= mesh_get_x_mirror_vert(ob, index);
|
|
|
|
if(j>=0) {
|
|
|
|
/* copy, not paint again */
|
|
|
|
if(vgroup_mirror != -1)
|
2010-01-26 17:07:47 +00:00
|
|
|
uw= defvert_verify_index(me->dvert+j, vgroup_mirror);
|
2009-01-07 19:23:22 +00:00
|
|
|
else
|
2010-01-26 17:07:47 +00:00
|
|
|
uw= defvert_verify_index(me->dvert+j, vgroup);
|
2011-05-30 16:33:23 +00:00
|
|
|
/* Jason */
|
2011-06-21 19:20:42 +00:00
|
|
|
//uw->weight= dw->weight;
|
2011-05-30 16:33:23 +00:00
|
|
|
/* Jason */
|
2011-09-14 05:56:25 +00:00
|
|
|
apply_mp_lcks_normalize(me, j, uw, tdw, defbase_len, change, oldChange, oldw, neww, defbase_sel, selected, bone_groups, validmap, flags, multipaint);
|
2011-05-27 19:13:54 +00:00
|
|
|
}
|
|
|
|
}
|
2011-06-01 15:45:09 +00:00
|
|
|
/* Jason */
|
|
|
|
if(flags) {
|
|
|
|
MEM_freeN(flags);
|
|
|
|
}
|
2011-09-14 05:56:25 +00:00
|
|
|
MEM_freeN(defbase_sel);
|
2011-06-01 17:04:32 +00:00
|
|
|
if(!validmap) {
|
|
|
|
MEM_freeN(bone_groups);
|
|
|
|
}
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
/* *************** set wpaint operator ****************** */
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int set_wpaint(bContext *C, wmOperator *UNUSED(op)) /* toggle */
|
2009-01-10 14:19:14 +00:00
|
|
|
{
|
|
|
|
Object *ob= CTX_data_active_object(C);
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
|
|
|
VPaint *wp= scene->toolsettings->wpaint;
|
|
|
|
Mesh *me;
|
|
|
|
|
2009-01-07 19:23:22 +00:00
|
|
|
me= get_mesh(ob);
|
2009-07-25 13:40:59 +00:00
|
|
|
if(ob->id.lib || me==NULL) return OPERATOR_PASS_THROUGH;
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-08-15 21:46:25 +00:00
|
|
|
if(ob->mode & OB_MODE_WEIGHT_PAINT) ob->mode &= ~OB_MODE_WEIGHT_PAINT;
|
|
|
|
else ob->mode |= OB_MODE_WEIGHT_PAINT;
|
2009-01-10 14:19:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Weightpaint works by overriding colors in mesh,
|
|
|
|
* so need to make sure we recalc on enter and
|
|
|
|
* exit (exit needs doing regardless because we
|
|
|
|
* should redeform).
|
|
|
|
*/
|
2011-01-03 12:41:16 +00:00
|
|
|
DAG_id_tag_update(&me->id, 0);
|
2009-01-10 14:19:14 +00:00
|
|
|
|
2009-08-15 21:46:25 +00:00
|
|
|
if(ob->mode & OB_MODE_WEIGHT_PAINT) {
|
2009-01-10 14:19:14 +00:00
|
|
|
Object *par;
|
|
|
|
|
|
|
|
if(wp==NULL)
|
|
|
|
wp= scene->toolsettings->wpaint= new_vpaint(1);
|
2009-03-11 00:43:08 +00:00
|
|
|
|
2009-08-20 16:00:17 +00:00
|
|
|
paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
|
2009-09-18 15:48:49 +00:00
|
|
|
paint_cursor_start(C, weight_paint_poll);
|
2009-01-10 14:19:14 +00:00
|
|
|
|
|
|
|
mesh_octree_table(ob, NULL, NULL, 's');
|
|
|
|
|
|
|
|
/* verify if active weight group is also active bone */
|
|
|
|
par= modifiers_isDeformedByArmature(ob);
|
2009-08-16 03:24:23 +00:00
|
|
|
if(par && (par->mode & OB_MODE_POSE)) {
|
2009-12-15 18:15:38 +00:00
|
|
|
bArmature *arm= par->data;
|
2009-11-09 21:03:54 +00:00
|
|
|
|
|
|
|
if(arm->act_bone)
|
|
|
|
ED_vgroup_select_by_name(ob, arm->act_bone->name);
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
}
|
2009-01-10 14:19:14 +00:00
|
|
|
else {
|
2010-03-31 07:22:18 +00:00
|
|
|
mesh_octree_table(NULL, NULL, NULL, 'e');
|
|
|
|
mesh_mirrtopo_table(NULL, 'e');
|
2009-01-10 14:19:14 +00:00
|
|
|
}
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-02-10 15:38:00 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2009-02-01 13:24:19 +00:00
|
|
|
/* for switching to/from mode */
|
|
|
|
static int paint_poll_test(bContext *C)
|
|
|
|
{
|
|
|
|
if(CTX_data_edit_object(C))
|
|
|
|
return 0;
|
|
|
|
if(CTX_data_active_object(C)==NULL)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
void PAINT_OT_weight_paint_toggle(wmOperatorType *ot)
|
2009-01-10 14:19:14 +00:00
|
|
|
{
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Weight Paint Mode";
|
2009-02-19 23:53:40 +00:00
|
|
|
ot->idname= "PAINT_OT_weight_paint_toggle";
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
/* api callbacks */
|
|
|
|
ot->exec= set_wpaint;
|
2009-02-01 13:24:19 +00:00
|
|
|
ot->poll= paint_poll_test;
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-01-31 19:40:40 +00:00
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
}
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
/* ************ weight paint operator ********** */
|
|
|
|
|
|
|
|
struct WPaintData {
|
|
|
|
ViewContext vc;
|
|
|
|
int *indexar;
|
|
|
|
int vgroup_mirror;
|
|
|
|
float *vertexcosnos;
|
|
|
|
float wpimat[3][3];
|
2009-10-30 02:09:52 +00:00
|
|
|
|
|
|
|
/*variables for auto normalize*/
|
|
|
|
int auto_normalize;
|
|
|
|
char *vgroup_validmap; /*stores if vgroups tie to deforming bones or not*/
|
2009-01-10 14:19:14 +00:00
|
|
|
};
|
|
|
|
|
2010-10-16 14:32:17 +00:00
|
|
|
static char *wpaint_make_validmap(Object *ob)
|
2009-10-30 02:09:52 +00:00
|
|
|
{
|
|
|
|
bDeformGroup *dg;
|
|
|
|
ModifierData *md;
|
|
|
|
char *validmap;
|
|
|
|
bPose *pose;
|
|
|
|
bPoseChannel *chan;
|
|
|
|
ArmatureModifierData *amd;
|
2010-05-07 07:54:25 +00:00
|
|
|
GHash *gh = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "wpaint_make_validmap gh");
|
2009-10-30 09:50:35 +00:00
|
|
|
int i = 0, step1=1;
|
2009-10-30 02:09:52 +00:00
|
|
|
|
|
|
|
/*add all names to a hash table*/
|
|
|
|
for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
|
|
|
|
BLI_ghash_insert(gh, dg->name, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!i)
|
2009-11-02 16:07:49 +00:00
|
|
|
return NULL;
|
2009-10-30 02:09:52 +00:00
|
|
|
|
|
|
|
validmap = MEM_callocN(i, "wpaint valid map");
|
|
|
|
|
|
|
|
/*now loop through the armature modifiers and identify deform bones*/
|
2009-10-30 09:50:35 +00:00
|
|
|
for (md = ob->modifiers.first; md; md= !md->next && step1 ? (step1=0), modifiers_getVirtualModifierList(ob) : md->next) {
|
|
|
|
if (!(md->mode & (eModifierMode_Realtime|eModifierMode_Virtual)))
|
2009-10-30 02:09:52 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (md->type == eModifierType_Armature)
|
|
|
|
{
|
|
|
|
amd = (ArmatureModifierData*) md;
|
|
|
|
|
2009-12-14 17:08:02 +00:00
|
|
|
if(amd->object && amd->object->pose) {
|
|
|
|
pose = amd->object->pose;
|
|
|
|
|
|
|
|
for (chan=pose->chanbase.first; chan; chan=chan->next) {
|
|
|
|
if (chan->bone->flag & BONE_NO_DEFORM)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (BLI_ghash_haskey(gh, chan->name)) {
|
|
|
|
BLI_ghash_remove(gh, chan->name, NULL, NULL);
|
|
|
|
BLI_ghash_insert(gh, chan->name, SET_INT_IN_POINTER(1));
|
|
|
|
}
|
2009-10-30 02:09:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*add all names to a hash table*/
|
|
|
|
for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) {
|
|
|
|
if (BLI_ghash_lookup(gh, dg->name) != NULL) {
|
|
|
|
validmap[i] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_ghash_free(gh, NULL, NULL);
|
|
|
|
|
|
|
|
return validmap;
|
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
|
2009-01-10 14:19:14 +00:00
|
|
|
{
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
Scene *scene= CTX_data_scene(C);
|
2009-08-20 15:25:12 +00:00
|
|
|
struct PaintStroke *stroke = op->customdata;
|
2009-01-10 14:19:14 +00:00
|
|
|
ToolSettings *ts= CTX_data_tool_settings(C);
|
|
|
|
VPaint *wp= ts->wpaint;
|
|
|
|
Object *ob= CTX_data_active_object(C);
|
|
|
|
struct WPaintData *wpd;
|
2009-01-07 19:23:22 +00:00
|
|
|
Mesh *me;
|
2009-01-10 14:19:14 +00:00
|
|
|
float mat[4][4], imat[4][4];
|
2011-05-27 19:13:54 +00:00
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
if(scene->obedit) return OPERATOR_CANCELLED;
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
me= get_mesh(ob);
|
2009-07-25 13:40:59 +00:00
|
|
|
if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
/* if nothing was added yet, we make dverts and a vertex deform group */
|
2010-12-17 16:04:05 +00:00
|
|
|
if (!me->dvert) {
|
2.5: Object module
* Split object_edit.c into multiple files:
object_add.c, object_edit.c, object_hook.c, object_relations.c,
object_select.c, object_transform.c.
* Rename files to have consistent object_ and mball_ prefix:
object_shapekey.c, object_lattice.c, object_vgroup.c, mball_edit.c.
* Added operators:
* vertex group menu and set active
* apply location, rotation, scale, visual transform (location is new)
* make local
* make vertex parent
* move to layer
* convert to curve/mesh (not finished yet)
* Many small fixes for marked issues, but still much code to be cleaned
up here...
2009-09-09 11:52:56 +00:00
|
|
|
ED_vgroup_data_create(&me->id);
|
2010-12-17 16:04:05 +00:00
|
|
|
WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
|
|
|
|
}
|
2011-05-27 19:13:54 +00:00
|
|
|
|
|
|
|
|
2009-08-20 15:25:12 +00:00
|
|
|
/* make mode data storage */
|
|
|
|
wpd= MEM_callocN(sizeof(struct WPaintData), "WPaintData");
|
|
|
|
paint_stroke_set_mode_data(stroke, wpd);
|
2009-01-10 14:19:14 +00:00
|
|
|
view3d_set_viewcontext(C, &wpd->vc);
|
|
|
|
wpd->vgroup_mirror= -1;
|
2011-06-08 19:05:17 +00:00
|
|
|
|
2009-10-30 02:09:52 +00:00
|
|
|
/*set up auto-normalize, and generate map for detecting which
|
|
|
|
vgroups affect deform bones*/
|
|
|
|
wpd->auto_normalize = ts->auto_normalize;
|
|
|
|
if (wpd->auto_normalize)
|
2010-10-16 14:32:17 +00:00
|
|
|
wpd->vgroup_validmap = wpaint_make_validmap(ob);
|
2009-10-30 02:09:52 +00:00
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
// if(qual & LR_CTRLKEY) {
|
|
|
|
// sample_wpaint(scene, ar, v3d, 0);
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
// if(qual & LR_SHIFTKEY) {
|
|
|
|
// sample_wpaint(scene, ar, v3d, 1);
|
|
|
|
// return;
|
|
|
|
// }
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
/* ALLOCATIONS! no return after this line */
|
|
|
|
/* painting on subsurfs should give correct points too, this returns me->totvert amount */
|
|
|
|
wpd->vertexcosnos= mesh_get_mapped_verts_nors(scene, ob);
|
2010-02-06 15:50:53 +00:00
|
|
|
wpd->indexar= get_indexarray(me);
|
2009-01-10 14:19:14 +00:00
|
|
|
copy_wpaint_prev(wp, me->dvert, me->totvert);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
/* this happens on a Bone select, when no vgroup existed yet */
|
|
|
|
if(ob->actdef<=0) {
|
|
|
|
Object *modob;
|
|
|
|
if((modob = modifiers_isDeformedByArmature(ob))) {
|
2010-01-18 16:21:23 +00:00
|
|
|
Bone *actbone= ((bArmature *)modob->data)->act_bone;
|
|
|
|
if(actbone) {
|
|
|
|
bPoseChannel *pchan= get_pose_channel(modob->pose, actbone->name);
|
|
|
|
|
|
|
|
if(pchan) {
|
2010-01-26 13:50:17 +00:00
|
|
|
bDeformGroup *dg= defgroup_find_name(ob, pchan->name);
|
2010-01-18 16:21:23 +00:00
|
|
|
if(dg==NULL)
|
|
|
|
dg= ED_vgroup_add_name(ob, pchan->name); /* sets actdef */
|
|
|
|
else
|
2010-01-26 13:50:17 +00:00
|
|
|
ob->actdef= 1 + defgroup_find_index(ob, dg);
|
2010-01-18 16:21:23 +00:00
|
|
|
}
|
2009-01-10 14:19:14 +00:00
|
|
|
}
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
}
|
|
|
|
}
|
2009-01-10 14:19:14 +00:00
|
|
|
if(ob->defbase.first==NULL) {
|
2.5: Object module
* Split object_edit.c into multiple files:
object_add.c, object_edit.c, object_hook.c, object_relations.c,
object_select.c, object_transform.c.
* Rename files to have consistent object_ and mball_ prefix:
object_shapekey.c, object_lattice.c, object_vgroup.c, mball_edit.c.
* Added operators:
* vertex group menu and set active
* apply location, rotation, scale, visual transform (location is new)
* make local
* make vertex parent
* move to layer
* convert to curve/mesh (not finished yet)
* Many small fixes for marked issues, but still much code to be cleaned
up here...
2009-09-09 11:52:56 +00:00
|
|
|
ED_vgroup_add(ob);
|
2010-01-18 16:21:23 +00:00
|
|
|
}
|
2009-01-10 14:19:14 +00:00
|
|
|
|
|
|
|
// if(ob->lay & v3d->lay); else error("Active object is not in this layer");
|
|
|
|
|
|
|
|
/* imat for normals */
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_m4_m4m4(mat, ob->obmat, wpd->vc.rv3d->viewmat);
|
|
|
|
invert_m4_m4(imat, mat);
|
|
|
|
copy_m3_m4(wpd->wpimat, imat);
|
2009-01-10 14:19:14 +00:00
|
|
|
|
|
|
|
/* if mirror painting, find the other group */
|
2009-10-19 13:09:13 +00:00
|
|
|
if(me->editflag & ME_EDIT_MIRROR_X) {
|
2011-05-26 22:20:29 +00:00
|
|
|
wpaint_mirror_vgroup_ensure(ob, &wpd->vgroup_mirror);
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
}
|
2011-05-27 19:13:54 +00:00
|
|
|
|
2009-08-20 15:25:12 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
|
|
|
|
{
|
|
|
|
ToolSettings *ts= CTX_data_tool_settings(C);
|
|
|
|
VPaint *wp= ts->wpaint;
|
|
|
|
Brush *brush = paint_brush(&wp->paint);
|
|
|
|
struct WPaintData *wpd= paint_stroke_mode_data(stroke);
|
2009-12-20 10:50:40 +00:00
|
|
|
ViewContext *vc;
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
2009-08-20 15:25:12 +00:00
|
|
|
float mat[4][4];
|
2011-01-12 03:41:12 +00:00
|
|
|
float paintweight;
|
2009-12-20 10:50:40 +00:00
|
|
|
int *indexar;
|
2009-11-20 01:39:27 +00:00
|
|
|
int totindex, index, totw, flip;
|
|
|
|
float alpha;
|
|
|
|
float mval[2], pressure;
|
2009-12-20 10:50:40 +00:00
|
|
|
|
2011-07-18 17:38:17 +00:00
|
|
|
// Jason
|
|
|
|
int selectedVerts;
|
|
|
|
|
2009-12-20 10:50:40 +00:00
|
|
|
/* cannot paint if there is no stroke data */
|
|
|
|
if (wpd == NULL) {
|
|
|
|
// XXX: force a redraw here, since even though we can't paint,
|
|
|
|
// at least view won't freeze until stroke ends
|
|
|
|
ED_region_tag_redraw(CTX_wm_region(C));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
vc= &wpd->vc;
|
|
|
|
ob= vc->obact;
|
|
|
|
me= ob->data;
|
|
|
|
indexar= wpd->indexar;
|
|
|
|
|
2009-08-20 15:25:12 +00:00
|
|
|
view3d_operator_needs_opengl(C);
|
2009-12-20 10:50:40 +00:00
|
|
|
|
2009-08-20 15:25:12 +00:00
|
|
|
/* load projection matrix */
|
2010-02-01 15:32:55 +00:00
|
|
|
mul_m4_m4m4(mat, ob->obmat, vc->rv3d->persmat);
|
2009-08-20 15:25:12 +00:00
|
|
|
|
2010-07-29 12:16:15 +00:00
|
|
|
flip = RNA_boolean_get(itemptr, "pen_flip");
|
2009-11-20 01:39:27 +00:00
|
|
|
pressure = RNA_float_get(itemptr, "pressure");
|
2009-08-20 15:25:12 +00:00
|
|
|
RNA_float_get_array(itemptr, "mouse", mval);
|
|
|
|
mval[0]-= vc->ar->winrct.xmin;
|
|
|
|
mval[1]-= vc->ar->winrct.ymin;
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
swap_m4m4(wpd->vc.rv3d->persmat, mat);
|
2009-08-20 15:25:12 +00:00
|
|
|
|
|
|
|
/* which faces are involved */
|
|
|
|
if(wp->flag & VP_AREA) {
|
2010-07-22 18:56:46 +00:00
|
|
|
totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size(brush));
|
2009-08-20 15:25:12 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
|
|
|
|
if(indexar[0]) totindex= 1;
|
|
|
|
else totindex= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(wp->flag & VP_COLINDEX) {
|
|
|
|
for(index=0; index<totindex; index++) {
|
|
|
|
if(indexar[index] && indexar[index]<=me->totface) {
|
|
|
|
MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
|
|
|
|
|
|
|
|
if(mface->mat_nr!=ob->actcol-1) {
|
|
|
|
indexar[index]= 0;
|
|
|
|
}
|
2009-11-20 01:39:27 +00:00
|
|
|
}
|
2009-08-20 15:25:12 +00:00
|
|
|
}
|
|
|
|
}
|
2011-07-18 17:38:17 +00:00
|
|
|
// Jason
|
|
|
|
selectedVerts = (me->editflag & ME_EDIT_VERT_SEL);
|
2009-08-20 15:25:12 +00:00
|
|
|
|
2009-10-20 19:27:27 +00:00
|
|
|
if((me->editflag & ME_EDIT_PAINT_MASK) && me->mface) {
|
2009-08-20 15:25:12 +00:00
|
|
|
for(index=0; index<totindex; index++) {
|
|
|
|
if(indexar[index] && indexar[index]<=me->totface) {
|
|
|
|
MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
|
|
|
|
|
|
|
|
if((mface->flag & ME_FACE_SEL)==0) {
|
|
|
|
indexar[index]= 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* make sure each vertex gets treated only once */
|
|
|
|
/* and calculate filter weight */
|
|
|
|
totw= 0;
|
2010-01-20 08:30:40 +00:00
|
|
|
if(brush->vertexpaint_tool==VP_BLUR)
|
2009-08-20 15:25:12 +00:00
|
|
|
paintweight= 0.0f;
|
|
|
|
else
|
|
|
|
paintweight= ts->vgroup_weight;
|
|
|
|
|
|
|
|
for(index=0; index<totindex; index++) {
|
|
|
|
if(indexar[index] && indexar[index]<=me->totface) {
|
|
|
|
MFace *mface= me->mface + (indexar[index]-1);
|
|
|
|
|
2011-07-20 15:56:35 +00:00
|
|
|
(me->dvert+mface->v1)->flag= selectedVerts ? ((me->mvert+mface->v1)->flag & SELECT): 1;
|
|
|
|
(me->dvert+mface->v2)->flag= selectedVerts ? ((me->mvert+mface->v2)->flag & SELECT): 1;
|
|
|
|
(me->dvert+mface->v3)->flag= selectedVerts ? ((me->mvert+mface->v3)->flag & SELECT): 1;
|
|
|
|
if(mface->v4) (me->dvert+mface->v4)->flag= selectedVerts ? ((me->mvert+mface->v4)->flag & SELECT): 1;
|
2009-08-20 15:25:12 +00:00
|
|
|
|
2010-01-20 08:30:40 +00:00
|
|
|
if(brush->vertexpaint_tool==VP_BLUR) {
|
2010-12-03 01:52:28 +00:00
|
|
|
MDeformWeight *dw, *(*dw_func)(MDeformVert *, const int);
|
2009-08-20 15:25:12 +00:00
|
|
|
|
|
|
|
if(wp->flag & VP_ONLYVGROUP)
|
2010-12-03 01:52:28 +00:00
|
|
|
dw_func= (MDeformWeight *(*)(MDeformVert *, const int))defvert_find_index;
|
2010-02-02 18:24:10 +00:00
|
|
|
else
|
|
|
|
dw_func= defvert_verify_index;
|
2009-08-20 15:25:12 +00:00
|
|
|
|
|
|
|
dw= dw_func(me->dvert+mface->v1, ob->actdef-1);
|
|
|
|
if(dw) {paintweight+= dw->weight; totw++;}
|
|
|
|
dw= dw_func(me->dvert+mface->v2, ob->actdef-1);
|
|
|
|
if(dw) {paintweight+= dw->weight; totw++;}
|
|
|
|
dw= dw_func(me->dvert+mface->v3, ob->actdef-1);
|
|
|
|
if(dw) {paintweight+= dw->weight; totw++;}
|
|
|
|
if(mface->v4) {
|
|
|
|
dw= dw_func(me->dvert+mface->v4, ob->actdef-1);
|
|
|
|
if(dw) {paintweight+= dw->weight; totw++;}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-20 08:30:40 +00:00
|
|
|
if(brush->vertexpaint_tool==VP_BLUR)
|
2009-08-20 15:25:12 +00:00
|
|
|
paintweight/= (float)totw;
|
|
|
|
|
|
|
|
for(index=0; index<totindex; index++) {
|
|
|
|
|
|
|
|
if(indexar[index] && indexar[index]<=me->totface) {
|
|
|
|
MFace *mface= me->mface + (indexar[index]-1);
|
|
|
|
|
|
|
|
if((me->dvert+mface->v1)->flag) {
|
2009-11-20 01:39:27 +00:00
|
|
|
alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval, pressure);
|
2009-08-20 15:25:12 +00:00
|
|
|
if(alpha) {
|
2009-10-30 02:09:52 +00:00
|
|
|
do_weight_paint_vertex(wp, ob, mface->v1,
|
2009-11-20 01:39:27 +00:00
|
|
|
alpha, paintweight, flip, wpd->vgroup_mirror,
|
2011-06-08 19:05:17 +00:00
|
|
|
wpd->vgroup_validmap, ts->multipaint);
|
2009-08-20 15:25:12 +00:00
|
|
|
}
|
|
|
|
(me->dvert+mface->v1)->flag= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((me->dvert+mface->v2)->flag) {
|
2009-11-20 01:39:27 +00:00
|
|
|
alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval, pressure);
|
2009-08-20 15:25:12 +00:00
|
|
|
if(alpha) {
|
2009-10-30 02:09:52 +00:00
|
|
|
do_weight_paint_vertex(wp, ob, mface->v2,
|
2009-11-20 01:39:27 +00:00
|
|
|
alpha, paintweight, flip, wpd->vgroup_mirror,
|
2011-06-08 19:05:17 +00:00
|
|
|
wpd->vgroup_validmap, ts->multipaint);
|
2009-08-20 15:25:12 +00:00
|
|
|
}
|
|
|
|
(me->dvert+mface->v2)->flag= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((me->dvert+mface->v3)->flag) {
|
2009-11-20 01:39:27 +00:00
|
|
|
alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval, pressure);
|
2009-08-20 15:25:12 +00:00
|
|
|
if(alpha) {
|
2009-10-30 02:09:52 +00:00
|
|
|
do_weight_paint_vertex(wp, ob, mface->v3,
|
2009-11-20 01:39:27 +00:00
|
|
|
alpha, paintweight, flip, wpd->vgroup_mirror,
|
2011-06-08 19:05:17 +00:00
|
|
|
wpd->vgroup_validmap, ts->multipaint);
|
2009-08-20 15:25:12 +00:00
|
|
|
}
|
|
|
|
(me->dvert+mface->v3)->flag= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((me->dvert+mface->v4)->flag) {
|
|
|
|
if(mface->v4) {
|
2009-11-20 01:39:27 +00:00
|
|
|
alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval, pressure);
|
2009-08-20 15:25:12 +00:00
|
|
|
if(alpha) {
|
2009-10-30 02:09:52 +00:00
|
|
|
do_weight_paint_vertex(wp, ob, mface->v4,
|
2009-11-20 01:39:27 +00:00
|
|
|
alpha, paintweight, flip, wpd->vgroup_mirror,
|
2011-06-08 19:05:17 +00:00
|
|
|
wpd->vgroup_validmap, ts->multipaint);
|
2009-08-20 15:25:12 +00:00
|
|
|
}
|
|
|
|
(me->dvert+mface->v4)->flag= 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
swap_m4m4(vc->rv3d->persmat, mat);
|
2009-08-20 15:25:12 +00:00
|
|
|
|
2011-01-03 12:41:16 +00:00
|
|
|
DAG_id_tag_update(ob->data, 0);
|
2009-08-20 15:25:12 +00:00
|
|
|
ED_region_tag_redraw(vc->ar);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void wpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
|
|
|
|
{
|
|
|
|
ToolSettings *ts= CTX_data_tool_settings(C);
|
|
|
|
Object *ob= CTX_data_active_object(C);
|
|
|
|
struct WPaintData *wpd= paint_stroke_mode_data(stroke);
|
|
|
|
|
2009-12-20 10:50:40 +00:00
|
|
|
if(wpd) {
|
|
|
|
if(wpd->vertexcosnos)
|
|
|
|
MEM_freeN(wpd->vertexcosnos);
|
|
|
|
MEM_freeN(wpd->indexar);
|
|
|
|
|
|
|
|
if (wpd->vgroup_validmap)
|
|
|
|
MEM_freeN(wpd->vgroup_validmap);
|
|
|
|
|
|
|
|
MEM_freeN(wpd);
|
|
|
|
}
|
2009-08-20 15:25:12 +00:00
|
|
|
|
|
|
|
/* frees prev buffer */
|
|
|
|
copy_wpaint_prev(ts->wpaint, NULL, 0);
|
|
|
|
|
|
|
|
/* and particles too */
|
|
|
|
if(ob->particlesystem.first) {
|
|
|
|
ParticleSystem *psys;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(psys= ob->particlesystem.first; psys; psys= psys->next) {
|
|
|
|
for(i=0; i<PSYS_TOT_VG; i++) {
|
|
|
|
if(psys->vgroup[i]==ob->actdef) {
|
|
|
|
psys->recalc |= PSYS_RECALC_RESET;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-03 12:41:16 +00:00
|
|
|
DAG_id_tag_update(ob->data, 0);
|
2009-08-20 15:25:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
|
|
|
{
|
|
|
|
|
2009-10-27 19:53:34 +00:00
|
|
|
op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start,
|
2009-08-20 15:25:12 +00:00
|
|
|
wpaint_stroke_update_step,
|
2011-03-01 16:26:37 +00:00
|
|
|
wpaint_stroke_done, event->type);
|
2009-01-10 14:19:14 +00:00
|
|
|
|
|
|
|
/* add modal handler */
|
2009-09-18 12:43:36 +00:00
|
|
|
WM_event_add_modal_handler(C, op);
|
2009-08-21 00:46:36 +00:00
|
|
|
|
|
|
|
op->type->modal(C, op, event);
|
2009-01-10 14:19:14 +00:00
|
|
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
}
|
|
|
|
|
2011-06-06 11:04:54 +00:00
|
|
|
static int wpaint_cancel(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
paint_stroke_cancel(C, op);
|
|
|
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
void PAINT_OT_weight_paint(wmOperatorType *ot)
|
2009-01-10 14:19:14 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Weight Paint";
|
2009-02-19 23:53:40 +00:00
|
|
|
ot->idname= "PAINT_OT_weight_paint";
|
2009-01-10 14:19:14 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= wpaint_invoke;
|
2009-08-20 15:25:12 +00:00
|
|
|
ot->modal= paint_stroke_modal;
|
2009-01-10 14:19:14 +00:00
|
|
|
/* ot->exec= vpaint_exec; <-- needs stroke property */
|
2009-09-18 15:48:49 +00:00
|
|
|
ot->poll= weight_paint_poll;
|
2011-06-06 11:04:54 +00:00
|
|
|
ot->cancel= wpaint_cancel;
|
2009-01-10 14:19:14 +00:00
|
|
|
|
2009-01-31 19:40:40 +00:00
|
|
|
/* flags */
|
2009-07-11 14:51:13 +00:00
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
|
2009-08-20 15:25:12 +00:00
|
|
|
|
|
|
|
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
}
|
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int weight_paint_set_exec(bContext *C, wmOperator *UNUSED(op))
|
2009-10-22 12:59:14 +00:00
|
|
|
{
|
|
|
|
struct Scene *scene= CTX_data_scene(C);
|
|
|
|
Object *obact = CTX_data_active_object(C);
|
|
|
|
|
|
|
|
wpaint_fill(scene->toolsettings->wpaint, obact, scene->toolsettings->vgroup_weight);
|
|
|
|
ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PAINT_OT_weight_set(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2011-04-01 22:19:03 +00:00
|
|
|
ot->name= "Set Weight";
|
2009-10-22 12:59:14 +00:00
|
|
|
ot->idname= "PAINT_OT_weight_set";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->exec= weight_paint_set_exec;
|
2011-07-18 17:38:17 +00:00
|
|
|
ot->poll= mask_paint_poll; // Jason, it was facemask_paint_poll
|
2009-10-22 12:59:14 +00:00
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
|
|
|
}
|
|
|
|
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
/* ************ set / clear vertex paint mode ********** */
|
|
|
|
|
|
|
|
|
|
|
|
static int set_vpaint(bContext *C, wmOperator *op) /* toggle */
|
|
|
|
{
|
|
|
|
Object *ob= CTX_data_active_object(C);
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
2009-01-10 14:19:14 +00:00
|
|
|
VPaint *vp= scene->toolsettings->vpaint;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
Mesh *me;
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-02-10 15:38:00 +00:00
|
|
|
me= get_mesh(ob);
|
|
|
|
|
|
|
|
if(me==NULL || object_data_is_libdata(ob)) {
|
2009-08-15 20:36:15 +00:00
|
|
|
ob->mode &= ~OB_MODE_VERTEX_PAINT;
|
2009-07-25 13:40:59 +00:00
|
|
|
return OPERATOR_PASS_THROUGH;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
}
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-10-22 12:59:14 +00:00
|
|
|
if(me && me->mcol==NULL) make_vertexcol(ob);
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
|
|
|
/* toggle: end vpaint */
|
2009-08-15 20:36:15 +00:00
|
|
|
if(ob->mode & OB_MODE_VERTEX_PAINT) {
|
2009-01-10 14:19:14 +00:00
|
|
|
|
2009-08-15 20:36:15 +00:00
|
|
|
ob->mode &= ~OB_MODE_VERTEX_PAINT;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
}
|
|
|
|
else {
|
2009-08-15 20:36:15 +00:00
|
|
|
ob->mode |= OB_MODE_VERTEX_PAINT;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
/* Turn off weight painting */
|
2009-08-15 21:46:25 +00:00
|
|
|
if (ob->mode & OB_MODE_WEIGHT_PAINT)
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
set_wpaint(C, op);
|
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
if(vp==NULL)
|
|
|
|
vp= scene->toolsettings->vpaint= new_vpaint(0);
|
|
|
|
|
2009-09-18 15:48:49 +00:00
|
|
|
paint_cursor_start(C, vertex_paint_poll);
|
2009-08-17 02:49:31 +00:00
|
|
|
|
2009-08-20 16:00:17 +00:00
|
|
|
paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT);
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (me)
|
|
|
|
/* update modifier stack for mapping requirements */
|
2011-01-03 12:41:16 +00:00
|
|
|
DAG_id_tag_update(&me->id, 0);
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
2009-02-10 15:38:00 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
void PAINT_OT_vertex_paint_toggle(wmOperatorType *ot)
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
/* identifiers */
|
2009-01-10 14:19:14 +00:00
|
|
|
ot->name= "Vertex Paint Mode";
|
2009-02-19 23:53:40 +00:00
|
|
|
ot->idname= "PAINT_OT_vertex_paint_toggle";
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->exec= set_vpaint;
|
2009-02-01 13:24:19 +00:00
|
|
|
ot->poll= paint_poll_test;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
2009-01-31 19:40:40 +00:00
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
}
|
2009-01-07 19:23:22 +00:00
|
|
|
|
|
|
|
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
|
|
|
/* ********************** vertex paint operator ******************* */
|
|
|
|
|
|
|
|
/* Implementation notes:
|
|
|
|
|
|
|
|
Operator->invoke()
|
|
|
|
- validate context (add mcol)
|
|
|
|
- create customdata storage
|
|
|
|
- call paint once (mouse click)
|
|
|
|
- add modal handler
|
|
|
|
|
|
|
|
Operator->modal()
|
|
|
|
- for every mousemove, apply vertex paint
|
|
|
|
- exit on mouse release, free customdata
|
2010-03-22 09:30:00 +00:00
|
|
|
(return OPERATOR_FINISHED also removes handler and operator)
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
|
|
|
For future:
|
|
|
|
- implement a stroke event (or mousemove with past positons)
|
2009-01-10 14:19:14 +00:00
|
|
|
- revise whether op->customdata should be added in object, in set_vpaint
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
|
|
|
*/
|
|
|
|
|
2009-08-28 21:07:55 +00:00
|
|
|
typedef struct VPaintData {
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
ViewContext vc;
|
|
|
|
unsigned int paintcol;
|
|
|
|
int *indexar;
|
|
|
|
float *vertexcosnos;
|
|
|
|
float vpimat[3][3];
|
2009-08-28 21:07:55 +00:00
|
|
|
} VPaintData;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
2010-10-15 01:36:14 +00:00
|
|
|
static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *UNUSED(event))
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
{
|
2009-01-10 14:19:14 +00:00
|
|
|
ToolSettings *ts= CTX_data_tool_settings(C);
|
2009-08-20 05:13:07 +00:00
|
|
|
struct PaintStroke *stroke = op->customdata;
|
|
|
|
VPaint *vp= ts->vpaint;
|
|
|
|
struct VPaintData *vpd;
|
|
|
|
Object *ob= CTX_data_active_object(C);
|
|
|
|
Mesh *me;
|
|
|
|
float mat[4][4], imat[4][4];
|
|
|
|
|
|
|
|
/* context checks could be a poll() */
|
|
|
|
me= get_mesh(ob);
|
|
|
|
if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
2009-10-22 12:59:14 +00:00
|
|
|
if(me->mcol==NULL) make_vertexcol(ob);
|
2009-08-20 05:13:07 +00:00
|
|
|
if(me->mcol==NULL) return OPERATOR_CANCELLED;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
2009-08-20 05:13:07 +00:00
|
|
|
/* make mode data storage */
|
|
|
|
vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
|
|
|
|
paint_stroke_set_mode_data(stroke, vpd);
|
|
|
|
view3d_set_viewcontext(C, &vpd->vc);
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
2009-08-20 05:13:07 +00:00
|
|
|
vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob);
|
2010-02-06 15:50:53 +00:00
|
|
|
vpd->indexar= get_indexarray(me);
|
2009-08-20 05:13:07 +00:00
|
|
|
vpd->paintcol= vpaint_get_current_col(vp);
|
|
|
|
|
|
|
|
/* for filtering */
|
|
|
|
copy_vpaint_prev(vp, (unsigned int *)me->mcol, me->totface);
|
|
|
|
|
|
|
|
/* some old cruft to sort out later */
|
2009-11-10 20:43:45 +00:00
|
|
|
mul_m4_m4m4(mat, ob->obmat, vpd->vc.rv3d->viewmat);
|
|
|
|
invert_m4_m4(imat, mat);
|
|
|
|
copy_m3_m4(vpd->vpimat, imat);
|
2009-08-20 05:13:07 +00:00
|
|
|
|
|
|
|
return 1;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
}
|
|
|
|
|
2011-05-20 14:11:05 +00:00
|
|
|
static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, int index, const float mval[2], float pressure, int UNUSED(flip))
|
2009-08-28 21:07:55 +00:00
|
|
|
{
|
|
|
|
ViewContext *vc = &vpd->vc;
|
2010-01-20 08:30:40 +00:00
|
|
|
Brush *brush = paint_brush(&vp->paint);
|
2009-08-28 21:07:55 +00:00
|
|
|
Mesh *me = get_mesh(ob);
|
|
|
|
MFace *mface= ((MFace*)me->mface) + index;
|
2011-07-20 15:56:35 +00:00
|
|
|
|
2009-08-28 21:07:55 +00:00
|
|
|
unsigned int *mcol= ((unsigned int*)me->mcol) + 4*index;
|
|
|
|
unsigned int *mcolorig= ((unsigned int*)vp->vpaint_prev) + 4*index;
|
2009-11-20 01:39:27 +00:00
|
|
|
float alpha;
|
|
|
|
int i;
|
2011-07-20 15:56:35 +00:00
|
|
|
|
2009-08-28 21:07:55 +00:00
|
|
|
if((vp->flag & VP_COLINDEX && mface->mat_nr!=ob->actcol-1) ||
|
2011-07-21 18:46:59 +00:00
|
|
|
((me->editflag & ME_EDIT_PAINT_MASK) && !(mface->flag & ME_FACE_SEL)))
|
2011-07-20 15:56:35 +00:00
|
|
|
return;
|
2009-08-28 21:07:55 +00:00
|
|
|
|
2010-01-20 08:30:40 +00:00
|
|
|
if(brush->vertexpaint_tool==VP_BLUR) {
|
2009-08-28 21:07:55 +00:00
|
|
|
unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128);
|
|
|
|
if(mface->v4) {
|
|
|
|
unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128);
|
|
|
|
vpd->paintcol= mcol_blend( fcol1, fcol2, 128);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
vpd->paintcol= mcol_blend( mcol[2], fcol1, 170);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i = 0; i < (mface->v4 ? 4 : 3); ++i) {
|
2011-07-21 18:46:59 +00:00
|
|
|
alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*(&mface->v1)[i], mval, pressure);
|
|
|
|
if(alpha)
|
|
|
|
vpaint_blend(vp, mcol+i, mcolorig+i, vpd->paintcol, (int)(alpha*255.0f));
|
2009-08-28 21:07:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-20 05:13:07 +00:00
|
|
|
static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
{
|
2009-01-10 14:19:14 +00:00
|
|
|
ToolSettings *ts= CTX_data_tool_settings(C);
|
2009-08-20 05:13:07 +00:00
|
|
|
struct VPaintData *vpd = paint_stroke_mode_data(stroke);
|
2009-01-10 14:19:14 +00:00
|
|
|
VPaint *vp= ts->vpaint;
|
2009-08-17 02:49:31 +00:00
|
|
|
Brush *brush = paint_brush(&vp->paint);
|
2009-08-19 21:24:52 +00:00
|
|
|
ViewContext *vc= &vpd->vc;
|
|
|
|
Object *ob= vc->obact;
|
|
|
|
Mesh *me= ob->data;
|
|
|
|
float mat[4][4];
|
|
|
|
int *indexar= vpd->indexar;
|
2009-11-20 01:39:27 +00:00
|
|
|
int totindex, index, flip;
|
|
|
|
float pressure, mval[2];
|
2009-08-20 05:13:07 +00:00
|
|
|
|
|
|
|
RNA_float_get_array(itemptr, "mouse", mval);
|
2010-07-29 12:16:15 +00:00
|
|
|
flip = RNA_boolean_get(itemptr, "pen_flip");
|
2009-11-20 01:39:27 +00:00
|
|
|
pressure = RNA_float_get(itemptr, "pressure");
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
2009-08-19 21:24:52 +00:00
|
|
|
view3d_operator_needs_opengl(C);
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
2009-08-19 21:24:52 +00:00
|
|
|
/* load projection matrix */
|
2010-02-01 15:32:55 +00:00
|
|
|
mul_m4_m4m4(mat, ob->obmat, vc->rv3d->persmat);
|
2009-08-20 05:13:07 +00:00
|
|
|
|
|
|
|
mval[0]-= vc->ar->winrct.xmin;
|
|
|
|
mval[1]-= vc->ar->winrct.ymin;
|
|
|
|
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
2009-08-19 21:24:52 +00:00
|
|
|
/* which faces are involved */
|
|
|
|
if(vp->flag & VP_AREA) {
|
2010-07-22 18:56:46 +00:00
|
|
|
totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush_size(brush));
|
2009-08-19 21:24:52 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
|
|
|
|
if(indexar[0]) totindex= 1;
|
|
|
|
else totindex= 0;
|
|
|
|
}
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
swap_m4m4(vc->rv3d->persmat, mat);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-08-28 21:07:55 +00:00
|
|
|
for(index=0; index<totindex; index++) {
|
|
|
|
if(indexar[index] && indexar[index]<=me->totface)
|
2009-11-20 01:39:27 +00:00
|
|
|
vpaint_paint_face(vp, vpd, ob, indexar[index]-1, mval, pressure, flip);
|
2009-08-19 21:24:52 +00:00
|
|
|
}
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
2009-11-10 20:43:45 +00:00
|
|
|
swap_m4m4(vc->rv3d->persmat, mat);
|
2009-09-14 19:49:40 +00:00
|
|
|
|
|
|
|
/* was disabled because it is slow, but necessary for blur */
|
2010-01-20 08:30:40 +00:00
|
|
|
if(brush->vertexpaint_tool == VP_BLUR)
|
2009-09-14 19:49:40 +00:00
|
|
|
do_shared_vertexcol(me);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-08-19 21:24:52 +00:00
|
|
|
ED_region_tag_redraw(vc->ar);
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
2011-01-03 12:41:16 +00:00
|
|
|
DAG_id_tag_update(ob->data, 0);
|
2009-08-19 21:24:52 +00:00
|
|
|
}
|
|
|
|
|
2009-08-20 05:13:07 +00:00
|
|
|
static void vpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
|
2009-08-19 21:24:52 +00:00
|
|
|
{
|
2009-08-20 05:13:07 +00:00
|
|
|
ToolSettings *ts= CTX_data_tool_settings(C);
|
|
|
|
struct VPaintData *vpd= paint_stroke_mode_data(stroke);
|
2009-08-19 21:24:52 +00:00
|
|
|
|
2009-08-20 05:13:07 +00:00
|
|
|
if(vpd->vertexcosnos)
|
|
|
|
MEM_freeN(vpd->vertexcosnos);
|
|
|
|
MEM_freeN(vpd->indexar);
|
|
|
|
|
|
|
|
/* frees prev buffer */
|
|
|
|
copy_vpaint_prev(ts->vpaint, NULL, 0);
|
|
|
|
|
|
|
|
MEM_freeN(vpd);
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
|
|
|
{
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2009-10-27 19:53:34 +00:00
|
|
|
op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start,
|
2009-08-20 05:13:07 +00:00
|
|
|
vpaint_stroke_update_step,
|
2011-03-01 16:26:37 +00:00
|
|
|
vpaint_stroke_done, event->type);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
/* add modal handler */
|
2009-09-18 12:43:36 +00:00
|
|
|
WM_event_add_modal_handler(C, op);
|
2009-08-21 00:46:36 +00:00
|
|
|
|
|
|
|
op->type->modal(C, op, event);
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
}
|
2009-01-07 19:23:22 +00:00
|
|
|
|
2011-06-06 11:04:54 +00:00
|
|
|
static int vpaint_cancel(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
paint_stroke_cancel(C, op);
|
|
|
|
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2009-02-19 23:53:40 +00:00
|
|
|
void PAINT_OT_vertex_paint(wmOperatorType *ot)
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
2009-01-10 14:19:14 +00:00
|
|
|
ot->name= "Vertex Paint";
|
2009-02-19 23:53:40 +00:00
|
|
|
ot->idname= "PAINT_OT_vertex_paint";
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= vpaint_invoke;
|
2009-08-20 05:13:07 +00:00
|
|
|
ot->modal= paint_stroke_modal;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
/* ot->exec= vpaint_exec; <-- needs stroke property */
|
2009-09-18 15:48:49 +00:00
|
|
|
ot->poll= vertex_paint_poll;
|
2011-06-06 11:04:54 +00:00
|
|
|
ot->cancel= vpaint_cancel;
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
|
2009-01-31 19:40:40 +00:00
|
|
|
/* flags */
|
2009-07-11 14:51:13 +00:00
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
|
2009-08-20 05:13:07 +00:00
|
|
|
|
|
|
|
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
|
2009-01-07 19:23:22 +00:00
|
|
|
}
|
|
|
|
|
2010-01-26 11:11:53 +00:00
|
|
|
/* ********************** weight from bones operator ******************* */
|
|
|
|
|
|
|
|
static int weight_from_bones_poll(bContext *C)
|
|
|
|
{
|
|
|
|
Object *ob= CTX_data_active_object(C);
|
|
|
|
|
|
|
|
return (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && modifiers_isDeformedByArmature(ob));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int weight_from_bones_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
|
|
|
Object *ob= CTX_data_active_object(C);
|
|
|
|
Object *armob= modifiers_isDeformedByArmature(ob);
|
|
|
|
Mesh *me= ob->data;
|
|
|
|
int type= RNA_enum_get(op->ptr, "type");
|
|
|
|
|
2010-10-11 00:15:49 +00:00
|
|
|
create_vgroups_from_armature(op->reports, scene, ob, armob, type, (me->editflag & ME_EDIT_MIRROR_X));
|
2010-01-26 11:11:53 +00:00
|
|
|
|
2011-01-03 12:41:16 +00:00
|
|
|
DAG_id_tag_update(&me->id, 0);
|
2010-01-26 11:11:53 +00:00
|
|
|
WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PAINT_OT_weight_from_bones(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
static EnumPropertyItem type_items[]= {
|
2010-02-11 02:03:18 +00:00
|
|
|
{ARM_GROUPS_AUTO, "AUTOMATIC", 0, "Automatic", "Automatic weights froms bones"},
|
|
|
|
{ARM_GROUPS_ENVELOPE, "ENVELOPES", 0, "From Envelopes", "Weights from envelopes with user defined radius"},
|
2010-01-26 11:11:53 +00:00
|
|
|
{0, NULL, 0, NULL, NULL}};
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Weight from Bones";
|
|
|
|
ot->idname= "PAINT_OT_weight_from_bones";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->exec= weight_from_bones_exec;
|
|
|
|
ot->invoke= WM_menu_invoke;
|
|
|
|
ot->poll= weight_from_bones_poll;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
ot->prop= RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "Method to use for assigning weights.");
|
|
|
|
}
|
|
|
|
|