skin.cpp 46 KB

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