diff --git a/PYProjects/skin_plus_plus/__init__.py b/PYProjects/skin_plus_plus/__init__.py index 2f494bb..da6b816 100644 --- a/PYProjects/skin_plus_plus/__init__.py +++ b/PYProjects/skin_plus_plus/__init__.py @@ -2,12 +2,35 @@ import importlib import pathlib -import site import sys +get_skin_data = None +set_skin_weights = None +# get_vertex_positions = None + +def __get_dcc_backend(dcc:str, version: str, api:str): + current_directory = pathlib.Path(__file__).parent + sub_module_name = f"skin_plus_plus_{api}_{version}" + sub_module_path = current_directory / f"dccs/{dcc}" / sub_module_name + + print(f"sub_module_path: {sub_module_path}") + + if not sub_module_path.exists(): + raise FileNotFoundError(f"Unsupported DCC version!") + + import_path = f"{__name__}.dccs.{dcc}.{sub_module_name}.skin_plus_plus_{api}" + backend = importlib.import_module(import_path) + + global get_skin_data + global set_skin_weights + # global get_vertex_positions + + get_skin_data = backend.get_skin_data + set_skin_weights = backend.set_skin_weights + # get_vertex_positions = skin_plus_plus_pymxs.get_vertex_positions + + return backend -# DO NOT REMOVE - Required for access to SkinData class: -from . import skin_plus_plus_py executable = sys.executable.lower() if "3ds max" in executable: @@ -16,29 +39,15 @@ version_info = mxRt.MaxVersion() version_number = version_info[0] - current_directory = pathlib.Path(__file__).parent - max_sub_module_name = f"skin_plus_plus_pymxs_{version_number}" - max_sub_module_path = current_directory / "dccs/max" / max_sub_module_name - - if not max_sub_module_path.exists(): - raise FileNotFoundError(f"Unsupported DCC version!") - - import_path = f"{__name__}.dccs.max.{max_sub_module_name}.skin_plus_plus_pymxs" - skin_plus_plus_pymxs = importlib.import_module(import_path) - - get_skin_data = skin_plus_plus_pymxs.get_skin_data - # get_vertex_positions = skin_plus_plus_pymxs.get_vertex_positions - set_skin_weights = skin_plus_plus_pymxs.set_skin_weights + __get_dcc_backend("max", version_number, "pymxs") elif "maya" in executable: - # from maya import cmds - from .dccs.maya.skin_plus_plus_pymaya_2022 import skin_plus_plus_pymaya + from pymel import versions - get_skin_data = skin_plus_plus_pymaya.get_skin_data - # get_vertex_positions = skin_plus_plus_pymaya.get_vertex_positions - set_skin_weights = skin_plus_plus_pymaya.set_skin_weights + version = str(versions.current())[:4] + __get_dcc_backend("maya", version, "pymaya") else: raise RuntimeError(f"Unsupported executable: {executable}") diff --git a/PYProjects/skin_plus_plus/dccs/max/skin_plus_plus_pymxs_24000/skin_plus_plus_pymxs.pyd b/PYProjects/skin_plus_plus/dccs/max/skin_plus_plus_pymxs_24000/skin_plus_plus_pymxs.pyd index aa3c44e..474a6a9 100644 Binary files a/PYProjects/skin_plus_plus/dccs/max/skin_plus_plus_pymxs_24000/skin_plus_plus_pymxs.pyd and b/PYProjects/skin_plus_plus/dccs/max/skin_plus_plus_pymxs_24000/skin_plus_plus_pymxs.pyd differ diff --git a/PYProjects/skin_plus_plus/dccs/maya/skin_plus_plus_pymaya_2022/skin_plus_plus_pymaya.pyd b/PYProjects/skin_plus_plus/dccs/maya/skin_plus_plus_pymaya_2022/skin_plus_plus_pymaya.pyd index 91ff2a0..c33e9aa 100644 Binary files a/PYProjects/skin_plus_plus/dccs/maya/skin_plus_plus_pymaya_2022/skin_plus_plus_pymaya.pyd and b/PYProjects/skin_plus_plus/dccs/maya/skin_plus_plus_pymaya_2022/skin_plus_plus_pymaya.pyd differ diff --git a/PYProjects/skin_plus_plus/skin_plus_plus_py.pyd b/PYProjects/skin_plus_plus/skin_plus_plus_py.pyd index 72bc952..8b14676 100644 Binary files a/PYProjects/skin_plus_plus/skin_plus_plus_py.pyd and b/PYProjects/skin_plus_plus/skin_plus_plus_py.pyd differ diff --git a/PYProjects/skin_plus_plus_test/__init__.py b/PYProjects/skin_plus_plus_test/__init__.py index 15cfa40..e69de29 100644 --- a/PYProjects/skin_plus_plus_test/__init__.py +++ b/PYProjects/skin_plus_plus_test/__init__.py @@ -1,25 +0,0 @@ -import sys - -# Required for access to SkinData class: -from . import _skin_plus_plus_py - -executable = sys.executable -if "3ds max" in executable: - from ._skin_plus_plus_pymxs import get_data - from ._skin_plus_plus_pymxs import get_vertex_positions - from ._skin_plus_plus_pymxs import set_skin_weights - -else: - raise RuntimeError(f"Unsupported executable: {executable}") - - -from .core import export_skin_data -from .core import import_skin_data - -__all__ = ( - "export_skin_data", - "get_vertex_positions", - "get_data", - "import_skin_data", - "set_skin_weights" -) diff --git a/PYProjects/skin_plus_plus_test/skin_plus_plus_test.ms b/PYProjects/skin_plus_plus_test/skin_plus_plus_test.ms index 17f22f0..285e4e9 100644 --- a/PYProjects/skin_plus_plus_test/skin_plus_plus_test.ms +++ b/PYProjects/skin_plus_plus_test/skin_plus_plus_test.ms @@ -2,9 +2,9 @@ pyTime = python.import "time" _SKINPPOPS = SkinPPOps() --- -- getPropNames _SKINPPOPS -vals = _SKINPPOPS.GetSkinWeights $Sphere002 -vals[3].Count +-- getPropNames _SKINPPOPS +-- vals = _SKINPPOPS.GetSkinWeights $Sphere002 +-- vals[3].Count -- _SKINPPOPS.getPositions $Sphere001 -- SkinPP.GetSkinWeights $Sphere001 diff --git a/PYProjects/skin_plus_plus_test/skin_plus_plus_test.py b/PYProjects/skin_plus_plus_test/skin_plus_plus_test.py index e805d24..fe37828 100644 --- a/PYProjects/skin_plus_plus_test/skin_plus_plus_test.py +++ b/PYProjects/skin_plus_plus_test/skin_plus_plus_test.py @@ -370,32 +370,33 @@ def setup_maya_environment(cls): def test_get_performance(self): get_timer_dict: dict[str, tuple[float, Any, str]] = {} - def findRelatedSkinCluster(geometry): + def find_related_skin_cluster(geometry): if not self.cmds.objExists(geometry): - raise Exception('Object '+geometry+' does not exist!') + raise Exception(f"Object {geometry} does not exist!") if self.cmds.objectType(geometry) == "transform": try: geometry = self.cmds.listRelatives(geometry, s=True, ni=True, pa=True)[0] - except: raise Exception('Object '+geometry+' has no deformable geometry!') + except: raise Exception(f"Object {geometry} has no deformable geometry!") - skin = self.mel.eval(f'findRelatedSkinCluster "{geometry}"') + skin = self.mel.eval(f"findRelatedSkinCluster '{geometry}'") if not skin: skin = self.cmds.ls(self.cmds.listHistory(geometry),type='skinCluster') - if skin: skin = skin[0] - if not skin: skin = '' + skin = skin[0] if skin else None + + if not skin: + raise RuntimeError(f"{geometry} has no skin cluster!") return skin @timer(get_timer_dict) - def get_skin_weights_cmds(_obj: str): + def cmds_get_skin_weights(_obj: str): vertex_count = self.cmds.polyEvaluate(_obj, vertex=True) - skin_cluster = findRelatedSkinCluster(_obj) + skin_cluster = find_related_skin_cluster(_obj) skin_weights = np.empty((vertex_count, 6), dtype=float) skin_bone_names = [None] * vertex_count positions: np.ndarray[float, Any] = np.empty((vertex_count, 3), dtype=float) for vertex_index in range(vertex_count): vertex_index_str = f"{_obj}.vtx[{vertex_index}]" - vertex_weights = np.array( self.cmds.skinPercent( skin_cluster, @@ -428,7 +429,7 @@ def get_skin_weights_cmds(_obj: str): return skin_weights, positions, skin_bone_names @timer(get_timer_dict) - def get_skin_weights_pymel(_obj: str): + def pymel_get_skin_weights(_obj: str): def get_skin_cluster(__obj): """Get the skincluster of a given object @@ -550,8 +551,8 @@ def skin_plus_plus_get_skin_data(_obj: str): get_function_list = ( - get_skin_weights_cmds, - get_skin_weights_pymel, + cmds_get_skin_weights, + pymel_get_skin_weights, skin_plus_plus_get_skin_data, ) @@ -610,7 +611,7 @@ def set_skin_weights(_obj, _boneIDs, _weights): if __name__ == "__main__": - # get_skin_weights_cmds("test_mesh_low") + # cmds_get_skin_weights("test_mesh_low") # from pymxs import runtime as mxRt @@ -618,7 +619,8 @@ def set_skin_weights(_obj, _boneIDs, _weights): # unittest.main() suite = unittest.TestSuite() - suite.addTest(SkinPlusPlusTestMaya("test_get_performance")) + suite.addTest(SkinPlusPlusTestMax("test_get_performance")) + # suite.addTest(SkinPlusPlusTestMaya("test_get_performance")) runner = unittest.TextTestRunner() runner.run(suite) diff --git a/PYProjects/source/skin_plus_plus_py/headers/skin_plus_plus_py.h b/PYProjects/source/skin_plus_plus_py/headers/skin_plus_plus_py.h index 85cb996..307cddb 100644 --- a/PYProjects/source/skin_plus_plus_py/headers/skin_plus_plus_py.h +++ b/PYProjects/source/skin_plus_plus_py/headers/skin_plus_plus_py.h @@ -11,6 +11,7 @@ #define FMT_HEADER_ONLY #include +#include namespace py = pybind11; diff --git a/PYProjects/source/skin_plus_plus_pymaya/skin_plus_plus_pymaya.cpp b/PYProjects/source/skin_plus_plus_pymaya/skin_plus_plus_pymaya.cpp index ab9fafd..481e53f 100644 --- a/PYProjects/source/skin_plus_plus_pymaya/skin_plus_plus_pymaya.cpp +++ b/PYProjects/source/skin_plus_plus_pymaya/skin_plus_plus_pymaya.cpp @@ -1,8 +1,6 @@ #include - - //bool getMeshPositions(const MDagPath& dagPath, Array* pointArray) //{ // nvDebugCheck(pointArray != NULL); @@ -108,25 +106,6 @@ PySkinData SkinManagerMaya::getData() bool SkinManagerMaya::setSkinWeights(eg::MatrixXi& boneIDs, eg::MatrixXf& vertexWeights) { - /* - if you want to set the weights for three components for influences 7 and 10, - the influence array would contain[7, 10], and the values array would contain: - [ - component#1 weight for influence 7, - component #1 weight for influence 10, - component#2 weight for influence 7, - component#2 weight for influence 10, - ... - ] - setWeights(const MDagPath & path, - const MObject & components, - MIntArray & influenceIndices, - MDoubleArray & values, - bool normalize = true, - MDoubleArray * oldValues = NULL - ) - */ - size_t vertexCount = boneIDs.rows(); size_t vertexWeightsRows = vertexWeights.rows(); size_t influenceCount = boneIDs.cols(); @@ -140,6 +119,7 @@ bool SkinManagerMaya::setSkinWeights(eg::MatrixXi& boneIDs, eg::MatrixXf& vertex } if (influenceCount != vertexWeightsCols) { + //fmt::to_char(); const char* exceptionText = convertStringToChar( fmt::format("boneIDs column size: {} does not match vertexWeights column size: {}", influenceCount, vertexWeightsCols) ); @@ -158,10 +138,6 @@ bool SkinManagerMaya::setSkinWeights(eg::MatrixXi& boneIDs, eg::MatrixXf& vertex arrayIndex += influenceIndex; auto boneID = boneIDs(vertexIndex, influenceIndex); auto vertexWeight = vertexWeights(vertexIndex, influenceIndex); - //if (!fixedIds) - //{ - // mBoneIDs[arrayIndex] = boneID; - //} mWeights[arrayIndex] = vertexWeight; } } @@ -181,6 +157,8 @@ bool SkinManagerMaya::setSkinWeights(eg::MatrixXi& boneIDs, eg::MatrixXf& vertex PYBIND11_MODULE(skin_plus_plus_pymaya, m) { + #include + m.def("get_skin_data", [&](wchar_t* name) { SkinManagerMaya skinData(name); diff --git a/PYProjects/source/skin_plus_plus_pymxs/source/skin_plus_plus_pymxs.cpp b/PYProjects/source/skin_plus_plus_pymxs/source/skin_plus_plus_pymxs.cpp index 9bde135..6b5ae15 100644 --- a/PYProjects/source/skin_plus_plus_pymxs/source/skin_plus_plus_pymxs.cpp +++ b/PYProjects/source/skin_plus_plus_pymxs/source/skin_plus_plus_pymxs.cpp @@ -11,11 +11,15 @@ char convertWCharToChar(const wchar_t* text) return StoreTextBuffer[0]; } -std::string convertWChartoString(const wchar_t* text) -{ - std::wstring ws(text); - return std::string(ws.begin(), ws.end()); -} + +//std::string convertWChartoString(const wchar_t* text) +//{ +// //fmt::format(text); +// auto text_ = fmt::to_string(text); +// std::wstring ws(text); +// return std::string(ws.begin(), ws.end()); +//} + INode* getChildByName(const wchar_t* name, INode* parent) { @@ -131,36 +135,6 @@ bool SkinManager::initialise(const wchar_t* name) } -//std::vector>> SkinManager::getSkinWeights() -//{ -// if (!this->isValid) -// { -// throw std::exception("SkinData object is invalid. Cannot get skin weights."); -// } -// unsigned int vertexCount = this->iSkinContextData->GetNumPoints(); -// std::vector>> skinDataArray( -// 2, std::vector>(vertexCount) -// ); -// for (unsigned int vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) -// { -// auto influenceCount = this->iSkinContextData->GetNumAssignedBones(vertexIndex); -// std::vector influenceWeights(influenceCount); -// std::vector influenceBoneIDs(influenceCount); -// skinDataArray[0][vertexIndex] = influenceWeights; //influenceWeights -// skinDataArray[1][vertexIndex] = influenceBoneIDs; //influenceBoneIDs -// for (auto influenceIndex = 0; influenceIndex < influenceCount; influenceIndex++) -// { -// auto infuenceWeight = this->iSkinContextData->GetBoneWeight(vertexIndex, influenceIndex); -// if (infuenceWeight <= 0.0f) continue; -// auto influenceBoneID = this->iSkinContextData->GetAssignedBone(vertexIndex, influenceIndex); -// influenceWeights[influenceIndex] = infuenceWeight; -// influenceBoneIDs[influenceIndex] = float(influenceBoneID); -// } -// }; -// return skinDataArray; -//} -// - void SkinManager::collectWeightsAndBoneIDs(PySkinData* pySkinData, unsigned int vertexIndex) { auto influenceCount = this->iSkinContextData->GetNumAssignedBones(vertexIndex); @@ -194,7 +168,7 @@ PySkinData* SkinManager::getData() this->pySkinData->boneNames = std::vector(skinBonesCount); for (auto boneIndex = 0; boneIndex < skinBonesCount; boneIndex++) { - this->pySkinData->boneNames[boneIndex] = convertWChartoString(this->iSkin->GetBone(boneIndex)->GetName()); + this->pySkinData->boneNames[boneIndex] = fmt::to_string(this->iSkin->GetBone(boneIndex)->GetName()); } auto meshType = getMeshType(this->node); if (meshType == 0) @@ -300,7 +274,7 @@ bool SkinManager::setSkinWeights(PySkinData& skinData) continue; } skinBones.Append(1, &bone); - skinBoneNames[boneIndex] = convertWChartoString(bone->GetName()); + skinBoneNames[boneIndex] = fmt::to_string(bone->GetName()); } auto sortedBoneIDs = getSortedBoneIDs(skinData.boneNames, skinBoneNames); for (auto vertexIndex = 0; vertexIndex < boneIDsRows; vertexIndex++) @@ -330,13 +304,6 @@ bool SkinManager::setSkinWeights(PySkinData& skinData) } -//inline std::vector>> getSkinWeights(wchar_t* name) -//{ -// SkinManager skinData(name); -// return skinData.getSkinWeights(); -//} - - bool setSkinWeights(wchar_t* name, PySkinData& skinData) { SkinManager skinData_(name); @@ -345,35 +312,8 @@ bool setSkinWeights(wchar_t* name, PySkinData& skinData) PYBIND11_MODULE(skin_plus_plus_pymxs, m) { - //m.def("get_skin_weights", [&](wchar_t* name, int return_type) - // { - // std::vector>> weights = getSkinWeights(name); - // switch (return_type) { - // case 0: - // return py::cast(weights); - // case 1: - // return py::cast(weights, py::return_value_policy::take_ownership); - // case 2: - // return py::cast(weights, py::return_value_policy::copy); - // case 3: - // return py::cast(weights, py::return_value_policy::move); - // case 4: - // return py::cast(weights, py::return_value_policy::reference); - // case 5: - // return py::cast(weights, py::return_value_policy::reference_internal); - // case 6: - // return py::cast(weights, py::return_value_policy::automatic); - // case 7: - // return py::cast(weights, py::return_value_policy::automatic_reference); - // default: - // return py::cast(weights); - // } - // - // }, - // "Get Skin Weights", - // py::arg("name"), - // py::arg("return_type") - //); + #include + m.def("get_skin_data", [&](wchar_t* name) { SkinManager skinData(name);