| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** 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 3 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, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Commando Tools - WWSkin *
- * *
- * $Archive:: /Commando/Code/Tools/max2w3d/skin.cpp $*
- * *
- * $Author:: Greg_h $*
- * *
- * $Modtime:: 4/24/01 5:15p $*
- * *
- * $Revision:: 13 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "skin.h"
- #include "dllmain.h"
- #include "max.h"
- #include "simpmod.h"
- #include "simpobj.h"
- #include "resource.h"
- #include "skindata.h"
- #include "bpick.h"
- #include "namedsel.h"
- #include "boneicon.h"
- #if defined W3D_MAX4 //defined as in the project (.dsp)
- static GenSubObjType _SubObjectTypeVertex(1);
- #endif
- /*
- ** Static functions
- */
- static BOOL CALLBACK _sot_dialog_proc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
- static BOOL CALLBACK _skeleton_dialog_thunk(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
- static BOOL CALLBACK _bone_influence_dialog_thunk(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
- static TriObject * Get_Tri_Object(TimeValue t,ObjectState & os,Interval & valid,BOOL & needsdel);
- static float Bone_Distance(INode * bone,TimeValue time,const Point3 & vertex);
- /*
- ** Static variables
- */
- HWND SkinWSMObjectClass::SotHWND = NULL;
- HWND SkinWSMObjectClass::SkeletonHWND = NULL;
- HWND SkinWSMObjectClass::BoneListHWND = NULL;
- IObjParam * SkinWSMObjectClass::InterfacePtr = NULL;
- ICustButton * SkinWSMObjectClass::AddBonesButton = NULL;
- ICustButton * SkinWSMObjectClass::RemoveBonesButton = NULL;
- ISpinnerControl * SkinWSMObjectClass::BasePoseSpin = NULL;
- /*******************************************************************************
- **
- ** Class Descriptor for SkinWSMObjectClass
- **
- *******************************************************************************/
- class SkinWSMObjectClassDesc:public ClassDesc
- {
- public:
- int IsPublic() { return 1; }
- void * Create(BOOL loading = FALSE) { return new SkinWSMObjectClass; }
- const TCHAR * ClassName() { return _T("WWSkin"); }
- SClass_ID SuperClassID() { return WSM_OBJECT_CLASS_ID; }
- Class_ID ClassID() { return SKIN_OBJ_CLASS_ID; }
- const TCHAR* Category() { return _T("Westwood Space Warps"); }
- };
- static SkinWSMObjectClassDesc _SkinWSMObjectDesc;
- ClassDesc * Get_Skin_Obj_Desc() { return &_SkinWSMObjectDesc; }
- /*******************************************************************************
- **
- ** Class Descriptor for the SkinModifier
- **
- *******************************************************************************/
- class SkinModClassDesc:public ClassDesc
- {
- public:
- int IsPublic() { return 0; }
- void * Create(BOOL loading = FALSE) { return new SkinModifierClass; }
- const TCHAR * ClassName() { return _T("WWSkin"); }
- SClass_ID SuperClassID() { return WSM_CLASS_ID; }
- Class_ID ClassID() { return SKIN_MOD_CLASS_ID; }
- const TCHAR * Category() { return _T("Westwood Space Warps"); }
- };
- static SkinModClassDesc _SkinModDesc;
- ClassDesc * Get_Skin_Mod_Desc() { return &_SkinModDesc; }
- /*******************************************************************************
- **
- ** SkinWSMObjectCreateCallback
- ** A class derived from CreateMouseCallBack to handle
- ** the user input during the creation phase of the SkinWSMObject.
- **
- *******************************************************************************/
- class SkinWSMObjectCreateCallBack : public CreateMouseCallBack
- {
- public:
- int proc( ViewExp * vpt,int msg, int point, int flags, IPoint2 m, Matrix3 & mat)
- {
- if (msg == MOUSE_POINT) {
- Point3 pos = vpt->GetPointOnCP(m);
- mat.IdentityMatrix();
- mat.SetTrans(pos);
- return CREATE_STOP;
- }
- return TRUE;
- }
- };
- static SkinWSMObjectCreateCallBack _SkinCreateCB;
- /*******************************************************************************
- **
- ** SkinWSMObjectClass
- **
- *******************************************************************************/
- SkinWSMObjectClass::SkinWSMObjectClass()
- {
- /*
- ** Initialize class variables to default state!
- */
- MeshBuilt = FALSE;
- BoneSelectionMode = BONE_SEL_MODE_NONE;
- BoneTab.SetCount(0);
- BasePoseFrame = 0;
- pblock = NULL;
- }
- SkinWSMObjectClass::~SkinWSMObjectClass(void)
- {
- assert(!((InterfacePtr == NULL) && (SotHWND != NULL)));
- if (SotHWND != NULL) {
- InterfacePtr->UnRegisterDlgWnd(SotHWND);
- InterfacePtr->DeleteRollupPage(SotHWND);
- SotHWND = NULL;
- }
- assert(!((InterfacePtr == NULL) && (SkeletonHWND != NULL)));
- if (SkeletonHWND != NULL) {
- InterfacePtr->UnRegisterDlgWnd(SkeletonHWND);
- InterfacePtr->DeleteRollupPage(SkeletonHWND);
- SkeletonHWND = NULL;
- }
- }
- void SkinWSMObjectClass::BeginEditParams(IObjParam *ip, ULONG flags,Animatable *prev)
- {
- SimpleWSMObject::BeginEditParams(ip,flags,prev);
- /*
- ** save off a copy of the interface pointer
- */
- InterfacePtr = ip;
- /*
- ** Install the "supports objects of type" rollup
- */
- if (SotHWND == NULL) {
- SotHWND = ip->AddRollupPage(
- AppInstance,
- MAKEINTRESOURCE(IDD_SKIN_SOT),
- _sot_dialog_proc,
- Get_String(IDS_SOT),
- (LPARAM)InterfacePtr,
- APPENDROLL_CLOSED);
- } else {
- SetWindowLong(SotHWND,GWL_USERDATA,(LPARAM)ip);
- }
- /*
- ** Install the skeleton rollup
- */
- if (SkeletonHWND == NULL) {
- SkeletonHWND = InterfacePtr->AddRollupPage(
- AppInstance,
- MAKEINTRESOURCE(IDD_SKELETON_PARAMETERS),
- _skeleton_dialog_thunk,
- Get_String(IDS_SKELETON_PARAMETERS),
- (LPARAM)this,
- 0);
- } else {
- SetWindowLong(SkeletonHWND,GWL_USERDATA,(LPARAM)this);
- }
- Update_Bone_List();
- }
- void SkinWSMObjectClass::EndEditParams(IObjParam *ip, ULONG flags,Animatable *next)
- {
- SimpleWSMObject::EndEditParams(ip,flags,next);
- if (flags & END_EDIT_REMOVEUI) {
- /*
- ** Remove the Sot rollup
- */
- if (SotHWND != NULL) {
- InterfacePtr->UnRegisterDlgWnd(SotHWND);
- InterfacePtr->DeleteRollupPage(SotHWND);
- SotHWND = NULL;
- }
-
- /*
- ** Remove the info rollup
- */
- if (SkeletonHWND != NULL) {
- InterfacePtr->UnRegisterDlgWnd(SkeletonHWND);
- InterfacePtr->DeleteRollupPage(SkeletonHWND);
- SkeletonHWND = NULL;
- }
- }
- /*
- ** get rid of our copy of the interface pointer
- */
- InterfacePtr = NULL;
- }
- RefTargetHandle SkinWSMObjectClass::Clone(RemapDir & remap)
- {
- /*
- ** create another SkinWSMObject and return it.
- */
- SkinWSMObjectClass * sobj = new SkinWSMObjectClass();
- return(sobj);
- }
- RefTargetHandle SkinWSMObjectClass::GetReference(int i)
- {
- /*
- ** return reference "i". If i==0, the reference belongs
- ** to SimpleWSMObject so thunk down to it.
- */
- if (i < SimpleWSMObject::NumRefs()) {
- return SimpleWSMObject::GetReference(i);
- }
- /*
- ** The rest of the references are ours.
- */
- int boneidx = To_Bone_Index(i);
- return BoneTab[boneidx];
- }
- void SkinWSMObjectClass::SetReference(int i, RefTargetHandle rtarg)
- {
- if (i < SimpleWSMObject::NumRefs()) {
- SimpleWSMObject::SetReference(i,rtarg);
- } else {
- int boneidx = To_Bone_Index(i);
- assert(boneidx >= 0);
- assert(boneidx < BoneTab.Count());
- BoneTab[boneidx] = (INode *)rtarg;
- }
- }
- RefResult SkinWSMObjectClass::NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID& partID, RefMessage message)
- {
- int i;
- switch (message) {
- case REFMSG_TARGET_DELETED:
- for (i=0; i<BoneTab.Count(); i++) {
- if (BoneTab[i] == hTarget) {
- break;
- }
- }
- if (i < BoneTab.Count()) {
- BoneTab.Delete(i,1);
- // TODO: cause all Modifier objects to re-index to accomodate
- // the deletion of this bone!!
- }
- break;
- }
- return(REF_SUCCEED);
- }
- CreateMouseCallBack * SkinWSMObjectClass::GetCreateMouseCallBack(void)
- {
- /*
- ** The "CreateMouseCallback" is used when creating the
- ** object. Since our object doesn't need an interactive
- ** creation phase, we return NULL.
- */
- return &_SkinCreateCB;
- }
- Modifier * SkinWSMObjectClass::CreateWSMMod(INode *node)
- {
- /*
- ** create an instance of a SkinModifierClass...
- */
- return new SkinModifierClass(node,this);
- }
- void SkinWSMObjectClass::BuildMesh(TimeValue t)
- {
- int i;
- /*
- ** We only need to build the object mesh once since it
- ** doesn't change or animate...
- */
- if (MeshBuilt) return;
- /*
- ** Set our validity interval, since this mesh doesn't animate
- ** we just use FOREVER.
- */
- ivalid = FOREVER;
-
- /*
- ** Ok, this is the first time BuildMesh has been called.
- ** Create a mesh which will represent this space warp object in
- ** in the max viewports. Note that we are using the mesh
- ** member which is inherited from SimpleWSMObject.
- */
- mesh.setNumVerts(NumBoneIconVerts);
- mesh.setNumFaces(NumBoneIconFaces);
- for (i=0; i<NumBoneIconVerts; i++) {
- mesh.setVert(i, Point3(BoneIconVerts[i].X, BoneIconVerts[i].Y, BoneIconVerts[i].Z));
- }
- for (i=0; i<NumBoneIconFaces; i++) {
- Build_Tri(&(mesh.faces[i]),BoneIconFaces[i].V0,BoneIconFaces[i].V1,BoneIconFaces[i].V2);
- }
- mesh.InvalidateGeomCache();
- MeshBuilt = TRUE;
- }
- void SkinWSMObjectClass::Build_Tri(Face * f, int a, int b, int c)
- {
- f->setVerts(a, b, c);
- f->setSmGroup(0);
- f->setEdgeVisFlags(1,1,1);
- }
- void SkinWSMObjectClass::User_Picked_Bone(INode * node)
- {
- // TODO: Undo/Redo!
- switch (BoneSelectionMode) {
- case BONE_SEL_MODE_ADD:
- Add_Bone(node);
- break;
- case BONE_SEL_MODE_REMOVE:
- Remove_Bone(node);
- break;
- default:
- assert(0);
- }
-
- Set_Bone_Selection_Mode(BONE_SEL_MODE_NONE);
- Update_Bone_List();
- }
- void SkinWSMObjectClass::User_Picked_Bones(INodeTab & nodetab)
- {
- // TODO: Undo/Redo!
- switch (BoneSelectionMode) {
- case BONE_SEL_MODE_ADD_MANY:
- Add_Bones(nodetab);
- break;
- case BONE_SEL_MODE_REMOVE_MANY:
- Remove_Bones(nodetab);
- break;
- default:
- assert(0);
- }
- Set_Bone_Selection_Mode(BONE_SEL_MODE_NONE);
- Update_Bone_List();
- }
- void SkinWSMObjectClass::Set_Bone_Selection_Mode(int mode)
- {
- assert(mode >= BONE_SEL_MODE_NONE);
- assert(mode <= BONE_SEL_MODE_REMOVE_MANY);
-
- /*
- ** store the selection mode
- */
- BoneSelectionMode = mode;
- /*
- ** update the dialog box buttons
- */
- AddBonesButton->SetCheck(mode == BONE_SEL_MODE_ADD_MANY);
- RemoveBonesButton->SetCheck(mode == BONE_SEL_MODE_REMOVE_MANY);
- }
- int SkinWSMObjectClass::Add_Bone(INode * node)
- {
- int refidx;
- int boneidx;
- /*
- ** If we already have this bone, just return
- */
- boneidx = Find_Bone(node);
- if (boneidx != -1) {
- return boneidx;
- }
- /*
- ** Otherwise, look for a NULL bone and we'll re-use
- ** its slot. This happens when a user removes a bone or
- ** a bone in the scene is deleted.
- */
- boneidx = Find_Bone(NULL);
- if (boneidx != -1) {
- refidx = To_Ref_Index(boneidx);
- MakeRefByID(FOREVER,refidx,node);
- return boneidx;
- }
-
- /*
- ** If we made it here, add the bone to the end of the
- ** reference array.
- */
- BoneTab.Append(1,&node);
- boneidx = BoneTab.Count() - 1;
- refidx = To_Ref_Index(boneidx);
- MakeRefByID(FOREVER,refidx,node);
- return boneidx;
- }
- void SkinWSMObjectClass::Add_Bones(INodeTab & nodetab)
- {
- /*
- ** Add each bone individually
- */
- for (int i=0; i<nodetab.Count(); i++) {
- Add_Bone(nodetab[i]);
- }
- }
- void SkinWSMObjectClass::Remove_Bone(INode * node)
- {
- int boneidx = Find_Bone(node);
- if (boneidx != -1) {
- BoneTab[boneidx] = NULL;
- DeleteReference(To_Ref_Index(boneidx));
- }
- }
- void SkinWSMObjectClass::Remove_Bones(INodeTab & nodetab)
- {
- /*
- ** remove each bone
- */
- for (int i=0; i<nodetab.Count(); i++) {
- Remove_Bone(nodetab[i]);
- }
- }
- void SkinWSMObjectClass::Update_Bone_List(void)
- {
- assert(BoneListHWND != NULL);
- /*
- ** remove all strings in the bone listbox
- */
- SendMessage(BoneListHWND,LB_RESETCONTENT,0,0);
- /*
- ** loop through the bone tab and add the name of each
- */
- for (int i=0; i<BoneTab.Count(); i++) {
- if (BoneTab[i] != NULL) {
- SendMessage(BoneListHWND,LB_ADDSTRING,0,(LPARAM)BoneTab[i]->GetName());
- }
- }
- }
- int SkinWSMObjectClass::Find_Bone(INode * node)
- {
- for (int i=0; i<BoneTab.Count(); i++) {
- if (BoneTab[i] == node) return i;
- }
- return -1;
- }
- IOResult SkinWSMObjectClass::Save(ISave * isave)
- {
- ULONG nb;
- SimpleWSMObject::Save(isave);
- /*
- ** Save the number of bones
- */
- ULONG numbones = BoneTab.Count();
- if (numbones > 0) {
- isave->BeginChunk(NUM_BONES_CHUNK);
- isave->Write(&numbones,sizeof(ULONG),&nb);
- isave->EndChunk();
- }
- return IO_OK;
- }
- IOResult SkinWSMObjectClass::Load(ILoad * iload)
- {
- SimpleWSMObject::Load(iload);
- IOResult res;
- ULONG nb;
- int level = -1;
- while (IO_OK==(res=iload->OpenChunk())) {
- switch (iload->CurChunkID()) {
- case NUM_BONES_CHUNK: {
- ULONG numbones;
- res = iload->Read(&numbones,sizeof(numbones),&nb);
- BoneTab.SetCount(numbones);
- for (int i=0; i<BoneTab.Count(); i++) {
- BoneTab[i] = NULL;
- }
- }
- break;
- }
- iload->CloseChunk();
- if (res!=IO_OK) {
- return res;
- }
- }
- return IO_OK;
- }
- int SkinWSMObjectClass::Find_Closest_Bone(const Point3 & vertex)
- {
- float mindist = 10000.0f;
- int minindex = -1;
- TimeValue basetime = Get_Base_Pose_Time();
- for (int boneidx = 0; boneidx < BoneTab.Count(); boneidx++) {
-
- if (BoneTab[boneidx] == NULL) continue;
- float bonedist = Bone_Distance(BoneTab[boneidx],basetime,vertex);
- if (bonedist < mindist) {
- mindist = bonedist;
- minindex = boneidx;
- }
- }
- return minindex;
- }
- /*******************************************************************************
- **
- ** SkinModifierClass
- **
- *******************************************************************************/
- SkinModifierClass::SkinModifierClass(void)
- {
- Default_Init();
- }
- SkinModifierClass::SkinModifierClass(INode * node,SkinWSMObjectClass * skin_obj)
- {
- Default_Init();
- /*
- ** Make the reference to the space warp node.
- */
- MakeRefByID(FOREVER,NODE_REF,node);
- /*
- ** Make reference to the WSMObject
- */
- MakeRefByID(FOREVER,OBJ_REF,skin_obj);
- }
- void SkinModifierClass::Default_Init(void)
- {
- SubObjSelLevel = VERTEX_SEL_LEVEL;
- WSMObjectRef = NULL;
- WSMNodeRef = NULL;
- InterfacePtr = NULL;
- BoneInfluenceHWND = NULL;
- LinkButton = NULL;
- LinkByNameButton = NULL;
- AutoLinkButton = NULL;
- UnLinkButton = NULL;
- }
- RefTargetHandle SkinModifierClass::Clone(RemapDir & remap)
- {
- SkinModifierClass * newmod = new SkinModifierClass(WSMNodeRef,(SkinWSMObjectClass *)WSMObjectRef);
- return newmod;
- }
- void SkinModifierClass::BeginEditParams(IObjParam * ip, ULONG flags,Animatable * prev)
- {
- static int i=0;
- i++;
- /*
- ** Grab a copy of the interface pointer
- */
- InterfacePtr = ip;
-
- /*
- ** allocate the selection command mode for use in vertex selection
- */
- SelectMode = new SelectModBoxCMode(this,InterfacePtr);
- /*
- ** register the desired sub-object selection types.
- */
- const TCHAR * ptype[] = { "Vertices" };
- #if defined W3D_MAX4 //defined as in the project (.dsp)
- InterfacePtr->SetSubObjectLevel(1);
- #else
- //---This call is obsolete from version 4.
- InterfacePtr->RegisterSubObjectTypes( ptype, 1);
- #endif
- /*
- ** Restore the selection level.
- */
- ip->SetSubObjectLevel(SubObjSelLevel);
- }
- void SkinModifierClass::EndEditParams(IObjParam *ip, ULONG flags,Animatable *next)
- {
- /*
- ** just checking...
- */
- assert(ip == InterfacePtr);
- /*
- ** Make sure we clear out the pick mode
- */
- InterfacePtr->ClearPickMode();
- /*
- ** remove and deallocate the selection command mode
- */
- InterfacePtr->DeleteMode(SelectMode);
- if (SelectMode ) delete SelectMode;
- SelectMode = NULL;
-
- /*
- ** Remove the rollup window(s) if needed
- */
- if (flags & END_EDIT_REMOVEUI) {
- Remove_Bone_Influence_Dialog();
- }
- /*
- ** Make sure we don't hang onto an invalid interface
- */
- InterfacePtr = NULL;
- }
- Interval SkinModifierClass::Get_Validity(TimeValue t)
- {
- /*
- ** Start with an infinite interval and chop it down
- ** using the validity intervals of each of the controlling bones
- */
- Interval valid = FOREVER;
- /*
- ** Now intersect the validity with the validities of all of
- ** the controlling bones.
- */
- SkinWSMObjectClass * obj = (SkinWSMObjectClass *)Get_WSMObject();
- // for (int i=0; i<obj->Num_Bones(); i++) {
- // valid &= obj->Get_Bone(i)->tmValid(); //TODO: is this right?
- // }
- // return valid;
- return Interval(t,t+1); //KLUDGE - only valid for this frame
- }
- RefTargetHandle SkinModifierClass::GetReference(int i)
- {
- switch (i) {
- case OBJ_REF: return WSMObjectRef;
- case NODE_REF: return WSMNodeRef;
- default: return NULL;
- }
- }
- void SkinModifierClass::SetReference(int i, RefTargetHandle rtarg)
- {
- switch (i) {
- case OBJ_REF: WSMObjectRef = (SkinWSMObjectClass *)rtarg; break;
- case NODE_REF: WSMNodeRef = (INode *)rtarg; break;
- }
- }
- RefResult SkinModifierClass::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
- {
- switch (message) {
- case REFMSG_TARGET_DELETED:
-
- /*
- ** This means the WSM node is being deleted. As a result,
- ** we must delete ourselves.
- */
- DeleteMe(); // also deletes all refs and
- // sends REFMSG_TARGET_DELETED to all Dependents
- return REF_STOP;
- }
- return(REF_SUCCEED);
- }
- void SkinModifierClass::ModifyObject(TimeValue t, ModContext & mc, ObjectState * os, INode * node)
- {
- /*
- ** Get a TriObject from the object state
- */
- assert(os->obj->IsSubClassOf(triObjectClassID));
- TriObject *triobj = (TriObject *)os->obj;
- /*
- ** Get the skin data from the ModContext.
- */
- SkinDataClass * skindata = (SkinDataClass *)mc.localData;
-
- /*
- ** If there is no skin data, allocate it
- ** Also, do an initial auto attach.
- */
- if (skindata == NULL) {
- mc.localData = skindata = new SkinDataClass(&triobj->mesh);
- }
- if (!skindata->IsValid()) {
- skindata->Validate(&triobj->mesh);
- }
-
- /*
- ** If in vertex selection mode, tell the mesh to display the
- ** selected vertices and turn on vertex tick marks. Otherwise
- ** make sure vertex tick marks are off.
- */
- if (SubObjSelLevel == VERTEX_SEL_LEVEL) {
- triobj->mesh.vertSel = skindata->VertSel;
- triobj->mesh.SetDispFlag(DISP_VERTTICKS|DISP_SELVERTS);
- if (triobj->mesh.selLevel != MESH_VERTEX) {
- triobj->mesh.selLevel = MESH_VERTEX;
- }
- } else {
- triobj->mesh.selLevel = MESH_OBJECT;
- triobj->mesh.ClearDispFlag(DISP_VERTTICKS|DISP_SELVERTS);
- }
- /*
- ** Loop through the points in the deformable object
- */
- for (int vidx = 0; vidx < triobj->NumPoints(); vidx++) {
- // TODO: Allow multiple bone influences here...
- // issues - UI to set the weights, rebalance weights whenever
- // a bone is deleted, should also then never get NULL bones
- // and remove the need to check for NULL bones in this routine...
-
- /*
- ** Get a pointer to the bone that this vertex is attached to
- */
- InfluenceStruct * inf = &(skindata->VertData[vidx]);
- int boneidx = inf->BoneIdx[0];
- if ((boneidx != -1) && (boneidx < WSMObjectRef->Num_Bones())) {
-
- INode * bone = WSMObjectRef->Get_Bone(inf->BoneIdx[0]);
- if (bone == NULL) {
- /*
- ** this bone has gone away for some reason so
- ** clear this vert's bone influence index
- */
- inf->BoneIdx[0] = -1;
-
- } else {
-
- /*
- ** Ok, got the bone, now transform the point and
- ** give it back to the mesh
- */
- Point3 pnew;
- Matrix3 tm;
- pnew = triobj->GetPoint(vidx);
-
- if (os->GetTM()) {
- tm = *(os->GetTM());
- } else {
- tm.IdentityMatrix();
- }
- pnew = tm * pnew;
-
- TimeValue basetime = WSMObjectRef->Get_Base_Pose_Time();
- Matrix3 basetm = bone->GetObjectTM(basetime);
- Matrix3 curtm = bone->GetObjectTM(t);
- pnew = (pnew * Inverse(basetm)) * curtm;
-
- pnew = Inverse(tm) * pnew;
- triobj->SetPoint(vidx,pnew);
- }
- }
- }
- /*
- ** Tell the object that points were changed
- */
- triobj->PointsWereChanged();
- /*
- ** Set the validity of the updated geometry data
- */
- triobj->UpdateValidity(GEOM_CHAN_NUM,Get_Validity(t));
- }
- IOResult SkinModifierClass::Save(ISave * isave)
- {
- ULONG nb;
- Modifier::Save(isave);
- /*
- ** Save the sub object selection level
- */
- short sl = SubObjSelLevel;
- isave->BeginChunk(SEL_LEVEL_CHUNK);
- isave->Write(&sl,sizeof(short),&nb);
- isave->EndChunk();
- return IO_OK;
- }
- IOResult SkinModifierClass::Load(ILoad * iload)
- {
- Modifier::Load(iload);
- IOResult res;
- ULONG nb;
- int level = -1;
- while (IO_OK==(res=iload->OpenChunk())) {
- switch (iload->CurChunkID()) {
- case SEL_LEVEL_CHUNK: {
- short sl;
- res = iload->Read(&sl,sizeof(short),&nb);
- SubObjSelLevel = sl;
- }
- break;
- }
- iload->CloseChunk();
- if (res!=IO_OK) {
- return res;
- }
- }
- return IO_OK;
- }
- IOResult SkinModifierClass::SaveLocalData(ISave *isave, LocalModData *ld)
- {
- SkinDataClass * skindata = (SkinDataClass *)ld;
- return skindata->Save(isave);
- }
- IOResult SkinModifierClass::LoadLocalData(ILoad *iload, LocalModData **pld)
- {
- /*
- ** Create a new SkinDataClass
- */
- if (*pld==NULL) {
- *pld = (SkinDataClass *) new SkinDataClass();
- }
- SkinDataClass * newskin = (SkinDataClass *)*pld;
- /*
- ** Initialize it from ILoad...
- */
- return newskin->Load(iload);
- }
- void SkinModifierClass::ActivateSubobjSel(int level, XFormModes & modes)
- {
- /*
- ** Storing the current sub-object selection level
- */
- SubObjSelLevel = level;
- /*
- ** Set the appropriate command mode. We only want selection.
- */
- switch (SubObjSelLevel)
- {
- case OBJECT_SEL_LEVEL:
- Remove_Bone_Influence_Dialog();
- break;
- case VERTEX_SEL_LEVEL: // Modifying Vertices
- modes = XFormModes(NULL,NULL,NULL,NULL,NULL,SelectMode);
- Install_Bone_Influence_Dialog();
- break;
- }
- /*
- ** Put our named subobject selection sets into the drop down list
- */
- Create_Named_Selection_Sets();
-
- /*
- ** Notify our dependents that the subselection type,
- ** and the display have changed
- */
- NotifyDependents(FOREVER, PART_SUBSEL_TYPE|PART_DISPLAY, REFMSG_CHANGE);
- /*
- ** Notify the pipeline that the selection level has changed.
- */
- InterfacePtr->PipeSelLevelChanged();
- /*
- ** Notify our dependents that the selection channel,
- ** display attributes, and subselection type channels have changed
- */
- NotifyDependents(FOREVER, SELECT_CHANNEL|DISP_ATTRIB_CHANNEL|SUBSEL_TYPE_CHANNEL, REFMSG_CHANGE);
- }
- int SkinModifierClass::HitTest
- (
- TimeValue t,
- INode * inode,
- int type,
- int crossing,
- int flags,
- IPoint2 * p,
- ViewExp * vpt,
- ModContext * mc
- )
- {
- Interval valid = FOREVER;
- int needsdel;
- int savedLimits;
- int res = 0;
- HitRegion hr;
- Matrix3 mat;
- MakeHitRegion(hr,type, crossing,4,p);
- mat = inode->GetObjectTM(t);
- /*
- ** Set up the graphics window to do the hit test
- */
- GraphicsWindow *gw = vpt->getGW();
- gw->setHitRegion(&hr);
- gw->setTransform(mat);
- gw->setRndLimits(((savedLimits = gw->getRndLimits()) | GW_PICK) & ~GW_ILLUM);
-
- if (1 /*IgnoreBackfaces*/) {
- gw->setRndLimits(gw->getRndLimits() | GW_BACKCULL);
- } else {
- gw->setRndLimits(gw->getRndLimits() & ~GW_BACKCULL);
- }
- gw->clearHitCode();
- /*
- ** Do the hit test!
- */
- SubObjHitList hitlist;
- MeshSubHitRec * rec;
-
- ObjectState os = inode->EvalWorldState(InterfacePtr->GetTime());
- TriObject * tobj = Get_Tri_Object(InterfacePtr->GetTime(),os,valid,needsdel);
- res = tobj->mesh.SubObjectHitTest(gw,gw->getMaterial(),&hr,flags | SUBHIT_VERTS,hitlist);
-
- /*
- ** Record all of the hits
- */
- rec = hitlist.First();
- while (rec)
- {
- /*
- ** rec->index is the index of vertex which was hit!
- ** Remember that we are always turning on vertex hit testing;
- ** if we were testing for edges, index would be the edge index.
- */
- vpt->LogHit(inode,mc,rec->dist,rec->index,NULL);
- rec = rec->Next();
- }
- /*
- ** Cleanup
- */
- gw->setRndLimits(savedLimits);
-
- if (needsdel) {
- tobj->DeleteThis();
- }
- return res;
- }
- void SkinModifierClass::SelectSubComponent(HitRecord *hitRec, BOOL selected, BOOL all, BOOL invert)
- {
- SkinDataClass * skindata = NULL;
- int count = 0;
- switch (SubObjSelLevel) {
-
- case VERTEX_SEL_LEVEL:
- while (hitRec) {
- skindata = (SkinDataClass *)hitRec->modContext->localData;
- /*
- ** Undo/Redo functionality
- */
- #if 0
- if (theHold.Holding() && !SelData->held) {
- theHold.Put(new SubSelRestore(this,SelData));
- }
- theHold.Accept(_T("Select Vertex"));
- #endif
-
- BitArray * array = &(skindata->VertSel);
- if (all & invert) {
- /*
- ** hitRec->hitInfo is the MeshSubHitRec::index that was stored in the
- ** HitTest method through LogHit
- */
- if ((*array)[hitRec->hitInfo]) {
- array->Clear(hitRec->hitInfo);
- } else {
- array->Set(hitRec->hitInfo,selected);
- }
- } else {
- array->Set(hitRec->hitInfo,selected);
- }
-
- if (!all) break;
- hitRec = hitRec->Next();
- }
- break;
- }
- NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
- }
- void SkinModifierClass::ClearSelection(int selLevel)
- {
- int needsdel = 0;
- Interval valid = FOREVER;
- ModContextList mcList;
- INodeTab nodes;
- if (!InterfacePtr ) return;
-
- InterfacePtr->GetModContexts(mcList,nodes);
- InterfacePtr->ClearCurNamedSelSet();
- for (int i = 0; i < mcList.Count(); i++) {
- SkinDataClass * skindata = (SkinDataClass *)mcList[i]->localData;
-
- if (skindata==NULL) continue;
-
- ObjectState os = nodes[i]->EvalWorldState(InterfacePtr->GetTime());
- TriObject * tobj = Get_Tri_Object(InterfacePtr->GetTime(),os,valid,needsdel);
- switch (SubObjSelLevel) {
- #if 0
- case OBJECT_SEL_LEVEL:
- assert(0);
- return;
- #endif
- case VERTEX_SEL_LEVEL:
- #if 0 // undo/redo
- if (theHold.Holding()) {
- theHold.Put(new VertexSelRestore(meshData,this));
- }
- #endif
- tobj->mesh.vertSel.ClearAll();
- skindata->VertSel.ClearAll();
- break;
- }
- if (needsdel) {
- tobj->DeleteThis();
- }
- }
-
- /*
- ** Get rid of the temporary copies of the INodes.
- */
- nodes.DisposeTemporary();
- /*
- ** Tell our dependents that the selection set has changed
- */
- NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
- }
- void SkinModifierClass::SelectAll(int selLevel)
- {
- int needsdel = 0;
- Interval valid = FOREVER;
- ModContextList mclist;
- INodeTab nodes;
- if (!InterfacePtr) return;
-
- InterfacePtr->GetModContexts(mclist,nodes);
- InterfacePtr->ClearCurNamedSelSet();
- for (int i = 0; i < mclist.Count(); i++) {
- SkinDataClass * skindata = (SkinDataClass *)mclist[i]->localData;
-
- if (skindata==NULL) continue;
-
- ObjectState os = nodes[i]->EvalWorldState(InterfacePtr->GetTime());
- TriObject * tobj = Get_Tri_Object(InterfacePtr->GetTime(),os,valid,needsdel);
- switch (SubObjSelLevel) {
- case OBJECT_SEL_LEVEL:
- assert(0);
- return;
- case VERTEX_SEL_LEVEL:
- #if 0 // undo/redo
- if (theHold.Holding()) {
- theHold.Put(new VertexSelRestore(meshData,this));
- }
- #endif
- tobj->mesh.vertSel.SetAll();
- skindata->VertSel.SetAll();
- break;
- }
- if (needsdel) {
- tobj->DeleteThis();
- }
- }
-
- /*
- ** Get rid of the temporary copies of the INodes.
- */
- nodes.DisposeTemporary();
- /*
- ** Tell our dependents that the selection set has changed
- */
- NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
- }
- void SkinModifierClass::InvertSelection(int selLevel)
- {
- int needsdel = 0;
- Interval valid = FOREVER;
- ModContextList mclist;
- INodeTab nodes;
- if (!InterfacePtr) return;
-
- InterfacePtr->GetModContexts(mclist,nodes);
- InterfacePtr->ClearCurNamedSelSet();
- for (int i = 0; i < mclist.Count(); i++) {
- SkinDataClass * skindata = (SkinDataClass *)mclist[i]->localData;
-
- if (skindata==NULL) continue;
-
- ObjectState os = nodes[i]->EvalWorldState(InterfacePtr->GetTime());
- TriObject * tobj = Get_Tri_Object(InterfacePtr->GetTime(),os,valid,needsdel);
- switch (SubObjSelLevel) {
- case OBJECT_SEL_LEVEL:
- assert(0);
- return;
- case VERTEX_SEL_LEVEL:
- #if 0 // undo/redo
- if (theHold.Holding()) {
- theHold.Put(new VertexSelRestore(meshData,this));
- }
- #endif
- for (int j=0; j<tobj->mesh.vertSel.GetSize(); j++) {
- if (tobj->mesh.vertSel[j]) tobj->mesh.vertSel.Clear(j);
- else tobj->mesh.vertSel.Set(j);
- }
- skindata->VertSel = tobj->mesh.vertSel;
- break;
- }
- if (needsdel) {
- tobj->DeleteThis();
- }
- }
-
- /*
- ** Get rid of the temporary copies of the INodes.
- */
- nodes.DisposeTemporary();
- /*
- ** Tell our dependents that the selection set has changed
- */
- NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
- }
- void SkinModifierClass::User_Picked_Bone(INode * node)
- {
- assert(InterfacePtr != NULL);
- /*
- ** Get a pointer to the ModContext and SkinData for
- ** the mesh currently being messed with.
- */
- ModContext * mc = NULL;
- ModContextList mclist;
- INodeTab nodelist;
- InterfacePtr->GetModContexts(mclist,nodelist);
-
- /*
- ** This seems wrong... But I always get only one ModContext and
- ** it is the one that I want so I'll just use it...
- ** I believe that OS Modifiers can get multiple ones but WS modifiers
- ** don't
- */
- mc = mclist[0];
- assert(mc != NULL);
- SkinDataClass * skindata = (SkinDataClass *)(mc->localData);
- /*
- ** Add this bone to the influences of all selected vertices
- */
- int boneidx = WSMObjectRef->Find_Bone(node);
- assert(boneidx != -1);
- skindata->Add_Influence(boneidx);
- /*
- ** Recreate all of the named selection sets!
- */
- Create_Named_Selection_Sets();
- /*
- ** Update dependents and redraw the views.
- */
- NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
- InterfacePtr->RedrawViews(InterfacePtr->GetTime());
- }
-
- void SkinModifierClass::User_Picked_Bones(INodeTab & nodetab)
- {
- /*
- ** One by one, add the selected bones to the influences of
- ** all selected vertices.
- */
- for (int i=0; i<nodetab.Count() && i<2; i++) {
- User_Picked_Bone(nodetab[i]);
- }
- }
- void SkinModifierClass::ActivateSubSelSet(TSTR & setname)
- {
- ModContextList mclist;
- INodeTab nodes;
-
- if (InterfacePtr == NULL) return;
- InterfacePtr->GetModContexts(mclist,nodes);
- for (int i = 0; i < mclist.Count(); i++) {
- SkinDataClass * skindata = (SkinDataClass *)mclist[i]->localData;
- if (!skindata) continue;
-
- int index = skindata->VertSelSets.Find_Set(setname);
- if (index < 0) continue;
- int needsdel;
- Interval valid;
- ObjectState os = nodes[i]->EvalWorldState(InterfacePtr->GetTime());
- TriObject * tobj = Get_Tri_Object(InterfacePtr->GetTime(),os,valid,needsdel);
- Mesh * mesh = &(tobj->mesh);
-
- // TODO: undo redo
- #if 0
- if (theHold.Holding()) {
- theHold.Put(new VertexSelRestore(meshData,this));
- }
- #endif
-
- if (skindata->VertSelSets[index].GetSize() != mesh->getNumVerts()) {
- skindata->VertSelSets[index].SetSize(mesh->getNumVerts(),TRUE);
- }
- mesh->vertSel = skindata->VertSelSets[index];
- skindata->VertSel = mesh->vertSel;
-
- if (needsdel) {
- tobj->DeleteThis();
- }
- }
-
- nodes.DisposeTemporary();
- NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
- InterfacePtr->RedrawViews(InterfacePtr->GetTime());
- }
- void SkinModifierClass::NewSetFromCurSel(TSTR &setname)
- {
- Install_Named_Selection_Sets();
- }
- void SkinModifierClass::RemoveSubSelSet(TSTR &setname)
- {
- Install_Named_Selection_Sets();
- }
- void SkinModifierClass::Create_Named_Selection_Sets(void)
- {
- /*
- ** This function creates a named selection set of vertices
- ** for each bone in the skeleton.
- */
- if (InterfacePtr == NULL) return;
- SkinWSMObjectClass * skinobj = WSMObjectRef;
- if (skinobj == NULL) return;
- ModContextList mclist;
- INodeTab nodes;
- InterfacePtr->GetModContexts(mclist,nodes);
- SkinDataClass * skindata = (SkinDataClass *)mclist[0]->localData;
- if (skindata == NULL) return;
- /*
- ** Clear out the old selection sets
- */
- skindata->VertSelSets.Reset();
- /*
- ** Create and add a set for each bone
- */
- for (int boneidx = 0; boneidx < skinobj->Num_Bones(); boneidx++) {
- if (skinobj->Get_Bone(boneidx) != NULL) {
- BitArray boneverts;
- boneverts.SetSize(skindata->VertData.Count());
-
- for (int vertidx = 0; vertidx < skindata->VertData.Count(); vertidx++) {
- if (skindata->VertData[vertidx].BoneIdx[0] == boneidx) boneverts.Set(vertidx);
- else boneverts.Clear(vertidx);
- }
- TSTR bonename = skinobj->Get_Bone(boneidx)->GetName();
- skindata->VertSelSets.Append_Set(boneverts,bonename);
- }
- }
- Install_Named_Selection_Sets();
- nodes.DisposeTemporary();
- }
- void SkinModifierClass::Install_Named_Selection_Sets(void)
- {
- /*
- ** If we are in sub-object selection mode add the sets
- ** to the drop down box.
- */
- if ((SubObjSelLevel == VERTEX_SEL_LEVEL) && (InterfacePtr != NULL)) {
- ModContextList mclist;
- INodeTab nodes;
- InterfacePtr->GetModContexts(mclist,nodes);
- SkinDataClass * skindata = (SkinDataClass *)mclist[0]->localData;
- if (skindata == NULL) return;
-
- InterfacePtr->ClearSubObjectNamedSelSets();
- for (int i=0; i < skindata->VertSelSets.Count(); i++) {
- InterfacePtr->AppendSubObjectNamedSelSet(*skindata->VertSelSets.Names[i]);
- }
- nodes.DisposeTemporary();
- }
- }
- void SkinModifierClass::Auto_Attach_Verts(BOOL all)
- {
- assert(InterfacePtr);
- /*
- ** Get the skin data.
- */
- ModContextList mclist;
- INodeTab nodes;
- InterfacePtr->GetModContexts(mclist,nodes);
- SkinDataClass * skindata = (SkinDataClass *)mclist[0]->localData;
- if (skindata == NULL) return;
-
- /*
- ** get the skin WSM object.
- */
- SkinWSMObjectClass * skinobj = WSMObjectRef;
- if (skinobj == NULL) return;
- /*
- ** Get a triobject representing the object state in the base pose.
- */
- Interval valid;
- BOOL needsdel;
- TimeValue basetime = WSMObjectRef->Get_Base_Pose_Time();
- ObjectState os = nodes[0]->EvalWorldState(basetime);
- TriObject * triobj = Get_Tri_Object(basetime,os,valid,needsdel);
-
- /*
- ** Attach each selected vertex (or all of them) to their closest bone.
- */
- for (int vertidx = 0; vertidx < skindata->VertData.Count(); vertidx++){
- if (skindata->VertSel[vertidx] || all) {
-
- Point3 vert = triobj->GetPoint(vertidx);
- if (os.GetTM()) vert = vert * (*os.GetTM());
- int boneidx = skinobj->Find_Closest_Bone(vert);
- skindata->VertData[vertidx].Set_Influence(boneidx);
- }
- }
- /*
- ** Re-create the named selection sets
- */
- Create_Named_Selection_Sets();
- /*
- ** Update dependents and redraw the views.
- */
- NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
- InterfacePtr->RedrawViews(InterfacePtr->GetTime());
- /*
- ** Cleanup...
- */
- nodes.DisposeTemporary();
-
- if (needsdel) {
- triobj->DeleteThis();
- }
- }
- void SkinModifierClass::Unlink_Verts(void)
- {
- assert(InterfacePtr);
- /*
- ** Get the skin data.
- */
- ModContextList mclist;
- INodeTab nodes;
- InterfacePtr->GetModContexts(mclist,nodes);
- SkinDataClass * skindata = (SkinDataClass *)mclist[0]->localData;
- if (skindata == NULL) return;
-
- /*
- ** Unlink each selected vertex (give them bone index -1)
- */
- for (int vertidx = 0; vertidx < skindata->VertData.Count(); vertidx++){
- if (skindata->VertSel[vertidx]) {
- skindata->VertData[vertidx].Set_Influence(-1);
- }
- }
- /*
- ** Re-create the named selection sets
- */
- Create_Named_Selection_Sets();
- /*
- ** Update dependents and redraw the views.
- */
- NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
- InterfacePtr->RedrawViews(InterfacePtr->GetTime());
- /*
- ** Cleanup...
- */
- nodes.DisposeTemporary();
- }
- /****************************************************************************
- **
- ** DIALOG BOX JUNK
- **
- ****************************************************************************/
- void SkinModifierClass::Install_Bone_Influence_Dialog(void)
- {
- if (BoneInfluenceHWND != NULL) return;
- /*
- ** loading resource string for the name of the dialog
- */
- static int loaded = 0;
- static TCHAR string[MAX_STRING_LENGTH];
- if (!loaded) {
- LoadString(AppInstance,IDS_BONE_INFLUENCE_PARAMS,string,MAX_STRING_LENGTH);
- loaded = 1;
- }
- /*
- ** Put up the UI that is used to assign vertices to bones
- */
- BoneInfluenceHWND = InterfacePtr->AddRollupPage(
- AppInstance,
- MAKEINTRESOURCE(IDD_BONE_INFLUENCE_PARAMS),
- _bone_influence_dialog_thunk,
- string,
- (LPARAM)this,
- 0);
- }
- void SkinModifierClass::Remove_Bone_Influence_Dialog(void)
- {
- /*
- ** If it is currently up, remove the bone influences dialog
- */
- if (BoneInfluenceHWND != NULL) {
- InterfacePtr->UnRegisterDlgWnd(BoneInfluenceHWND);
- InterfacePtr->DeleteRollupPage(BoneInfluenceHWND);
- BoneInfluenceHWND = NULL;
- }
- }
- /*********************************************************************************
- *
- * _sot_dialog_proc
- *
- *********************************************************************************/
- static BOOL CALLBACK _sot_dialog_proc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
- {
- IObjParam *ip = (IObjParam*)GetWindowLong(hWnd,GWL_USERDATA);
- switch (message) {
- case WM_INITDIALOG:
- SetWindowLong(hWnd,GWL_USERDATA,lParam);
- break;
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_MOUSEMOVE:
- if (ip) ip->RollupMouseMessage(hWnd,message,wParam,lParam);
- return FALSE;
- default:
- return FALSE;
- }
- return TRUE;
- }
- /*********************************************************************************
- *
- * _skeleton_dialog_proc
- *
- *********************************************************************************/
- static BOOL CALLBACK _skeleton_dialog_thunk(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
- {
- SkinWSMObjectClass * skinobj = (SkinWSMObjectClass *)GetWindowLong(hWnd,GWL_USERDATA);
- if (!skinobj && message != WM_INITDIALOG) return FALSE;
-
- if (message == WM_INITDIALOG) {
- skinobj = (SkinWSMObjectClass *)lParam;
- SetWindowLong(hWnd,GWL_USERDATA,(LONG)skinobj);
- }
- return skinobj->Skeleton_Dialog_Proc(hWnd,message,wParam,lParam);
- }
- BOOL SkinWSMObjectClass::Skeleton_Dialog_Proc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
- {
- switch (message) {
- case WM_INITDIALOG:
- BoneListHWND = GetDlgItem(hWnd,IDC_BONE_LIST);
- /*
- ** Intitialize the add bone and remove bone check buttons
- */
- AddBonesButton = GetICustButton(GetDlgItem(hWnd, IDC_ADD_BONES_BUTTON));
- RemoveBonesButton = GetICustButton(GetDlgItem(hWnd, IDC_REMOVE_BONES_BUTTON));
-
- AddBonesButton->SetType(CBT_CHECK);
- AddBonesButton->SetHighlightColor(GREEN_WASH);
- AddBonesButton->SetTooltip(TRUE, _T("Add bones by name"));
- RemoveBonesButton->SetType(CBT_CHECK);
- RemoveBonesButton->SetHighlightColor(GREEN_WASH);
- RemoveBonesButton->SetTooltip(TRUE, _T("Remove bones by name"));
-
- /*
- ** Initialize the "Base Pose Frame" spinner
- */
- BasePoseSpin = GetISpinner(GetDlgItem(hWnd, IDC_BASE_POSE_SPIN));
- BasePoseSpin->SetLimits(0,9999, FALSE);
- BasePoseSpin->SetValue(0,FALSE);
- BasePoseSpin->SetResetValue(0);
- BasePoseSpin->LinkToEdit(GetDlgItem(hWnd,IDC_BASE_POSE_EDIT),EDITTYPE_INT);
- return TRUE;
- case WM_DESTROY:
- ReleaseICustButton(AddBonesButton);
- ReleaseICustButton(RemoveBonesButton);
- ReleaseISpinner(BasePoseSpin);
-
- AddBonesButton = NULL;
- RemoveBonesButton = NULL;
- BasePoseSpin = NULL;
- BoneListHWND = NULL;
-
- return FALSE;
-
- case CC_SPINNER_CHANGE:
- switch (LOWORD(wParam))
- {
- case IDC_BASE_POSE_SPIN:
- BasePoseFrame = BasePoseSpin->GetIVal();
- break;
- }
- NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
- InterfacePtr->RedrawViews(InterfacePtr->GetTime(),REDRAW_INTERACTIVE);
- return TRUE;
- case CC_SPINNER_BUTTONUP:
- NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
- InterfacePtr->RedrawViews(InterfacePtr->GetTime(),REDRAW_END);
- return TRUE;
-
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_MOUSEMOVE:
- InterfacePtr->RollupMouseMessage(hWnd,message,wParam,lParam);
- return FALSE;
- case WM_COMMAND:
- switch (LOWORD(wParam))
- {
- case IDC_ADD_BONES_BUTTON:
- TheBonePicker.Set_User(this);
- Set_Bone_Selection_Mode(BONE_SEL_MODE_ADD_MANY);
- InterfacePtr->DoHitByNameDialog(&TheBonePicker);
- Set_Bone_Selection_Mode(BONE_SEL_MODE_NONE);
- break;
- case IDC_REMOVE_BONES_BUTTON:
- TheBonePicker.Set_User(this,FALSE,&(BoneTab));
- Set_Bone_Selection_Mode(BONE_SEL_MODE_REMOVE_MANY);
- InterfacePtr->DoHitByNameDialog(&TheBonePicker);
- Set_Bone_Selection_Mode(BONE_SEL_MODE_NONE);
- break;
- }
- default:
- return FALSE;
- }
- }
- /*********************************************************************************
- *
- * Bone_Influence_Dialog_Proc
- *
- *********************************************************************************/
- static BOOL CALLBACK _bone_influence_dialog_thunk(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
- {
- SkinModifierClass * skinmod = (SkinModifierClass *)GetWindowLong(hWnd,GWL_USERDATA);
- if (!skinmod && message != WM_INITDIALOG) return FALSE;
-
- if (message == WM_INITDIALOG) {
- skinmod = (SkinModifierClass *)lParam;
- SetWindowLong(hWnd,GWL_USERDATA,(LONG)skinmod);
- }
- return skinmod->Bone_Influence_Dialog_Proc(hWnd,message,wParam,lParam);
- }
- BOOL SkinModifierClass::Bone_Influence_Dialog_Proc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
- {
- switch (message) {
- case WM_INITDIALOG:
- /*
- ** Intitialize the bone influence buttons
- */
- LinkButton = GetICustButton(GetDlgItem(hWnd, IDC_LINK_BUTTON));
- LinkByNameButton = GetICustButton(GetDlgItem(hWnd, IDC_LINK_BY_NAME_BUTTON));
- AutoLinkButton = GetICustButton(GetDlgItem(hWnd, IDC_AUTO_LINK_BUTTON));
- UnLinkButton = GetICustButton(GetDlgItem(hWnd, IDC_UNLINK_BUTTON));
-
- LinkButton->SetType(CBT_PUSH);
- LinkButton->SetTooltip(TRUE, _T("Link Vertices to a bone by selecting the bone"));
- LinkByNameButton->SetType(CBT_PUSH);
- LinkByNameButton->SetTooltip(TRUE, _T("Link Vertices to a bone by name"));
-
- AutoLinkButton->SetType(CBT_PUSH);
- AutoLinkButton->SetTooltip(TRUE, _T("Link Vertices to nearest bone"));
-
- UnLinkButton->SetType(CBT_PUSH);
- UnLinkButton->SetTooltip(TRUE, _T("Unlink selected vertices"));
-
- return TRUE;
- case WM_DESTROY:
- ReleaseICustButton(LinkButton);
- ReleaseICustButton(LinkByNameButton);
- ReleaseICustButton(AutoLinkButton);
- ReleaseICustButton(UnLinkButton);
- LinkButton = NULL;
- LinkByNameButton = NULL;
- AutoLinkButton = NULL;
- UnLinkButton = NULL;
- return FALSE;
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_MOUSEMOVE:
- InterfacePtr->RollupMouseMessage(hWnd,message,wParam,lParam);
- return FALSE;
- case WM_COMMAND:
- switch (LOWORD(wParam))
- {
- case IDC_LINK_BUTTON:
- {
- /*
- ** user picks a bone out of the scene to link to.
- */
- assert(WSMObjectRef != NULL);
- INodeTab * bonetab = &(WSMObjectRef->Get_Bone_List());
- TheBonePicker.Set_User(this,TRUE,bonetab);
- InterfacePtr->SetPickMode(&TheBonePicker);
- break;
- }
- case IDC_LINK_BY_NAME_BUTTON:
- {
- /*
- ** pop up a bone selection dialog
- */
- assert(WSMObjectRef != NULL);
- INodeTab * bonetab = &(WSMObjectRef->Get_Bone_List());
- TheBonePicker.Set_User(this,TRUE,bonetab);
- InterfacePtr->DoHitByNameDialog(&TheBonePicker);
- break;
- }
- case IDC_AUTO_LINK_BUTTON:
- {
- Auto_Attach_Verts();
- break;
- }
-
- case IDC_UNLINK_BUTTON:
- {
- Unlink_Verts();
- break;
- }
- }
- default:
- return FALSE;
- }
- }
- static TriObject * Get_Tri_Object(TimeValue t,ObjectState & os,Interval & valid,BOOL & needsdel)
- {
- needsdel = FALSE;
- valid &= os.Validity(t);
-
- if (os.obj->IsSubClassOf(triObjectClassID)) {
- return (TriObject *)os.obj;
- } else {
- if (os.obj->CanConvertToType(triObjectClassID)) {
- Object * oldObj = os.obj;
- TriObject * tobj = (TriObject *)os.obj->ConvertToType(t,triObjectClassID);
- needsdel = (tobj != oldObj);
- return tobj;
- }
- }
- return NULL;
- }
- float Bone_Distance(INode * bone,TimeValue time,const Point3 & vertex)
- {
- /*
- ** Average the pivot point of this bone with the pivot points of
- ** all of its children.
- */
- Point3 icenter = bone->GetObjectTM(time).GetTrans();
- for (int ci=0; ci<bone->NumberOfChildren(); ci++) {
- icenter += bone->GetChildNode(ci)->GetObjectTM(time).GetTrans();
- }
- icenter = icenter / (float)(bone->NumberOfChildren() + 1);
- return Length(icenter - vertex);
- }
- #if defined W3D_MAX4 //defined as in the project (.dsp)
- int SkinModifierClass::NumSubObjTypes()
- {
- return 1;
- }
- ////////////////////////////////////////////////////////////////////////////////////////
- ISubObjType *SkinModifierClass::GetSubObjType(int i)
- {
- static bool _initialized = false;
- if(!_initialized){
- _initialized = true;
- _SubObjectTypeVertex.SetName("Vertices");
- }
- if(i == -1){
- if(GetSubObjectLevel() > 0){
- return GetSubObjType(GetSubObjectLevel()-1);
- }
- }
- return &_SubObjectTypeVertex;
- }
- #endif
|