The original code is at c:\projects\HouseOfCards\pythonscript.txt
import bpy import itertools import random bpy.ops.object.mode_set(mode='OBJECT') cardPointer = 53 # start past the start of the deck cardDeck = [] # ob = bpy.data.objects["Panel"]; # me = ob.data; # This is from pythonScript.txt. print ("\n\n") # some space def getObjectNameAndUVCoordinatesFromOrdinal(ord, quantityX, quantityY, prefix="Panel", reverseX=False): xpos = ord % quantityX if (reverseX): xpos = quantityX - xpos - 1 ypos = (ord - (ord % quantityX)) / float(quantityX) name = "%s.%s" % (prefix, str(ord + 1).zfill(3)) return {'name':name, 'xpos':xpos, 'ypos':ypos} #for i in range(20): # result = getObjectNameAndUVCoordinatesFromOrdinal(i, 4, 5) # print ("Result %i, %s, %f, %f" % (i, result['name'], result['xpos']f, result['ypos'])) # vertexGroupName is something like "Card Face" or "Card Back" def changeUVsForObjectFaceContainingVertexGroup(ob, vertexGroupName, xStart, yStart, xCount, yCount): if (xStart < 0): print("xStart ", xStart, " must be 0 or greater"); return if (xStart >= xCount): print("xStart ", xStart, " must be less than xCount ", xCount); return if (yStart < 0): print("yStart ", yStart, " must be 0 or greater"); return if (yStart >= yCount): print("yStart ", yStart, " must be less than yCount ", yCount); return if (xCount < 1): print("xCount ", xCount, " must be 1 or greater"); return if (yCount < 1): print("yCount ", yCount, " must be 1 or greater"); return debug = False # First, get list of Vertexes in Vertex Group groupIndex = -1 # This is an Object with a Mesh, see if it has the supported group name for i in range(0, len(ob.vertex_groups)): group = ob.vertex_groups[i] if group.name == vertexGroupName: groupIndex = i # if we didn't find it, exit if (groupIndex < 0): raise ValueError("VertexGroup %s not found" % vertexGroupName) # Now access the vertices that are assigned to this group bmVertGroupMembers = [] for v in ob.data.vertices: for vertGroup in v.groups: if vertGroup.group == groupIndex: print("Vertex %d is part of group."%(v.index)) # bmVertGroupMembers.append(v) bmVertGroupMembers.append(v.index) # Sort into integer order (because they are integers bmVertGroupMembers.sort() if (debug): print ("Group members array: ", bmVertGroupMembers) # at this point, we have a list of vertices in bmVertGroupMembers # belonging to group vertexGroupName, with index groupIndex # Now let's iterate through polygons, to find the one with the matching # vertices # We have to do this, because the UVs are associated with a polygon, # not vertices me = ob.data; for f in me.polygons: if (debug): print("Polygon", f.index, "from loop index", f.loop_start, "and length", f.loop_total) polyVertIndexList = [] for i in f.loop_indices: # <-- python Range object with the proper indices already set l = me.loops[i] # The loop entry this polygon point refers to v = me.vertices[l.vertex_index] # The vertex data that loop entry refers to if (debug): print("\tLoop index", l.index, "points to vertex index", l.vertex_index, \ "at position", v.co) for j,ul in enumerate(me.uv_layers): if (debug): print("\t\tUV Map", j, "has coordinates", ul.data[l.index].uv, \ "for this loop index") ul = me.uv_layers[0] myUv = ul.data[l.index].uv if (len(me.uv_layers) > 0): polyVertIndexList.append(l.vertex_index) polyVertIndexList.sort() if (polyVertIndexList != bmVertGroupMembers): continue # If we get here, we found the correct polygon, in "f" uvsToAdjust = [] for i in f.loop_indices: # <-- python Range object with the proper indices already set l = me.loops[i] # The loop entry this polygon point refers to v = me.vertices[l.vertex_index] # The vertex data that loop entry refers to print("\tFor found frame, loop index", l.index, "points to vertex index", l.vertex_index, \ "at position", v.co) # for j,ul in enumerate(me.uv_layers): # print("\t\tUV Map", j, "has coordinates", ul.data[l.index].uv, \ # "for this loop index") ul = me.uv_layers[0] myUv = ul.data[l.index].uv if (debug): print("\t\tFound UV Map, loop index ", i, "has coordinates", myUv, " ", myUv[0]) # if (myUv[1] > .67 and myUv[1] < .68): # myUv[1] = myUv[1] - .1 uvsToAdjust.append(myUv) # At this point we have an array of uvsToAdjust # We need to order them in a predictable way # We need to find the center of the "square" then # count rotation points based on if x or y is greater # than the center lowX = 2 highX = 0 lowY = 2 highY = 0 for uv0 in uvsToAdjust: if (uv0[0] < lowX): lowX = uv0[0] if (uv0[0] > highX): highX = uv0[0] if (uv0[1] < lowY): lowY = uv0[1] if (uv0[1] > highY): highY = uv0[1] centerX = (highX + lowX)/2.0 centerY = (highY + lowY)/2.0 # print("Unadjusted ", uvsToAdjust, "lowX", lowX, "highX", highX, "lowy", lowY, "highY", \ # highY, " centerX ", centerX, "centerY ", centerY) for i in range(len(uvsToAdjust) - 1): for j in range(i + 1, len(uvsToAdjust)): if (rotationPoints(uvsToAdjust[j][0], uvsToAdjust[j][1], centerX, centerY) > \ rotationPoints(uvsToAdjust[i][0], uvsToAdjust[i][1], centerX, centerY)): # Trade them uv2 = uvsToAdjust[i] uvsToAdjust[i] = uvsToAdjust[j] uvsToAdjust[j] = uv2 # print("Sorted ", uvsToAdjust) # At this point we have an array with the uvs in this order # 0 = upper right # 1 = lower right # 2 = upper left # 3 = lower left # Start, yStart, xCount, yCount # Now, move them to their new positions # The first dimension is the UV number, second is the vector coordinate 0=x, 1=y uvsToAdjust[0][0] = (xStart + 1)/xCount uvsToAdjust[1][0] = (xStart + 1)/xCount uvsToAdjust[2][0] = xStart/xCount uvsToAdjust[3][0] = xStart/xCount uvsToAdjust[0][1] = (yStart + 1)/yCount uvsToAdjust[1][1] = yStart/yCount uvsToAdjust[2][1] = (yStart + 1)/yCount uvsToAdjust[3][1] = yStart/yCount # print("Calculated ", uvsToAdjust) def rotationPoints(xPos, yPos, centerX, centerY): points = 0 if (xPos > centerX): points = points + 3 if (yPos > centerY): points = points + 2 return points def run48CardBackTest(): for i in range(192): result = getObjectNameAndUVCoordinatesFromOrdinal(i, 16, 12, "Panel", True) print ("Result %i, %s, %f, %f" % (i, result['name'], result['xpos'], result['ypos'])) ob = bpy.data.objects[result['name']] changeUVsForObjectFaceContainingVertexGroup(ob, "Card Back", result['xpos'], result['ypos'], 16, 12) # returns card which is a a list of two numbers # [0] = 0 through 3 (suit) # [1] = 1 through 13 (rank) # Handles getting a new deck when one runs out def getRandomCard(): global cardPointer global cardDeck if (cardPointer > 51): # make new deck cardDeck =list(itertools.product(range(0,4), range(1,14))) # shuffle it random.shuffle(cardDeck) # point pointer back to start cardPointer = 0 card = (cardDeck[cardPointer][0], cardDeck[cardPointer][1]) cardPointer = cardPointer + 1 return card def testGetRandomCard(): for i in range(1, 81): card = getRandomCard() if (i == 53): print("New Deck++++") print(card) def applyCardFaces(): for i in range(192): result = getObjectNameAndUVCoordinatesFromOrdinal(i, 16, 12, "Panel", False) print ("Result %i, %s, %f, %f" % (i, result['name'], result['xpos'], result['ypos'])) ob = bpy.data.objects[result['name']] card = getRandomCard(); # print("Card ", card) # following calculates UVs for Card face graphic changeUVsForObjectFaceContainingVertexGroup(ob, "Card Front", card[0], card[1], 5, 13) # testGetRandomCard() # run48CardBackTest() applyCardFaces()