( local obj = $ local faceSel /* while (obj.modifiers.count > 0) do (deletemodifier obj 1) */ case of ( ((obj == undefined) or (isKindOf obj array) or (not isKindOf obj.baseObject Editable_Poly)): ( messageBox "Please select an Editable Poly object" title:"" ) (obj.modifiers.count != 0): ( messageBox "Please select an Editable Poly object with no modifiers" title:"Object has modifiers" ) ( (subObjectLevel !=0) and ((polyop.getFaceSelection obj) == 0) ): ( messageBox "Please select at least one face on object" title:"No faces selected" ) Default: ( local initialFaceSel = polyop.getFaceSelection obj local initialEdgeSel = polyop.getEdgeSelection obj local useFaces = if (subObjectLevel ==0) then #{1..obj.numfaces} else polyop.getFaceSelection obj local faceEdges = for n = 1 to useFaces.count collect ( if useFaces[n] then (polyop.getFaceEdges obj n) else undefined ) for faceNum in useFaces do ( -- Don't include non-quads: if (polyop.getFaceVerts obj faceNum).count != 4 do ( useFaces[faceNum] = false ) ) -- Create UVWunwrap modifier, select the relevant quads: local newUVmod = Unwrap_UVW() newUVmod.unwrap5.setShowMapSeams off newUVmod.unwrap5.setPeltAlwaysShowSeams off addModifier obj newUVmod /* newUVmod.setApplyToWholeObject true newUVmod.selectPolygonsUpdate useFaces true newUVmod.setApplyToWholeObject false */ -- Work out which faces are contiguous: local faceGroups = for n in useFaces collect #{n} local faceGroupEdges = for item in faceEdges where (item != undefined) collect (item as bitarray) -- Get edge-lengths for all used edges: local allUsedEdges = #{} for item in faceGroupEdges do (allUsedEdges += item) local edgeNum, edgeVerts local edgeLengths = for n = 1 to allUsedEdges.count collect ( if allUsedEdges[n] then ( edgeVerts = polyop.getEdgeVerts obj n distance (polyop.getVert obj edgeVerts[1]) (polyop.getVert obj edgeVerts[2]) ) else undefined ) local existingGroups = #{1..faceGroups.count} local repeatLoop = true local combinedEdges while repeatLoop do ( repeatLoop = false for grpNum = 1 to faceGroups.count where existingGroups[grpNum] do ( for compareNum = (grpNum + 1) to faceGroups.count where existingGroups[compareNum] do ( combinedEdges = faceGroupEdges[grpNum] + faceGroupEdges[compareNum] -- If the edge-bitarrays overlap, the combined array will have fewer items than the seperate arrays: if (combinedEdges.numberSet != (faceGroupEdges[grpNum].numberSet + faceGroupEdges[compareNum].numberSet)) do ( faceGroupEdges[grpNum] = combinedEdges faceGroups[grpNum] += faceGroups[compareNum] existingGroups[compareNum] = false repeatLoop = true ) ) ) ) -- Keep only the combined facegroups: local faceGroups = for n = 1 to faceGroups.count where existingGroups[n] collect faceGroups[n] struct faceEdgeData (faceNum, pos, faceEdges, faceVerts = #(1,2,3,4), neighbours, xSize, ySize) for faceNums in faceGroups do ( -- Work out 2d positions for each quad: local faceEdgeBits = for faceNum in faceNums collect (faceEdges[faceNum] as bitarray) -- Make array with initial face: local faceInfoArray = for faceNum in faceNums collect (faceEdgeData faceNum:faceNum faceEdges:faceEdges[faceNum]) faceInfoArray[1].pos = [0,0] local doneFaces = #{} local toDofaces = #{1} local minPos = [0,0] local maxPos = [0,0] local adjFaceNum, adjFaceInfo, adjPos, adjFaceEdges, newEdgeList, neighbourNum, rotateVal while (toDofaces.numberSet != 0) do ( for toDoNum in toDofaces do ( toDofaces[toDoNum] = false doneFaces[toDoNum] = true local faceInfo = faceInfoArray[toDoNum] faceInfo.xSize = 0.5 * (edgeLengths[faceInfo.faceEdges[1]] + edgeLengths[faceInfo.faceEdges[3]]) faceInfo.ySize = 0.5 * (edgeLengths[faceInfo.faceEdges[2]] + edgeLengths[faceInfo.faceEdges[4]]) neighbourNum = 0 faceInfo.neighbours = for edgeNum in faceInfo.faceEdges collect ( neighbourNum += 1 -- Find faces sharing this face's edges: adjFaceNum = undefined for n = 1 to faceInfoArray.count where faceEdgeBits[n][edgeNum] and (n != toDoNum) while (adjFaceNum == undefined) do ( adjFaceNum = n ) -- Set up neighbour-face info, if it hasn't been done already: if (adjFaceNum != undefined) and not doneFaces[adjFaceNum] and not toDofaces[adjFaceNum] do ( toDofaces[adjFaceNum] = true adjFaceInfo = faceInfoArray[adjFaceNum] adjFaceEdges = adjFaceInfo.faceEdges -- Rotate neighbour edge-lists to match source-face's alignment: rotateVal = (findItem adjFaceEdges edgeNum) - #(3,4,1,2)[neighbourNum] if (rotateVal != 0) do ( rotateVal = (mod (4 + rotateVal) 4) as integer newEdgeList = for n = (rotateVal + 1) to 4 collect adjFaceEdges[n] join newEdgeList (for n = 1 to rotateVal collect adjFaceEdges[n]) adjFaceInfo.faceEdges = newEdgeList adjFaceInfo.faceVerts = case rotateVal of ( 1:#(2,3,4,1) 2:#(3,4,1,2) 3:#(4,1,2,3) ) ) -- Set neighbour's grid-position: adjPos = faceInfo.pos + #([0,-1],[1,0],[0,1],[-1,0])[neighbourNum] adjFaceInfo.pos = adjPos if (adjPos.x < minPos.x) do (minPos.x = adjPos.x) if (adjPos.y < minPos.y) do (minPos.y = adjPos.y) if (adjPos.x > maxPos.x) do (maxPos.x = adjPos.x) if (adjPos.y > maxPos.y) do (maxPos.y = adjPos.y) ) adjFaceNum ) ) ) -- Get rid of faces that weren't processed for some reason: for item in faceInfoArray where item.pos == undefined do useFaces[item.faceNum] = false faceInfoArray = for item in faceInfoArray where item.pos != undefined collect item -- Shift face-array position-values so that minimum is at [1,1] for item in faceInfoArray do ( item.pos -= (minPos - [1,1]) ) maxPos -= (minPos - [1,1]) -- Get heights/widths for each quad column/row: local columnWidths = for n = 1 to maxPos.x collect #() local rowHeights = for n = 1 to maxPos.y collect #() for item in faceInfoArray do ( append columnWidths[item.pos.x] item.xSize append rowHeights[item.pos.y] item.ySize ) -- Average the quad colum/row sizes: local sumSize columnWidths = for n = 1 to columnWidths.count collect ( sumSize = 0.0 for item in columnWidths[n] do ( sumSize += item ) sumSize / columnWidths[n].count ) rowHeights = for n = 1 to rowHeights.count collect ( sumSize = 0.0 for item in rowHeights[n] do ( sumSize += item ) sumSize / rowHeights[n].count ) local xPositions = #(0.0) local yPositions = #(0.0) for n = 1 to columnWidths.count do ( append xPositions (xPositions[n] + columnWidths[n]) ) for n = 1 to rowHeights.count do ( append yPositions (yPositions[n] + rowHeights[n]) ) local vertsToWeld = #{} -- Apply new grid-positions to UV verts: local minVertPos, maxVertPos, vertPositions for faceInfo in faceInfoArray do ( minVertPos = [xPositions[faceInfo.pos.x], yPositions[faceInfo.pos.y],0] maxVertPos = [xPositions[faceInfo.pos.x + 1], yPositions[faceInfo.pos.y + 1],0] vertPositions = #(minVertPos, [maxVertPos.x ,minVertPos.y, 0], maxVertPos, [minVertPos.x ,maxVertPos.y, 0]) for n = 1 to 4 do ( newUVmod.setFaceVertex vertPositions[n] faceInfo.faceNum faceInfo.faceVerts[n] false vertsToWeld[newUVmod.getVertexIndexFromFace faceInfo.faceNum n] = true ) ) newUVmod.selectVertices vertsToWeld newUVmod.weldSelected() ) -- Select the affected faces newUVmod.selectPolygonsUpdate useFaces true newUVmod.setTVSubObjectMode 3 redrawViews() ) ) OK )