skin.cpp 45 KB

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