| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927 |
- /*
- ** Command & Conquer Renegade(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:: Moumine_ballo $*
- * *
- * $Modtime:: 2/21/02 4:56p $*
- * *
- * $Revision:: 15 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * 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)
- {
- OutputDebugString("DeletingSkinWSMObjectClass\n");
- 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)
- {
- OutputDebugString("BeginEditParams\n");
- SimpleWSMObject::BeginEditParams(ip,flags,prev);
- Interface* interf = GetCOREInterface();
- IObjParam* iop = interf->GetIObjParam();
- /*
- ** 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)
- {
- OutputDebugString("SkinWSMObjectClass::EndEditParams");
- 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)
- {
- OutputDebugString("SkinWSMObjectClass::User_Picked_Bone\n");
- // 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)
- {
- OutputDebugString("SkinWSMObjectClass::User_Picked_Bones\n");
- // 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)
- {
- OutputDebugString("Adding a bone\n");
- 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)
- { OutputDebugString("Adding bones\n");
- /*
- ** 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)
- {
- OutputDebugString("Remove_Bones\n");
- /*
- ** remove each bone
- */
- for (int i=0; i<nodetab.Count(); i++) {
- Remove_Bone(nodetab[i]);
- }
- }
- void SkinWSMObjectClass::Update_Bone_List(void)
- {
- OutputDebugString("SkinWSMObjectClass: Update_Bone_List\n");
- 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)
- {
- OutputDebugString("SkinModifierClass::BeginEditParams\n");
- 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)
- {
- OutputDebugString("SkinModifierClass::EndEditParams");
- /*
- ** 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)
- {OutputDebugString("SkinModifierClass::ActivateSubSelSet\n");
- 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
|