User Tools

Site Tools


Sidebar

Dan's Wiki

DokuWiki Instructions (local) DokuWiki Manual
Site Checker (Orphans Wanted)

Edit Sidebar

projects:houseofcards:workingpython

Working Python Script - Spread Picture, and set card faces

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()
projects/houseofcards/workingpython.txt · Last modified: 2016/07/21 17:19 by dwheele