2010-05-06 00:08:41 +00:00
|
|
|
/**********************************************************************
|
|
|
|
*<
|
|
|
|
FILE: vertex_tree_paint.cpp
|
|
|
|
|
|
|
|
DESCRIPTION: Modifier implementation
|
|
|
|
|
|
|
|
CREATED BY: Christer Janson, Nikolai Sander
|
|
|
|
|
|
|
|
HISTORY:
|
|
|
|
|
|
|
|
*> Copyright (c) 1997, All Rights Reserved.
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
#include "vertex_tree_paint.h"
|
|
|
|
#include "meshdelta.h"
|
|
|
|
|
|
|
|
// flags:
|
|
|
|
#define VP_DISP_END_RESULT 0x01
|
|
|
|
|
|
|
|
static WNDPROC colorSwatchOriginalWndProc;
|
|
|
|
|
|
|
|
static HIMAGELIST hButtonImages = NULL;
|
|
|
|
|
|
|
|
static void LoadImages() {
|
|
|
|
if (hButtonImages) return;
|
|
|
|
HBITMAP hBitmap, hMask;
|
|
|
|
hButtonImages = ImageList_Create(15, 14, ILC_MASK, 2, 0); // 17 is kluge to center square. -SA
|
|
|
|
hBitmap = LoadBitmap (hInstance,MAKEINTRESOURCE(IDB_BUTTONS));
|
|
|
|
hMask = LoadBitmap (hInstance,MAKEINTRESOURCE(IDB_BUTTON_MASK));
|
|
|
|
ImageList_Add(hButtonImages, hBitmap, hMask);
|
|
|
|
DeleteObject(hBitmap);
|
|
|
|
DeleteObject(hMask);
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassDesc* GetVertexPaintDesc();
|
|
|
|
|
|
|
|
|
|
|
|
class VertexPaintClassDesc:public ClassDesc {
|
|
|
|
public:
|
|
|
|
int IsPublic() {return 1;}
|
|
|
|
void * Create(BOOL loading = FALSE){return new VertexPaint();}
|
|
|
|
const TCHAR * ClassName() {return GetString(IDS_CLASS_NAME);}
|
|
|
|
SClass_ID SuperClassID() {return OSM_CLASS_ID;}
|
|
|
|
Class_ID ClassID() {return VERTEX_TREE_PAINT_CLASS_ID;}
|
|
|
|
const TCHAR* Category() {return GetString(IDS_CATEGORY);}
|
|
|
|
void ResetClassParams(BOOL fileReset) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
static VertexPaintClassDesc VertexPaintDesc;
|
|
|
|
ClassDesc* GetVertexPaintDesc() {return &VertexPaintDesc;}
|
|
|
|
|
|
|
|
static BOOL CALLBACK VertexPaintDlgProc(
|
|
|
|
HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
int numPoints;
|
|
|
|
VertexPaint *mod = (VertexPaint*)GetWindowLong(hWnd,GWL_USERDATA);
|
|
|
|
if (!mod && msg!=WM_INITDIALOG) return FALSE;
|
|
|
|
int comboResult;
|
|
|
|
|
|
|
|
|
|
|
|
// Manages Spinners.
|
|
|
|
if (((msg==CC_SPINNER_BUTTONUP) && HIWORD(wParam)) ||
|
|
|
|
((msg==CC_SPINNER_CHANGE) ))
|
|
|
|
{
|
|
|
|
ISpinnerControl *spin;
|
|
|
|
spin = (ISpinnerControl *) lParam;
|
|
|
|
|
|
|
|
switch (LOWORD(wParam))
|
|
|
|
{
|
|
|
|
case IDC_TINT_SPIN:
|
|
|
|
if ((msg == CC_SPINNER_CHANGE))
|
|
|
|
{
|
|
|
|
mod->fTint = spin->GetFVal()/100;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IDC_BEND_SPIN:
|
|
|
|
if ((msg == CC_SPINNER_CHANGE))
|
|
|
|
{
|
|
|
|
mod->fGradientBend = spin->GetFVal()/100;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg) {
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
LoadImages();
|
|
|
|
mod = (VertexPaint*)lParam;
|
|
|
|
SetWindowLong(hWnd,GWL_USERDATA,lParam);
|
|
|
|
mod->hParams = hWnd;
|
|
|
|
mod->iPaintButton = GetICustButton(GetDlgItem(hWnd, IDC_PAINT));
|
|
|
|
mod->iPaintButton->SetType(CBT_CHECK);
|
|
|
|
mod->iPaintButton->SetHighlightColor(GREEN_WASH);
|
|
|
|
mod->iPaintButton->SetCheck(mod->ip->GetCommandMode()->ID() == CID_PAINT &&
|
|
|
|
!((PaintMouseProc *)mod->ip->GetCommandMode()->MouseProc(&numPoints))->GetPickMode());
|
|
|
|
mod->iPaintButton->SetImage(hButtonImages,0,0,0,0,15,14);
|
|
|
|
mod->iPaintButton->SetTooltip (TRUE, GetString (IDS_PAINT));
|
|
|
|
|
|
|
|
mod->iPickButton = GetICustButton(GetDlgItem(hWnd, IDC_PICK));
|
|
|
|
mod->iPickButton->SetType(CBT_CHECK);
|
|
|
|
mod->iPickButton->SetHighlightColor(GREEN_WASH);
|
|
|
|
mod->iPickButton->SetCheck(mod->ip->GetCommandMode()->ID() == CID_PAINT &&
|
|
|
|
((PaintMouseProc *)mod->ip->GetCommandMode()->MouseProc(&numPoints))->GetPickMode());
|
|
|
|
mod->iPickButton->SetImage(hButtonImages,1,1,1,1,15,14);
|
|
|
|
mod->iPickButton->SetTooltip (TRUE, GetString (IDS_PICK));
|
|
|
|
|
|
|
|
|
|
|
|
mod->iColor = GetIColorSwatch(GetDlgItem(hWnd, IDC_COLOR));
|
|
|
|
// change current Color according to editMode
|
|
|
|
mod->reloadBkupColor();
|
|
|
|
|
|
|
|
// Get interface For ZGradient, reload bkuped colors
|
|
|
|
mod->iColorGradient[0] = GetIColorSwatch(GetDlgItem(hWnd, IDC_PALETTE_GRAD0));
|
|
|
|
mod->iColorGradient[1] = GetIColorSwatch(GetDlgItem(hWnd, IDC_PALETTE_GRAD1));
|
|
|
|
mod->iColorGradient[0]->SetColor(mod->lastGradientColor[0]);
|
|
|
|
mod->iColorGradient[1]->SetColor(mod->lastGradientColor[1]);
|
|
|
|
|
|
|
|
|
|
|
|
// Init comboBox
|
|
|
|
SendDlgItemMessage(hWnd, IDC_COMBO_TYPE, CB_ADDSTRING, 0, (LPARAM)"Tree Weight");
|
|
|
|
SendDlgItemMessage(hWnd, IDC_COMBO_TYPE, CB_ADDSTRING, 0, (LPARAM)"Phase Level 1");
|
|
|
|
SendDlgItemMessage(hWnd, IDC_COMBO_TYPE, CB_ADDSTRING, 0, (LPARAM)"Phase Level 2");
|
|
|
|
SendDlgItemMessage(hWnd, IDC_COMBO_TYPE, CB_SETCURSEL, mod->getEditionType(), 0);
|
|
|
|
|
|
|
|
// If paint mode at last edit.
|
|
|
|
if(mod->_LastPaintMode)
|
|
|
|
{
|
|
|
|
// ActivatePaint / check button.
|
|
|
|
mod->ActivatePaint(TRUE);
|
|
|
|
mod->iPaintButton->SetCheck(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_POSTINIT:
|
|
|
|
mod->InitPalettes();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CC_COLOR_CHANGE:
|
|
|
|
if (LOWORD(wParam) == IDC_COLOR)
|
|
|
|
{
|
|
|
|
IColorSwatch* iCol = (IColorSwatch*)lParam;
|
|
|
|
switch(mod->getEditionType())
|
|
|
|
{
|
|
|
|
case 0: mod->lastWeightColor = iCol->GetColor(); break;
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
mod->lastPhaseColor = iCol->GetColor(); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
|
|
mod->SavePalettes();
|
|
|
|
mod->iPaintButton = NULL;
|
|
|
|
mod->iPickButton = NULL;
|
|
|
|
mod->iColor = NULL;
|
|
|
|
mod->iColorGradient[0] = NULL;
|
|
|
|
mod->iColorGradient[1] = NULL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch(LOWORD(wParam)) {
|
|
|
|
case IDC_PAINT:
|
|
|
|
mod->ActivatePaint(mod->iPaintButton->IsChecked());
|
|
|
|
break;
|
|
|
|
case IDC_PICK:
|
|
|
|
mod->ActivatePaint(mod->iPickButton->IsChecked(),TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDC_VC_ON:
|
|
|
|
mod->TurnVCOn(FALSE);
|
|
|
|
break;
|
|
|
|
case IDC_SHADED:
|
|
|
|
mod->TurnVCOn(TRUE);
|
|
|
|
break;
|
|
|
|
case IDC_COMBO_TYPE:
|
|
|
|
// Init default type.
|
|
|
|
comboResult= SendDlgItemMessage(hWnd, IDC_COMBO_TYPE, CB_GETCURSEL, 0, 0);
|
|
|
|
mod->setEditionType(comboResult);
|
|
|
|
break;
|
|
|
|
case IDC_BUTTON_FILL:
|
|
|
|
mod->fillSelectionColor();
|
|
|
|
break;
|
|
|
|
case IDC_BUTTON_GRADIENT:
|
|
|
|
mod->fillSelectionGradientColor();
|
|
|
|
break;
|
|
|
|
case IDC_BUTTON_GRAD0:
|
|
|
|
mod->iColorGradient[0]->SetColor(RGB(0,0,0));
|
|
|
|
mod->iColorGradient[1]->SetColor(RGB(85,85,85));
|
|
|
|
break;
|
|
|
|
case IDC_BUTTON_GRAD1:
|
|
|
|
mod->iColorGradient[0]->SetColor(RGB(85,85,85));
|
|
|
|
mod->iColorGradient[1]->SetColor(RGB(170,170,170));
|
|
|
|
break;
|
|
|
|
case IDC_BUTTON_GRAD2:
|
|
|
|
mod->iColorGradient[0]->SetColor(RGB(170,170,170));
|
|
|
|
mod->iColorGradient[1]->SetColor(RGB(255,255,255));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Subclass procedure
|
|
|
|
LRESULT APIENTRY colorSwatchSubclassWndProc(
|
|
|
|
HWND hwnd,
|
|
|
|
UINT uMsg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
|
|
|
switch (uMsg) {
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
case WM_LBUTTONUP:
|
|
|
|
case WM_LBUTTONDBLCLK: {
|
|
|
|
HWND hPanel = GetParent(hwnd);
|
|
|
|
LONG mod = GetWindowLong(hPanel,GWL_USERDATA);
|
|
|
|
if (mod) {
|
|
|
|
((VertexPaint*)mod)->PaletteButton(hwnd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
|
|
SetWindowLong(hwnd, GWL_WNDPROC, (LONG) colorSwatchOriginalWndProc);
|
|
|
|
// Fallthrough...
|
|
|
|
default:
|
|
|
|
return CallWindowProc(colorSwatchOriginalWndProc, hwnd, uMsg, wParam, lParam);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
IObjParam *VertexPaint::ip = NULL;
|
|
|
|
HWND VertexPaint::hParams = NULL;
|
|
|
|
VertexPaint* VertexPaint::editMod = NULL;
|
|
|
|
ICustButton* VertexPaint::iPaintButton = NULL;
|
|
|
|
ICustButton* VertexPaint::iPickButton = NULL;
|
|
|
|
IColorSwatch* VertexPaint::iColor = NULL;
|
|
|
|
COLORREF VertexPaint::lastWeightColor = RGB(85,85,85);
|
|
|
|
COLORREF VertexPaint::lastPhaseColor = RGB(0,0,0);
|
|
|
|
COLORREF VertexPaint::palColors[] = {
|
|
|
|
//RGB(32, 32, 32), RGB( 96,96,96), RGB( 160,160,160), RGB(224,224,224) };
|
|
|
|
RGB(0, 0, 0), RGB( 85,85,85), RGB( 170,170,170), RGB(255,255,255),
|
|
|
|
RGB(42, 42, 42), RGB( 127, 127, 127), RGB( 212, 212, 212)};
|
|
|
|
|
|
|
|
|
|
|
|
IColorSwatch* VertexPaint::iColorGradient[]= {NULL, NULL};
|
|
|
|
COLORREF VertexPaint::lastGradientColor[] = {RGB(0, 0, 0), RGB(85, 85, 85)};
|
|
|
|
|
|
|
|
|
|
|
|
//--- VertexPaint -------------------------------------------------------
|
|
|
|
VertexPaint::VertexPaint() : iTint(NULL), fTint(1.0f), iGradientBend(NULL), fGradientBend(0.0f)
|
|
|
|
{
|
|
|
|
flags = 0x0;
|
|
|
|
_EditType= 0;
|
|
|
|
_LastPaintMode= false;
|
|
|
|
}
|
|
|
|
|
|
|
|
VertexPaint::~VertexPaint()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Interval VertexPaint::LocalValidity(TimeValue t)
|
|
|
|
{
|
|
|
|
return FOREVER;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL VertexPaint::DependOnTopology(ModContext &mc)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefTargetHandle VertexPaint::Clone(RemapDir& remap)
|
|
|
|
{
|
|
|
|
VertexPaint* newmod = new VertexPaint();
|
|
|
|
return(newmod);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaint::NotifyInputChanged(Interval changeInt, PartID partID, RefMessage message, ModContext *mc)
|
|
|
|
{
|
|
|
|
if (!mc->localData) return;
|
|
|
|
((VertexPaintData*)mc->localData)->FreeCache();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaint::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node)
|
|
|
|
{
|
|
|
|
if (!os->obj->IsSubClassOf(triObjectClassID)) return;
|
|
|
|
|
|
|
|
os->obj->ReadyChannelsForMod(GEOM_CHANNEL|TOPO_CHANNEL|VERTCOLOR_CHANNEL|TEXMAP_CHANNEL);
|
|
|
|
|
|
|
|
TriObject *tobj = (TriObject*)os->obj;
|
|
|
|
VertexPaintData *d = (VertexPaintData*)mc.localData;
|
|
|
|
|
|
|
|
Mesh* mesh = &tobj->GetMesh();
|
|
|
|
|
|
|
|
if (mesh)
|
|
|
|
{
|
|
|
|
// We don't have any VColors yet, so we allocate the vcfaces
|
|
|
|
// and set all vcolors to black (index 0)
|
|
|
|
|
|
|
|
if (!mesh->vcFace)
|
|
|
|
{
|
|
|
|
mesh->setNumVCFaces(mesh->getNumFaces());
|
|
|
|
mesh->setNumVertCol(1);
|
|
|
|
|
|
|
|
mesh->vertCol[0] = Color(0,0,0);
|
|
|
|
|
|
|
|
for (int f=0; f<mesh->getNumFaces(); f++)
|
|
|
|
{
|
|
|
|
mesh->vcFace[f].t[0] = 0;
|
|
|
|
mesh->vcFace[f].t[1] = 0;
|
|
|
|
mesh->vcFace[f].t[2] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!d) mc.localData = d = new VertexPaintData(tobj->GetMesh());
|
|
|
|
if (!d->GetMesh()) d->SetCache(*mesh);
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
MeshDelta md(*mesh);
|
|
|
|
//MeshDelta mdc;
|
|
|
|
//if(cache) mdc.InitToMesh(*cache);
|
|
|
|
|
|
|
|
// If the incoming Mesh had no vertex colors, this will add a default map to start with.
|
|
|
|
// The default map has the same topology as the Mesh (so one color per vertex),
|
|
|
|
// with all colors set to white.
|
|
|
|
if (!mesh->mapSupport(0)) md.AddVertexColors ();
|
|
|
|
//if (cache && !cache->mapSupport(0)) mdc.AddVertexColors ();
|
|
|
|
|
|
|
|
// We used two routines -- VCreate to add new map vertices, and FRemap to make the
|
|
|
|
// existing map faces use the new verts. frFlags tell FRemap which vertices on a face
|
|
|
|
// should be "remapped", and the ww array contains the new locations.
|
|
|
|
VertColor nvc;
|
|
|
|
int j;
|
|
|
|
for (int v=0; v < d->GetNumColors(); v++)
|
|
|
|
{
|
|
|
|
ColorData cd = d->GetColorData(v);
|
|
|
|
|
|
|
|
// Edition Mode ??
|
|
|
|
if(editMod == this)
|
|
|
|
{
|
|
|
|
nvc= Color(cd.color);
|
|
|
|
// change color to view only monochromatic info for this channel;
|
|
|
|
switch(_EditType)
|
|
|
|
{
|
|
|
|
case 0: nvc.y= nvc.z= nvc.x;
|
|
|
|
nvc.y*= 0.7f;
|
|
|
|
nvc.z*= 0.7f;
|
|
|
|
break;
|
|
|
|
case 1: nvc.x= nvc.z= nvc.y;
|
|
|
|
nvc.x*= 0.7f;
|
|
|
|
nvc.z*= 0.7f;
|
|
|
|
break;
|
|
|
|
case 2: nvc.x= nvc.y= nvc.z;
|
|
|
|
nvc.x*= 0.7f;
|
|
|
|
nvc.y*= 0.7f;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// replace the VertexColor of the outgoing mesh
|
|
|
|
nvc= Color(cd.color);
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD ww[3], frFlags;
|
|
|
|
|
|
|
|
md.map->VCreate (&nvc);
|
|
|
|
|
|
|
|
// increase the number of vcol's and set the vcfaces as well
|
|
|
|
for(int i = 0 ; i < d->GetNVert(v).faces.Count() ; i++)
|
|
|
|
{
|
|
|
|
j = d->GetNVert(v).whichVertex[i];
|
|
|
|
frFlags = (1<<j);
|
|
|
|
ww[j] = md.map->outVNum()-1;
|
|
|
|
md.map->FRemap(d->GetNVert(v).faces[i], frFlags, ww);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
md.Apply(*mesh);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NotifyDependents(FOREVER, PART_VERTCOLOR, REFMSG_CHANGE);
|
|
|
|
os->obj->UpdateValidity(VERT_COLOR_CHAN_NUM, Interval(t,t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool oldShowEnd;
|
|
|
|
|
|
|
|
void VertexPaint::BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev )
|
|
|
|
{
|
|
|
|
|
|
|
|
this->ip = ip;
|
|
|
|
editMod = this;
|
|
|
|
if (!hParams) {
|
|
|
|
hParams = ip->AddRollupPage(
|
|
|
|
hInstance,
|
|
|
|
MAKEINTRESOURCE(IDD_PANEL),
|
|
|
|
VertexPaintDlgProc,
|
|
|
|
GetString(IDS_PARAMS),
|
|
|
|
(LPARAM)this);
|
|
|
|
|
|
|
|
// Subclass the palette controls
|
|
|
|
hPaletteWnd[ 0] = GetDlgItem(hParams, IDC_PALETTE_1);
|
|
|
|
hPaletteWnd[ 1] = GetDlgItem(hParams, IDC_PALETTE_2);
|
|
|
|
hPaletteWnd[ 2] = GetDlgItem(hParams, IDC_PALETTE_3);
|
|
|
|
hPaletteWnd[ 3] = GetDlgItem(hParams, IDC_PALETTE_4);
|
|
|
|
hPaletteWnd[ 4] = GetDlgItem(hParams, IDC_PALETTE_5);
|
|
|
|
hPaletteWnd[ 5] = GetDlgItem(hParams, IDC_PALETTE_6);
|
|
|
|
hPaletteWnd[ 6] = GetDlgItem(hParams, IDC_PALETTE_7);
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i=0; i<NUMPALETTES; i++) {
|
|
|
|
colorSwatchOriginalWndProc = (WNDPROC) SetWindowLong(hPaletteWnd[i], GWL_WNDPROC, (LONG) colorSwatchSubclassWndProc);
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMessage(hParams, WM_POSTINIT, 0, 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
SetWindowLong(hParams,GWL_USERDATA,(LONG)this);
|
|
|
|
}
|
|
|
|
|
|
|
|
iTint = SetupIntSpinner (hParams, IDC_TINT_SPIN, IDC_TINT, 0, 100, (int) (fTint*100.0f));
|
|
|
|
|
|
|
|
// Init Gradient Bend spinner
|
|
|
|
iGradientBend = SetupIntSpinner (hParams, IDC_BEND_SPIN, IDC_BEND, 0, 100, (int) (fGradientBend*100.0f));
|
|
|
|
|
|
|
|
|
|
|
|
// Set show end result.
|
|
|
|
oldShowEnd = ip->GetShowEndResult() ? TRUE : FALSE;
|
|
|
|
ip->SetShowEndResult (GetFlag (VP_DISP_END_RESULT));
|
|
|
|
|
|
|
|
// Force an eval to update caches.
|
|
|
|
NotifyDependents(FOREVER, PART_VERTCOLOR, REFMSG_CHANGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaint::EndEditParams( IObjParam *ip, ULONG flags,Animatable *next)
|
|
|
|
{
|
|
|
|
// Dsiable Painting.
|
|
|
|
bool lpm= _LastPaintMode;
|
|
|
|
ActivatePaint(FALSE);
|
|
|
|
// bkup lastPainMode
|
|
|
|
_LastPaintMode= lpm;
|
|
|
|
|
|
|
|
ReleaseISpinner (iTint);
|
|
|
|
ReleaseISpinner (iGradientBend);
|
|
|
|
|
|
|
|
ModContextList list;
|
|
|
|
INodeTab nodes;
|
|
|
|
ip->GetModContexts(list,nodes);
|
|
|
|
for (int i=0; i<list.Count(); i++) {
|
|
|
|
VertexPaintData *vd = (VertexPaintData*)list[i]->localData;
|
|
|
|
if (vd) vd->FreeCache();
|
|
|
|
}
|
|
|
|
nodes.DisposeTemporary();
|
|
|
|
|
|
|
|
// Reset show end result
|
|
|
|
SetFlag (VP_DISP_END_RESULT, ip->GetShowEndResult() ? TRUE : FALSE);
|
|
|
|
ip->SetShowEndResult(oldShowEnd);
|
|
|
|
|
|
|
|
|
|
|
|
// Exit editMod => draw true colored weights.
|
|
|
|
editMod = NULL;
|
|
|
|
NotifyDependents(FOREVER, PART_VERTCOLOR, REFMSG_CHANGE);
|
|
|
|
|
|
|
|
|
|
|
|
ip->DeleteRollupPage(hParams);
|
|
|
|
hParams = NULL;
|
|
|
|
iTint = NULL;
|
|
|
|
iGradientBend= NULL;
|
|
|
|
this->ip = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//From ReferenceMaker
|
|
|
|
RefResult VertexPaint::NotifyRefChanged(
|
|
|
|
Interval changeInt, RefTargetHandle hTarget,
|
|
|
|
PartID& partID, RefMessage message)
|
|
|
|
{
|
|
|
|
return REF_SUCCEED;
|
|
|
|
}
|
|
|
|
|
|
|
|
int VertexPaint::NumRefs()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefTargetHandle VertexPaint::GetReference(int i)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaint::SetReference(int i, RefTargetHandle rtarg)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int VertexPaint::NumSubs()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Animatable* VertexPaint::SubAnim(int i)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TSTR VertexPaint::SubAnimName(int i)
|
|
|
|
{
|
|
|
|
return _T("");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define VERSION_CHUNKID 0x100
|
|
|
|
#define COLORLIST_CHUNKID 0x120
|
|
|
|
|
|
|
|
static int currentVersion = 1;
|
|
|
|
|
|
|
|
IOResult VertexPaint::Load(ILoad *iload)
|
|
|
|
{
|
|
|
|
IOResult res;
|
|
|
|
ULONG nb;
|
|
|
|
int version = 1;
|
|
|
|
Modifier::Load(iload);
|
|
|
|
|
|
|
|
while (IO_OK==(res=iload->OpenChunk())) {
|
|
|
|
switch(iload->CurChunkID()) {
|
|
|
|
case VERSION_CHUNKID:
|
|
|
|
iload->Read (&version, sizeof(version), &nb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
iload->CloseChunk();
|
|
|
|
if (res!=IO_OK) return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
return IO_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
IOResult VertexPaint::Save(ISave *isave)
|
|
|
|
{
|
|
|
|
IOResult res;
|
|
|
|
ULONG nb;
|
|
|
|
|
|
|
|
Modifier::Save(isave);
|
|
|
|
|
|
|
|
isave->BeginChunk(VERSION_CHUNKID);
|
|
|
|
res = isave->Write (¤tVersion, sizeof(int), &nb);
|
|
|
|
isave->EndChunk();
|
|
|
|
|
|
|
|
return IO_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
IOResult VertexPaint::SaveLocalData(ISave *isave, LocalModData *ld)
|
|
|
|
{
|
|
|
|
VertexPaintData* d = (VertexPaintData*)ld;
|
|
|
|
IOResult res;
|
|
|
|
ULONG nb;
|
|
|
|
int numColors;
|
|
|
|
ColorData col;
|
|
|
|
|
|
|
|
isave->BeginChunk(VERSION_CHUNKID);
|
|
|
|
res = isave->Write (¤tVersion, sizeof(int), &nb);
|
|
|
|
isave->EndChunk();
|
|
|
|
|
|
|
|
isave->BeginChunk(COLORLIST_CHUNKID);
|
|
|
|
numColors = d->GetNumColors();
|
|
|
|
res = isave->Write(&numColors, sizeof(int), &nb);
|
|
|
|
for (int i=0; i<numColors ; i++) {
|
|
|
|
col = d->GetColorData(i);
|
|
|
|
isave->Write(&col.color,sizeof(col.color),&nb);
|
|
|
|
}
|
|
|
|
|
|
|
|
isave->EndChunk();
|
|
|
|
return IO_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
IOResult VertexPaint::LoadLocalData(ILoad *iload, LocalModData **pld) {
|
|
|
|
VertexPaintData *d = new VertexPaintData;
|
|
|
|
IOResult res;
|
|
|
|
ULONG nb;
|
|
|
|
int version = 1;
|
|
|
|
int numColors;
|
|
|
|
ColorData col;
|
|
|
|
|
|
|
|
*pld = d;
|
|
|
|
|
|
|
|
while (IO_OK==(res=iload->OpenChunk())) {
|
|
|
|
switch(iload->CurChunkID()) {
|
|
|
|
case VERSION_CHUNKID:
|
|
|
|
iload->Read (&version, sizeof(version), &nb);
|
|
|
|
break;
|
|
|
|
case COLORLIST_CHUNKID:
|
|
|
|
{
|
|
|
|
iload->Read(&numColors,sizeof(int), &nb);
|
|
|
|
d->AllocColorData(numColors);
|
|
|
|
for (int i=0; i<numColors; i++) {
|
|
|
|
iload->Read(&col.color,sizeof(col.color), &nb);
|
|
|
|
d->SetColor(i, col);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
iload->CloseChunk();
|
|
|
|
if (res!=IO_OK) return res;
|
|
|
|
}
|
|
|
|
return IO_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaint::PaletteButton(HWND hWnd)
|
|
|
|
{
|
|
|
|
IColorSwatch* iPal = GetIColorSwatch(hWnd);
|
|
|
|
if (iPal && iColor) {
|
|
|
|
iColor->SetColor(iPal->GetColor(), TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaint::InitPalettes()
|
|
|
|
{
|
|
|
|
IColorSwatch* c;
|
|
|
|
for (int i=0; i<NUMPALETTES; i++) {
|
|
|
|
c = GetIColorSwatch(hPaletteWnd[i]);
|
|
|
|
c->SetColor(palColors[i]);
|
|
|
|
ReleaseIColorSwatch(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaint::SavePalettes()
|
|
|
|
{
|
|
|
|
IColorSwatch* c;
|
|
|
|
for (int i=0; i<NUMPALETTES; i++) {
|
|
|
|
c = GetIColorSwatch(hPaletteWnd[i]);
|
|
|
|
palColors[i] = c->GetColor();
|
|
|
|
ReleaseIColorSwatch(c);
|
|
|
|
}
|
|
|
|
// Save Gradient Palettes.
|
|
|
|
lastGradientColor[0]= iColorGradient[0]->GetColor();
|
|
|
|
lastGradientColor[1]= iColorGradient[1]->GetColor();
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaint::TurnVCOn(BOOL shaded)
|
|
|
|
{
|
|
|
|
ModContextList list;
|
|
|
|
INodeTab NodeTab;
|
|
|
|
|
|
|
|
// Only the selected nodes will be affected
|
|
|
|
ip->GetModContexts(list,NodeTab);
|
|
|
|
|
|
|
|
for( int i = 0 ; i < NodeTab.Count() ; i++)
|
|
|
|
{
|
|
|
|
if(shaded)
|
|
|
|
NodeTab[i]->SetShadeCVerts(!NodeTab[i]->GetShadeCVerts());
|
|
|
|
else
|
|
|
|
NodeTab[i]->SetCVertMode(!NodeTab[i]->GetCVertMode());
|
|
|
|
|
|
|
|
}
|
|
|
|
NotifyDependents(FOREVER, PART_VERTCOLOR, REFMSG_CHANGE);
|
|
|
|
ip->RedrawViews(ip->GetTime());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// *****************************************************************
|
|
|
|
void VertexPaint::setEditionType(int editMode)
|
|
|
|
{
|
|
|
|
if(editMode<0) editMode= 0;
|
|
|
|
if(editMode>2) editMode= 2;
|
|
|
|
|
|
|
|
// backup current Color according to editMode
|
|
|
|
backupCurrentColor();
|
|
|
|
|
|
|
|
_EditType= editMode;
|
|
|
|
|
|
|
|
NotifyDependents(FOREVER, PART_VERTCOLOR, REFMSG_CHANGE);
|
|
|
|
ip->RedrawViews(ip->GetTime());
|
|
|
|
|
|
|
|
// Change Color Swatch according to editMode.
|
|
|
|
IColorSwatch* c;
|
|
|
|
for (int i=0; i<NUMPALETTES; i++)
|
|
|
|
{
|
|
|
|
// Change palColors[i].
|
|
|
|
int val;
|
|
|
|
if(editMode==0)
|
|
|
|
val= i*255 / (4-1); // 0, 85, 170, 255
|
|
|
|
else
|
|
|
|
val= (i*256+128) / 4; // 32, 96, 160, 224
|
|
|
|
// Change Addditional Palette colors.
|
|
|
|
if(i>=4)
|
|
|
|
{
|
|
|
|
if(editMode==0)
|
|
|
|
val= 42 + (i-4)*255 / (4-1); // 42, 127, 212
|
|
|
|
else
|
|
|
|
val= 0; // Phase not used
|
|
|
|
}
|
|
|
|
// Setup Color
|
|
|
|
palColors[i]= RGB(val, val, val);
|
|
|
|
|
|
|
|
|
|
|
|
c = GetIColorSwatch(hPaletteWnd[i]);
|
|
|
|
c->SetColor(palColors[i]);
|
|
|
|
ReleaseIColorSwatch(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
// change current Color according to editMode
|
|
|
|
reloadBkupColor();
|
|
|
|
}
|
|
|
|
|
|
|
|
// *****************************************************************
|
|
|
|
void VertexPaint::backupCurrentColor()
|
|
|
|
{
|
|
|
|
switch(getEditionType())
|
|
|
|
{
|
|
|
|
case 0: lastWeightColor = iColor->GetColor(); break;
|
|
|
|
case 1:
|
|
|
|
case 2: lastPhaseColor = iColor->GetColor(); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void VertexPaint::reloadBkupColor()
|
|
|
|
{
|
|
|
|
// Change current color according to editMode.
|
|
|
|
switch(getEditionType())
|
|
|
|
{
|
|
|
|
case 0: iColor->SetColor(lastWeightColor); break;
|
|
|
|
case 1:
|
|
|
|
case 2: iColor->SetColor(lastPhaseColor); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// *****************************************************************
|
|
|
|
void VertexPaint::fillSelectionColor()
|
|
|
|
{
|
|
|
|
int mci;
|
|
|
|
|
|
|
|
// Put Data in Undo/Redo List.
|
|
|
|
if(!theHold.Holding())
|
|
|
|
theHold.Begin();
|
|
|
|
|
|
|
|
ModContextList modContexts;
|
|
|
|
INodeTab nodeTab;
|
|
|
|
|
|
|
|
GetCOREInterface()->GetModContexts(modContexts, nodeTab);
|
|
|
|
|
|
|
|
for (mci=0; mci<modContexts.Count(); mci++)
|
|
|
|
{
|
|
|
|
ModContext *mc = modContexts[mci];
|
|
|
|
if(mc && mc->localData)
|
|
|
|
theHold.Put(new VertexPaintRestore((VertexPaintData*)mc->localData, this));
|
|
|
|
}
|
|
|
|
|
|
|
|
theHold.Accept(GetString(IDS_RESTORE_FILL));
|
|
|
|
|
|
|
|
|
|
|
|
// Which Component to change??
|
|
|
|
VertexPaintData::TComponent whichComponent;
|
|
|
|
switch(getEditionType())
|
|
|
|
{
|
|
|
|
case 0: whichComponent= VertexPaintData::Red; break;
|
|
|
|
case 1: whichComponent= VertexPaintData::Green; break;
|
|
|
|
case 2: whichComponent= VertexPaintData::Blue; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Modify all meshes.
|
|
|
|
for (mci=0; mci<modContexts.Count(); mci++)
|
|
|
|
{
|
|
|
|
ModContext *mc = modContexts[mci];
|
|
|
|
if(mc && mc->localData)
|
|
|
|
{
|
|
|
|
VertexPaintData* d = (VertexPaintData*)mc->localData;
|
|
|
|
Mesh* mesh = d->GetMesh();
|
|
|
|
if (mesh && mesh->vertCol)
|
|
|
|
{
|
|
|
|
// For all faces of the mesh
|
|
|
|
for(int fi=0; fi<mesh->getNumFaces(); fi++)
|
|
|
|
{
|
|
|
|
Face* f = &mesh->faces[fi];
|
|
|
|
|
|
|
|
for (int i=0; i<3; i++)
|
|
|
|
{
|
|
|
|
// Skip painting because not selected??
|
|
|
|
if(mesh->selLevel == MESH_VERTEX && !mesh->VertSel()[f->v[i]] )
|
|
|
|
continue;
|
|
|
|
if(mesh->selLevel == MESH_FACE && !mesh->FaceSel()[fi])
|
|
|
|
continue;
|
|
|
|
// Also skip if face is hidden.
|
|
|
|
if(f->Hidden())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Apply painting
|
|
|
|
d->SetColor(f->v[i], 1, GetActiveColor(), whichComponent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// refresh
|
|
|
|
NotifyDependents(FOREVER, PART_VERTCOLOR, REFMSG_CHANGE);
|
|
|
|
ip->RedrawViews(ip->GetTime());
|
|
|
|
}
|
|
|
|
|
|
|
|
// *****************************************************************
|
|
|
|
void VertexPaint::fillSelectionGradientColor()
|
|
|
|
{
|
|
|
|
int mci;
|
|
|
|
|
|
|
|
// Put Data in Undo/Redo List.
|
|
|
|
if(!theHold.Holding())
|
|
|
|
theHold.Begin();
|
|
|
|
|
|
|
|
ModContextList modContexts;
|
|
|
|
INodeTab nodeTab;
|
|
|
|
|
|
|
|
GetCOREInterface()->GetModContexts(modContexts, nodeTab);
|
|
|
|
|
|
|
|
for (mci=0; mci<modContexts.Count(); mci++)
|
|
|
|
{
|
|
|
|
ModContext *mc = modContexts[mci];
|
|
|
|
if(mc && mc->localData)
|
|
|
|
theHold.Put(new VertexPaintRestore((VertexPaintData*)mc->localData, this));
|
|
|
|
}
|
|
|
|
|
|
|
|
theHold.Accept(GetString(IDS_RESTORE_GRADIENT));
|
|
|
|
|
|
|
|
|
|
|
|
// Which Component to change??
|
|
|
|
VertexPaintData::TComponent whichComponent;
|
|
|
|
switch(getEditionType())
|
|
|
|
{
|
|
|
|
case 0: whichComponent= VertexPaintData::Red; break;
|
|
|
|
case 1: whichComponent= VertexPaintData::Green; break;
|
|
|
|
case 2: whichComponent= VertexPaintData::Blue; break;
|
|
|
|
}
|
|
|
|
COLORREF grad0= iColorGradient[0]->GetColor();
|
|
|
|
COLORREF grad1= iColorGradient[1]->GetColor();
|
|
|
|
|
|
|
|
|
|
|
|
// Get Matrix to viewport.
|
|
|
|
Matrix3 viewMat;
|
|
|
|
{
|
|
|
|
ViewExp *ve = GetCOREInterface()->GetActiveViewport();
|
|
|
|
// The affine TM transforms from world coords to view coords
|
|
|
|
ve->GetAffineTM(viewMat);
|
|
|
|
GetCOREInterface()->ReleaseViewport(ve);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Modify all meshes.
|
|
|
|
for (mci=0; mci<modContexts.Count(); mci++)
|
|
|
|
{
|
|
|
|
ModContext *mc = modContexts[mci];
|
|
|
|
if(mc && mc->localData)
|
|
|
|
{
|
|
|
|
VertexPaintData* d = (VertexPaintData*)mc->localData;
|
|
|
|
Mesh* mesh = d->GetMesh();
|
|
|
|
if (mesh && mesh->vertCol)
|
|
|
|
{
|
|
|
|
float yMini= FLT_MAX;
|
|
|
|
float yMaxi= -FLT_MAX;
|
|
|
|
|
|
|
|
// 1st, For all faces of the mesh, comute BBox of selection.
|
|
|
|
int fi;
|
|
|
|
for(fi=0; fi<mesh->getNumFaces(); fi++)
|
|
|
|
{
|
|
|
|
Face* f = &mesh->faces[fi];
|
|
|
|
|
|
|
|
for (int i=0; i<3; i++)
|
|
|
|
{
|
|
|
|
// Skip painting because not selected??
|
|
|
|
if(mesh->selLevel == MESH_VERTEX && !mesh->VertSel()[f->v[i]] )
|
|
|
|
continue;
|
|
|
|
if(mesh->selLevel == MESH_FACE && !mesh->FaceSel()[fi])
|
|
|
|
continue;
|
|
|
|
// Also skip if face is hidden.
|
|
|
|
if(f->Hidden())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Transform to viewSpace.
|
|
|
|
Point3 p= viewMat*mesh->getVert(f->v[i]);
|
|
|
|
// extend bbox.
|
|
|
|
yMini= p.y<yMini?p.y:yMini;
|
|
|
|
yMaxi= p.y>yMaxi?p.y:yMaxi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2nd, For all faces of the mesh, fill with gradient
|
|
|
|
for(fi=0; fi<mesh->getNumFaces(); fi++)
|
|
|
|
{
|
|
|
|
Face* f = &mesh->faces[fi];
|
|
|
|
|
|
|
|
for (int i=0; i<3; i++)
|
|
|
|
{
|
|
|
|
// Skip painting because not selected??
|
|
|
|
if(mesh->selLevel == MESH_VERTEX && !mesh->VertSel()[f->v[i]] )
|
|
|
|
continue;
|
|
|
|
if(mesh->selLevel == MESH_FACE && !mesh->FaceSel()[fi])
|
|
|
|
continue;
|
|
|
|
// Also skip if face is hidden.
|
|
|
|
if(f->Hidden())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Compute gradientValue.
|
|
|
|
float gradValue;
|
|
|
|
Point3 p= viewMat*mesh->getVert(f->v[i]);
|
|
|
|
gradValue= (p.y-yMini)/(yMaxi-yMini);
|
|
|
|
// Modifie with bendPower. 1->6.
|
|
|
|
float pow= 1 + fGradientBend * 5;
|
|
|
|
gradValue= powf(gradValue, pow);
|
|
|
|
|
|
|
|
// Apply painting
|
|
|
|
// Reset To 0.
|
|
|
|
d->SetColor(f->v[i], 1, grad0, whichComponent);
|
|
|
|
// Blend with gradientValue.
|
|
|
|
d->SetColor(f->v[i], gradValue, grad1, whichComponent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// refresh
|
|
|
|
NotifyDependents(FOREVER, PART_VERTCOLOR, REFMSG_CHANGE);
|
|
|
|
ip->RedrawViews(ip->GetTime());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// *****************************************************************
|
|
|
|
VertexPaintData::VertexPaintData(Mesh& m) : mesh(NULL), colordata(NULL), nverts(NULL),
|
|
|
|
nvcverts(NULL), numColors(0), numnverts(0), numnvcverts(0)
|
|
|
|
{
|
|
|
|
SetCache(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
VertexPaintData::VertexPaintData() : mesh(NULL), colordata(NULL), nverts(NULL),
|
|
|
|
nvcverts(NULL), numColors(0), numnverts(0), numnvcverts(0)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
VertexPaintData::~VertexPaintData()
|
|
|
|
{
|
|
|
|
FreeCache();
|
|
|
|
|
|
|
|
if (colordata) delete [] colordata;
|
|
|
|
if(nverts) delete [] nverts;
|
|
|
|
if(nvcverts) delete [] nvcverts;
|
|
|
|
|
|
|
|
nverts = NULL;
|
|
|
|
nvcverts = NULL;
|
|
|
|
colordata = NULL;
|
|
|
|
|
|
|
|
numColors = 0;
|
|
|
|
numnverts = 0;
|
|
|
|
numnvcverts = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaintData::SetCache(Mesh& m)
|
|
|
|
{
|
|
|
|
FreeCache();
|
|
|
|
mesh = new Mesh(m);
|
|
|
|
SynchVerts(m);
|
|
|
|
AllocColorData(mesh->getNumVerts());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaintData::FreeCache()
|
|
|
|
{
|
|
|
|
if (mesh) delete mesh;
|
|
|
|
if(nverts) delete [] nverts;
|
|
|
|
if(nvcverts) delete [] nvcverts;
|
|
|
|
|
|
|
|
mesh = NULL;
|
|
|
|
nverts = NULL;
|
|
|
|
nvcverts = NULL;
|
|
|
|
numnverts = 0;
|
|
|
|
numnvcverts = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Mesh* VertexPaintData::GetMesh()
|
|
|
|
{
|
|
|
|
return mesh;
|
|
|
|
}
|
|
|
|
|
|
|
|
NVert& VertexPaintData::GetNVert(int i)
|
|
|
|
{
|
|
|
|
static NVert nv;
|
|
|
|
|
|
|
|
if (numnverts > i)
|
|
|
|
return nverts[i];
|
|
|
|
else
|
|
|
|
return nv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NVert& VertexPaintData::GetNVCVert(int i)
|
|
|
|
{
|
|
|
|
static NVert nv;
|
|
|
|
|
|
|
|
if (numnvcverts > i)
|
|
|
|
return nvcverts[i];
|
|
|
|
else
|
|
|
|
return nv;
|
|
|
|
}
|
|
|
|
|
|
|
|
COLORREF& VertexPaintData::GetColor(int i)
|
|
|
|
{
|
|
|
|
static COLORREF c = RGB(0,0,0);
|
|
|
|
if (numColors > i)
|
|
|
|
return colordata[i].color;
|
|
|
|
else
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
ColorData& VertexPaintData::GetColorData(int i)
|
|
|
|
{
|
|
|
|
static ColorData c;
|
|
|
|
|
|
|
|
if (numColors > i)
|
|
|
|
return colordata[i];
|
|
|
|
else
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaintData::SetColor(int i, float bary, COLORREF c, TComponent whichComp)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (colordata && numColors > i)
|
|
|
|
{
|
|
|
|
// change color.
|
|
|
|
COLORREF oldColor= colordata[i].color;
|
|
|
|
int oldVal;
|
|
|
|
int editVal;
|
|
|
|
int newVal;
|
|
|
|
|
|
|
|
// Mask good component.
|
|
|
|
switch(whichComp)
|
|
|
|
{
|
|
|
|
case Red:
|
|
|
|
oldVal= GetRValue(colordata[i].color);
|
|
|
|
editVal= GetRValue(c);
|
|
|
|
break;
|
|
|
|
case Green:
|
|
|
|
oldVal= GetGValue(colordata[i].color);
|
|
|
|
editVal= GetGValue(c);
|
|
|
|
break;
|
|
|
|
case Blue:
|
|
|
|
oldVal= GetBValue(colordata[i].color);
|
|
|
|
editVal= GetBValue(c);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Blend Color component
|
|
|
|
// This color was set before !
|
|
|
|
float alpha = (1.0f-bary);
|
|
|
|
|
|
|
|
// Compute new value
|
|
|
|
newVal= (int)(alpha*oldVal + bary*editVal);
|
|
|
|
|
|
|
|
// Mask good component.
|
|
|
|
switch(whichComp)
|
|
|
|
{
|
|
|
|
case Red:
|
|
|
|
colordata[i].color= (RGB(newVal, 0, 0)) | (oldColor & RGB(0,255,255));
|
|
|
|
break;
|
|
|
|
case Green:
|
|
|
|
colordata[i].color= (RGB(0, newVal, 0)) | (oldColor & RGB(255,0,255));
|
|
|
|
break;
|
|
|
|
case Blue:
|
|
|
|
colordata[i].color= (RGB(0, 0, newVal)) | (oldColor & RGB(255,255,0));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaintData::SetColor(int i, const ColorData &c)
|
|
|
|
{
|
|
|
|
if (colordata && numColors > i)
|
|
|
|
{
|
|
|
|
colordata[i]= c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int VertexPaintData::GetNumColors()
|
|
|
|
{
|
|
|
|
return numColors;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaintData::AllocColorData(int numcols)
|
|
|
|
{
|
|
|
|
ColorData* newColorData;
|
|
|
|
|
|
|
|
// Colors already exist.
|
|
|
|
if (numColors == numcols)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (numColors > 0 )
|
|
|
|
{
|
|
|
|
// If the new number of colors is bigger than what we have in the colordata array
|
|
|
|
if(numcols > numColors)
|
|
|
|
{
|
|
|
|
// Allocate a new color list and fill in as many as
|
|
|
|
// we have from the previous set
|
|
|
|
newColorData = new ColorData[numcols];
|
|
|
|
|
|
|
|
for (int i=0; i<numcols; i++)
|
|
|
|
{
|
|
|
|
if (i < numColors)
|
|
|
|
{
|
|
|
|
newColorData[i] = colordata[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delete [] colordata;
|
|
|
|
|
|
|
|
colordata = newColorData;
|
|
|
|
|
|
|
|
numColors = numcols;
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
numColors = numcols;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Allocate a complete new set of colors
|
|
|
|
numColors = numcols;
|
|
|
|
colordata = new ColorData[numColors];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LocalModData* VertexPaintData::Clone()
|
|
|
|
{
|
|
|
|
VertexPaintData* d = new VertexPaintData();
|
|
|
|
|
|
|
|
if (colordata) {
|
|
|
|
d->colordata = new ColorData[numColors];
|
|
|
|
d->numColors = numColors;
|
|
|
|
for (int i=0; i<numColors; i++) {
|
|
|
|
d->colordata[i] = colordata[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(nverts)
|
|
|
|
{
|
|
|
|
d->nverts = new NVert[numnverts];
|
|
|
|
for(int i = 0 ; i < numnverts ; i++ ) {
|
|
|
|
d->nverts[i] = nverts[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
if(nvcverts)
|
|
|
|
{
|
|
|
|
d->nvcverts = new NVert[numnvcverts];
|
|
|
|
for(int i = 0 ; i < numnvcverts ; i++ ) {
|
|
|
|
d->nvcverts[i] = nvcverts[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void VertexPaintData::SynchVerts(Mesh &m)
|
|
|
|
{
|
2010-06-04 22:48:19 +00:00
|
|
|
if (mesh == NULL)
|
|
|
|
{
|
|
|
|
nlwarning("mesh == NULL");
|
|
|
|
return;
|
|
|
|
}
|
2010-05-06 00:08:41 +00:00
|
|
|
|
|
|
|
if(nverts)
|
|
|
|
delete [] nverts;
|
|
|
|
|
|
|
|
numnverts = m.getNumVerts();
|
|
|
|
|
|
|
|
nverts = new NVert[numnverts];
|
|
|
|
|
|
|
|
if(nvcverts)
|
|
|
|
delete [] nvcverts;
|
|
|
|
|
|
|
|
numnvcverts = m.getNumVertCol();
|
|
|
|
|
|
|
|
nvcverts = new NVert[numnvcverts];
|
|
|
|
|
|
|
|
for(int i = 0 ; i < mesh->getNumFaces() ; i++)
|
|
|
|
{
|
|
|
|
// for each vertex of each face
|
|
|
|
for(int j = 0 ; j < 3 ; j++)
|
|
|
|
{
|
|
|
|
int iCur = nverts[mesh->faces[i].v[j]].faces.Count();
|
|
|
|
|
|
|
|
// Tell the vertex, which to which face it belongs and which
|
|
|
|
// of the three face v-indices corresponds to the vertex
|
|
|
|
|
|
|
|
nverts[mesh->faces[i].v[j]].faces.SetCount(iCur+1);
|
|
|
|
nverts[mesh->faces[i].v[j]].whichVertex.SetCount(iCur+1);
|
|
|
|
|
|
|
|
nverts[mesh->faces[i].v[j]].faces[iCur] = i;
|
|
|
|
nverts[mesh->faces[i].v[j]].whichVertex[iCur] = j;
|
|
|
|
|
|
|
|
|
|
|
|
if(mesh->vcFace)
|
|
|
|
{
|
|
|
|
// Do the same for texture vertices
|
|
|
|
iCur = nvcverts[mesh->vcFace[i].t[j]].faces.Count();
|
|
|
|
|
|
|
|
nvcverts[mesh->vcFace[i].t[j]].faces.SetCount(iCur+1);
|
|
|
|
nvcverts[mesh->vcFace[i].t[j]].whichVertex.SetCount(iCur+1);
|
|
|
|
|
|
|
|
nvcverts[mesh->vcFace[i].t[j]].faces[iCur] = i;
|
|
|
|
nvcverts[mesh->vcFace[i].t[j]].whichVertex[iCur] = j;
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
//**
|
|
|
|
//** NVert
|
|
|
|
//**
|
|
|
|
//***************************************************************************
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NVert::NVert()
|
|
|
|
{
|
|
|
|
faces.SetCount(0);
|
|
|
|
whichVertex.SetCount(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
NVert& NVert::operator= (NVert &nvert)
|
|
|
|
{
|
|
|
|
faces = nvert.faces;
|
|
|
|
whichVertex = nvert.whichVertex;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
//**
|
|
|
|
//** ColorData
|
|
|
|
//**
|
|
|
|
//***************************************************************************
|
|
|
|
|
|
|
|
|
|
|
|
ColorData::ColorData(DWORD col) : color(col)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
ColorData::ColorData() : color(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
//**
|
|
|
|
//** VertexPaintRestore : public RestoreObj
|
|
|
|
//**
|
|
|
|
//***************************************************************************
|
|
|
|
|
|
|
|
VertexPaintRestore::VertexPaintRestore(VertexPaintData *pLocalData, VertexPaint *pVPaint)
|
|
|
|
: pMod(pVPaint), pPaintData(pLocalData), redoColordata(NULL)
|
|
|
|
{
|
|
|
|
colordata = new ColorData[pPaintData->numColors];
|
|
|
|
for(int i = 0; i < pPaintData->numColors ; i++)
|
|
|
|
{
|
|
|
|
colordata[i] = pPaintData->colordata[i];
|
|
|
|
}
|
|
|
|
numcolors = pPaintData->numColors;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
VertexPaintRestore::~VertexPaintRestore()
|
|
|
|
{
|
|
|
|
if(colordata)
|
|
|
|
delete [] colordata;
|
|
|
|
|
|
|
|
if(redoColordata)
|
|
|
|
delete [] redoColordata;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaintRestore::Restore(int isUndo)
|
|
|
|
{
|
|
|
|
if(isUndo)
|
|
|
|
{
|
|
|
|
assert(pPaintData->colordata);
|
|
|
|
|
|
|
|
redoColordata = pPaintData->colordata;
|
|
|
|
redonumcolors = pPaintData->numColors;
|
|
|
|
|
|
|
|
pPaintData->colordata = colordata;
|
|
|
|
pPaintData->numColors = numcolors;
|
|
|
|
|
|
|
|
colordata = NULL;
|
|
|
|
|
|
|
|
pMod->NotifyDependents(FOREVER, PART_VERTCOLOR, REFMSG_CHANGE);
|
|
|
|
GetCOREInterface()->RedrawViews(GetCOREInterface()->GetTime());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VertexPaintRestore::Redo()
|
|
|
|
{
|
|
|
|
assert(pPaintData->colordata);
|
|
|
|
|
|
|
|
colordata = pPaintData->colordata;
|
|
|
|
numcolors = pPaintData->numColors;
|
|
|
|
|
|
|
|
pPaintData->colordata = redoColordata;
|
|
|
|
pPaintData->numColors = redonumcolors;
|
|
|
|
|
|
|
|
redoColordata = NULL;
|
|
|
|
|
|
|
|
pMod->NotifyDependents(FOREVER, PART_VERTCOLOR, REFMSG_CHANGE);
|
|
|
|
GetCOREInterface()->RedrawViews(GetCOREInterface()->GetTime());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int VertexPaintRestore::Size()
|
|
|
|
{
|
|
|
|
int iSize = 0;
|
|
|
|
|
|
|
|
if(colordata)
|
|
|
|
iSize += sizeof(ColorData) * numcolors;
|
|
|
|
|
|
|
|
if(redoColordata)
|
|
|
|
iSize += sizeof(ColorData) * redonumcolors;
|
|
|
|
|
|
|
|
return iSize;
|
|
|
|
}
|
|
|
|
|