diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a445f87..9ecd044 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,7 +12,7 @@ jobs: compile_plugin: strategy: matrix: - maya: [2022, 2023, 2024, 2025, 2026] + maya: [2022, 2023, 2024, 2025, 2026, 2027] os: [macos-13, macos-latest, ubuntu-latest, windows-latest] include: # Add the maya update versions here @@ -26,6 +26,8 @@ jobs: update: 3 - maya: 2026 update: 2 + - maya: 2027 + update: 2 # cross-compiling is annoying so just fall back to macos-13 exclude: @@ -39,6 +41,8 @@ jobs: maya: 2025 - os: macos-13 maya: 2026 + - os: macos-13 + maya: 2027 fail-fast: false diff --git a/src/python/simplexui/commands/alembicCommon.py b/src/python/simplexui/commands/alembicCommon.py index 30302e5..7bb9c56 100644 --- a/src/python/simplexui/commands/alembicCommon.py +++ b/src/python/simplexui/commands/alembicCommon.py @@ -36,11 +36,14 @@ try: import numpy as np - from .numpytoimath import imathToNumpy, numpyToImath except ImportError: np = None - numpyToImath = None - imathToNumpy = None + arrayToNumpy = None +else: + try: + from imathnumpy import arrayToNumpy # pylint:disable=no-name-in-module + except ImportError: + arrayToNumpy = None def pbPrint(pBar, message=None, val=None, maxVal=None, _pbPrintLastComma=None): @@ -107,12 +110,22 @@ def mkArray(aType, iList): if isinstance(iList, aType): return iList - if np is None or numpyToImath is None: + if np is None: array = aType(len(iList)) for i in range(len(iList)): array[i] = tuple(iList[i]) return array - return numpyToImath(iList, aType) + elif arrayToNumpy is None: + array = aType(len(iList)) + for i in range(len(iList)): + array[i] = tuple(iList[i].tolist()) + return array + else: + iList = np.array(iList) + array = aType(len(iList)) + memView = arrayToNumpy(array) + np.copyto(memView, iList) + return array def mk1dArray(aType, iList): @@ -132,14 +145,19 @@ def mk1dArray(aType, iList): """ if isinstance(iList, aType): return iList - if np is None or numpyToImath is None: + if np is None or arrayToNumpy is None or aType is UnsignedIntArray: array = aType(len(iList)) for i in range(len(iList)): # Gotta cast to int because an "int" from numpy has # the type np.int32, which makes this conversion angry array[i] = int(iList[i]) return array - return numpyToImath(iList, aType) + else: + iList = np.array(iList) + array = aType(len(iList)) + memView = arrayToNumpy(array) + np.copyto(memView, iList) + return array def mkSampleVertexPoints(pts): @@ -288,11 +306,18 @@ def getSampleArray(imesh, pBar=None): meshSchema = imesh.getSchema() posProp = meshSchema.getPositionsProperty() numShapes = len(posProp.samples) - if imathToNumpy is not None and np is not None: + if arrayToNumpy is not None: shapes = np.empty((len(posProp.samples), len(posProp.samples[0]), 3)) for i, s in enumerate(posProp.samples): pbPrint(pBar, message="Reading Shape", val=i, maxVal=numShapes) - shapes[i] = imathToNumpy(s) + shapes[i] = arrayToNumpy(s) + elif np is not None: + shapes = [] + for i, s in enumerate(posProp.samples): + pbPrint(pBar, message="Reading Shape", val=i, maxVal=numShapes) + shapes.append((list(s.x), list(s.y), list(s.z))) + shapes = np.array(shapes) + shapes = shapes.transpose((0, 2, 1)) else: shapes = [] for i, s in enumerate(posProp.samples): @@ -339,11 +364,13 @@ def getStaticMeshArrays(imesh): The number of vertices per face as np.array if possible """ faces, counts = getStaticMeshData(imesh) - if np is None or imathToNumpy is None: - faces, counts = list(faces), list(counts) + if arrayToNumpy is not None: + faces = arrayToNumpy(faces).copy() + counts = arrayToNumpy(counts).copy() + elif np is not None: + faces, counts = np.array(faces), np.array(counts) else: - faces = imathToNumpy(faces) - counts = imathToNumpy(counts) + faces, counts = list(faces), list(counts) return faces, counts @@ -428,17 +455,20 @@ def getFlatUvFaces(imesh): if iuvs.isIndexed(): indexed = True idxs = iuvs.getIndexProperty().getValue() - if imathToNumpy is None or np is None: - idxs = list(idxs) + # if arrayToNumpy is not None: + # idxs = arrayToNumpy(idxs).copy() + # elif np is not None: + if np is not None: + idxs = np.array(idxs) else: - idxs = imathToNumpy(idxs) + idxs = list(idxs) else: indexed = False rawCount = sum(list(sch.getFaceCountsProperty().samples[0])) - if np is None: - idxs = list(range(rawCount)) - else: + if np is not None: idxs = np.arange(rawCount) + else: + idxs = list(range(rawCount)) return idxs, indexed @@ -678,6 +708,29 @@ def flattenFaces(faces): return faceCounts, faceIdxs +def unflattenFaces(faces, counts): + """Take a flat face/count representation of faces + and turn it into a nested list representation + + Parameters + ---------- + faces : np.array + The flat list of face connectivity + counts : np.array + The flat list of vertices per face + + Returns + ------- + : [[int, ...], ...] + The nested list representation + """ + out, ptr = [], 0 + for c in counts: + out.append(faces[ptr : ptr + c].tolist()) + ptr += c + return out + + def buildAbc( outPath, points, diff --git a/src/python/simplexui/menu/genericPlugins/unsubdivide.py b/src/python/simplexui/menu/genericPlugins/unsubdivide.py index 5cb7716..1ea0059 100644 --- a/src/python/simplexui/menu/genericPlugins/unsubdivide.py +++ b/src/python/simplexui/menu/genericPlugins/unsubdivide.py @@ -22,22 +22,21 @@ from Qt import QtCompat from Qt.QtWidgets import QAction, QMessageBox, QProgressDialog - try: - from ..commands.numpytoimath import numpyToImath + import imathnumpy except ImportError: - numpyToImath = None + imathnumpy = None def registerTool(window, menu): - if numpyToImath is not None: + if imathnumpy is not None: exportUnsubACT = QAction("Un Subdivide Smpx ...", window) menu.addAction(exportUnsubACT) exportUnsubACT.triggered.connect(partial(exportUnsubInterface, window)) def exportUnsubInterface(window): - if numpyToImath is None: + if imathnumpy is None: QMessageBox.warning( window, "No ImathToNumpy",