Advertisement
Guest User

New BSDismemberment code

a guest
Sep 5th, 2015
215
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 64.83 KB | None | 0 0
  1. /**********************************************************************
  2. *<
  3. FILE: BSDismemberSkin.cpp
  4.  
  5. DESCRIPTION: Mesh and Skin Import routines
  6.  
  7. CREATED BY: Blabba
  8.  
  9. HISTORY:
  10.  
  11. *>  Copyright (c) 2015, All Rights Reserved.
  12. **********************************************************************/
  13.  
  14. #include <max.h>
  15. #include <meshdlib.h>
  16. // #include <afxwin.h>
  17. #include "..\NifProps\iNifProps.h"
  18. #include "NifGui.h"
  19. // #include "utilapi.h"
  20.  
  21. // Class Definitions
  22. #define WM_UPDATE_CACHE (WM_USER + 0x2000)
  23. #ifndef MESHSELECTCONVERT_INTERFACE
  24. #define MESHSELECTCONVERT_INTERFACE Interface_ID(0x3da7dd5, 0x7ecf0391)
  25. #endif
  26.  
  27. // Button Definitions
  28. #define IDC_SELVERTEX   0x3260
  29. #define IDC_SELEDGE     0x3261
  30. #define IDC_SELFACE     0x3262
  31. #define IDC_SELPOLY     0x3263
  32. #define IDC_SELELEMENT  0x3264
  33. // extern int *meshSubTypeToolbarIDs;
  34.  
  35. // MeshSelMod flags:
  36. #define MS_DISP_END_RESULT 0x01
  37.  
  38. // BSDSModifier References:
  39. #define REF_PBLOCK 0
  40.  
  41. // Local static class instances
  42. static BSDSImageHandler theBSDSImageHandler;
  43. static BSDSPartImageHandler theBSDSPartImageHandler;
  44. // static GenSubObjType SOT_Vertex(_M("Vertex"), _M("SubObjectIcons"), 1);
  45. // static GenSubObjType SOT_Edge(_M("Edge"), _M("SubObjectIcons"), 2);
  46. static GenSubObjType SOT_Face(_M("Face"), _M("SubObjectIcons"), 3);
  47. static GenSubObjType SOT_Poly(_M("Poly"), _M("SubObjectIcons"), 4);
  48. static GenSubObjType SOT_Element(_M("Element"), _M("SubObjectIcons"), 5);
  49.  
  50. // Enum Lookup types for display in drowpdown list
  51. const EnumLookupType GameFlags[] = {
  52.     { DismemberPartition::NoGame, _T("No Game") },
  53.     { DismemberPartition::Skyrim, _T("Skyrim") },
  54.     { DismemberPartition::Fallout_NV, _T("Fallout: New Vegas") },
  55.     { DismemberPartition::Fallout_3, _T("Fallout_3") },
  56.     { DismemberPartition::Oblivion, _T("Oblivion") },
  57.     { DismemberPartition::Morrowind, _T("Morrowind") },
  58. };
  59.  
  60. // Forward class declaration for GetModifierData();
  61. class BSDSData;
  62.  
  63. // Main BSDismember Class Definition
  64. class BSDSModifier : public Modifier, public IBSDismemberSkinModifier, public FlagUser {
  65. public:
  66.  
  67.     IParamBlock2 *pblock;
  68.  
  69.     static IObjParam *ip;
  70.     static BSDSModifier *editMod;
  71.     static SelectModBoxCMode *selectMode;
  72.     static BOOL updateCachePosted;
  73.  
  74.     // Default Constructor
  75.     BSDSModifier();
  76.  
  77.     // Animatable Class Overrides
  78.     void DeleteThis() { delete this; }
  79.     void GetClassName(TSTR& s) { s = GetString(IDS_RB_BSDSMODIFIER); }
  80.     virtual Class_ID ClassID() { return BSDSMODIFIER_CLASS_ID; }
  81.     RefTargetHandle Clone(RemapDir& remap /*= DefaultRemapDir()*/);
  82.     const TCHAR *GetObjectName() { return GetString(IDS_RB_BSDSMODIFIER); }
  83.     void* GetInterface(ULONG id) { return (id == I_BSDISMEMBERSKINMODIFIER) ? (IBSDismemberSkinModifier*) this : Modifier::GetInterface(id); }
  84.  
  85.     // Modifier Class Overrides
  86.     ChannelMask ChannelsUsed()  { return PART_GEOM | PART_TOPO; }
  87.     ChannelMask ChannelsChanged() { return PART_SELECT | PART_SUBSEL_TYPE | PART_TOPO | PART_GEOM; }
  88.     Class_ID InputType() { return triObjectClassID; }
  89.     void ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node);
  90.     Interval LocalValidity(TimeValue t);
  91.     Interval GetValidity(TimeValue t);
  92.     BOOL DependOnTopology(ModContext &mc) { return TRUE; }
  93.  
  94.     // BaseObject Class Overrides
  95.     CreateMouseCallBack* GetCreateMouseCallBack() { return NULL; }
  96.     void BeginEditParams(IObjParam  *ip, ULONG flags, Animatable *prev);
  97.     void EndEditParams(IObjParam *ip, ULONG flags, Animatable *next);
  98.     int HitTest(TimeValue t, INode* inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt, ModContext* mc);
  99.     int Display(TimeValue t, INode* inode, ViewExp *vpt, int flagst, ModContext *mc);
  100.     void ActivateSubobjSel(int level, XFormModes& modes);
  101.     void SelectSubComponent(HitRecord *hitRec, BOOL selected, BOOL all, BOOL invert = FALSE);
  102.     void ClearSelection(int selLevel);
  103.     void SelectAll(int selLevel);
  104.     void InvertSelection(int selLevel);
  105.     void NotifyInputChanged(Interval changeInt, PartID partID, RefMessage message, ModContext *mc);
  106.     void ShowEndResultChanged(BOOL showEndResult) { NotifyDependents(FOREVER, PART_DISPLAY, REFMSG_CHANGE); }
  107.     BOOL SupportsNamedSubSels() { return FALSE; }
  108.  
  109.     // Unsure if needed?
  110.     // void ActivateSubSelSet(int index);
  111.  
  112.     // New SubObjType API
  113.     int NumSubObjTypes();
  114.     ISubObjType *GetSubObjType(int i);
  115.  
  116.     // IO Class Overrides
  117.     IOResult Save(ISave *isave);
  118.     IOResult Load(ILoad *iload);
  119.     IOResult SaveLocalData(ISave *isave, LocalModData *ld);
  120.     IOResult LoadLocalData(ILoad *iload, LocalModData **pld);
  121.  
  122.     int NumParamBlocks() { return 1; }
  123.     IParamBlock2 *GetParamBlock(int i) { return pblock; }
  124.     IParamBlock2 *GetParamBlockByID(short id) { return (pblock->ID() == id) ? pblock : NULL; }
  125.     int NumRefs() { return 1; }
  126.     RefTargetHandle GetReference(int i) { return pblock; }
  127. private:
  128.     virtual void SetReference(int i, RefTargetHandle rtarg) { pblock = (IParamBlock2 *)rtarg; }
  129. public:
  130.     int NumSubs() { return 1; }
  131.     Animatable* SubAnim(int i) { return GetReference(i); }
  132.     TSTR SubAnimName(int i) { return GetString(IDS_RB_PARAMETERS); }
  133.  
  134.     RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message);
  135.  
  136.     // Modifier Methods
  137.     void UpdateSelLevelDisplay();
  138.     void SetEnableStates();
  139.     void SelectByMatID(int id);
  140.     void SetNumSelLabel();
  141.     void UpdateCache(TimeValue t);
  142.     void InvalidateDialogElement(int elem);
  143.  
  144.     void LocalDataChanged();
  145.     void SelectUnused();
  146.     IBSDismemberSkinModifierData *GetModifierDataInterface();
  147.     BSDSData* GetModifierData();
  148. };
  149.  
  150. class BSDSData : public LocalModData, public IBSDismemberSkinModifierData {
  151. private:
  152.     // Temp data used for soft selections, adjacent edge / face lists.
  153.     MeshTempData *temp;
  154.  
  155. public:
  156.     // Get Interface of this type of LocalModData
  157.     void* GetInterface(ULONG id) { if (id == I_BSDISMEMBERSKINMODIFIERDATA) return(IMeshSelectData*)this; else return LocalModData::GetInterface(id); }
  158.  
  159.     // Selection sets
  160.     // Tab<BitArray> vertSel;
  161.     Tab<BitArray> faceSel;
  162.     // Tab<BitArray> edgeSel;
  163.  
  164.     BOOL held;
  165.     Mesh *mesh;
  166.     int currentPartition;
  167.     Tab<DismemberPartition> bodyParts;
  168.  
  169.     // BSDSData functions
  170.     BSDSData(Mesh &mesh);
  171.     // Re-define later and initialize 3 different BitArray's that are empty and append them to the tab
  172.     BSDSData();
  173.     ~BSDSData() { FreeCache(); }
  174.     LocalModData *Clone();
  175.     Mesh *GetMesh() { return mesh; }
  176.     AdjEdgeList *GetAdjEdgeList();
  177.     AdjFaceList *GetAdjFaceList();
  178.     void SetCache(Mesh &mesh);
  179.     void FreeCache();
  180.     void SynchBitArrays();
  181.  
  182.     void SelVertByFace();
  183.     void SelVertByEdge();
  184.     void SelFaceByVert();
  185.     void SelFaceByEdge();
  186.     void SelPolygonByVert(float thresh, int igVis);
  187.     void SelPolygonByEdge(float thresh, int igVis);
  188.     void SelElementByVert();
  189.     void SelElementByEdge();
  190.     void SelEdgeByVert();
  191.     void SelEdgeByFace();
  192.  
  193.     // void SetVertSel(BitArray &set, BSDSModifier *imod, TimeValue t);
  194.     void SetFaceSel(BitArray &set, BSDSModifier *imod, TimeValue t);
  195.     // void SetEdgeSel(BitArray set, BSDSModifier *imod, TimeValue t);
  196.     void SetFaceSel(BitArray &set, IBSDismemberSkinModifier *imod, TimeValue t) { SetFaceSel(set, (BSDSModifier*)imod, t); }
  197.     // void SetEdgeSel(BitArray set, IBSDismemberSkinModifier *imod, TimeValue t) { SetFaceSel(set, (BSDSModifier*)imod, t); }
  198.     Tab<DismemberPartition> GetDismembers() { return bodyParts; }
  199.     BitArray GetFaceSel() { return faceSel[currentPartition]; }
  200.     // BitArray GetEdgeSel() { return edgeSel[currentPartition]; }
  201.  
  202.     // Custom Methods
  203.     int AddPartition();
  204.     void RemovePartition(int num);
  205.     int GetCurrentPartition() { return currentPartition; }
  206.     int GetNumPartitions() { return bodyParts.Count(); }
  207.     BitArray GetUnused();
  208.     // Note:Zero indexed
  209.     void SetCurrentPartition(int i) { (i < bodyParts.Count()) ? currentPartition = i : currentPartition; }
  210. };
  211.  
  212. // Proc Class for getting Modifier local data.Maybe change this later?
  213. class SelectModContextEnumProc : public ModContextEnumProc {
  214. public:
  215.     virtual BOOL proc(ModContext *mc) {
  216.         data = (LocalModData*)mc->localData;
  217.         /*if (!data) {
  218.             data = (LocalModData*)&manual;
  219.             mc->localData = data;
  220.         }*/
  221.         return TRUE;
  222.     }
  223.     LocalModData *data;
  224.     // BSDSData manual;
  225. };
  226.  
  227. // Sub-Class Overrides
  228. class SelectRestore : public RestoreObj {
  229. public:
  230.     BitArray usel, rsel;
  231.     BitArray *sel;
  232.     BSDSModifier *mod;
  233.     BSDSData *d;
  234.     int level;
  235.  
  236.     SelectRestore(BSDSModifier *m, BSDSData *d);
  237.     // SelectRestore(BSDSModifier *m, BSDSData *d, int level);
  238.     void Restore(int isUndo);
  239.     void Redo();
  240.     int Size() { return 1; }
  241.     void EndHold() { d->held = FALSE; }
  242.     TSTR Description() { return TSTR(_T("SelectRestore")); }
  243. };
  244. //-------------------------------- ClassDescriptor and Class Vars ----------------------------------
  245.  
  246. IObjParam *BSDSModifier::ip = NULL;
  247. BSDSModifier *BSDSModifier::editMod = NULL;
  248. SelectModBoxCMode *BSDSModifier::selectMode = NULL;
  249. BOOL BSDSModifier::updateCachePosted = FALSE;
  250.  
  251. class BSDSClassDesc :public ClassDesc2 {
  252. public:
  253.     // BSDSClassDesc();
  254.     int             IsPublic() { return 1; }
  255.     void *          Create(BOOL loading = FALSE) { return new BSDSModifier; }
  256.     const TCHAR *   ClassName() { return GetString(IDS_RB_BSDSMODIFIER); }
  257.     SClass_ID       SuperClassID() { return OSM_CLASS_ID; }
  258.     Class_ID        ClassID() { return BSDSMODIFIER_CLASS_ID; }
  259.     const TCHAR*    Category() { return GetString(IDS_CATEGORY); }
  260.     const TCHAR * InternalName() { return _T("BSDSModifier"); }
  261.     HINSTANCE HInstance() { return hInstance; }
  262. };
  263.  
  264. static BSDSClassDesc BSDSDesc;
  265. ClassDesc2* GetBSDSModifierDesc() { return &BSDSDesc; }
  266. /*BSDSClassDesc::BSDSClassDesc() {
  267.     BSDS_desc.SetClassDesc(this);
  268. }*/
  269.  
  270. class BSDSModifierMainDlgProc : public ParamMap2UserDlgProc {
  271. public:
  272.     BSDSModifier *mod;
  273.     BSDSModifierMainDlgProc() { mod = NULL; }
  274.     void SetEnables(HWND hWnd);
  275.     void UpdateSelLevelDisplay(HWND hWnd);
  276.     INT_PTR DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
  277.     void DeleteThis() { }
  278.  
  279.     NpComboBox gameList;
  280.     // NpComboBox dismemberList;
  281.     ISpinnerControl *mActivePart;
  282.     ICustButton *mAddPart;
  283.     ICustButton *mDelPart;
  284. };
  285.  
  286. static BSDSModifierMainDlgProc theBSDSModifierMainDlgProc;
  287.  
  288. // Table to convert selLevel values to mesh selLevel flags.
  289. const int meshLevel[] = { MESH_OBJECT, /*MESH_VERTEX, MESH_EDGE,*/ MESH_FACE, MESH_FACE, MESH_FACE };
  290.  
  291. // Get display flags based on selLevel.
  292. const DWORD levelDispFlags[] = { 0, /*DISP_VERTTICKS | DISP_SELVERTS, DISP_SELEDGES,*/ DISP_SELFACES, DISP_SELPOLYS, DISP_SELPOLYS };
  293.  
  294. // For hit testing...
  295. const int hitLevel[] = { 0, /*SUBHIT_VERTS, SUBHIT_EDGES,*/ SUBHIT_FACES, SUBHIT_FACES, SUBHIT_FACES };
  296.  
  297. // Parameter block IDs:
  298. // Blocks themselves:
  299. enum { ms_pblock };
  300. // Parameter maps:
  301. enum { ms_map_main };
  302. // Parameters in first block:
  303. enum { ms_by_vertex, ms_ignore_backfacing, ms_matid, ms_ignore_visible, ms_planar_threshold, };
  304.  
  305. static ParamBlockDesc2 BSDS_desc(ms_pblock,
  306.     _T("BSDismemberSkinDescription"),
  307.     IDS_MS_SOFTSEL, &BSDSDesc,
  308.     P_AUTO_CONSTRUCT | P_AUTO_UI | P_MULTIMAP,
  309.     REF_PBLOCK,
  310.     //rollout descriptions
  311.     1,
  312.     ms_map_main, IDD_BSDS_SELECT, IDS_MS_PARAMS, 0, 0, NULL,
  313.  
  314.     // params
  315.     ms_by_vertex, _T("byVertex"), TYPE_BOOL, P_RESET_DEFAULT, IDS_BY_VERTEX,
  316.     p_default, false,
  317.     p_ui, ms_map_main, TYPE_SINGLECHEKBOX, IDC_MS_SEL_BYVERT,
  318.     p_end,
  319.  
  320.     ms_ignore_backfacing, _T("ignoreBackfacing"), TYPE_BOOL, P_RESET_DEFAULT, IDS_IGNORE_BACKFACING,
  321.     p_default, false,
  322.     p_ui, ms_map_main, TYPE_SINGLECHEKBOX, IDC_MS_IGNORE_BACKFACES,
  323.     p_end,
  324.  
  325.     ms_matid, _T("materialID"), TYPE_INT, P_TRANSIENT | P_RESET_DEFAULT, IDS_RB_MATERIALID,
  326.     p_default, 1,
  327.     p_range, 1, 65535,
  328.     p_ui, ms_map_main, TYPE_SPINNER, EDITTYPE_INT,
  329.     IDC_MS_MATID, IDC_MS_MATIDSPIN, .5f,
  330.     p_end,
  331.  
  332.     ms_ignore_visible, _T("ignoreVisibleEdges"), TYPE_BOOL, P_RESET_DEFAULT, IDS_IGNORE_VISIBLE,
  333.     p_default, false,
  334.     p_ui, ms_map_main, TYPE_SINGLECHEKBOX, IDC_MS_IGNORE_VISEDGE,
  335.     p_end,
  336.  
  337.     ms_planar_threshold, _T("planarThreshold"), TYPE_ANGLE, P_RESET_DEFAULT, IDS_RB_THRESHOLD,
  338.     p_default, PI / 4.0f,   // Default value for angles has to be in radians.
  339.     p_range, 0.0f, 180.0f// but range given in degrees.
  340.     p_ui, ms_map_main, TYPE_SPINNER, EDITTYPE_POS_FLOAT,
  341.     IDC_MS_PLANAR, IDC_MS_PLANARSPINNER, .1f,
  342.     p_end,
  343.     p_end
  344.     );
  345.  
  346. //-------------------------------- BDSDSModifier Methods ----------------------------------
  347.  
  348. BSDSData *BSDSModifier::GetModifierData() {
  349.     SelectModContextEnumProc selector;
  350.     this->EnumModContexts(&selector);
  351.     BSDSData *testData = dynamic_cast<BSDSData*>(selector.data);
  352.     return testData;
  353. }
  354.  
  355. IBSDismemberSkinModifierData *BSDSModifier::GetModifierDataInterface() {
  356.     SelectModContextEnumProc selector;
  357.     this->EnumModContexts(&selector);
  358.     BSDSData *testData = dynamic_cast<BSDSData*>(selector.data);
  359.     if (!testData)
  360.         return NULL;
  361.     if (IBSDismemberSkinModifierData *modData = static_cast<IBSDismemberSkinModifierData*>(testData->GetInterface(I_BSDISMEMBERSKINMODIFIERDATA)))
  362.         return modData;
  363.     return NULL;
  364. }
  365.  
  366. BSDSModifier::BSDSModifier() {
  367.     pblock = NULL;
  368.     BSDSDesc.MakeAutoParamBlocks(this);
  369.     assert(pblock);
  370. }
  371.  
  372. RefTargetHandle BSDSModifier::Clone(RemapDir& remap) {
  373.     BSDSModifier *mod = new BSDSModifier();
  374.     mod->ReplaceReference(0, remap.CloneRef(pblock));
  375.     BaseClone(this, mod, remap);
  376.     return mod;
  377. }
  378.  
  379. Interval BSDSModifier::LocalValidity(TimeValue t) {
  380.     // If we are being edited, return NEVER to forces a cache to be built after previous modifier.
  381.     if (TestAFlag(A_MOD_BEING_EDITED))
  382.         return NEVER;
  383.     return GetValidity(t);
  384. }
  385.  
  386. Interval BSDSModifier::GetValidity(TimeValue t) { return FOREVER; }
  387.  
  388. void BSDSModifier::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node) {
  389.     if (!os->obj->IsSubClassOf(triObjectClassID)) return;
  390.     TriObject *tobj = (TriObject*)os->obj;
  391.     BSDSData *d = dynamic_cast<BSDSData*>(mc.localData);
  392.     if (!d) mc.localData = d = new BSDSData(tobj->GetMesh());
  393.  
  394.     // BitArray vertSel = d->vertSel[d->currentPartition];
  395.     BitArray faceSel = d->faceSel[d->currentPartition];
  396.     // BitArray edgeSel = d->edgeSel[d->currentPartition];
  397.     // vertSel.SetSize(tobj->GetMesh().getNumVerts(), TRUE);
  398.     faceSel.SetSize(tobj->GetMesh().getNumFaces(), TRUE);
  399.     // edgeSel.SetSize(tobj->GetMesh().getNumFaces() * 3, TRUE);
  400.     // tobj->GetMesh().vertSel = vertSel;
  401.     tobj->GetMesh().faceSel = faceSel;
  402.     // tobj->GetMesh().edgeSel = edgeSel;
  403.     tobj->GetMesh().selLevel = meshLevel[d->bodyParts[d->currentPartition].selLevel];
  404.  
  405.     Interval outValid = tobj->ChannelValidity(t, SELECT_CHAN_NUM);
  406.  
  407.     // Update the cache used for display, hit-testing:
  408.     if (!d->GetMesh()) d->SetCache(tobj->GetMesh());
  409.     else *(d->GetMesh()) = tobj->GetMesh();
  410.  
  411.     // Set display flags - but be sure to turn off vertex display in stack result if
  412.     // "Show End Result" is turned on - we want the user to just see the Mesh Select
  413.     // level vertices (from the Display method).
  414.     tobj->GetMesh().dispFlags = 0;
  415.     if (/*d->bodyParts[d->currentPartition].selLevel != SEL_VERTEX ||*/ !ip || !ip->GetShowEndResult())
  416.         tobj->GetMesh().SetDispFlag(levelDispFlags[d->bodyParts[d->currentPartition].selLevel]);
  417.     tobj->SetChannelValidity(SELECT_CHAN_NUM, outValid);
  418.  
  419.     // Maybe un-needed?
  420.     // LocalDataChanged();
  421. }
  422.  
  423. void BSDSModifier::NotifyInputChanged(Interval changeInt, PartID partID, RefMessage message, ModContext *mc) {
  424.     if (!mc->localData) return;
  425.     if (partID == PART_SELECT) return;
  426.     ((BSDSData*)mc->localData)->FreeCache();
  427.  
  428.     if (!BSDSDesc.NumParamMaps()) return;
  429.     IParamMap2 *pmap = BSDSDesc.GetParamMap(ms_map_main);
  430.     if (!pmap) return;
  431.     HWND hWnd = pmap->GetHWnd();
  432.     if (!hWnd) return;
  433.     TimeValue t = ip->GetTime();
  434.     PostMessage(hWnd, WM_UPDATE_CACHE, (WPARAM)t, 0);
  435.     updateCachePosted = TRUE;
  436. }
  437.  
  438. void BSDSModifier::UpdateCache(TimeValue t) {
  439.     NotifyDependents(Interval(t, t), PART_GEOM | SELECT_CHANNEL | PART_SUBSEL_TYPE | PART_DISPLAY | PART_TOPO, REFMSG_MOD_EVAL);
  440.     updateCachePosted = FALSE;
  441. }
  442.  
  443. void BSDSModifier::UpdateSelLevelDisplay() {
  444.     if (theBSDSModifierMainDlgProc.mod != this) return;
  445.     if (!BSDSDesc.NumParamMaps()) return;
  446.     IParamMap2 *pmap = BSDSDesc.GetParamMap(ms_map_main);
  447.     if (!pmap) return;
  448.     HWND hWnd = pmap->GetHWnd();
  449.     if (!hWnd) return;
  450.     theBSDSModifierMainDlgProc.UpdateSelLevelDisplay(hWnd);
  451. }
  452.  
  453. static int butIDs[] = { 0, IDC_SELFACE, IDC_SELPOLY, IDC_SELELEMENT };
  454. void BSDSModifierMainDlgProc::UpdateSelLevelDisplay(HWND hWnd) {
  455.     if (!mod) return;
  456.     BSDSData *d = mod->GetModifierData();
  457.     int selLevel, nParts, nActive;
  458.     if (!d) {
  459.         selLevel = SEL_OBJECT;
  460.         nParts = 1;
  461.         nActive = 0;
  462.         gameList.select(1);
  463.         // dismemberList.SelectString(_T("Body"));
  464.     }
  465.     else {
  466.         selLevel = d->bodyParts[d->currentPartition].selLevel;
  467.         nParts = d->bodyParts.Count();
  468.         nActive = d->currentPartition;
  469.         gameList.select(d->bodyParts[d->currentPartition].thisGame);
  470.         // dismemberList.SelectString(d->bodyParts[d->currentPartition].currentSlot.c_str());
  471.     }
  472.     ICustToolbar *iToolbar = GetICustToolbar(GetDlgItem(hWnd, IDC_MS_SELTYPE));
  473.     ICustButton *but;
  474.     int level = mod->ip->GetSubObjectLevel();
  475.     // DWORD selLevel = d->bodyParts[d->currentPartition].selLevel;
  476.     for (int i = 1; i< 4; i++) {
  477.         but = iToolbar->GetICustButton(butIDs[i]);
  478.         but->SetCheck(level != 0 && i == selLevel);
  479.         ReleaseICustButton(but);
  480.     }
  481.     ReleaseICustToolbar(iToolbar);
  482.  
  483.     if (mActivePart) {
  484.         // int nParts = d->GetNumPartitions();
  485.         // int nActive = d->currentPartition;
  486.         mActivePart->SetLimits(0, nParts - 1, TRUE);
  487.         mActivePart->SetValue(nActive, 0);
  488.     }
  489.     // gameList.select(EnumToIndex(d->bodyParts[d->currentPartition].thisGame, GameFlags));
  490.     // DismemberList Update May work?
  491.     // dismemberList.SelectString(d->bodyParts[d->currentPartition].currentSlot.c_str());
  492.     UpdateWindow(hWnd);
  493. }
  494.  
  495. static bool oldShowEnd;
  496. void BSDSModifier::BeginEditParams(IObjParam  *ip, ULONG flags, Animatable *prev) {
  497.     this->ip = ip;
  498.     editMod = this;
  499.  
  500.     // Use our classdesc2 to put up our parammap2 maps:
  501.     BSDSDesc.BeginEditParams(ip, this, flags, prev);
  502.     theBSDSModifierMainDlgProc.mod = this;
  503.     BSDSDesc.SetUserDlgProc(&BSDS_desc, ms_map_main, &theBSDSModifierMainDlgProc);
  504.  
  505.     selectMode = new SelectModBoxCMode(this, ip);
  506.  
  507.     // Restore the selection level.
  508.     // ip->SetSubObjectLevel( GetActivePartition() + 1 );
  509.  
  510.     SetEnableStates();
  511.     UpdateSelLevelDisplay();
  512.     SetNumSelLabel();
  513.  
  514.     // Set show end result.
  515.     oldShowEnd = ip->GetShowEndResult() ? TRUE : FALSE;
  516.     ip->SetShowEndResult(GetFlag(MS_DISP_END_RESULT));
  517.  
  518.     // NotifyDependents(FOREVER, PART_ALL, REFMSG_NUM_SUBOBJECTTYPES_CHANGED);
  519.  
  520.     TimeValue t = ip->GetTime();
  521.     NotifyDependents(Interval(t, t), PART_ALL, REFMSG_BEGIN_EDIT);
  522.     NotifyDependents(Interval(t, t), PART_ALL, REFMSG_MOD_DISPLAY_ON);
  523.     SetAFlag(A_MOD_BEING_EDITED);
  524.     // Ensure creation of local mod data
  525.     // ip->GetSelNode(0)->EvalWorldState(0);
  526. }
  527.  
  528. void BSDSModifier::EndEditParams(IObjParam *ip, ULONG flags, Animatable *next) {
  529.     BSDSDesc.EndEditParams(ip, this, flags, next);
  530.     theBSDSModifierMainDlgProc.mod = NULL;
  531.  
  532.     ip->DeleteMode(selectMode);
  533.     if (selectMode) delete selectMode;
  534.     selectMode = NULL;
  535.  
  536.     // Reset show end result
  537.     SetFlag(MS_DISP_END_RESULT, ip->GetShowEndResult() ? TRUE : FALSE);
  538.     ip->SetShowEndResult(oldShowEnd);
  539.  
  540.     this->ip = NULL;
  541.     editMod = NULL;
  542.  
  543.     TimeValue t = ip->GetTime();
  544.     ClearAFlag(A_MOD_BEING_EDITED);
  545.     NotifyDependents(Interval(t, t), PART_ALL, REFMSG_END_EDIT);
  546.     NotifyDependents(Interval(t, t), PART_ALL, REFMSG_MOD_DISPLAY_OFF);
  547. }
  548.  
  549. int BSDSModifier::HitTest(TimeValue t, INode* inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt, ModContext* mc) {
  550.     if (!vpt || !vpt->IsAlive()) {
  551.         // ViewPort Error
  552.         DbgAssert(!_T("Invalid viewport!"));
  553.         return FALSE;
  554.     }
  555.  
  556.     Interval valid;
  557.     int savedLimits, res = 0;
  558.     GraphicsWindow *gw = vpt->getGW();
  559.     HitRegion hr;
  560.  
  561.     int selByVert, ignoreBackfaces;
  562.     pblock->GetValue(ms_by_vertex, t, selByVert, FOREVER);
  563.     pblock->GetValue(ms_ignore_backfacing, t, ignoreBackfaces, FOREVER);
  564.  
  565.     // Setup GW
  566.     MakeHitRegion(hr, type, crossing, 4, p);
  567.     gw->setHitRegion(&hr);
  568.     Matrix3 mat = inode->GetObjectTM(t);
  569.     gw->setTransform(mat);
  570.     gw->setRndLimits(((savedLimits = gw->getRndLimits()) | GW_PICK) & ~GW_ILLUM);
  571.     if (ignoreBackfaces) gw->setRndLimits(gw->getRndLimits() | GW_BACKCULL);
  572.     else gw->setRndLimits(gw->getRndLimits() & ~GW_BACKCULL);
  573.     gw->clearHitCode();
  574.  
  575.     SubObjHitList hitList;
  576.     MeshSubHitRec *rec;
  577.  
  578.     if (!mc->localData || !((BSDSData*)mc->localData)->GetMesh()) return 0;
  579.     BSDSData *d = (BSDSData*)mc->localData;
  580.  
  581.     DWORD hitFlags;
  582.     if (selByVert) {
  583.         hitFlags = SUBHIT_VERTS;
  584.         // if (d->bodyParts[d->currentPartition].selLevel > SEL_VERTEX) hitFlags |= SUBHIT_USEFACESEL;
  585.         if (d->bodyParts[d->currentPartition].selLevel > SEL_OBJECT) hitFlags |= SUBHIT_USEFACESEL;
  586.     }
  587.     else {
  588.         hitFlags = hitLevel[d->bodyParts[d->currentPartition].selLevel];
  589.     }
  590.  
  591.     Mesh &mesh = *(d)->GetMesh();
  592.  
  593.     // cache backfacing vertices as hidden:
  594.     BitArray oldHide;
  595.     if ((hitFlags & SUBHIT_VERTS) && ignoreBackfaces) {
  596.         BOOL flip = mat.Parity();
  597.         oldHide = mesh.vertHide;
  598.         BitArray faceBack;
  599.         faceBack.SetSize(mesh.getNumFaces());
  600.         faceBack.ClearAll();
  601.         for (int i = 0; i<mesh.getNumFaces(); i++) {
  602.             DWORD *vv = mesh.faces[i].v;
  603.             IPoint3 A[3];
  604.             for (int j = 0; j<3; j++) gw->wTransPoint(&(mesh.verts[vv[j]]), &(A[j]));
  605.             IPoint3 d1 = A[1] - A[0];
  606.             IPoint3 d2 = A[2] - A[0];
  607.             if (flip) {
  608.                 if ((d1^d2).z > 0) continue;
  609.             }
  610.             else {
  611.                 if ((d1^d2).z < 0) continue;
  612.             }
  613.             for (int j = 0; j<3; j++) mesh.vertHide.Set(vv[j]);
  614.             faceBack.Set(i);
  615.         }
  616.         for (int i = 0; i<mesh.getNumFaces(); i++) {
  617.             if (faceBack[i]) continue;
  618.             DWORD *vv = mesh.faces[i].v;
  619.             for (int j = 0; j<3; j++) mesh.vertHide.Clear(vv[j]);
  620.         }
  621.         mesh.vertHide |= oldHide;
  622.     }
  623.  
  624.     res = mesh.SubObjectHitTest(gw, gw->getMaterial(), &hr, flags | hitFlags, hitList);
  625.  
  626.     if ((hitFlags & SUBHIT_VERTS) && ignoreBackfaces) mesh.vertHide = oldHide;
  627.  
  628.     rec = hitList.First();
  629.     while (rec) {
  630.         vpt->LogHit(inode, mc, rec->dist, rec->index, NULL);
  631.         rec = rec->Next();
  632.     }
  633.  
  634.     gw->setRndLimits(savedLimits);
  635.     return res;
  636. }
  637.  
  638. int BSDSModifier::Display(TimeValue t, INode* inode, ViewExp *vpt, int flags, ModContext *mc) {
  639.  
  640.     if (!vpt || !vpt->IsAlive())
  641.     {
  642.         // why are we here
  643.         DbgAssert(!_T("Invalid viewport!"));
  644.         return FALSE;
  645.     }
  646.  
  647.     if (!ip || !ip->GetShowEndResult()) return 0;
  648.     if (!mc->localData) return 0;
  649.     BSDSData *modData = (BSDSData*)mc->localData;
  650.     if (!modData->currentPartition) return 0;
  651.     Mesh *mesh = modData->GetMesh();
  652.     if (!mesh) return 0;
  653.  
  654.     // Set up GW
  655.     GraphicsWindow *gw = vpt->getGW();
  656.     Matrix3 tm = inode->GetObjectTM(t);
  657.     int savedLimits;
  658.     gw->setRndLimits((savedLimits = gw->getRndLimits()) & ~GW_ILLUM);
  659.     gw->setTransform(tm);
  660.  
  661.     // We need to draw a "gizmo" version of the mesh:
  662.     Point3 colSel = GetSubSelColor();
  663.     Point3 colTicks = GetUIColor(COLOR_VERT_TICKS);
  664.     Point3 colGiz = GetUIColor(COLOR_GIZMOS);
  665.     Point3 colGizSel = GetUIColor(COLOR_SEL_GIZMOS);
  666.     gw->setColor(LINE_COLOR, colGiz);
  667.  
  668.     AdjEdgeList *ae = modData->GetAdjEdgeList();
  669.     Point3 rp[3];
  670.     int i, ect = ae->edges.Count();
  671.  
  672. #ifdef MESH_CAGE_BACKFACE_CULLING
  673.     // Figure out backfacing from frontfacing.
  674.     BitArray fBackfacing, vBackfacing;
  675.     bool backCull = (savedLimits & GW_BACKCULL) ? true : false;
  676.     if (backCull)
  677.     {
  678.         fBackfacing.SetSize(mesh->numFaces);
  679.         vBackfacing.SetSize(mesh->numVerts);
  680.         vBackfacing.SetAll();
  681.         BitArray nonIsoVerts;
  682.         nonIsoVerts.SetSize(mesh->numVerts);
  683.  
  684.         mesh->checkNormals(false);  // Allocates rVerts.
  685.         RVertex *rv = mesh->getRVertPtr(0);
  686.         BOOL gwFlipped = gw->getFlipped();
  687.  
  688.         for (i = 0; i <mesh->numVerts; i++) {
  689.             rv[i].rFlags = (rv[i].rFlags & ~(GW_PLANE_MASK | RND_MASK | RECT_MASK)) |
  690.                 gw->hTransPoint(&(mesh->verts[i]), (IPoint3 *)rv[i].pos);
  691.         }
  692.         for (i = 0; i<mesh->numFaces; i++)
  693.         {
  694.             Face & f = mesh->faces[i];
  695.             fBackfacing.Set(i, hIsFacingBack(rv[f.v[0]].pos, rv[f.v[1]].pos, rv[f.v[2]].pos, gwFlipped));
  696.             for (int j = 0; j<3; j++) nonIsoVerts.Set(f.v[j]);
  697.             if (fBackfacing[i]) continue;
  698.             for (int j = 0; j<3; j++) vBackfacing.Clear(f.v[j]);
  699.         }
  700.         vBackfacing &= nonIsoVerts; // so isolated vertices aren't labeled as backfacing.
  701.     }
  702. #endif
  703.  
  704.     int es[3];
  705.     gw->startSegments();
  706.     for (i = 0; i<ect; i++) {
  707.         MEdge & me = ae->edges[i];
  708.         if (me.Hidden(mesh->faces)) continue;
  709.         if (me.Visible(mesh->faces)) {
  710.             es[0] = GW_EDGE_VIS;
  711.         }
  712.         else {
  713.             // if (modData->bodyParts[modData->currentPartition].selLevel < SEL_EDGE) continue;
  714.             if (modData->bodyParts[modData->currentPartition].selLevel == SEL_OBJECT) continue;
  715.             if (modData->bodyParts[modData->currentPartition].selLevel > SEL_FACE) continue;
  716.             es[0] = GW_EDGE_INVIS;
  717.         }
  718.  
  719. #ifdef MESH_CAGE_BACKFACE_CULLING
  720.         if (backCull && fBackfacing[me.f[0]] && ((me.f[1] == UNDEFINED) || fBackfacing[me.f[1]]))
  721.             continue;
  722. #endif
  723.         /*if (modData->bodyParts[modData->currentPartition].selLevel == SEL_EDGE) {
  724.             // Unsure if correct? Need Memory address but returning a pointer?
  725.             if (ae->edges[i].Selected(mesh->faces, modData->edgeSel[modData->currentPartition])) gw->setColor(LINE_COLOR, colGizSel);
  726.             else gw->setColor(LINE_COLOR, colGiz);
  727.         }*/
  728.         if (modData->bodyParts[modData->currentPartition].selLevel >= SEL_FACE) {
  729.             // Unsure if correct? Need Memory address but returning a pointer?
  730.             if (ae->edges[i].AFaceSelected(modData->faceSel[modData->currentPartition])) gw->setColor(LINE_COLOR, colGizSel);
  731.             else gw->setColor(LINE_COLOR, colGiz);
  732.         }
  733.         rp[0] = mesh->verts[me.v[0]];
  734.         rp[1] = mesh->verts[me.v[1]];
  735.         //gw->polyline (2, rp, NULL, NULL, FALSE, es);
  736.         if (es[0] == GW_EDGE_VIS)
  737.             gw->segment(rp, 1);
  738.         else gw->segment(rp, 0);
  739.     }
  740.     gw->endSegments();
  741. }
  742.  
  743. void BSDSModifier::ActivateSubobjSel(int level, XFormModes& modes) {
  744.     BSDSData *modData = GetModifierData();
  745.     // Set the meshes level
  746.     modData->bodyParts[modData->currentPartition].selLevel = level;
  747.  
  748.     // Fill in modes with our sub-object modes
  749.     if (level != SEL_OBJECT) {
  750.         modes = XFormModes(NULL, NULL, NULL, NULL, NULL, selectMode);
  751.     }
  752.  
  753.     // Update UI
  754.     UpdateSelLevelDisplay();
  755.     SetEnableStates();
  756.     SetNumSelLabel();
  757.  
  758.     NotifyDependents(FOREVER, PART_ALL, PART_SUBSEL_TYPE | PART_DISPLAY, REFMSG_CHANGE);
  759.     // Not needed since this modifier is only there to store selection face data for nif export, not modelling
  760.     // ip->PipeSelLevelChanged();
  761.     // NotifyDependents(FOREVER, SELECT_CHANNEL | DISP_ATTRIB_CHANNEL | SUBSEL_TYPE_CHANNEL, REFMSG_CHANGE);
  762. }
  763.  
  764. void BSDSModifier::LocalDataChanged() {
  765.     // BOOL changed = FALSE;
  766.     BSDSData *modData = GetModifierData();
  767.     if (!modData) return;
  768.     // Setup Sub-Objects
  769.     // changed = (subObjects.Count() != modData->bodyParts.Count());
  770.  
  771.     // subObjects.SetCount(modData->bodyParts.Count());
  772.     /*for (int i = 0; i < subObjects.Count(); i++) {
  773.         TSTR name(modData->bodyParts[i].currentSlot.c_str());
  774.         subObjects[i].SetName(name);
  775.         changed |= (name != subObjects[i].GetNameRef()) ? true : false;
  776.     }*/
  777.  
  778.     /*if (changed)
  779.         NotifyDependents(FOREVER, PART_ALL, REFMSG_NUM_SUBOBJECTTYPES_CHANGED);
  780.     else
  781.         NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);*/
  782.     NotifyDependents(FOREVER, PART_SELECT, REFMSG_CHANGE);
  783.     if (ip && editMod == this)
  784.         SetNumSelLabel();
  785. }
  786.  
  787. void BSDSModifier::SelectSubComponent(HitRecord *hitRec, BOOL selected, BOOL all, BOOL invert) {
  788.     BSDSData *d = NULL,*od = NULL;
  789.  
  790.     int selByVert, ignoreVisEdge;
  791.     float planarThresh;
  792.     TimeValue t = ip->GetTime();
  793.     pblock->GetValue(ms_by_vertex, t, selByVert, FOREVER);
  794.     pblock->GetValue(ms_ignore_visible, t, ignoreVisEdge, FOREVER);
  795.     pblock->GetValue(ms_planar_threshold, t, planarThresh, FOREVER);
  796.  
  797.     // int nd;
  798.     BitArray nsel;
  799.     AdjEdgeList *ae = NULL;
  800.     AdjFaceList *af = NULL;
  801.     Mesh *mesh;
  802.  
  803.     d = (BSDSData*)GetModifierData();
  804.     // if (!d) return;
  805.     HitRecord *hr = hitRec;
  806.     // if (!all && (hr->modContext->localData != d)) return;
  807.     for (; hr != NULL; hr = hr->Next()) if (hr->modContext->localData == d) break;
  808.     // if (!hr) return;
  809.     mesh = d->GetMesh();
  810.     // if (!mesh) return;
  811.     BaseInterface *msci = mesh->GetInterface(MESHSELECTCONVERT_INTERFACE);
  812.  
  813.     if (selByVert) {
  814.         ae = d->GetAdjEdgeList();
  815.         // if (!ae) return;
  816.     }
  817.  
  818.     int selectLevel = d->bodyParts[d->currentPartition].selLevel;
  819.     switch (selectLevel) {
  820.     // case SEL_VERTEX: break;
  821.     /*case SEL_EDGE:
  822.         if (msci && selByVert) {
  823.             // Use new improved selection conversion:
  824.             BitArray vhit;
  825.             vhit.SetSize(mesh->numVerts);
  826.             for (hr = hitRec; hr != NULL; hr = hr->Next()) {
  827.                 if (d != hr->modContext->localData) continue;
  828.                 vhit.Set(hr->hitInfo);
  829.                 if (!all) break;
  830.             }
  831. #if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0)
  832.             MeshSelectionConverter *pConv = static_cast<MeshSelectionConverter*>(msci);
  833.             pConv->VertexToEdge(*mesh, vhit, nsel);
  834.             if (invert) nsel ^= d->edgeSel[d->currentPartition];
  835.             else {
  836.                 if (selected) nsel |= d->edgeSel[d->currentPartition];
  837.                 else nsel = d->edgeSel[d->currentPartition] & ~nsel;
  838.             }
  839. #endif
  840.         }
  841.         else {
  842.             BitArray &edgeSel = d->edgeSel[d->currentPartition];
  843.             nsel = d->edgeSel[d->currentPartition];
  844.             for (; hr != NULL; hr = hr->Next()) {
  845.                 if (d != hr->modContext->localData) continue;
  846.                 if (selByVert) {
  847.                     DWORDTab & list = ae->list[hr->hitInfo];
  848.                     for (int i = 0; i < list.Count(); i++) {
  849.                         MEdge & me = ae->edges[list[i]];
  850.                         for (int j = 0; j < 2; j++) {
  851.                             if (me.f[j] == UNDEFINED) continue;
  852.                             DWORD ei = mesh->faces[me.f[j]].GetEdgeIndex(me.v[0], me.v[1]);
  853.                             if (ei > 2) continue;
  854.                             ei += me.f[j] * 3;
  855.                             nsel.Set(ei, invert ? !edgeSel[ei] : selected);
  856.                         }
  857.                     }
  858.                 }
  859.                 else {
  860.                     nsel.Set(hr->hitInfo, invert ? !edgeSel[hr->hitInfo] : selected);
  861.                 }
  862.                 if (!all) break;
  863.             }
  864.         }
  865.         d->SetEdgeSel(nsel, this, t);
  866.         break;*/
  867.     case SEL_FACE:
  868.         if (msci && selByVert) {
  869.             // Use new improved selection conversion:
  870.             BitArray vhit;
  871.             vhit.SetSize(mesh->numVerts);
  872.             for (hr = hitRec; hr != NULL; hr = hr->Next()) {
  873.                 if (d != hr->modContext->localData) continue;
  874.                 vhit.Set(hr->hitInfo);
  875.                 if (!all) break;
  876.             }
  877. #if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0)
  878.             MeshSelectionConverter *pConv = static_cast<MeshSelectionConverter*>(msci);
  879.             pConv->VertexToFace(*mesh, vhit, nsel);
  880.             if (invert) nsel ^= d->faceSel[d->currentPartition];
  881.             else {
  882.                 if (selected) nsel |= d->faceSel[d->currentPartition];
  883.                 else nsel = d->faceSel[d->currentPartition] & ~nsel;
  884.             }
  885. #endif
  886.         }
  887.         else {
  888.             // BitArray &faceSel = d->faceSel[d->currentPartition];
  889.             nsel = d->faceSel[d->currentPartition];
  890.             for (; hr != NULL; hr = hr->Next()) {
  891.                 if (d != hr->modContext->localData) continue;
  892.                 if (selByVert) {
  893.                     DWORDTab & list = ae->list[hr->hitInfo];
  894.                     for (int i = 0; i < list.Count(); i++) {
  895.                         MEdge & me = ae->edges[list[i]];
  896.                         for (int j = 0; j < 2; j++) {
  897.                             if (me.f[j] == UNDEFINED) continue;
  898.                             nsel.Set(me.f[j], invert ? !d->faceSel[d->currentPartition][me.f[j]] : selected);
  899.                         }
  900.                     }
  901.                 }
  902.                 else {
  903.                     nsel.Set(hr->hitInfo, invert ? !d->faceSel[d->currentPartition][hr->hitInfo] : selected);
  904.                 }
  905.                 if (!all) break;
  906.             }
  907.         }
  908.         d->SetFaceSel(nsel, this, t);
  909.         break;
  910.     case SEL_POLY:
  911.     case SEL_ELEMENT:
  912.         af = d->GetAdjFaceList();
  913.         if (msci) {
  914.             // Use new improved selection conversion:
  915. #if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0)
  916.             MeshSelectionConverter *pConv = static_cast<MeshSelectionConverter*>(msci);
  917.             if (selByVert) {
  918.                 BitArray vhit;
  919.                 vhit.SetSize(mesh->numVerts);
  920.                 for (hr = hitRec; hr != NULL; hr = hr->Next()) {
  921.                     if (d != hr->modContext->localData) continue;
  922.                     vhit.Set(hr->hitInfo);
  923.                     if (!all) break;
  924.                 }
  925.                 if (selectLevel == SEL_ELEMENT) pConv->VertexToElement(*mesh, af, vhit, nsel);
  926.                 else pConv->VertexToPolygon(*mesh, af, vhit, nsel, planarThresh, ignoreVisEdge ? true : false);
  927.             }
  928.             else {
  929.                 BitArray fhit;
  930.                 fhit.SetSize(mesh->numFaces);
  931.                 for (hr = hitRec; hr != NULL; hr = hr->Next()) {
  932.                     if (d != hr->modContext->localData) continue;
  933.                     fhit.Set(hr->hitInfo);
  934.                     if (!all) break;
  935.                 }
  936.                 if (selectLevel == SEL_ELEMENT) pConv->FaceToElement(*mesh, af, fhit, nsel);
  937.                 else pConv->FaceToPolygon(*mesh, af, fhit, nsel, planarThresh, ignoreVisEdge ? true : false);
  938.             }
  939. #endif
  940.         }
  941.         else {
  942.             // Otherwise we'll take the old approach of converting faces to polygons or elements as we go.
  943.             nsel.SetSize(mesh->numFaces);
  944.             nsel.ClearAll();
  945.             for (; hr != NULL; hr = hr->Next()) {
  946.                 if (d != hr->modContext->localData) continue;
  947.                 if (!selByVert) {
  948.                     if (selectLevel == SEL_ELEMENT)
  949.                         mesh->ElementFromFace(hr->hitInfo, nsel, af);
  950.                     else
  951.                         mesh->PolyFromFace(hr->hitInfo, nsel, planarThresh, ignoreVisEdge, af);
  952.                 }
  953.                 else {
  954.                     DWORDTab & list = ae->list[hr->hitInfo];
  955.                     for (int i = 0; i < list.Count(); i++) {
  956.                         MEdge & me = ae->edges[list[i]];
  957.                         for (int j = 0; j < 2; j++) {
  958.                             if (me.f[j] == UNDEFINED) continue;
  959.                             if (selectLevel == SEL_ELEMENT)
  960.                                 mesh->ElementFromFace(me.f[j], nsel, af);
  961.                             else
  962.                                 mesh->PolyFromFace(me.f[j], nsel, planarThresh, ignoreVisEdge, af);
  963.                         }
  964.                     }
  965.                 }
  966.                 if (!all) break;
  967.             }
  968.         }
  969.  
  970.         if (invert) nsel ^= d->faceSel[d->currentPartition];
  971.         else if (selected) nsel |= d->faceSel[d->currentPartition];
  972.         else nsel = d->faceSel[d->currentPartition] & ~nsel;
  973.  
  974.         d->SetFaceSel(nsel, this, t);
  975.         break;
  976.     }
  977.     LocalDataChanged();
  978. }
  979.  
  980. void BSDSModifier::ClearSelection(int selLevel) {
  981.     if (!ip) return;
  982.     BSDSData *d = (BSDSData*)GetModifierData();
  983.     if (!d) return;
  984.     // int selectionLevel = d->bodyParts[d->currentPartition].selLevel;
  985.     if (theHold.Holding() && !d->held) theHold.Put(new SelectRestore(this, d));
  986.     d->SynchBitArrays();
  987.     switch (selLevel) {
  988.     // case SEL_VERTEX: break;
  989.     case SEL_FACE:
  990.     case SEL_POLY:
  991.     case SEL_ELEMENT:
  992.         d->faceSel[d->currentPartition].ClearAll();
  993.         break;
  994.     /*case SEL_EDGE:
  995.         d->edgeSel[d->currentPartition].ClearAll();
  996.         break;*/
  997.     }
  998.     LocalDataChanged();
  999. }
  1000.  
  1001. void BSDSModifier::SelectAll(int selLevel) {
  1002.     if (!ip) return;
  1003.     if (selLevel == SEL_OBJECT) return;
  1004.     BSDSData *d = GetModifierData();
  1005.     if (!d) return;
  1006.     // int selectionLevel = d->bodyParts[d->currentPartition].selLevel;
  1007.     if (theHold.Holding() && !d->held) theHold.Put(new SelectRestore(this, d));
  1008.     d->SynchBitArrays();
  1009.     switch (selLevel) {
  1010.     // case SEL_VERTEX: break;
  1011.     case SEL_FACE:
  1012.     case SEL_POLY:
  1013.     case SEL_ELEMENT:
  1014.         d->faceSel[d->currentPartition].SetAll();
  1015.         break;
  1016.     /*case SEL_EDGE:
  1017.         d->edgeSel[d->currentPartition].SetAll();
  1018.         break;*/
  1019.     }
  1020.     LocalDataChanged();
  1021. }
  1022.  
  1023. void BSDSModifier::InvertSelection(int selLevel) {
  1024.     if (!ip) return;
  1025.     BSDSData *d = (BSDSData*)GetModifierData();
  1026.     if (!d) return;
  1027.     // int selectionLevel = d->bodyParts[d->currentPartition].selLevel;
  1028.     if (theHold.Holding() && !d->held) theHold.Put(new SelectRestore(this, d));
  1029.     d->SynchBitArrays();
  1030.     switch (selLevel) {
  1031.     // case SEL_VERTEX: break;
  1032.     case SEL_FACE:
  1033.     case SEL_POLY:
  1034.     case SEL_ELEMENT:
  1035.         d->faceSel[d->currentPartition].Reverse();
  1036.         break;
  1037.     /*case SEL_EDGE:
  1038.         d->edgeSel[d->currentPartition].Reverse();
  1039.         break;*/
  1040.     }
  1041.     LocalDataChanged();
  1042. }
  1043.  
  1044. void BSDSModifier::SelectByMatID(int id) {
  1045.     if (!ip) return;
  1046.     BOOL add = GetKeyState(VK_CONTROL) < 0 ? TRUE : FALSE;
  1047.     BOOL sub = GetKeyState(VK_MENU) < 0 ? TRUE : FALSE;
  1048.     theHold.Begin();
  1049.     BSDSData *d = (BSDSData*)GetModifierData();
  1050.     // if (!d) return;
  1051.     if (!d->held) theHold.Put(new SelectRestore(this, d));
  1052.     d->SynchBitArrays();
  1053.     if (!add && !sub) d->faceSel[d->currentPartition].ClearAll();
  1054.     Mesh *mesh = d->GetMesh();
  1055.     // if (!mesh) return;
  1056.     for (int i = 0; i<mesh->numFaces; i++) {
  1057.         if (mesh->faces[i].getMatID() == (MtlID)id) {
  1058.             if (sub) d->faceSel[d->currentPartition].Clear(i);
  1059.             else d->faceSel[d->currentPartition].Set(i);
  1060.         }
  1061.     }
  1062.     theHold.Accept(GetString(IDS_RB_SELECTBYMATID));
  1063.  
  1064.     LocalDataChanged();
  1065.     ip->RedrawViews(ip->GetTime());
  1066. }
  1067.  
  1068. //-------------------------------- BDSDSModifier I/O Methods ----------------------------------
  1069. // old-style parameter block for loading old scenes:
  1070. #define NUM_OLDVERSIONS 0
  1071.  
  1072. // #define SELLEVEL_CHUNKID     0x0100
  1073. #define FLAGS_CHUNKID           0x0240
  1074. #define VERSION_CHUNKID         0x0230
  1075. static int currentVersion = 1;
  1076.  
  1077. // #define NAMEDVSEL_NAMES_CHUNK    0x2805
  1078. // #define NAMEDFSEL_NAMES_CHUNK    0x2806
  1079. // #define NAMEDESEL_NAMES_CHUNK    0x2807
  1080. // #define NAMEDSEL_STRING_CHUNK    0x2809
  1081. // #define NAMEDSEL_ID_CHUNK        0x2810
  1082.  
  1083. // #define VSELSET_CHUNK            0x2845
  1084. #define TAB_SIZE_CHUNK      0x2840
  1085. #define FSEL_CHUNK          0x2850
  1086. #define ESEL_CHUNK          0x2860
  1087. #define CURPART_CHUNK       0x2870
  1088. #define PARTS_CHUNK         0x2880
  1089.  
  1090. // static int namedSelID[] = { NAMEDVSEL_NAMES_CHUNK, NAMEDESEL_NAMES_CHUNK, NAMEDFSEL_NAMES_CHUNK, NAMEDFSEL_NAMES_CHUNK, NAMEDFSEL_NAMES_CHUNK };
  1091.  
  1092. // Fix these up, they are for saving/loading modifier scene data
  1093. IOResult BSDSModifier::Save(ISave *isave) {
  1094.     IOResult res;
  1095.     ULONG nb;
  1096.     Modifier::Save(isave);
  1097.  
  1098.     isave->BeginChunk(VERSION_CHUNKID);
  1099.     res = isave->Write(&currentVersion, sizeof(int), &nb);
  1100.     isave->EndChunk();
  1101.  
  1102.     DWORD flags = ExportFlags();
  1103.     isave->BeginChunk(FLAGS_CHUNKID);
  1104.     res = isave->Write(&flags, sizeof(DWORD), &nb);
  1105.     isave->EndChunk();
  1106.  
  1107.     return res;
  1108. }
  1109.  
  1110. IOResult BSDSModifier::Load(ILoad *iload) {
  1111.     IOResult res;
  1112.     ULONG nb;
  1113.     int version = 1;
  1114.     DWORD flags;
  1115.  
  1116.     Modifier::Load(iload);
  1117.  
  1118.     while (IO_OK == (res = iload->OpenChunk())) {
  1119.         switch (iload->CurChunkID())  {
  1120.         case VERSION_CHUNKID:
  1121.             iload->Read(&version, sizeof(version), &nb);
  1122.             break;
  1123.  
  1124.         case FLAGS_CHUNKID:
  1125.             iload->Read(&flags, sizeof(DWORD), &nb);
  1126.             ImportFlags(flags);
  1127.             break;
  1128.         }
  1129.         iload->CloseChunk();
  1130.         if (res != IO_OK) return res;
  1131.     }
  1132.     return IO_OK;
  1133. }
  1134.  
  1135. IOResult BSDSModifier::SaveLocalData(ISave *isave, LocalModData *ld) {
  1136.     BSDSData *d = (BSDSData*)ld;
  1137.     ULONG nb;
  1138.  
  1139.     int tabSize = d->bodyParts.Count();
  1140.     isave->BeginChunk(TAB_SIZE_CHUNK);
  1141.     isave->Write(&tabSize, sizeof(int), &nb);
  1142.     isave->EndChunk();
  1143.  
  1144.     /*isave->BeginChunk(ESEL_CHUNK);
  1145.     for (int i = 0; i < d->edgeSel.Count(); i++) {
  1146.         d->edgeSel[i].Save(isave);
  1147.     }
  1148.     isave->EndChunk();*/
  1149.  
  1150.     isave->BeginChunk(FSEL_CHUNK);
  1151.     for (int i = 0; i < d->faceSel.Count(); i++) {
  1152.         d->faceSel[i].Save(isave);
  1153.     }
  1154.     isave->EndChunk();
  1155.  
  1156.     isave->BeginChunk(CURPART_CHUNK);
  1157.     isave->Write(&d->currentPartition, sizeof(int), &nb);
  1158.     isave->EndChunk();
  1159.  
  1160.     isave->BeginChunk(PARTS_CHUNK);
  1161.     for (int i = 0; i < tabSize; i++) {
  1162.         wstring temp = d->bodyParts[i].GetGameName();
  1163.         int selectLevel = d->bodyParts[i].selLevel;
  1164.         wstring tempFlag = d->bodyParts[i].currentSlot;
  1165.         isave->WriteWString(temp.c_str());
  1166.         isave->Write(&selectLevel, sizeof(int), &nb);
  1167.         isave->WriteWString(tempFlag.c_str());
  1168.     }
  1169.     isave->EndChunk();
  1170.     return IO_OK;
  1171. }
  1172.  
  1173. IOResult BSDSModifier::LoadLocalData(ILoad *iload, LocalModData **pld) {
  1174.     BSDSData *d = new BSDSData;
  1175.     ULONG nb = 0;
  1176.     *pld = d;
  1177.     IOResult res;
  1178.     while (IO_OK == (res = iload->OpenChunk())) {
  1179.         switch (iload->CurChunkID())  {
  1180.         case TAB_SIZE_CHUNK:
  1181.             int size;
  1182.             iload->Read(&size, sizeof(int), &nb);
  1183.             d->bodyParts.SetCount(size);
  1184.             // d->edgeSel.SetCount(size);
  1185.             d->faceSel.SetCount(size);
  1186.             break;
  1187.         /*case ESEL_CHUNK:
  1188.             for (int i = 0; i < d->edgeSel.Count(); i++) {
  1189.                 BitArray temp;
  1190.                 temp.Load(iload);
  1191.                 d->edgeSel[i] = temp;
  1192.             }
  1193.             break;*/
  1194.         case FSEL_CHUNK:
  1195.             for (int i = 0; i < d->faceSel.Count(); i++) {
  1196.                 BitArray temp;
  1197.                 temp.Load(iload);
  1198.                 d->faceSel[i] = temp;
  1199.             }
  1200.             break;
  1201.         case CURPART_CHUNK:
  1202.             iload->Read(&d->currentPartition, sizeof(int), &nb);
  1203.             break;
  1204.         case PARTS_CHUNK:
  1205.             for (int i = 0; i<d->bodyParts.Count(); i++) {
  1206.                 TCHAR *buffer1;
  1207.                 TCHAR *buffer2;
  1208.                 int selectLevel;
  1209.                 res = iload->ReadWStringChunk(&buffer1);
  1210.                 res = iload->Read(&selectLevel, sizeof(int), &nb);
  1211.                 res = iload->ReadWStringChunk(&buffer2);
  1212.                 wstring temp(buffer1);
  1213.                 wstring tempFlag(buffer2);
  1214.                 DismemberPartition newPart(temp, selectLevel, tempFlag);
  1215.                 d->bodyParts[i] = newPart;
  1216.             }
  1217.         }
  1218.         iload->CloseChunk();
  1219.         if (res != IO_OK) return res;
  1220.     }
  1221.     LocalDataChanged();
  1222.     return IO_OK;
  1223. }
  1224.  
  1225. //-------------------------------- Window Procs ----------------------------------
  1226.  
  1227. void BSDSModifier::SetEnableStates() {
  1228.     if (!BSDSDesc.NumParamMaps()) return;
  1229.     IParamMap2 *pmap = BSDSDesc.GetParamMap(ms_map_main);
  1230.     if (!pmap) return;
  1231.     HWND hWnd = pmap->GetHWnd();
  1232.     if (!hWnd) return;
  1233.     theBSDSModifierMainDlgProc.SetEnables(hWnd);
  1234. }
  1235.  
  1236. void BSDSModifierMainDlgProc::SetEnables(HWND hParams) {
  1237.     if (!mod) return;
  1238.     int nPart, selLevel;
  1239.     BSDSData *d = mod->GetModifierData();
  1240.     if (!d) {
  1241.         selLevel = SEL_OBJECT;
  1242.         nPart = 1;
  1243.     }
  1244.     else {
  1245.         selLevel = d->bodyParts[d->currentPartition].selLevel;
  1246.         nPart = d->bodyParts.Count();
  1247.     }
  1248.     // int selLevel = d->bodyParts[d->currentPartition].selLevel;
  1249.     ICustButton *but;
  1250.     ISpinnerControl *spin;
  1251.  
  1252.     int nSub = mod->ip->GetSubObjectLevel();
  1253.     bool subSel = (nSub != 0);
  1254.  
  1255.     bool obj = (selLevel == SEL_OBJECT) ? TRUE : FALSE;
  1256.     // bool vert = (selLevel == SEL_VERTEX) ? TRUE : FALSE;
  1257.     // bool edge = (selLevel == SEL_EDGE) ? TRUE : FALSE;
  1258.     bool poly = (selLevel == SEL_POLY) ? TRUE : FALSE;
  1259.     bool face = (selLevel == SEL_FACE) || (selLevel == SEL_ELEMENT) || poly ? TRUE : FALSE;
  1260.  
  1261.     EnableWindow(GetDlgItem(hParams, IDC_MS_SEL_BYVERT), subSel && (/*edge || */face));
  1262.     // EnableWindow (GetDlgItem (hParams, IDC_MS_IGNORE_BACKFACES), subSel&&(edge||face));
  1263.     EnableWindow(GetDlgItem(hParams, IDC_MS_IGNORE_VISEDGE), subSel&&poly);
  1264.     EnableWindow(GetDlgItem(hParams, IDC_MS_PLANAR_TEXT), subSel&&poly);
  1265.     spin = GetISpinner(GetDlgItem(hParams, IDC_MS_PLANARSPINNER));
  1266.     spin->Enable(subSel&&poly);
  1267.     ReleaseISpinner(spin);
  1268.  
  1269.     EnableWindow(GetDlgItem(hParams, IDC_MS_IGNORE_BACKFACES), subSel);
  1270.  
  1271.     EnableWindow(GetDlgItem(hParams, IDC_MS_SELBYMAT_BOX), subSel&&face);
  1272.     EnableWindow(GetDlgItem(hParams, IDC_MS_SELBYMAT_TEXT), subSel&&face);
  1273.     but = GetICustButton(GetDlgItem(hParams, IDC_MS_SELBYMAT));
  1274.     but->Enable(subSel&&face);
  1275.     ReleaseICustButton(but);
  1276.  
  1277.     spin = GetISpinner(GetDlgItem(hParams, IDC_MS_MATIDSPIN));
  1278.     spin->Enable(subSel&&face);
  1279.     ReleaseISpinner(spin);
  1280.  
  1281.     // int npart = d->bodyParts.Count();
  1282.     mDelPart->Enable((nPart > 1) ? TRUE : FALSE);
  1283.  
  1284.     but = GetICustButton(GetDlgItem(hParams, IDC_MS_SELUNUSED));
  1285.     but->Enable(subSel);
  1286.     ReleaseICustButton(but);
  1287.  
  1288.     /*but = GetICustButton(GetDlgItem(hParams, IDC_MS_FIXDUPL));
  1289.     but->Enable(subSel);
  1290.     ReleaseICustButton(but);*/
  1291. }
  1292.  
  1293. INT_PTR BSDSModifierMainDlgProc::DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  1294.     if (!mod) return FALSE;
  1295.     BSDSData *d = mod->GetModifierData();
  1296.     DismemberPartition tempInit;
  1297.     ICustToolbar *iToolbar;
  1298.     ICustButton *but;
  1299.     int matid;
  1300.     int nParts;
  1301.     int nActive;
  1302.     int objLevel;
  1303.     codeproject::bimap<wstring, int>::iterator itr;
  1304.  
  1305.     switch (msg) {
  1306.     case WM_INITDIALOG:
  1307.         // ListBox Game UI Control
  1308.         gameList.init(GetDlgItem(hWnd, IDC_CB_GAMETYPE));
  1309.         for (const EnumLookupType *gameFlag = GameFlags; gameFlag->name != NULL; ++gameFlag) {
  1310.             gameList.add(gameFlag->name);
  1311.         }
  1312.         gameList.select(1);
  1313.  
  1314.         // ListBox BodyPartUI Control
  1315.         /*dismemberList.init(GetDlgItem(hWnd, IDC_CB_BODYPART));
  1316.         for (itr = tempInit.slots.begin(); itr != tempInit.slots.end(); ++itr) {
  1317.             dismemberList.add(itr->first.c_str());
  1318.         }
  1319.         dismemberList.SelectString(tempInit.currentSlot.c_str());*/
  1320.  
  1321.         nParts = 1; // d->bodyParts.Count();
  1322.         nActive = 0; // d->currentPartition;
  1323.         objLevel = SEL_OBJECT; // d->bodyParts[d->currentPartition].selLevel;
  1324.         EnableWindow(GetDlgItem(hWnd, IDC_MS_PARTITION), TRUE);
  1325.         mActivePart = GetISpinner(GetDlgItem(hWnd, IDC_MS_PARTSPIN));
  1326.         mActivePart->LinkToEdit(GetDlgItem(hWnd, IDC_MS_PARTITION), EDITTYPE_POS_INT);
  1327.         mActivePart->SetValue(nActive, 0);
  1328.         mActivePart->SetLimits(0, nParts - 1, TRUE);
  1329.         mActivePart->SetAutoScale(FALSE);
  1330.         mActivePart->SetScale(1);
  1331.         mActivePart->SetResetValue(0);
  1332.  
  1333.         mAddPart = GetICustButton(GetDlgItem(hWnd, IDC_MS_ADDPART));
  1334. #if VERSION_3DSMAX < ((10000<<16)+(24<<8)+0) // Version 7
  1335.         mAddPart->SetTooltip(TRUE, "Create New Partition");
  1336. #endif
  1337.         mAddPart->SetImage(theBSDSPartImageHandler.LoadImages(), 0, 2, 0, 2, 16, 16);
  1338.  
  1339.         mDelPart = GetICustButton(GetDlgItem(hWnd, IDC_MS_DELPART));
  1340. #if VERSION_3DSMAX < ((10000<<16)+(24<<8)+0) // Version 7
  1341.         mDelPart->SetTooltip(TRUE, "Delete Active Partition");
  1342. #endif
  1343.         mDelPart->SetImage(theBSDSPartImageHandler.LoadImages(), 1, 3, 1, 3, 16, 16);
  1344.  
  1345.         iToolbar = GetICustToolbar(GetDlgItem(hWnd, IDC_MS_SELTYPE));
  1346.         iToolbar->SetImage(theBSDSImageHandler.LoadImages());
  1347.         // iToolbar->AddTool(ToolButtonItem(CTB_CHECKBUTTON,0,5,0,5,24,23,24,23,IDC_SELVERTEX));
  1348.         // iToolbar->AddTool(ToolButtonItem(CTB_CHECKBUTTON,1,6,1,6,24,23,24,23,IDC_SELEDGE));
  1349.         iToolbar->AddTool(ToolButtonItem(CTB_CHECKBUTTON, 2, 7, 2, 7, 24, 23, 24, 23, IDC_SELFACE));
  1350.         iToolbar->AddTool(ToolButtonItem(CTB_CHECKBUTTON, 3, 8, 3, 8, 24, 23, 24, 23, IDC_SELPOLY));
  1351.         iToolbar->AddTool(ToolButtonItem(CTB_CHECKBUTTON, 4, 9, 4, 9, 24, 23, 24, 23, IDC_SELELEMENT));
  1352.         ReleaseICustToolbar(iToolbar);
  1353.  
  1354. #if VERSION_3DSMAX < ((10000<<16)+(24<<8)+0) // Version 11+
  1355.         but = GetICustButton(GetDlgItem(hWnd, IDC_MS_SELUNUSED));
  1356.         but->SetTooltip(TRUE, "Select unused faces into active partition");
  1357.         ReleaseICustButton(but);
  1358.  
  1359.         but = GetICustButton(GetDlgItem(hWnd, IDC_MS_FIXDUPL));
  1360.         but->SetTooltip(TRUE, "Remove duplicate faces from partitions");
  1361.         ReleaseICustButton(but);
  1362. #endif
  1363.  
  1364.         UpdateSelLevelDisplay(hWnd);
  1365.         SetEnables(hWnd);
  1366.         break;
  1367.  
  1368.     case WM_NCDESTROY:
  1369.         if (mActivePart) {
  1370.             ReleaseISpinner(mActivePart);
  1371.             mActivePart = NULL;
  1372.         }
  1373.         if (mAddPart) {
  1374.             ReleaseICustButton(mAddPart);
  1375.             mAddPart = NULL;
  1376.         }
  1377.         if (mDelPart) {
  1378.             ReleaseICustButton(mDelPart);
  1379.             mDelPart = NULL;
  1380.         }
  1381.         break;
  1382.  
  1383.     case WM_UPDATE_CACHE:
  1384.         mod->UpdateCache((TimeValue)wParam);
  1385.         break;
  1386.  
  1387.     case CC_SPINNER_CHANGE:
  1388.         switch (LOWORD(wParam)) {
  1389.         case IDC_MS_PARTSPIN:
  1390.             if (d) {
  1391.                 int idx = mActivePart->GetIVal();
  1392.                 d->currentPartition = idx;
  1393.                 mod->LocalDataChanged();
  1394.                 mod->ip->SetSubObjectLevel(d->bodyParts[d->currentPartition].selLevel);
  1395.             }
  1396.             break;
  1397.         }
  1398.         break;
  1399.  
  1400.     case WM_CUSTEDIT_ENTER:
  1401.         switch (LOWORD(wParam)) {
  1402.         case IDC_MS_PARTITION:
  1403.             if (d){
  1404.                 int idx = mActivePart->GetIVal();
  1405.                 d->currentPartition = idx;
  1406.                 mod->ip->SetSubObjectLevel(d->bodyParts[d->currentPartition].selLevel);
  1407.             }
  1408.             break;
  1409.         }
  1410.         break;
  1411.  
  1412.     case WM_COMMAND:
  1413.         switch (LOWORD(wParam)) {
  1414.  
  1415.         case IDC_CB_GAMETYPE:
  1416.             if (HIWORD(wParam) == CBN_SELCHANGE) {
  1417.                 d->bodyParts[d->currentPartition].thisGame = DismemberPartition::BethesdaGame (gameList.selection());
  1418.                 d->bodyParts[d->currentPartition].configureMap();
  1419.                
  1420.                 // dismemberList.Reset();
  1421.                 /*for (itr = d->bodyParts[d->currentPartition].slots.begin(); itr != d->bodyParts[d->currentPartition].slots.end(); ++itr) {
  1422.                     dismemberList.add(itr->first.c_str());
  1423.                 }
  1424.                 dismemberList.SelectString(d->bodyParts[d->currentPartition].currentSlot.c_str());*/
  1425.  
  1426.                 mod->LocalDataChanged();
  1427.                 // mod->NotifyDependents(FOREVER, PART_ALL, REFMSG_NUM_SUBOBJECTTYPES_CHANGED);
  1428.             }
  1429.             break;
  1430.  
  1431.         case IDC_CB_BODYPART:
  1432.             if (HIWORD(wParam) == CBN_SELCHANGE) {
  1433.                 // d->bodyParts[d->currentPartition].currentSlot = dismemberList.GetStringSelection();
  1434.                
  1435.                 mod->LocalDataChanged();
  1436.                 // mod->NotifyDependents(FOREVER, PART_ALL, REFMSG_NUM_SUBOBJECTTYPES_CHANGED);
  1437.             }
  1438.  
  1439.         case IDC_MS_ADDPART:
  1440.             if (mActivePart) {
  1441.                 if (d) {
  1442.                     int idx = d->AddPartition();
  1443.                     nParts = d->bodyParts.Count();
  1444.                     mod->ip->SetSubObjectLevel(d->bodyParts[d->currentPartition].selLevel);
  1445.                     mActivePart->SetLimits(0, nParts - 1, TRUE);
  1446.                     mActivePart->SetValue(idx, TRUE);
  1447.                     mod->LocalDataChanged();
  1448.                     // mod->NotifyDependents(FOREVER, PART_ALL, REFMSG_NUM_SUBOBJECTTYPES_CHANGED);
  1449.                 }
  1450.             }
  1451.             break;
  1452.  
  1453.         case IDC_MS_DELPART:
  1454.             if (mActivePart) {
  1455.                 if (d) {
  1456.                     int idx = mActivePart->GetIVal();
  1457.                     d->RemovePartition(idx);
  1458.                     mod->ip->SetSubObjectLevel(d->bodyParts[d->currentPartition].selLevel);
  1459.                     nParts = d->bodyParts.Count();
  1460.                     mActivePart->SetLimits(0, nParts, TRUE);
  1461.                     mActivePart->SetValue(d->currentPartition, TRUE);
  1462.                     mod->LocalDataChanged();
  1463.                     // mod->NotifyDependents(FOREVER, PART_ALL, REFMSG_NUM_SUBOBJECTTYPES_CHANGED);
  1464.                 }
  1465.             }
  1466.             break;
  1467.  
  1468.         /*case IDC_MS_FIXDUPL:
  1469.             mod->FixDuplicates();
  1470.             break;*/
  1471.  
  1472.         case IDC_MS_SELUNUSED:
  1473.             mod->SelectUnused();
  1474.             break;
  1475.  
  1476.         case IDC_MS_SELBYMAT:
  1477.             mod->pblock->GetValue(ms_matid, t, matid, FOREVER);
  1478.             mod->SelectByMatID(matid - 1);
  1479.             break;
  1480.  
  1481.         case IDC_SELFACE:
  1482.             if (d->bodyParts[d->currentPartition].selLevel == SEL_FACE) {
  1483.                 mod->ip->SetSubObjectLevel(SEL_OBJECT);
  1484.             }
  1485.             else {
  1486.                 mod->ip->SetSubObjectLevel(SEL_FACE);
  1487.             }
  1488.             /*if (d->bodyParts[d->currentPartition].selLevel != SEL_FACE) {
  1489.                 d->bodyParts[d->currentPartition].selLevel = SEL_FACE;
  1490.                 mod->ip->SetSubObjectLevel(SEL_FACE);
  1491.             }
  1492.             else {
  1493.                 if (mod->ip->GetSubObjectLevel() != 0)
  1494.                     mod->ip->SetSubObjectLevel(0);
  1495.                 else
  1496.                     mod->ip->SetSubObjectLevel(d->bodyParts[d->currentPartition].selLevel);
  1497.             }
  1498.             UpdateWindow(hWnd);*/
  1499.             break;
  1500.         case IDC_SELPOLY:
  1501.             if (d->bodyParts[d->currentPartition].selLevel != SEL_POLY) {
  1502.                 d->bodyParts[d->currentPartition].selLevel = SEL_POLY;
  1503.                 mod->ip->SetSubObjectLevel(d->bodyParts[d->currentPartition].selLevel);
  1504.             }
  1505.             else {
  1506.                 if (mod->ip->GetSubObjectLevel() != 0)
  1507.                     mod->ip->SetSubObjectLevel(0);
  1508.                 else
  1509.                     mod->ip->SetSubObjectLevel(d->bodyParts[d->currentPartition].selLevel);
  1510.             }
  1511.             UpdateWindow(hWnd);
  1512.             break;
  1513.         case IDC_SELELEMENT:
  1514.             if (d->bodyParts[d->currentPartition].selLevel != SEL_ELEMENT) {
  1515.                 d->bodyParts[d->currentPartition].selLevel = SEL_ELEMENT;
  1516.                 mod->ip->SetSubObjectLevel(d->bodyParts[d->currentPartition].selLevel);
  1517.             }
  1518.             else {
  1519.                 if (mod->ip->GetSubObjectLevel() != 0)
  1520.                     mod->ip->SetSubObjectLevel(0);
  1521.                 else
  1522.                     mod->ip->SetSubObjectLevel(d->bodyParts[d->currentPartition].selLevel);
  1523.             }
  1524.             UpdateWindow(hWnd);
  1525.             break;
  1526.         }
  1527.         break;
  1528.  
  1529.     case WM_NOTIFY:
  1530.         if (((LPNMHDR)lParam)->code != TTN_NEEDTEXT) break;
  1531.         LPTOOLTIPTEXT lpttt;
  1532.         lpttt = (LPTOOLTIPTEXT)lParam;
  1533.         switch (lpttt->hdr.idFrom) {
  1534.             //case IDC_SELVERTEX:
  1535.             //  lpttt->lpszText = GetString (IDS_RB_VERTEX);
  1536.             //  break;
  1537.             //case IDC_SELEDGE:
  1538.             //  lpttt->lpszText = GetString (IDS_RB_EDGE);
  1539.             //  break;
  1540.         case IDC_SELFACE:
  1541.             lpttt->lpszText = GetString(IDS_RB_FACE);
  1542.             break;
  1543.         case IDC_SELPOLY:
  1544.             lpttt->lpszText = GetString(IDS_EM_POLY);
  1545.             break;
  1546.         case IDC_SELELEMENT:
  1547.             lpttt->lpszText = GetString(IDS_EM_ELEMENT);
  1548.             break;
  1549.         }
  1550.         break;
  1551.  
  1552.     default: return FALSE;
  1553.     }
  1554.     return TRUE;
  1555. }
  1556.  
  1557. //-------------------------------- BSDSData Functions ----------------------------------
  1558.  
  1559. LocalModData *BSDSData::Clone() {
  1560.     BSDSData *d = new BSDSData;
  1561.     d->currentPartition = currentPartition;
  1562.     for (int i = 0; i < bodyParts.Count(); i++) {
  1563.         d->bodyParts.Append(1, &bodyParts[i]);
  1564.     }
  1565.     /*for (int i = 0; i < bodyParts.Count(); i++) {
  1566.         d->edgeSel.Append(1, &edgeSel[i]);
  1567.     }*/
  1568.     for (int i = 0; i < bodyParts.Count(); i++) {
  1569.         d->faceSel.Append(1, &faceSel[i]);
  1570.     }
  1571.     return d;
  1572. }
  1573.  
  1574. BSDSData::BSDSData(Mesh &mesh) {
  1575.     held = FALSE; this->mesh = NULL; temp = NULL;
  1576.     currentPartition = 0;
  1577.     BitArray tempEdge(mesh.edgeSel);
  1578.     BitArray tempFace(mesh.faceSel);
  1579.     faceSel.Append(1, &tempEdge);
  1580.     // edgeSel.Append(1, &tempFace);
  1581.     DismemberPartition test;
  1582.     bodyParts.Append(1, &test);
  1583. }
  1584.  
  1585. BSDSData::BSDSData(){
  1586.     held = FALSE;
  1587.     mesh = NULL;
  1588.     temp = NULL;
  1589.     BitArray empty;
  1590.     DismemberPartition first;
  1591.     bodyParts.Append(1, &first);
  1592.     currentPartition = 0;
  1593.     // edgeSel.Append(1, &empty);
  1594.     faceSel.Append(1, &empty);
  1595. }
  1596.  
  1597. void BSDSData::SynchBitArrays() {
  1598.     if (!mesh) return;
  1599.     if (faceSel[currentPartition].GetSize() != mesh->getNumFaces()) faceSel[currentPartition].SetSize(mesh->getNumFaces(), TRUE);
  1600.     // if (edgeSel[currentPartition].GetSize() != mesh->getNumFaces() * 3) edgeSel[currentPartition].SetSize(mesh->getNumFaces() * 3, TRUE);
  1601. }
  1602.  
  1603. AdjEdgeList *BSDSData::GetAdjEdgeList() {
  1604.     if (!mesh) return NULL;
  1605.     if (!temp) temp = new MeshTempData;
  1606.     temp->SetMesh(mesh);
  1607.     return temp->AdjEList();
  1608. }
  1609.  
  1610. AdjFaceList *BSDSData::GetAdjFaceList() {
  1611.     if (!mesh) return NULL;
  1612.     if (!temp) temp = new MeshTempData;
  1613.     temp->SetMesh(mesh);
  1614.     return temp->AdjFList();
  1615. }
  1616.  
  1617. void BSDSData::SetCache(Mesh &mesh) {
  1618.     if (this->mesh) delete this->mesh;
  1619.     this->mesh = new Mesh(mesh);
  1620.     if (temp) temp->Invalidate(PART_TOPO);
  1621.     SynchBitArrays();
  1622. }
  1623.  
  1624. void BSDSData::FreeCache() {
  1625.     if (mesh) delete mesh;
  1626.     mesh = NULL;
  1627.     if (temp) delete temp;
  1628.     temp = NULL;
  1629. }
  1630.  
  1631. void BSDSData::SetFaceSel(BitArray &set, BSDSModifier *imod, TimeValue t) {
  1632.     BSDSModifier *mod = imod;
  1633.     if (theHold.Holding()) theHold.Put(new SelectRestore(mod, this/*, SEL_FACE*/));
  1634.     if (mesh) {
  1635.         mesh->faceSel = set;
  1636.         faceSel[currentPartition] = set;
  1637.     }
  1638. }
  1639.  
  1640. /*void BSDSData::SetEdgeSel(BitArray set, BSDSModifier *imod, TimeValue t) {
  1641.     BSDSModifier *mod = (BSDSModifier *)imod;
  1642.     if (theHold.Holding()) theHold.Put(new SelectRestore(mod, this, SEL_EDGE));
  1643.     edgeSel[currentPartition] = set;
  1644.     if (mesh) mesh->edgeSel = set;
  1645. }*/
  1646.  
  1647. void BSDSData::SelVertByFace() {
  1648.     DbgAssert(mesh);
  1649.     if (!mesh) return;
  1650.     BitArray vertSel = mesh->vertSel;
  1651.     BitArray faceSel = faceSel[currentPartition];
  1652.     for (int i = 0; i<mesh->getNumFaces(); i++) {
  1653.         if (!faceSel[i]) continue;
  1654.         for (int j = 0; j<3; j++) vertSel.Set(mesh->faces[i].v[j]);
  1655.     }
  1656. }
  1657.  
  1658. /*void BSDSData::SelVertByEdge() {
  1659.     DbgAssert(mesh);
  1660.     if (!mesh) return;
  1661.     BitArray vertSel = mesh->vertSel;
  1662.     for (int i = 0; i<mesh->getNumFaces(); i++) {
  1663.         for (int j = 0; j<3; j++) {
  1664.             if (!edgeSel[currentPartition][i * 3 + j]) continue;
  1665.             vertSel.Set(mesh->faces[i].v[j], TRUE);
  1666.             vertSel.Set(mesh->faces[i].v[(j + 1) % 3], TRUE);
  1667.         }
  1668.     }
  1669. }*/
  1670.  
  1671. void BSDSData::SelFaceByVert() {
  1672.     DbgAssert(mesh);
  1673.     if (!mesh) return;
  1674.     BitArray vertSel = mesh->vertSel;
  1675.     BitArray faceSel = faceSel[currentPartition];
  1676.     for (int i = 0; i<mesh->getNumFaces(); i++) {
  1677.         for (int j = 0; j<3; j++) if (vertSel[mesh->faces[i].v[j]]) { faceSel.Set(i); break; }
  1678.     }
  1679. }
  1680.  
  1681. void BSDSData::SelFaceByEdge() {
  1682.     DbgAssert(mesh);
  1683.     if (!mesh) return;
  1684.     BitArray edgeSel = edgeSel[currentPartition];
  1685.     BitArray faceSel = faceSel[currentPartition];
  1686.     for (int i = 0; i<mesh->getNumFaces(); i++) {
  1687.         for (int j = 0; j<3; j++) if (edgeSel[i * 3 + j]) { faceSel.Set(i); break; }
  1688.     }
  1689. }
  1690.  
  1691. void BSDSData::SelPolygonByVert(float thresh, int igVis) {
  1692.     DbgAssert(mesh);
  1693.     if (!mesh) return;
  1694.     BitArray vertSel = mesh->vertSel;
  1695.     BitArray faceSel = faceSel[currentPartition];
  1696.     BitArray nfsel;
  1697.     nfsel.SetSize(mesh->getNumFaces());
  1698.     for (int i = 0; i<mesh->getNumFaces(); i++) {
  1699.         for (int j = 0; j<3; j++) if (vertSel[mesh->faces[i].v[j]])
  1700.         {
  1701.             mesh->PolyFromFace(i, nfsel, thresh, igVis, GetAdjFaceList()); break;
  1702.         }
  1703.     }
  1704.     faceSel |= nfsel;
  1705. }
  1706.  
  1707. void BSDSData::SelPolygonByEdge(float thresh, int igVis) {
  1708.     DbgAssert(mesh);
  1709.     if (!mesh) return;
  1710.     BitArray edgeSel = edgeSel[currentPartition];
  1711.     BitArray faceSel = faceSel[currentPartition];
  1712.     BitArray nfsel;
  1713.     nfsel.SetSize(mesh->getNumFaces());
  1714.     for (int i = 0; i<mesh->getNumFaces(); i++) {
  1715.         for (int j = 0; j<3; j++) if (edgeSel[i * 3 + j])
  1716.         {
  1717.             mesh->PolyFromFace(i, nfsel, thresh, igVis, GetAdjFaceList()); break;
  1718.         }
  1719.     }
  1720.     faceSel |= nfsel;
  1721. }
  1722.  
  1723. /*void BSDSData::SelElementByVert() {
  1724.     DbgAssert(mesh);
  1725.     if (!mesh) return;
  1726.     BitArray vertSel = edgeSel[currentPartition];
  1727.     BitArray faceSel = faceSel[currentPartition];
  1728.     BitArray nfsel;
  1729.     nfsel.SetSize(mesh->getNumFaces());
  1730.     for (int i = 0; i<mesh->getNumFaces(); i++) {
  1731.         for (int j = 0; j<3; j++) if (vertSel[mesh->faces[i].v[j]])
  1732.         {
  1733.             mesh->ElementFromFace(i, nfsel, GetAdjFaceList()); break;
  1734.         }
  1735.     }
  1736.     faceSel |= nfsel;
  1737. }*/
  1738.  
  1739. void BSDSData::SelElementByEdge() {
  1740.     DbgAssert(mesh);
  1741.     if (!mesh) return;
  1742.     BitArray edgeSel = edgeSel[currentPartition];
  1743.     BitArray faceSel = faceSel[currentPartition];
  1744.     BitArray nfsel;
  1745.     nfsel.SetSize(mesh->getNumFaces());
  1746.     for (int i = 0; i<mesh->getNumFaces(); i++) {
  1747.         for (int j = 0; j<3; j++) if (edgeSel[i * 3 + j])
  1748.         {
  1749.             mesh->ElementFromFace(i, nfsel, GetAdjFaceList()); break;
  1750.         }
  1751.     }
  1752.     faceSel |= nfsel;
  1753. }
  1754.  
  1755. void BSDSData::SelEdgeByVert() {
  1756.     DbgAssert(mesh);
  1757.     if (!mesh) return;
  1758.     BitArray vertSel = mesh->vertSel;
  1759.     BitArray edgeSel = edgeSel[currentPartition];
  1760.     for (int i = 0; i<mesh->getNumFaces(); i++) {
  1761.         for (int j = 0; j<3; j++) {
  1762.             if (vertSel[mesh->faces[i].v[j]]) edgeSel.Set(i * 3 + j);
  1763.             if (vertSel[mesh->faces[i].v[(j + 1) % 3]]) edgeSel.Set(i * 3 + j);
  1764.         }
  1765.     }
  1766. }
  1767.  
  1768. void BSDSData::SelEdgeByFace() {
  1769.     DbgAssert(mesh);
  1770.     if (!mesh) return;
  1771.     BitArray edgeSel = edgeSel[currentPartition];
  1772.     BitArray faceSel = faceSel[currentPartition];
  1773.     for (int i = 0; i<mesh->getNumFaces(); i++) {
  1774.         if (!faceSel[i]) continue;
  1775.         for (int j = 0; j<3; j++) edgeSel.Set(i * 3 + j);
  1776.     }
  1777. }
  1778.  
  1779. // Unfixed version of code, possibly not needed anymore
  1780. /*void BSDSData::SetActivePartition(int partition)
  1781. {
  1782.     currentPartition = partition;
  1783.     while (flags.Count() <= partition) {
  1784.         BSDSPartitionData flag;
  1785.         flag.bodyPart = BP_TORSO;
  1786.         flag.partFlag = 1;
  1787.         flag.selLevel = SEL_FACE;
  1788.         flags.Append(1, &flag);
  1789.     }
  1790.     BitArray empty;
  1791.     while (vselSet.Count() <= partition){
  1792.         vselSet.AppendSet(empty);
  1793.     }
  1794.     while (fselSet.Count() <= partition){
  1795.         fselSet.AppendSet(empty);
  1796.     }
  1797.     while (eselSet.Count() <= partition){
  1798.         eselSet.AppendSet(empty);
  1799.     }
  1800.  
  1801. }*/
  1802.  
  1803. void BSDSData::RemovePartition(int num)
  1804. {
  1805.     if (num < bodyParts.Count() && bodyParts.Count() > 1)
  1806.     {
  1807.         bodyParts.Delete(num, 1);
  1808.         // edgeSel.Delete(num, 1);
  1809.         faceSel.Delete(num, 1);
  1810.         if (num >= bodyParts.Count())
  1811.             currentPartition = 0;
  1812.     }
  1813. }
  1814.  
  1815. int BSDSData::AddPartition() {
  1816.     DismemberPartition add;
  1817.     BitArray empty;
  1818.     // edgeSel.Append(1, &empty);
  1819.     faceSel.Append(1, &empty);
  1820.     bodyParts.Append(1, &add);
  1821.     currentPartition += 1;
  1822.     return currentPartition;
  1823. }
  1824.  
  1825. BitArray BSDSData::GetUnused()
  1826. {
  1827.     SynchBitArrays();
  1828.     BitArray toSelect;
  1829.     toSelect.SetSize(faceSel.Count());
  1830.     toSelect.SetAll();
  1831.     Tab<BitArray>inverses;
  1832.     for (int i = 0; i < faceSel.Count(); i++) {
  1833.         BitArray temp = faceSel[i];
  1834.         temp.Reverse();
  1835.         inverses.Append(1, &temp);
  1836.     }
  1837.     if (inverses.Count() > 0) {
  1838.         for (int i = 0; i < inverses.Count(); i++) {
  1839.             toSelect &= inverses[i];
  1840.         }
  1841.     }
  1842.     return toSelect;
  1843. }
  1844.  
  1845. /*SelectRestore::SelectRestore(BSDSModifier *m, BSDSData *data, int sLevel) {
  1846.     mod = m;
  1847.     level = sLevel;
  1848.     d = data;
  1849.     d->held = TRUE;
  1850.     switch (level) {
  1851.     case SEL_OBJECT: DbgAssert(0); break;
  1852.     // case SEL_VERTEX: break;
  1853.     case SEL_EDGE:
  1854.         usel = d->edgeSel[sLevel]; break;
  1855.     default:
  1856.         usel = d->faceSel[sLevel]; break;
  1857.     }
  1858. }*/
  1859.  
  1860. SelectRestore::SelectRestore(BSDSModifier *m, BSDSData *data) {
  1861.     mod = m;
  1862.     d = data;
  1863.     level = d->bodyParts[d->currentPartition].selLevel;
  1864.     d->held = TRUE;
  1865.     switch (level) {
  1866.     case SEL_OBJECT: DbgAssert(0); break;
  1867.     default:
  1868.         usel = d->faceSel[d->currentPartition]; break;
  1869.     }
  1870.     //SelectRestore::SelectRestore(m, d, d->bodyParts[d->currentPartition].selLevel);
  1871. }
  1872.  
  1873. void SelectRestore::Restore(int isUndo) {
  1874.     if (isUndo) {
  1875.         switch (level) {
  1876.         // case SEL_VERTEX: break;
  1877.         case SEL_FACE:
  1878.         case SEL_POLY:
  1879.         case SEL_ELEMENT:
  1880.             rsel = d->faceSel[d->currentPartition]; break;
  1881.         /*case SEL_EDGE:
  1882.             rsel = d->edgeSel[d->currentPartition]; break;*/
  1883.         }
  1884.     }
  1885.     switch (level) {
  1886.     // case SEL_VERTEX: break;
  1887.     case SEL_FACE:
  1888.     case SEL_POLY:
  1889.     case SEL_ELEMENT:
  1890.         d->faceSel[d->currentPartition] = usel; break;
  1891.     /*case SEL_EDGE:
  1892.         d->edgeSel[d->currentPartition] = usel; break;*/
  1893.     }
  1894.     mod->LocalDataChanged();
  1895. }
  1896.  
  1897. void SelectRestore::Redo() {
  1898.     switch (level) {
  1899.     // case SEL_VERTEX: break;
  1900.     case SEL_FACE:
  1901.     case SEL_POLY:
  1902.     case SEL_ELEMENT:
  1903.         d->faceSel[d->currentPartition] = rsel; break;
  1904.     /*case SEL_EDGE:
  1905.         d->edgeSel[d->currentPartition] = rsel; break;*/
  1906.     }
  1907.     mod->LocalDataChanged();
  1908. }
  1909.  
  1910. void BSDSModifier::SetNumSelLabel() {
  1911.     TSTR buf;
  1912.     int num = 0;
  1913.     int which = 0;
  1914.     BSDSData* d = (BSDSData*)GetModifierData();
  1915.  
  1916.     if (!BSDSDesc.NumParamMaps()) return;
  1917.     IParamMap2 *pmap = BSDSDesc.GetParamMap(ms_map_main);
  1918.     if (!pmap) return;
  1919.     HWND hParams = pmap->GetHWnd();
  1920.     if (!hParams) return;
  1921.  
  1922.     // int selLevel = SEL_OBJECT;
  1923.     // Tab<IBSDismemberSkinModifierData*> list = GetModifierData();
  1924.     // for (int i = 0; i<list.Count(); i++) {
  1925.         // BSDSData *meshData = (BSDSData *)list[i];
  1926.         if (!d) return;
  1927.  
  1928.         // selLevel = meshData->GetSelectionLevel();
  1929.         switch (d->bodyParts[d->currentPartition].selLevel) {
  1930.         /*case SEL_VERTEX:
  1931.             num += meshData->GetVertSel().NumberSet();
  1932.             if (meshData->GetVertSel().NumberSet() == 1) {
  1933.                 for (which = 0; which<meshData->GetVertSel().GetSize(); which++) if (meshData->GetVertSel()[which]) break;
  1934.             }*/
  1935.             break;
  1936.         case SEL_FACE:
  1937.         case SEL_POLY:
  1938.         case SEL_ELEMENT:
  1939.             num += d->faceSel[d->currentPartition].NumberSet();
  1940.             if (d->faceSel[d->currentPartition].NumberSet() == 1) {
  1941.                 for (which = 0; which<d->faceSel[d->currentPartition].GetSize(); which++) if (d->faceSel[d->currentPartition][which]) break;
  1942.             }
  1943.             break;
  1944.         /*case SEL_EDGE:
  1945.             num += d->edgeSel[d->currentPartition].NumberSet();
  1946.             if (d->edgeSel[d->currentPartition].NumberSet() == 1) {
  1947.                 for (which = 0; which<d->edgeSel[d->currentPartition].GetSize(); which++) if (d->edgeSel[d->currentPartition][which]) break;
  1948.             }
  1949.             break;*/
  1950.         }
  1951.     // }
  1952.  
  1953.         switch (d->bodyParts[d->currentPartition].selLevel) {
  1954.     /*case SEL_VERTEX:
  1955.         if (num == 1) buf.printf(GetString(IDS_EM_WHICHVERTSEL), which + 1);
  1956.         else buf.printf(GetString(IDS_RB_NUMVERTSELP), num);
  1957.         break;*/
  1958.     case SEL_FACE:
  1959.     case SEL_POLY:
  1960.     case SEL_ELEMENT:
  1961.         if (num == 1) buf.printf(GetString(IDS_EM_WHICHFACESEL), which + 1);
  1962.         else buf.printf(GetString(IDS_RB_NUMFACESELP), num);
  1963.         break;
  1964.     /*case SEL_EDGE:
  1965.         if (num == 1) buf.printf(GetString(IDS_EM_WHICHEDGESEL), which + 1);
  1966.         else buf.printf(GetString(IDS_RB_NUMEDGESELP), num);
  1967.         break;*/
  1968.     case SEL_OBJECT:
  1969.         buf = GetString(IDS_EM_OBJECT_SEL);
  1970.         break;
  1971.     }
  1972.  
  1973.     SetDlgItemText(hParams, IDC_MS_NUMBER_SEL, buf);
  1974. }
  1975.  
  1976. void BSDSModifier::SelectUnused()
  1977. {
  1978.     theHold.Begin();
  1979.     BSDSData *d = (BSDSData*)GetModifierData();
  1980.     if (!d->held) theHold.Put(new SelectRestore(this, d));
  1981.     d->faceSel[d->currentPartition] = d->GetUnused();
  1982.     theHold.Accept(GetString(IDS_RB_SELUNUSED));
  1983.  
  1984.     LocalDataChanged();
  1985.     ip->RedrawViews(ip->GetTime());
  1986. }
  1987.  
  1988. RefResult BSDSModifier::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
  1989.     PartID& partID, RefMessage message) {
  1990.     if ((message == REFMSG_CHANGE) && (hTarget == pblock)) {
  1991.         // if this was caused by a NotifyDependents from pblock, LastNotifyParamID()
  1992.         // will contain ID to update, else it will be -1 => inval whole rollout
  1993.         int pid = pblock->LastNotifyParamID();
  1994.         InvalidateDialogElement(pid);
  1995.     }
  1996.     return(REF_SUCCEED);
  1997. }
  1998.  
  1999. int BSDSModifier::NumSubObjTypes()
  2000. {
  2001.     return 3;
  2002. }
  2003.  
  2004. ISubObjType *BSDSModifier::GetSubObjType(int i)
  2005. {
  2006.     /*static bool initialized = false;
  2007.     if (!initialized)
  2008.     {
  2009.         initialized = true;
  2010.         // SOT_Vertex.SetName(GetString(IDS_RB_VERTEX));
  2011.         // SOT_Edge.SetName(GetString(IDS_RB_EDGE));
  2012.         SOT_Face.SetName(GetString(IDS_RB_FACE));
  2013.         GetString(IDS_EM_POLY);
  2014.         SOT_Poly.SetName(GetString(IDS_EM_POLY));
  2015.         SOT_Element.SetName(GetString(IDS_EM_ELEMENT));
  2016.     }
  2017.     switch (i)
  2018.     {
  2019.     case -1:
  2020.         if (GetSubObjectLevel() > 0)
  2021.             return GetSubObjType(GetSubObjectLevel() - 1);
  2022.         break;
  2023.     case 0:
  2024.         return &SOT_Vertex;
  2025.     case 1:
  2026.         return &SOT_Edge;
  2027.     case 2:
  2028.         return &SOT_Face;
  2029.     case 3:
  2030.         return &SOT_Poly;
  2031.     case 4:
  2032.         return &SOT_Element;
  2033.     }*/
  2034.     switch (i)
  2035.     {
  2036.     case -1:
  2037.         /*if (GetSubObjectLevel() > 0)
  2038.             return GetSubObjType(GetSubObjectLevel() - 1);*/
  2039.         break;
  2040.     case 0:
  2041.         return &SOT_Face;
  2042.     case 1:
  2043.         return &SOT_Poly;
  2044.     case 2:
  2045.         return &SOT_Element;
  2046.     }
  2047.     return NULL;
  2048.     // Old code
  2049.     /*BSDSData *d = (BSDSData*)GetModifierData();
  2050.     if (i >= subObjects.Count())
  2051.         return NULL;
  2052.     if (i < 0) {
  2053.         if (d->currentPartition > 0)
  2054.             return GetSubObjType(d->currentPartition - 1);
  2055.         return NULL;
  2056.     }
  2057.     return &subObjects[i];*/
  2058. }
  2059.  
  2060. void BSDSModifier::InvalidateDialogElement(int elem) {
  2061.     if (!pblock) return;
  2062.     if (!BSDSDesc.NumParamMaps()) return;
  2063.     IParamMap2 *pmap = BSDSDesc.GetParamMap(ms_map_main);
  2064.     if (pmap) pmap->Invalidate(elem);
  2065. }
  2066.  
  2067. // Get or Create the BSDismember Modifier
  2068. Modifier *GetOrCreateBSDismemberSkin(INode *node)
  2069. {
  2070.     Modifier *BSMod = GetBSDismemberSkin(node);
  2071.     if (BSMod)
  2072.         return BSMod;
  2073.     Object *pObj = node->GetObjectRef();
  2074.     IDerivedObject *pDerObj = NULL;
  2075.     if (pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID)
  2076.         pDerObj = dynamic_cast<IDerivedObject*>(pObj);
  2077.     else {
  2078.         pDerObj = CreateDerivedObject(pObj);
  2079.     }
  2080.     // Never ever do the following line, it spawns multiple DerivedObjects, each node should only have 1 Derived Object.
  2081.     // IDerivedObject *dobj = CreateDerivedObject(node->GetObjectRef());
  2082.  
  2083.     //create a BSDismemberment modifier and add it
  2084.     BSMod = (Modifier*)CreateInstance(OSM_CLASS_ID, BSDSMODIFIER_CLASS_ID);
  2085.     pDerObj->SetAFlag(A_LOCK_TARGET);
  2086.     pDerObj->AddModifier(BSMod);
  2087.     pDerObj->ClearAFlag(A_LOCK_TARGET);
  2088.     node->SetObjectRef(pDerObj);
  2089.     return BSMod;
  2090. }
  2091.  
  2092. Modifier *GetBSDismemberSkin(INode *node)
  2093. {
  2094.     Object* pObj = node->GetObjectRef();
  2095.     if (!pObj) return NULL;
  2096.     while (pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID)
  2097.     {
  2098.         IDerivedObject* pDerObj = (IDerivedObject *)(pObj);
  2099.         int Idx = 0;
  2100.         while (Idx < pDerObj->NumModifiers())
  2101.         {
  2102.             // Get the modifier.
  2103.             Modifier* mod = pDerObj->GetModifier(Idx);
  2104.             if (mod->ClassID() == BSDSMODIFIER_CLASS_ID)
  2105.                 return mod;
  2106.             Idx++;
  2107.         }
  2108.         pObj = pDerObj->GetObjRef();
  2109.     }
  2110.     return NULL;
  2111. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement