1353 lines
30 KiB
C++
1353 lines
30 KiB
C++
/**********************************************************************
|
|
*<
|
|
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 INT_PTR CALLBACK VertexPaintDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int numPoints;
|
|
VertexPaint *mod = (VertexPaint*)GetWindowLongPtr(hWnd, GWLP_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;
|
|
SetWindowLongPtr(hWnd, GWLP_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_PTR mod = GetWindowLongPtr(hPanel, GWLP_USERDATA);
|
|
if (mod)
|
|
{
|
|
((VertexPaint*)mod)->PaletteButton(hwnd);
|
|
}
|
|
}
|
|
break;
|
|
case WM_DESTROY:
|
|
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)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)SetWindowLongPtr(hPaletteWnd[i], GWLP_WNDPROC, (LONG_PTR)colorSwatchSubclassWndProc);
|
|
}
|
|
|
|
SendMessage(hParams, WM_POSTINIT, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
SetWindowLongPtr(hParams, GWLP_USERDATA, (LONG_PTR)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(const Interval& changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message, BOOL propagate)
|
|
{
|
|
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)
|
|
{
|
|
if (mesh == NULL)
|
|
{
|
|
nlwarning("mesh == NULL");
|
|
return;
|
|
}
|
|
|
|
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
|
|
nlassert(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)
|
|
{
|
|
nlassert(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()
|
|
{
|
|
nlassert(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;
|
|
}
|
|
|