Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
skin.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/***********************************************************************************************
20 *** 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 ***
21 ***********************************************************************************************
22 * *
23 * Project Name : Commando Tools - WWSkin *
24 * *
25 * $Archive:: /Commando/Code/Tools/max2w3d/skin.cpp $*
26 * *
27 * $Author:: Greg_h $*
28 * *
29 * $Modtime:: 4/24/01 5:15p $*
30 * *
31 * $Revision:: 13 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37
38#include "skin.h"
39#include "dllmain.h"
40#include "max.h"
41#include "simpmod.h"
42#include "simpobj.h"
43#include "resource.h"
44
45#include "skindata.h"
46#include "bpick.h"
47#include "namedsel.h"
48#include "boneicon.h"
49
50#if defined W3D_MAX4 //defined as in the project (.dsp)
51static GenSubObjType _SubObjectTypeVertex(1);
52#endif
53
54/*
55** Static functions
56*/
57static BOOL CALLBACK _sot_dialog_proc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
58static BOOL CALLBACK _skeleton_dialog_thunk(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
59static BOOL CALLBACK _bone_influence_dialog_thunk(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
60static TriObject * Get_Tri_Object(TimeValue t,ObjectState & os,Interval & valid,BOOL & needsdel);
61static float Bone_Distance(INode * bone,TimeValue time,const Point3 & vertex);
62
63/*
64** Static variables
65*/
72ISpinnerControl * SkinWSMObjectClass::BasePoseSpin = NULL;
73
74
75/*******************************************************************************
76**
77** Class Descriptor for SkinWSMObjectClass
78**
79*******************************************************************************/
80class SkinWSMObjectClassDesc:public ClassDesc
81{
82public:
83
84 int IsPublic() { return 1; }
85 void * Create(BOOL loading = FALSE) { return new SkinWSMObjectClass; }
86 const TCHAR * ClassName() { return _T("WWSkin"); }
87 SClass_ID SuperClassID() { return WSM_OBJECT_CLASS_ID; }
88 Class_ID ClassID() { return SKIN_OBJ_CLASS_ID; }
89 const TCHAR* Category() { return _T("Westwood Space Warps"); }
90};
91
92static SkinWSMObjectClassDesc _SkinWSMObjectDesc;
93ClassDesc * Get_Skin_Obj_Desc() { return &_SkinWSMObjectDesc; }
94
95
96/*******************************************************************************
97**
98** Class Descriptor for the SkinModifier
99**
100*******************************************************************************/
101class SkinModClassDesc:public ClassDesc
102{
103public:
104
105 int IsPublic() { return 0; }
106 void * Create(BOOL loading = FALSE) { return new SkinModifierClass; }
107 const TCHAR * ClassName() { return _T("WWSkin"); }
108 SClass_ID SuperClassID() { return WSM_CLASS_ID; }
109 Class_ID ClassID() { return SKIN_MOD_CLASS_ID; }
110 const TCHAR * Category() { return _T("Westwood Space Warps"); }
111};
112
113static SkinModClassDesc _SkinModDesc;
114ClassDesc * Get_Skin_Mod_Desc() { return &_SkinModDesc; }
115
116
117
118/*******************************************************************************
119**
120** SkinWSMObjectCreateCallback
121** A class derived from CreateMouseCallBack to handle
122** the user input during the creation phase of the SkinWSMObject.
123**
124*******************************************************************************/
125class SkinWSMObjectCreateCallBack : public CreateMouseCallBack
126{
127public:
128 int proc( ViewExp * vpt,int msg, int point, int flags, IPoint2 m, Matrix3 & mat)
129 {
130 if (msg == MOUSE_POINT) {
131 Point3 pos = vpt->GetPointOnCP(m);
132 mat.IdentityMatrix();
133 mat.SetTrans(pos);
134 return CREATE_STOP;
135 }
136 return TRUE;
137 }
138};
139
140static SkinWSMObjectCreateCallBack _SkinCreateCB;
141
142/*******************************************************************************
143**
144** SkinWSMObjectClass
145**
146*******************************************************************************/
148{
149 /*
150 ** Initialize class variables to default state!
151 */
154 BoneTab.SetCount(0);
155 BasePoseFrame = 0;
156
157 pblock = NULL;
158}
159
161{
162 assert(!((InterfacePtr == NULL) && (SotHWND != NULL)));
163 if (SotHWND != NULL) {
164 InterfacePtr->UnRegisterDlgWnd(SotHWND);
165 InterfacePtr->DeleteRollupPage(SotHWND);
166 SotHWND = NULL;
167 }
168
169 assert(!((InterfacePtr == NULL) && (SkeletonHWND != NULL)));
170 if (SkeletonHWND != NULL) {
171 InterfacePtr->UnRegisterDlgWnd(SkeletonHWND);
172 InterfacePtr->DeleteRollupPage(SkeletonHWND);
174 }
175}
176
177void SkinWSMObjectClass::BeginEditParams(IObjParam *ip, ULONG flags,Animatable *prev)
178{
179 SimpleWSMObject::BeginEditParams(ip,flags,prev);
180
181 /*
182 ** save off a copy of the interface pointer
183 */
184 InterfacePtr = ip;
185
186 /*
187 ** Install the "supports objects of type" rollup
188 */
189 if (SotHWND == NULL) {
190 SotHWND = ip->AddRollupPage(
192 MAKEINTRESOURCE(IDD_SKIN_SOT),
193 _sot_dialog_proc,
195 (LPARAM)InterfacePtr,
196 APPENDROLL_CLOSED);
197 } else {
198 SetWindowLong(SotHWND,GWL_USERDATA,(LPARAM)ip);
199 }
200
201 /*
202 ** Install the skeleton rollup
203 */
204 if (SkeletonHWND == NULL) {
205 SkeletonHWND = InterfacePtr->AddRollupPage(
207 MAKEINTRESOURCE(IDD_SKELETON_PARAMETERS),
210 (LPARAM)this,
211 0);
212 } else {
213 SetWindowLong(SkeletonHWND,GWL_USERDATA,(LPARAM)this);
214 }
215
217}
218
219void SkinWSMObjectClass::EndEditParams(IObjParam *ip, ULONG flags,Animatable *next)
220{
221 SimpleWSMObject::EndEditParams(ip,flags,next);
222
223 if (flags & END_EDIT_REMOVEUI) {
224 /*
225 ** Remove the Sot rollup
226 */
227 if (SotHWND != NULL) {
228 InterfacePtr->UnRegisterDlgWnd(SotHWND);
229 InterfacePtr->DeleteRollupPage(SotHWND);
230 SotHWND = NULL;
231 }
232
233 /*
234 ** Remove the info rollup
235 */
236 if (SkeletonHWND != NULL) {
237 InterfacePtr->UnRegisterDlgWnd(SkeletonHWND);
238 InterfacePtr->DeleteRollupPage(SkeletonHWND);
240 }
241 }
242
243 /*
244 ** get rid of our copy of the interface pointer
245 */
247}
248
249RefTargetHandle SkinWSMObjectClass::Clone(RemapDir & remap)
250{
251 /*
252 ** create another SkinWSMObject and return it.
253 */
255 return(sobj);
256}
257
259{
260 /*
261 ** return reference "i". If i==0, the reference belongs
262 ** to SimpleWSMObject so thunk down to it.
263 */
264 if (i < SimpleWSMObject::NumRefs()) {
265 return SimpleWSMObject::GetReference(i);
266 }
267
268 /*
269 ** The rest of the references are ours.
270 */
271 int boneidx = To_Bone_Index(i);
272 return BoneTab[boneidx];
273}
274
275void SkinWSMObjectClass::SetReference(int i, RefTargetHandle rtarg)
276{
277 if (i < SimpleWSMObject::NumRefs()) {
278 SimpleWSMObject::SetReference(i,rtarg);
279 } else {
280 int boneidx = To_Bone_Index(i);
281 assert(boneidx >= 0);
282 assert(boneidx < BoneTab.Count());
283 BoneTab[boneidx] = (INode *)rtarg;
284 }
285}
286
287RefResult SkinWSMObjectClass::NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID& partID, RefMessage message)
288{
289 int i;
290 switch (message) {
291
292 case REFMSG_TARGET_DELETED:
293 for (i=0; i<BoneTab.Count(); i++) {
294 if (BoneTab[i] == hTarget) {
295 break;
296 }
297 }
298 if (i < BoneTab.Count()) {
299 BoneTab.Delete(i,1);
300 // TODO: cause all Modifier objects to re-index to accomodate
301 // the deletion of this bone!!
302 }
303 break;
304
305 }
306
307 return(REF_SUCCEED);
308}
309
311{
312 /*
313 ** The "CreateMouseCallback" is used when creating the
314 ** object. Since our object doesn't need an interactive
315 ** creation phase, we return NULL.
316 */
317 return &_SkinCreateCB;
318}
319
320Modifier * SkinWSMObjectClass::CreateWSMMod(INode *node)
321{
322 /*
323 ** create an instance of a SkinModifierClass...
324 */
325 return new SkinModifierClass(node,this);
326}
327
329{
330 int i;
331
332 /*
333 ** We only need to build the object mesh once since it
334 ** doesn't change or animate...
335 */
336 if (MeshBuilt) return;
337
338 /*
339 ** Set our validity interval, since this mesh doesn't animate
340 ** we just use FOREVER.
341 */
342 ivalid = FOREVER;
343
344 /*
345 ** Ok, this is the first time BuildMesh has been called.
346 ** Create a mesh which will represent this space warp object in
347 ** in the max viewports. Note that we are using the mesh
348 ** member which is inherited from SimpleWSMObject.
349 */
350 mesh.setNumVerts(NumBoneIconVerts);
351 mesh.setNumFaces(NumBoneIconFaces);
352 for (i=0; i<NumBoneIconVerts; i++) {
353 mesh.setVert(i, Point3(BoneIconVerts[i].X, BoneIconVerts[i].Y, BoneIconVerts[i].Z));
354 }
355
356 for (i=0; i<NumBoneIconFaces; i++) {
357 Build_Tri(&(mesh.faces[i]),BoneIconFaces[i].V0,BoneIconFaces[i].V1,BoneIconFaces[i].V2);
358 }
359
360 mesh.InvalidateGeomCache();
361
362 MeshBuilt = TRUE;
363}
364
365void SkinWSMObjectClass::Build_Tri(Face * f, int a, int b, int c)
366{
367 f->setVerts(a, b, c);
368 f->setSmGroup(0);
369 f->setEdgeVisFlags(1,1,1);
370}
371
373{
374 // TODO: Undo/Redo!
375 switch (BoneSelectionMode) {
377 Add_Bone(node);
378 break;
379
381 Remove_Bone(node);
382 break;
383
384 default:
385 assert(0);
386 }
387
390}
391
393{
394 // TODO: Undo/Redo!
395 switch (BoneSelectionMode) {
397 Add_Bones(nodetab);
398 break;
399
401 Remove_Bones(nodetab);
402 break;
403
404 default:
405 assert(0);
406 }
407
410}
411
413{
414 assert(mode >= BONE_SEL_MODE_NONE);
415 assert(mode <= BONE_SEL_MODE_REMOVE_MANY);
416
417 /*
418 ** store the selection mode
419 */
420 BoneSelectionMode = mode;
421
422 /*
423 ** update the dialog box buttons
424 */
425 AddBonesButton->SetCheck(mode == BONE_SEL_MODE_ADD_MANY);
427}
428
430{
431 int refidx;
432 int boneidx;
433
434 /*
435 ** If we already have this bone, just return
436 */
437 boneidx = Find_Bone(node);
438 if (boneidx != -1) {
439 return boneidx;
440 }
441
442 /*
443 ** Otherwise, look for a NULL bone and we'll re-use
444 ** its slot. This happens when a user removes a bone or
445 ** a bone in the scene is deleted.
446 */
447 boneidx = Find_Bone(NULL);
448 if (boneidx != -1) {
449 refidx = To_Ref_Index(boneidx);
450 MakeRefByID(FOREVER,refidx,node);
451 return boneidx;
452 }
453
454 /*
455 ** If we made it here, add the bone to the end of the
456 ** reference array.
457 */
458 BoneTab.Append(1,&node);
459 boneidx = BoneTab.Count() - 1;
460 refidx = To_Ref_Index(boneidx);
461 MakeRefByID(FOREVER,refidx,node);
462 return boneidx;
463}
464
465void SkinWSMObjectClass::Add_Bones(INodeTab & nodetab)
466{
467 /*
468 ** Add each bone individually
469 */
470 for (int i=0; i<nodetab.Count(); i++) {
471 Add_Bone(nodetab[i]);
472 }
473}
474
476{
477 int boneidx = Find_Bone(node);
478 if (boneidx != -1) {
479 BoneTab[boneidx] = NULL;
480 DeleteReference(To_Ref_Index(boneidx));
481 }
482}
483
484void SkinWSMObjectClass::Remove_Bones(INodeTab & nodetab)
485{
486 /*
487 ** remove each bone
488 */
489 for (int i=0; i<nodetab.Count(); i++) {
490 Remove_Bone(nodetab[i]);
491 }
492}
493
495{
496 assert(BoneListHWND != NULL);
497
498 /*
499 ** remove all strings in the bone listbox
500 */
501 SendMessage(BoneListHWND,LB_RESETCONTENT,0,0);
502
503 /*
504 ** loop through the bone tab and add the name of each
505 */
506 for (int i=0; i<BoneTab.Count(); i++) {
507 if (BoneTab[i] != NULL) {
508 SendMessage(BoneListHWND,LB_ADDSTRING,0,(LPARAM)BoneTab[i]->GetName());
509 }
510 }
511}
512
514{
515 for (int i=0; i<BoneTab.Count(); i++) {
516 if (BoneTab[i] == node) return i;
517 }
518 return -1;
519}
520
521IOResult SkinWSMObjectClass::Save(ISave * isave)
522{
523 ULONG nb;
524 SimpleWSMObject::Save(isave);
525
526 /*
527 ** Save the number of bones
528 */
529 ULONG numbones = BoneTab.Count();
530 if (numbones > 0) {
531 isave->BeginChunk(NUM_BONES_CHUNK);
532 isave->Write(&numbones,sizeof(ULONG),&nb);
533 isave->EndChunk();
534 }
535 return IO_OK;
536}
537
538IOResult SkinWSMObjectClass::Load(ILoad * iload)
539{
540 SimpleWSMObject::Load(iload);
541
542 IOResult res;
543 ULONG nb;
544 int level = -1;
545
546 while (IO_OK==(res=iload->OpenChunk())) {
547
548 switch (iload->CurChunkID()) {
549
550 case NUM_BONES_CHUNK: {
551 ULONG numbones;
552 res = iload->Read(&numbones,sizeof(numbones),&nb);
553 BoneTab.SetCount(numbones);
554 for (int i=0; i<BoneTab.Count(); i++) {
555 BoneTab[i] = NULL;
556 }
557 }
558 break;
559 }
560
561 iload->CloseChunk();
562
563 if (res!=IO_OK) {
564 return res;
565 }
566 }
567 return IO_OK;
568}
569
570
572{
573 float mindist = 10000.0f;
574 int minindex = -1;
575 TimeValue basetime = Get_Base_Pose_Time();
576
577 for (int boneidx = 0; boneidx < BoneTab.Count(); boneidx++) {
578
579 if (BoneTab[boneidx] == NULL) continue;
580
581 float bonedist = Bone_Distance(BoneTab[boneidx],basetime,vertex);
582 if (bonedist < mindist) {
583 mindist = bonedist;
584 minindex = boneidx;
585 }
586 }
587
588 return minindex;
589}
590
591
592
593/*******************************************************************************
594**
595** SkinModifierClass
596**
597*******************************************************************************/
598
603
605{
606 Default_Init();
607
608 /*
609 ** Make the reference to the space warp node.
610 */
611 MakeRefByID(FOREVER,NODE_REF,node);
612
613 /*
614 ** Make reference to the WSMObject
615 */
616 MakeRefByID(FOREVER,OBJ_REF,skin_obj);
617
618}
619
633
634
635RefTargetHandle SkinModifierClass::Clone(RemapDir & remap)
636{
638 return newmod;
639}
640
641
642void SkinModifierClass::BeginEditParams(IObjParam * ip, ULONG flags,Animatable * prev)
643{
644 static int i=0;
645
646 i++;
647
648 /*
649 ** Grab a copy of the interface pointer
650 */
651 InterfacePtr = ip;
652
653 /*
654 ** allocate the selection command mode for use in vertex selection
655 */
656 SelectMode = new SelectModBoxCMode(this,InterfacePtr);
657
658 /*
659 ** register the desired sub-object selection types.
660 */
661 const TCHAR * ptype[] = { "Vertices" };
662#if defined W3D_MAX4 //defined as in the project (.dsp)
663 InterfacePtr->SetSubObjectLevel(1);
664#else
665 //---This call is obsolete from version 4.
666 InterfacePtr->RegisterSubObjectTypes( ptype, 1);
667#endif
668 /*
669 ** Restore the selection level.
670 */
671 ip->SetSubObjectLevel(SubObjSelLevel);
672
673}
674
675
676void SkinModifierClass::EndEditParams(IObjParam *ip, ULONG flags,Animatable *next)
677{
678 /*
679 ** just checking...
680 */
681 assert(ip == InterfacePtr);
682
683 /*
684 ** Make sure we clear out the pick mode
685 */
686 InterfacePtr->ClearPickMode();
687
688 /*
689 ** remove and deallocate the selection command mode
690 */
691 InterfacePtr->DeleteMode(SelectMode);
692 if (SelectMode ) delete SelectMode;
694
695 /*
696 ** Remove the rollup window(s) if needed
697 */
698 if (flags & END_EDIT_REMOVEUI) {
699 Remove_Bone_Influence_Dialog();
700 }
701
702 /*
703 ** Make sure we don't hang onto an invalid interface
704 */
706}
707
709{
710 /*
711 ** Start with an infinite interval and chop it down
712 ** using the validity intervals of each of the controlling bones
713 */
714 Interval valid = FOREVER;
715
716 /*
717 ** Now intersect the validity with the validities of all of
718 ** the controlling bones.
719 */
721
722// for (int i=0; i<obj->Num_Bones(); i++) {
723// valid &= obj->Get_Bone(i)->tmValid(); //TODO: is this right?
724// }
725
726// return valid;
727 return Interval(t,t+1); //KLUDGE - only valid for this frame
728}
729
731{
732 switch (i) {
733 case OBJ_REF: return WSMObjectRef;
734 case NODE_REF: return WSMNodeRef;
735 default: return NULL;
736 }
737}
738
739void SkinModifierClass::SetReference(int i, RefTargetHandle rtarg)
740{
741 switch (i) {
742 case OBJ_REF: WSMObjectRef = (SkinWSMObjectClass *)rtarg; break;
743 case NODE_REF: WSMNodeRef = (INode *)rtarg; break;
744 }
745}
746
747RefResult SkinModifierClass::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
748{
749 switch (message) {
750
751 case REFMSG_TARGET_DELETED:
752
753 /*
754 ** This means the WSM node is being deleted. As a result,
755 ** we must delete ourselves.
756 */
757 DeleteMe(); // also deletes all refs and
758 // sends REFMSG_TARGET_DELETED to all Dependents
759 return REF_STOP;
760 }
761
762 return(REF_SUCCEED);
763
764}
765
766void SkinModifierClass::ModifyObject(TimeValue t, ModContext & mc, ObjectState * os, INode * node)
767{
768 /*
769 ** Get a TriObject from the object state
770 */
771 assert(os->obj->IsSubClassOf(triObjectClassID));
772 TriObject *triobj = (TriObject *)os->obj;
773
774 /*
775 ** Get the skin data from the ModContext.
776 */
777 SkinDataClass * skindata = (SkinDataClass *)mc.localData;
778
779 /*
780 ** If there is no skin data, allocate it
781 ** Also, do an initial auto attach.
782 */
783 if (skindata == NULL) {
784 mc.localData = skindata = new SkinDataClass(&triobj->mesh);
785 }
786
787 if (!skindata->IsValid()) {
788 skindata->Validate(&triobj->mesh);
789 }
790
791 /*
792 ** If in vertex selection mode, tell the mesh to display the
793 ** selected vertices and turn on vertex tick marks. Otherwise
794 ** make sure vertex tick marks are off.
795 */
797 triobj->mesh.vertSel = skindata->VertSel;
798 triobj->mesh.SetDispFlag(DISP_VERTTICKS|DISP_SELVERTS);
799
800 if (triobj->mesh.selLevel != MESH_VERTEX) {
801 triobj->mesh.selLevel = MESH_VERTEX;
802 }
803 } else {
804 triobj->mesh.selLevel = MESH_OBJECT;
805 triobj->mesh.ClearDispFlag(DISP_VERTTICKS|DISP_SELVERTS);
806 }
807
808 /*
809 ** Loop through the points in the deformable object
810 */
811 for (int vidx = 0; vidx < triobj->NumPoints(); vidx++) {
812
813
814 // TODO: Allow multiple bone influences here...
815 // issues - UI to set the weights, rebalance weights whenever
816 // a bone is deleted, should also then never get NULL bones
817 // and remove the need to check for NULL bones in this routine...
818
819 /*
820 ** Get a pointer to the bone that this vertex is attached to
821 */
822 InfluenceStruct * inf = &(skindata->VertData[vidx]);
823
824 int boneidx = inf->BoneIdx[0];
825 if ((boneidx != -1) && (boneidx < WSMObjectRef->Num_Bones())) {
826
827 INode * bone = WSMObjectRef->Get_Bone(inf->BoneIdx[0]);
828
829 if (bone == NULL) {
830 /*
831 ** this bone has gone away for some reason so
832 ** clear this vert's bone influence index
833 */
834 inf->BoneIdx[0] = -1;
835
836 } else {
837
838 /*
839 ** Ok, got the bone, now transform the point and
840 ** give it back to the mesh
841 */
842 Point3 pnew;
843 Matrix3 tm;
844
845 pnew = triobj->GetPoint(vidx);
846
847 if (os->GetTM()) {
848 tm = *(os->GetTM());
849 } else {
850 tm.IdentityMatrix();
851 }
852
853 pnew = tm * pnew;
854
855 TimeValue basetime = WSMObjectRef->Get_Base_Pose_Time();
856 Matrix3 basetm = bone->GetObjectTM(basetime);
857 Matrix3 curtm = bone->GetObjectTM(t);
858 pnew = (pnew * Inverse(basetm)) * curtm;
859
860 pnew = Inverse(tm) * pnew;
861
862 triobj->SetPoint(vidx,pnew);
863 }
864 }
865 }
866
867 /*
868 ** Tell the object that points were changed
869 */
870 triobj->PointsWereChanged();
871
872 /*
873 ** Set the validity of the updated geometry data
874 */
875 triobj->UpdateValidity(GEOM_CHAN_NUM,Get_Validity(t));
876}
877
878IOResult SkinModifierClass::Save(ISave * isave)
879{
880 ULONG nb;
881 Modifier::Save(isave);
882
883 /*
884 ** Save the sub object selection level
885 */
886 short sl = SubObjSelLevel;
887 isave->BeginChunk(SEL_LEVEL_CHUNK);
888 isave->Write(&sl,sizeof(short),&nb);
889 isave->EndChunk();
890
891 return IO_OK;
892}
893
894IOResult SkinModifierClass::Load(ILoad * iload)
895{
896 Modifier::Load(iload);
897
898 IOResult res;
899 ULONG nb;
900 int level = -1;
901
902 while (IO_OK==(res=iload->OpenChunk())) {
903
904 switch (iload->CurChunkID()) {
905
906 case SEL_LEVEL_CHUNK: {
907 short sl;
908 res = iload->Read(&sl,sizeof(short),&nb);
909 SubObjSelLevel = sl;
910 }
911 break;
912 }
913
914 iload->CloseChunk();
915
916 if (res!=IO_OK) {
917 return res;
918 }
919 }
920 return IO_OK;
921}
922
923IOResult SkinModifierClass::SaveLocalData(ISave *isave, LocalModData *ld)
924{
925 SkinDataClass * skindata = (SkinDataClass *)ld;
926
927 return skindata->Save(isave);
928}
929
930IOResult SkinModifierClass::LoadLocalData(ILoad *iload, LocalModData **pld)
931{
932 /*
933 ** Create a new SkinDataClass
934 */
935 if (*pld==NULL) {
936 *pld = (SkinDataClass *) new SkinDataClass();
937 }
938 SkinDataClass * newskin = (SkinDataClass *)*pld;
939
940 /*
941 ** Initialize it from ILoad...
942 */
943 return newskin->Load(iload);
944}
945
946
947void SkinModifierClass::ActivateSubobjSel(int level, XFormModes & modes)
948{
949 /*
950 ** Storing the current sub-object selection level
951 */
952 SubObjSelLevel = level;
953
954 /*
955 ** Set the appropriate command mode. We only want selection.
956 */
957 switch (SubObjSelLevel)
958 {
959 case OBJECT_SEL_LEVEL:
960 Remove_Bone_Influence_Dialog();
961 break;
962
963 case VERTEX_SEL_LEVEL: // Modifying Vertices
964 modes = XFormModes(NULL,NULL,NULL,NULL,NULL,SelectMode);
965 Install_Bone_Influence_Dialog();
966 break;
967 }
968
969 /*
970 ** Put our named subobject selection sets into the drop down list
971 */
973
974 /*
975 ** Notify our dependents that the subselection type,
976 ** and the display have changed
977 */
978 NotifyDependents(FOREVER, PART_SUBSEL_TYPE|PART_DISPLAY, REFMSG_CHANGE);
979
980 /*
981 ** Notify the pipeline that the selection level has changed.
982 */
983 InterfacePtr->PipeSelLevelChanged();
984
985 /*
986 ** Notify our dependents that the selection channel,
987 ** display attributes, and subselection type channels have changed
988 */
989 NotifyDependents(FOREVER, SELECT_CHANNEL|DISP_ATTRIB_CHANNEL|SUBSEL_TYPE_CHANNEL, REFMSG_CHANGE);
990}
991
993(
994 TimeValue t,
995 INode * inode,
996 int type,
997 int crossing,
998 int flags,
999 IPoint2 * p,
1000 ViewExp * vpt,
1001 ModContext * mc
1002)
1003{
1004 Interval valid = FOREVER;
1005 int needsdel;
1006 int savedLimits;
1007 int res = 0;
1008 HitRegion hr;
1009 Matrix3 mat;
1010
1011 MakeHitRegion(hr,type, crossing,4,p);
1012 mat = inode->GetObjectTM(t);
1013
1014 /*
1015 ** Set up the graphics window to do the hit test
1016 */
1017 GraphicsWindow *gw = vpt->getGW();
1018 gw->setHitRegion(&hr);
1019 gw->setTransform(mat);
1020 gw->setRndLimits(((savedLimits = gw->getRndLimits()) | GW_PICK) & ~GW_ILLUM);
1021
1022 if (1 /*IgnoreBackfaces*/) {
1023 gw->setRndLimits(gw->getRndLimits() | GW_BACKCULL);
1024 } else {
1025 gw->setRndLimits(gw->getRndLimits() & ~GW_BACKCULL);
1026 }
1027
1028 gw->clearHitCode();
1029
1030 /*
1031 ** Do the hit test!
1032 */
1033 SubObjHitList hitlist;
1034 MeshSubHitRec * rec;
1035
1036 ObjectState os = inode->EvalWorldState(InterfacePtr->GetTime());
1037 TriObject * tobj = Get_Tri_Object(InterfacePtr->GetTime(),os,valid,needsdel);
1038 res = tobj->mesh.SubObjectHitTest(gw,gw->getMaterial(),&hr,flags | SUBHIT_VERTS,hitlist);
1039
1040 /*
1041 ** Record all of the hits
1042 */
1043 rec = hitlist.First();
1044 while (rec)
1045 {
1046 /*
1047 ** rec->index is the index of vertex which was hit!
1048 ** Remember that we are always turning on vertex hit testing;
1049 ** if we were testing for edges, index would be the edge index.
1050 */
1051 vpt->LogHit(inode,mc,rec->dist,rec->index,NULL);
1052 rec = rec->Next();
1053 }
1054
1055 /*
1056 ** Cleanup
1057 */
1058 gw->setRndLimits(savedLimits);
1059
1060 if (needsdel) {
1061 tobj->DeleteThis();
1062 }
1063
1064 return res;
1065}
1066
1067void SkinModifierClass::SelectSubComponent(HitRecord *hitRec, BOOL selected, BOOL all, BOOL invert)
1068{
1069 SkinDataClass * skindata = NULL;
1070 int count = 0;
1071
1072 switch (SubObjSelLevel) {
1073
1074 case VERTEX_SEL_LEVEL:
1075
1076 while (hitRec) {
1077
1078 skindata = (SkinDataClass *)hitRec->modContext->localData;
1079
1080 /*
1081 ** Undo/Redo functionality
1082 */
1083#if 0
1084 if (theHold.Holding() && !SelData->held) {
1085 theHold.Put(new SubSelRestore(this,SelData));
1086 }
1087 theHold.Accept(_T("Select Vertex"));
1088#endif
1089
1090 BitArray * array = &(skindata->VertSel);
1091
1092 if (all & invert) {
1093
1094 /*
1095 ** hitRec->hitInfo is the MeshSubHitRec::index that was stored in the
1096 ** HitTest method through LogHit
1097 */
1098 if ((*array)[hitRec->hitInfo]) {
1099 array->Clear(hitRec->hitInfo);
1100 } else {
1101 array->Set(hitRec->hitInfo,selected);
1102 }
1103 } else {
1104 array->Set(hitRec->hitInfo,selected);
1105 }
1106
1107 if (!all) break;
1108 hitRec = hitRec->Next();
1109 }
1110 break;
1111 }
1112
1113 NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
1114}
1115
1117{
1118 int needsdel = 0;
1119 Interval valid = FOREVER;
1120 ModContextList mcList;
1121 INodeTab nodes;
1122
1123 if (!InterfacePtr ) return;
1124
1125 InterfacePtr->GetModContexts(mcList,nodes);
1126 InterfacePtr->ClearCurNamedSelSet();
1127
1128 for (int i = 0; i < mcList.Count(); i++) {
1129
1130 SkinDataClass * skindata = (SkinDataClass *)mcList[i]->localData;
1131
1132 if (skindata==NULL) continue;
1133
1134 ObjectState os = nodes[i]->EvalWorldState(InterfacePtr->GetTime());
1135 TriObject * tobj = Get_Tri_Object(InterfacePtr->GetTime(),os,valid,needsdel);
1136
1137 switch (SubObjSelLevel) {
1138#if 0
1139 case OBJECT_SEL_LEVEL:
1140 assert(0);
1141 return;
1142#endif
1143
1144 case VERTEX_SEL_LEVEL:
1145#if 0 // undo/redo
1146 if (theHold.Holding()) {
1147 theHold.Put(new VertexSelRestore(meshData,this));
1148 }
1149#endif
1150 tobj->mesh.vertSel.ClearAll();
1151 skindata->VertSel.ClearAll();
1152 break;
1153 }
1154
1155 if (needsdel) {
1156 tobj->DeleteThis();
1157 }
1158 }
1159
1160 /*
1161 ** Get rid of the temporary copies of the INodes.
1162 */
1163 nodes.DisposeTemporary();
1164
1165 /*
1166 ** Tell our dependents that the selection set has changed
1167 */
1168 NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
1169
1170}
1171
1173{
1174 int needsdel = 0;
1175 Interval valid = FOREVER;
1176 ModContextList mclist;
1177 INodeTab nodes;
1178
1179 if (!InterfacePtr) return;
1180
1181 InterfacePtr->GetModContexts(mclist,nodes);
1182 InterfacePtr->ClearCurNamedSelSet();
1183
1184 for (int i = 0; i < mclist.Count(); i++) {
1185
1186 SkinDataClass * skindata = (SkinDataClass *)mclist[i]->localData;
1187
1188 if (skindata==NULL) continue;
1189
1190 ObjectState os = nodes[i]->EvalWorldState(InterfacePtr->GetTime());
1191 TriObject * tobj = Get_Tri_Object(InterfacePtr->GetTime(),os,valid,needsdel);
1192
1193 switch (SubObjSelLevel) {
1194
1195 case OBJECT_SEL_LEVEL:
1196 assert(0);
1197 return;
1198
1199 case VERTEX_SEL_LEVEL:
1200#if 0 // undo/redo
1201 if (theHold.Holding()) {
1202 theHold.Put(new VertexSelRestore(meshData,this));
1203 }
1204#endif
1205 tobj->mesh.vertSel.SetAll();
1206 skindata->VertSel.SetAll();
1207 break;
1208 }
1209
1210 if (needsdel) {
1211 tobj->DeleteThis();
1212 }
1213 }
1214
1215 /*
1216 ** Get rid of the temporary copies of the INodes.
1217 */
1218 nodes.DisposeTemporary();
1219
1220 /*
1221 ** Tell our dependents that the selection set has changed
1222 */
1223 NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
1224}
1225
1227{
1228 int needsdel = 0;
1229 Interval valid = FOREVER;
1230 ModContextList mclist;
1231 INodeTab nodes;
1232
1233 if (!InterfacePtr) return;
1234
1235 InterfacePtr->GetModContexts(mclist,nodes);
1236 InterfacePtr->ClearCurNamedSelSet();
1237
1238 for (int i = 0; i < mclist.Count(); i++) {
1239
1240 SkinDataClass * skindata = (SkinDataClass *)mclist[i]->localData;
1241
1242 if (skindata==NULL) continue;
1243
1244 ObjectState os = nodes[i]->EvalWorldState(InterfacePtr->GetTime());
1245 TriObject * tobj = Get_Tri_Object(InterfacePtr->GetTime(),os,valid,needsdel);
1246
1247 switch (SubObjSelLevel) {
1248
1249 case OBJECT_SEL_LEVEL:
1250 assert(0);
1251 return;
1252
1253 case VERTEX_SEL_LEVEL:
1254#if 0 // undo/redo
1255 if (theHold.Holding()) {
1256 theHold.Put(new VertexSelRestore(meshData,this));
1257 }
1258#endif
1259 for (int j=0; j<tobj->mesh.vertSel.GetSize(); j++) {
1260 if (tobj->mesh.vertSel[j]) tobj->mesh.vertSel.Clear(j);
1261 else tobj->mesh.vertSel.Set(j);
1262 }
1263 skindata->VertSel = tobj->mesh.vertSel;
1264 break;
1265 }
1266
1267 if (needsdel) {
1268 tobj->DeleteThis();
1269 }
1270 }
1271
1272 /*
1273 ** Get rid of the temporary copies of the INodes.
1274 */
1275 nodes.DisposeTemporary();
1276
1277 /*
1278 ** Tell our dependents that the selection set has changed
1279 */
1280 NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
1281
1282}
1283
1285{
1286 assert(InterfacePtr != NULL);
1287
1288 /*
1289 ** Get a pointer to the ModContext and SkinData for
1290 ** the mesh currently being messed with.
1291 */
1292 ModContext * mc = NULL;
1293 ModContextList mclist;
1294 INodeTab nodelist;
1295
1296 InterfacePtr->GetModContexts(mclist,nodelist);
1297
1298 /*
1299 ** This seems wrong... But I always get only one ModContext and
1300 ** it is the one that I want so I'll just use it...
1301 ** I believe that OS Modifiers can get multiple ones but WS modifiers
1302 ** don't
1303 */
1304 mc = mclist[0];
1305 assert(mc != NULL);
1306 SkinDataClass * skindata = (SkinDataClass *)(mc->localData);
1307
1308 /*
1309 ** Add this bone to the influences of all selected vertices
1310 */
1311 int boneidx = WSMObjectRef->Find_Bone(node);
1312 assert(boneidx != -1);
1313 skindata->Add_Influence(boneidx);
1314
1315 /*
1316 ** Recreate all of the named selection sets!
1317 */
1319
1320 /*
1321 ** Update dependents and redraw the views.
1322 */
1323 NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
1324 InterfacePtr->RedrawViews(InterfacePtr->GetTime());
1325}
1326
1328{
1329 /*
1330 ** One by one, add the selected bones to the influences of
1331 ** all selected vertices.
1332 */
1333 for (int i=0; i<nodetab.Count() && i<2; i++) {
1334 User_Picked_Bone(nodetab[i]);
1335 }
1336}
1337
1339{
1340 ModContextList mclist;
1341 INodeTab nodes;
1342
1343 if (InterfacePtr == NULL) return;
1344
1345 InterfacePtr->GetModContexts(mclist,nodes);
1346
1347 for (int i = 0; i < mclist.Count(); i++) {
1348
1349 SkinDataClass * skindata = (SkinDataClass *)mclist[i]->localData;
1350 if (!skindata) continue;
1351
1352 int index = skindata->VertSelSets.Find_Set(setname);
1353 if (index < 0) continue;
1354
1355 int needsdel;
1356 Interval valid;
1357 ObjectState os = nodes[i]->EvalWorldState(InterfacePtr->GetTime());
1358 TriObject * tobj = Get_Tri_Object(InterfacePtr->GetTime(),os,valid,needsdel);
1359 Mesh * mesh = &(tobj->mesh);
1360
1361 // TODO: undo redo
1362#if 0
1363 if (theHold.Holding()) {
1364 theHold.Put(new VertexSelRestore(meshData,this));
1365 }
1366#endif
1367
1368 if (skindata->VertSelSets[index].GetSize() != mesh->getNumVerts()) {
1369 skindata->VertSelSets[index].SetSize(mesh->getNumVerts(),TRUE);
1370 }
1371 mesh->vertSel = skindata->VertSelSets[index];
1372 skindata->VertSel = mesh->vertSel;
1373
1374 if (needsdel) {
1375 tobj->DeleteThis();
1376 }
1377 }
1378
1379 nodes.DisposeTemporary();
1380
1381 NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
1382 InterfacePtr->RedrawViews(InterfacePtr->GetTime());
1383}
1384
1389
1394
1396{
1397 /*
1398 ** This function creates a named selection set of vertices
1399 ** for each bone in the skeleton.
1400 */
1401 if (InterfacePtr == NULL) return;
1402
1403 SkinWSMObjectClass * skinobj = WSMObjectRef;
1404 if (skinobj == NULL) return;
1405
1406 ModContextList mclist;
1407 INodeTab nodes;
1408 InterfacePtr->GetModContexts(mclist,nodes);
1409 SkinDataClass * skindata = (SkinDataClass *)mclist[0]->localData;
1410 if (skindata == NULL) return;
1411
1412 /*
1413 ** Clear out the old selection sets
1414 */
1415 skindata->VertSelSets.Reset();
1416
1417 /*
1418 ** Create and add a set for each bone
1419 */
1420 for (int boneidx = 0; boneidx < skinobj->Num_Bones(); boneidx++) {
1421
1422 if (skinobj->Get_Bone(boneidx) != NULL) {
1423 BitArray boneverts;
1424 boneverts.SetSize(skindata->VertData.Count());
1425
1426 for (int vertidx = 0; vertidx < skindata->VertData.Count(); vertidx++) {
1427 if (skindata->VertData[vertidx].BoneIdx[0] == boneidx) boneverts.Set(vertidx);
1428 else boneverts.Clear(vertidx);
1429 }
1430
1431 TSTR bonename = skinobj->Get_Bone(boneidx)->GetName();
1432
1433 skindata->VertSelSets.Append_Set(boneverts,bonename);
1434 }
1435 }
1436
1438
1439 nodes.DisposeTemporary();
1440}
1441
1443{
1444 /*
1445 ** If we are in sub-object selection mode add the sets
1446 ** to the drop down box.
1447 */
1449
1450 ModContextList mclist;
1451 INodeTab nodes;
1452 InterfacePtr->GetModContexts(mclist,nodes);
1453 SkinDataClass * skindata = (SkinDataClass *)mclist[0]->localData;
1454 if (skindata == NULL) return;
1455
1456 InterfacePtr->ClearSubObjectNamedSelSets();
1457 for (int i=0; i < skindata->VertSelSets.Count(); i++) {
1458 InterfacePtr->AppendSubObjectNamedSelSet(*skindata->VertSelSets.Names[i]);
1459 }
1460
1461 nodes.DisposeTemporary();
1462 }
1463}
1464
1466{
1467 assert(InterfacePtr);
1468
1469 /*
1470 ** Get the skin data.
1471 */
1472 ModContextList mclist;
1473 INodeTab nodes;
1474 InterfacePtr->GetModContexts(mclist,nodes);
1475 SkinDataClass * skindata = (SkinDataClass *)mclist[0]->localData;
1476 if (skindata == NULL) return;
1477
1478 /*
1479 ** get the skin WSM object.
1480 */
1481 SkinWSMObjectClass * skinobj = WSMObjectRef;
1482 if (skinobj == NULL) return;
1483
1484 /*
1485 ** Get a triobject representing the object state in the base pose.
1486 */
1487 Interval valid;
1488 BOOL needsdel;
1489
1490 TimeValue basetime = WSMObjectRef->Get_Base_Pose_Time();
1491 ObjectState os = nodes[0]->EvalWorldState(basetime);
1492 TriObject * triobj = Get_Tri_Object(basetime,os,valid,needsdel);
1493
1494 /*
1495 ** Attach each selected vertex (or all of them) to their closest bone.
1496 */
1497 for (int vertidx = 0; vertidx < skindata->VertData.Count(); vertidx++){
1498 if (skindata->VertSel[vertidx] || all) {
1499
1500 Point3 vert = triobj->GetPoint(vertidx);
1501 if (os.GetTM()) vert = vert * (*os.GetTM());
1502 int boneidx = skinobj->Find_Closest_Bone(vert);
1503 skindata->VertData[vertidx].Set_Influence(boneidx);
1504 }
1505 }
1506
1507 /*
1508 ** Re-create the named selection sets
1509 */
1511
1512 /*
1513 ** Update dependents and redraw the views.
1514 */
1515 NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
1516 InterfacePtr->RedrawViews(InterfacePtr->GetTime());
1517
1518 /*
1519 ** Cleanup...
1520 */
1521 nodes.DisposeTemporary();
1522
1523 if (needsdel) {
1524 triobj->DeleteThis();
1525 }
1526}
1527
1529{
1530 assert(InterfacePtr);
1531
1532 /*
1533 ** Get the skin data.
1534 */
1535 ModContextList mclist;
1536 INodeTab nodes;
1537 InterfacePtr->GetModContexts(mclist,nodes);
1538 SkinDataClass * skindata = (SkinDataClass *)mclist[0]->localData;
1539 if (skindata == NULL) return;
1540
1541 /*
1542 ** Unlink each selected vertex (give them bone index -1)
1543 */
1544 for (int vertidx = 0; vertidx < skindata->VertData.Count(); vertidx++){
1545 if (skindata->VertSel[vertidx]) {
1546 skindata->VertData[vertidx].Set_Influence(-1);
1547 }
1548 }
1549
1550 /*
1551 ** Re-create the named selection sets
1552 */
1554
1555 /*
1556 ** Update dependents and redraw the views.
1557 */
1558 NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
1559 InterfacePtr->RedrawViews(InterfacePtr->GetTime());
1560
1561 /*
1562 ** Cleanup...
1563 */
1564 nodes.DisposeTemporary();
1565}
1566
1567
1568/****************************************************************************
1569**
1570** DIALOG BOX JUNK
1571**
1572****************************************************************************/
1573
1574void SkinModifierClass::Install_Bone_Influence_Dialog(void)
1575{
1576 if (BoneInfluenceHWND != NULL) return;
1577
1578 /*
1579 ** loading resource string for the name of the dialog
1580 */
1581 static int loaded = 0;
1582 static TCHAR string[MAX_STRING_LENGTH];
1583
1584 if (!loaded) {
1586 loaded = 1;
1587 }
1588
1589 /*
1590 ** Put up the UI that is used to assign vertices to bones
1591 */
1592 BoneInfluenceHWND = InterfacePtr->AddRollupPage(
1594 MAKEINTRESOURCE(IDD_BONE_INFLUENCE_PARAMS),
1596 string,
1597 (LPARAM)this,
1598 0);
1599}
1600
1601void SkinModifierClass::Remove_Bone_Influence_Dialog(void)
1602{
1603 /*
1604 ** If it is currently up, remove the bone influences dialog
1605 */
1606 if (BoneInfluenceHWND != NULL) {
1607 InterfacePtr->UnRegisterDlgWnd(BoneInfluenceHWND);
1608 InterfacePtr->DeleteRollupPage(BoneInfluenceHWND);
1610 }
1611}
1612
1613/*********************************************************************************
1614*
1615* _sot_dialog_proc
1616*
1617*********************************************************************************/
1618static BOOL CALLBACK _sot_dialog_proc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
1619{
1620 IObjParam *ip = (IObjParam*)GetWindowLong(hWnd,GWL_USERDATA);
1621
1622 switch (message) {
1623 case WM_INITDIALOG:
1624 SetWindowLong(hWnd,GWL_USERDATA,lParam);
1625 break;
1626
1627 case WM_LBUTTONDOWN:
1628 case WM_LBUTTONUP:
1629 case WM_MOUSEMOVE:
1630 if (ip) ip->RollupMouseMessage(hWnd,message,wParam,lParam);
1631 return FALSE;
1632
1633 default:
1634 return FALSE;
1635 }
1636 return TRUE;
1637}
1638
1639
1640/*********************************************************************************
1641*
1642* _skeleton_dialog_proc
1643*
1644*********************************************************************************/
1645static BOOL CALLBACK _skeleton_dialog_thunk(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
1646{
1647 SkinWSMObjectClass * skinobj = (SkinWSMObjectClass *)GetWindowLong(hWnd,GWL_USERDATA);
1648 if (!skinobj && message != WM_INITDIALOG) return FALSE;
1649
1650 if (message == WM_INITDIALOG) {
1651 skinobj = (SkinWSMObjectClass *)lParam;
1652 SetWindowLong(hWnd,GWL_USERDATA,(LONG)skinobj);
1653 }
1654
1655 return skinobj->Skeleton_Dialog_Proc(hWnd,message,wParam,lParam);
1656}
1657
1658BOOL SkinWSMObjectClass::Skeleton_Dialog_Proc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
1659{
1660 switch (message) {
1661
1662 case WM_INITDIALOG:
1663
1664 BoneListHWND = GetDlgItem(hWnd,IDC_BONE_LIST);
1665
1666 /*
1667 ** Intitialize the add bone and remove bone check buttons
1668 */
1669 AddBonesButton = GetICustButton(GetDlgItem(hWnd, IDC_ADD_BONES_BUTTON));
1670 RemoveBonesButton = GetICustButton(GetDlgItem(hWnd, IDC_REMOVE_BONES_BUTTON));
1671
1672 AddBonesButton->SetType(CBT_CHECK);
1673 AddBonesButton->SetHighlightColor(GREEN_WASH);
1674 AddBonesButton->SetTooltip(TRUE, _T("Add bones by name"));
1675
1676 RemoveBonesButton->SetType(CBT_CHECK);
1677 RemoveBonesButton->SetHighlightColor(GREEN_WASH);
1678 RemoveBonesButton->SetTooltip(TRUE, _T("Remove bones by name"));
1679
1680 /*
1681 ** Initialize the "Base Pose Frame" spinner
1682 */
1683 BasePoseSpin = GetISpinner(GetDlgItem(hWnd, IDC_BASE_POSE_SPIN));
1684 BasePoseSpin->SetLimits(0,9999, FALSE);
1685 BasePoseSpin->SetValue(0,FALSE);
1686 BasePoseSpin->SetResetValue(0);
1687 BasePoseSpin->LinkToEdit(GetDlgItem(hWnd,IDC_BASE_POSE_EDIT),EDITTYPE_INT);
1688 return TRUE;
1689
1690 case WM_DESTROY:
1691 ReleaseICustButton(AddBonesButton);
1692 ReleaseICustButton(RemoveBonesButton);
1693 ReleaseISpinner(BasePoseSpin);
1694
1699
1700 return FALSE;
1701
1702 case CC_SPINNER_CHANGE:
1703 switch (LOWORD(wParam))
1704 {
1705 case IDC_BASE_POSE_SPIN:
1706 BasePoseFrame = BasePoseSpin->GetIVal();
1707 break;
1708 }
1709 NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
1710 InterfacePtr->RedrawViews(InterfacePtr->GetTime(),REDRAW_INTERACTIVE);
1711 return TRUE;
1712
1713 case CC_SPINNER_BUTTONUP:
1714 NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
1715 InterfacePtr->RedrawViews(InterfacePtr->GetTime(),REDRAW_END);
1716 return TRUE;
1717
1718
1719 case WM_LBUTTONDOWN:
1720 case WM_LBUTTONUP:
1721 case WM_MOUSEMOVE:
1722 InterfacePtr->RollupMouseMessage(hWnd,message,wParam,lParam);
1723 return FALSE;
1724
1725 case WM_COMMAND:
1726 switch (LOWORD(wParam))
1727 {
1728
1730 TheBonePicker.Set_User(this);
1732 InterfacePtr->DoHitByNameDialog(&TheBonePicker);
1734 break;
1735
1737 TheBonePicker.Set_User(this,FALSE,&(BoneTab));
1739 InterfacePtr->DoHitByNameDialog(&TheBonePicker);
1741 break;
1742 }
1743
1744 default:
1745 return FALSE;
1746 }
1747}
1748
1749/*********************************************************************************
1750*
1751* Bone_Influence_Dialog_Proc
1752*
1753*********************************************************************************/
1754static BOOL CALLBACK _bone_influence_dialog_thunk(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
1755{
1756 SkinModifierClass * skinmod = (SkinModifierClass *)GetWindowLong(hWnd,GWL_USERDATA);
1757 if (!skinmod && message != WM_INITDIALOG) return FALSE;
1758
1759 if (message == WM_INITDIALOG) {
1760 skinmod = (SkinModifierClass *)lParam;
1761 SetWindowLong(hWnd,GWL_USERDATA,(LONG)skinmod);
1762 }
1763
1764 return skinmod->Bone_Influence_Dialog_Proc(hWnd,message,wParam,lParam);
1765}
1766
1767
1768BOOL SkinModifierClass::Bone_Influence_Dialog_Proc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
1769{
1770 switch (message) {
1771
1772 case WM_INITDIALOG:
1773 /*
1774 ** Intitialize the bone influence buttons
1775 */
1776 LinkButton = GetICustButton(GetDlgItem(hWnd, IDC_LINK_BUTTON));
1777 LinkByNameButton = GetICustButton(GetDlgItem(hWnd, IDC_LINK_BY_NAME_BUTTON));
1778 AutoLinkButton = GetICustButton(GetDlgItem(hWnd, IDC_AUTO_LINK_BUTTON));
1779 UnLinkButton = GetICustButton(GetDlgItem(hWnd, IDC_UNLINK_BUTTON));
1780
1781 LinkButton->SetType(CBT_PUSH);
1782 LinkButton->SetTooltip(TRUE, _T("Link Vertices to a bone by selecting the bone"));
1783
1784 LinkByNameButton->SetType(CBT_PUSH);
1785 LinkByNameButton->SetTooltip(TRUE, _T("Link Vertices to a bone by name"));
1786
1787 AutoLinkButton->SetType(CBT_PUSH);
1788 AutoLinkButton->SetTooltip(TRUE, _T("Link Vertices to nearest bone"));
1789
1790 UnLinkButton->SetType(CBT_PUSH);
1791 UnLinkButton->SetTooltip(TRUE, _T("Unlink selected vertices"));
1792
1793 return TRUE;
1794
1795 case WM_DESTROY:
1796 ReleaseICustButton(LinkButton);
1797 ReleaseICustButton(LinkByNameButton);
1798 ReleaseICustButton(AutoLinkButton);
1799 ReleaseICustButton(UnLinkButton);
1800
1801 LinkButton = NULL;
1805 return FALSE;
1806
1807 case WM_LBUTTONDOWN:
1808 case WM_LBUTTONUP:
1809 case WM_MOUSEMOVE:
1810 InterfacePtr->RollupMouseMessage(hWnd,message,wParam,lParam);
1811 return FALSE;
1812
1813 case WM_COMMAND:
1814 switch (LOWORD(wParam))
1815 {
1816 case IDC_LINK_BUTTON:
1817 {
1818 /*
1819 ** user picks a bone out of the scene to link to.
1820 */
1821 assert(WSMObjectRef != NULL);
1822 INodeTab * bonetab = &(WSMObjectRef->Get_Bone_List());
1823 TheBonePicker.Set_User(this,TRUE,bonetab);
1824 InterfacePtr->SetPickMode(&TheBonePicker);
1825 break;
1826 }
1827
1829 {
1830 /*
1831 ** pop up a bone selection dialog
1832 */
1833 assert(WSMObjectRef != NULL);
1834 INodeTab * bonetab = &(WSMObjectRef->Get_Bone_List());
1835 TheBonePicker.Set_User(this,TRUE,bonetab);
1836 InterfacePtr->DoHitByNameDialog(&TheBonePicker);
1837 break;
1838 }
1839
1841 {
1843 break;
1844 }
1845
1846 case IDC_UNLINK_BUTTON:
1847 {
1848 Unlink_Verts();
1849 break;
1850 }
1851 }
1852
1853 default:
1854 return FALSE;
1855 }
1856}
1857
1858static TriObject * Get_Tri_Object(TimeValue t,ObjectState & os,Interval & valid,BOOL & needsdel)
1859{
1860 needsdel = FALSE;
1861 valid &= os.Validity(t);
1862
1863 if (os.obj->IsSubClassOf(triObjectClassID)) {
1864 return (TriObject *)os.obj;
1865 } else {
1866 if (os.obj->CanConvertToType(triObjectClassID)) {
1867 Object * oldObj = os.obj;
1868 TriObject * tobj = (TriObject *)os.obj->ConvertToType(t,triObjectClassID);
1869 needsdel = (tobj != oldObj);
1870 return tobj;
1871 }
1872 }
1873 return NULL;
1874}
1875
1876
1877float Bone_Distance(INode * bone,TimeValue time,const Point3 & vertex)
1878{
1879 /*
1880 ** Average the pivot point of this bone with the pivot points of
1881 ** all of its children.
1882 */
1883 Point3 icenter = bone->GetObjectTM(time).GetTrans();
1884
1885 for (int ci=0; ci<bone->NumberOfChildren(); ci++) {
1886 icenter += bone->GetChildNode(ci)->GetObjectTM(time).GetTrans();
1887 }
1888
1889 icenter = icenter / (float)(bone->NumberOfChildren() + 1);
1890
1891 return Length(icenter - vertex);
1892}
1893
1894#if defined W3D_MAX4 //defined as in the project (.dsp)
1895
1896int SkinModifierClass::NumSubObjTypes()
1897{
1898 return 1;
1899}
1901ISubObjType *SkinModifierClass::GetSubObjType(int i)
1902{
1903
1904 static bool _initialized = false;
1905 if(!_initialized){
1906 _initialized = true;
1907 _SubObjectTypeVertex.SetName("Vertices");
1908 }
1909 if(i == -1){
1910 if(GetSubObjectLevel() > 0){
1911 return GetSubObjType(GetSubObjectLevel()-1);
1912 }
1913 }
1914 return &_SubObjectTypeVertex;
1915}
1916#endif
#define NULL
Definition BaseType.h:92
#define TRUE
Definition BaseType.h:109
#define FALSE
Definition BaseType.h:113
@ FOREVER
Definition GameCommon.h:196
unsigned int UINT
Definition bittype.h:63
unsigned long ULONG
Definition bittype.h:64
#define IDS_BONE_INFLUENCE_PARAMS
Definition resource.h:396
#define IDS_SOT
Definition resource.h:47
#define IDD_SKELETON_PARAMETERS
Definition resource.h:71
#define IDC_UNLINK_BUTTON
Definition resource.h:180
#define IDD_BONE_INFLUENCE_PARAMS
Definition resource.h:70
#define IDC_BASE_POSE_SPIN
Definition resource.h:169
#define IDS_SKELETON_PARAMETERS
Definition resource.h:398
#define IDC_REMOVE_BONES_BUTTON
Definition resource.h:177
#define IDC_LINK_BUTTON
Definition resource.h:176
#define IDC_LINK_BY_NAME_BUTTON
Definition resource.h:163
#define IDC_BONE_LIST
Definition resource.h:181
#define IDC_ADD_BONES_BUTTON
Definition resource.h:173
#define IDD_SKIN_SOT
Definition resource.h:72
#define IDC_BASE_POSE_EDIT
Definition resource.h:164
#define IDC_AUTO_LINK_BUTTON
Definition resource.h:168
#define BOOL
Definition Wnd_File.h:57
const int NumBoneIconFaces
Definition boneicon.cpp:42
VertexStruct BoneIconVerts[NumBoneIconVerts]
Definition boneicon.cpp:49
FaceStruct BoneIconFaces[NumBoneIconFaces]
Definition boneicon.cpp:238
const int NumBoneIconVerts
Definition boneicon.cpp:41
BonePickerClass TheBonePicker
Definition bpick.cpp:50
void Set_User(BonePickerUserClass *user, int singlepick=FALSE, INodeTab *bonelist=NULL)
Definition bpick.h:75
void Reset(void)
Definition namedsel.cpp:80
Tab< TSTR * > Names
Definition namedsel.h:55
int Find_Set(TSTR &setname)
Definition namedsel.cpp:110
void Append_Set(BitArray &nset, TSTR &setname)
Definition namedsel.cpp:52
NamedSelSetList VertSelSets
Definition skindata.h:142
BitArray VertSel
Definition skindata.h:137
void Add_Influence(int boneidx)
Definition skindata.h:114
Tab< InfluenceStruct > VertData
Definition skindata.h:147
IOResult Load(ILoad *iload)
Definition skindata.cpp:116
IOResult Save(ISave *isave)
Definition skindata.cpp:56
void Validate(Mesh *mesh)
Definition skindata.h:96
BOOL IsValid()
Definition skindata.h:94
Class_ID ClassID()
Definition skin.cpp:109
SClass_ID SuperClassID()
Definition skin.cpp:108
void * Create(BOOL loading=FALSE)
Definition skin.cpp:106
const TCHAR * ClassName()
Definition skin.cpp:107
const TCHAR * Category()
Definition skin.cpp:110
virtual void User_Picked_Bones(INodeTab &nodetab)
Definition skin.cpp:1327
void Create_Named_Selection_Sets(void)
Definition skin.cpp:1395
void EndEditParams(IObjParam *ip, ULONG flags, Animatable *next)
Definition skin.cpp:676
void InvertSelection(int selLevel)
Definition skin.cpp:1226
IObjParam * InterfacePtr
Definition skin.h:385
void BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev)
Definition skin.cpp:642
void SetReference(int i, RefTargetHandle rtarg)
Definition skin.cpp:739
SkinModifierClass(void)
Definition skin.cpp:599
virtual void ActivateSubSelSet(TSTR &setName)
Definition skin.cpp:1338
void Install_Named_Selection_Sets(void)
Definition skin.cpp:1442
virtual void RemoveSubSelSet(TSTR &setName)
Definition skin.cpp:1390
virtual void NewSetFromCurSel(TSTR &setName)
Definition skin.cpp:1385
int SubObjSelLevel
Definition skin.h:370
SelectModBoxCMode * SelectMode
Definition skin.h:386
RefTargetHandle Clone(RemapDir &remap=NoRemap())
Definition skin.cpp:635
RefTargetHandle GetReference(int i)
Definition skin.cpp:730
void SelectSubComponent(HitRecord *hitRec, BOOL selected, BOOL all, BOOL invert=FALSE)
Definition skin.cpp:1067
ICustButton * LinkByNameButton
Definition skin.h:378
ICustButton * LinkButton
Definition skin.h:377
INode * WSMNodeRef
Definition skin.h:360
friend BOOL CALLBACK _bone_influence_dialog_thunk(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
Definition skin.cpp:1754
SkinWSMObjectClass * WSMObjectRef
Definition skin.h:359
WSMObject * Get_WSMObject(void)
Definition skin.h:320
virtual IOResult SaveLocalData(ISave *isave, LocalModData *ld)
Definition skin.cpp:923
virtual void ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node)
Definition skin.cpp:766
Interval Get_Validity(TimeValue t)
Definition skin.cpp:708
virtual IOResult LoadLocalData(ILoad *iload, LocalModData **pld)
Definition skin.cpp:930
void Default_Init(void)
Definition skin.cpp:620
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID &partID, RefMessage message)
Definition skin.cpp:747
HWND BoneInfluenceHWND
Definition skin.h:376
IOResult Save(ISave *isave)
Definition skin.cpp:878
IOResult Load(ILoad *iload)
Definition skin.cpp:894
void Unlink_Verts(void)
Definition skin.cpp:1528
ICustButton * UnLinkButton
Definition skin.h:380
ICustButton * AutoLinkButton
Definition skin.h:379
int HitTest(TimeValue t, INode *inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt, ModContext *mc)
Definition skin.cpp:993
void SelectAll(int selLevel)
Definition skin.cpp:1172
void Auto_Attach_Verts(BOOL all=FALSE)
Definition skin.cpp:1465
void ClearSelection(int selLevel)
Definition skin.cpp:1116
virtual void User_Picked_Bone(INode *node)
Definition skin.cpp:1284
void ActivateSubobjSel(int level, XFormModes &modes)
Definition skin.cpp:947
const TCHAR * ClassName()
Definition skin.cpp:86
const TCHAR * Category()
Definition skin.cpp:89
void * Create(BOOL loading=FALSE)
Definition skin.cpp:85
SClass_ID SuperClassID()
Definition skin.cpp:87
Class_ID ClassID()
Definition skin.cpp:88
static HWND SotHWND
Definition skin.h:169
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID &partID, RefMessage message)
Definition skin.cpp:287
void Remove_Bone(INode *node)
Definition skin.cpp:475
int Get_Base_Pose_Time(void)
Definition skin.h:155
static ISpinnerControl * BasePoseSpin
Definition skin.h:175
virtual ~SkinWSMObjectClass()
Definition skin.cpp:160
static ICustButton * RemoveBonesButton
Definition skin.h:174
@ BONE_SEL_MODE_ADD_MANY
Definition skin.h:189
@ BONE_SEL_MODE_REMOVE_MANY
Definition skin.h:190
IOResult Save(ISave *isave)
Definition skin.cpp:521
int To_Ref_Index(int boneidx)
Definition skin.h:145
virtual void User_Picked_Bone(INode *node)
Definition skin.cpp:372
virtual void SetReference(int i, RefTargetHandle rtarg)
Definition skin.cpp:275
void Set_Bone_Selection_Mode(int mode)
Definition skin.cpp:412
void BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev)
Definition skin.cpp:177
int BoneSelectionMode
Definition skin.h:193
INodeTab & Get_Bone_List(void)
Definition skin.h:152
void Add_Bones(INodeTab &nodetab)
Definition skin.cpp:465
int Find_Closest_Bone(const Point3 &vertex)
Definition skin.cpp:571
static HWND BoneListHWND
Definition skin.h:171
Modifier * CreateWSMMod(INode *node)
Definition skin.cpp:320
friend BOOL CALLBACK _skeleton_dialog_thunk(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
Definition skin.cpp:1645
void Remove_Bones(INodeTab &nodetab)
Definition skin.cpp:484
BOOL Skeleton_Dialog_Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
Definition skin.cpp:1658
static ICustButton * AddBonesButton
Definition skin.h:173
int Add_Bone(INode *node)
Definition skin.cpp:429
int Find_Bone(INode *node)
Definition skin.cpp:513
void BuildMesh(TimeValue t)
Definition skin.cpp:328
void EndEditParams(IObjParam *ip, ULONG flags, Animatable *next)
Definition skin.cpp:219
static IObjParam * InterfacePtr
Definition skin.h:172
static HWND SkeletonHWND
Definition skin.h:170
virtual RefTargetHandle GetReference(int i)
Definition skin.cpp:258
virtual void User_Picked_Bones(INodeTab &nodetab)
Definition skin.cpp:392
INodeTab BoneTab
Definition skin.h:194
IOResult Load(ILoad *iload)
Definition skin.cpp:538
RefTargetHandle Clone(RemapDir &remap=NoRemap())
Definition skin.cpp:249
int Num_Bones(void)
Definition skin.h:150
void Update_Bone_List(void)
Definition skin.cpp:494
INode * Get_Bone(int idx)
Definition skin.h:151
int To_Bone_Index(int refidx)
Definition skin.h:144
void Build_Tri(Face *f, int a, int b, int c)
Definition skin.cpp:365
CreateMouseCallBack * GetCreateMouseCallBack()
Definition skin.cpp:310
int proc(ViewExp *vpt, int msg, int point, int flags, IPoint2 m, Matrix3 &mat)
Definition skin.cpp:128
HINSTANCE AppInstance
Definition dllmain.cpp:67
TCHAR * Get_String(int id)
Definition dllmain.cpp:198
#define MAX_STRING_LENGTH
Definition dllmain.h:46
MSG msg
Definition patch.cpp:409
WWINLINE Quaternion Inverse(const Quaternion &a)
Definition quat.h:117
ClassDesc * Get_Skin_Mod_Desc()
Definition skin.cpp:114
ClassDesc * Get_Skin_Obj_Desc()
Definition skin.cpp:93
#define SKIN_OBJ_CLASS_ID
Definition skin.h:49
#define SKIN_MOD_CLASS_ID
Definition skin.h:50
int BoneIdx[2]
Definition skindata.h:54