from awSupportApi import Vector, AffineMatrix, Point
from DialogInterpreter import DialogFactory
from GenericMenu import GenericMenu
from GridArrangeDialog import GridArrangeDialog
from Message import Message
from MessageInterpreter import MessageInterpreter
from MessageRegistry import theMessageRegistry
from UserCustomization import UserCustomBase, CustomInfo
from RunInUiThread import RunInUiThread
from RTFapi import Node
from SceneGraphUtilities import ComputeBoundingBox
def instantiate():
return PositionCustomization()
class PositionCustomization(UserCustomBase):
def __init__(self):
self.__myInterpreter = PositionCustomInterpreter()
def appendMenu(self, menuInterpreter):
menu = menuInterpreter.appendMenu(ToolsMenu)
def getInterpreter(self, isInteractive):
return self.__myInterpreter
class ToolsMenu(GenericMenu):
def __init__(self, parentWindow):
GenericMenu.__init__(self, parentWindow, menuId=u'CarCustom')
self.__myDocumentLoaded = False
self.__mySpectating = False
self.__myGridId = self.appendItem('Arrange items in a grid...', self.__onShowGridDialog)
self.__updateMenu()
def __onShowGridDialog(self, event):
self.sendMessage('SHOW_GRID_DIALOG', ())
def getLabel(self):
return 'Tools'
def __updateMenu(self):
enableStates = {}
enableStates[self.__myGridId] = self.__myDocumentLoaded and not self.__mySpectating
self.enableMenuItems(enableStates)
def CLIENT_CONNECTION_STATUS(self, message):
(self.__mySpectating, statusMessage) = message.data
RunInUiThread(self.__updateMenu)
def APPLICATION_CLOSE_SCENE(self, message):
self.__myDocumentLoaded = False
RunInUiThread(self.__updateMenu)
def DOCUMENT_LOADED( self, message ):
self.__myDocumentLoaded = True
RunInUiThread(self.__updateMenu)
class PositionCustomInterpreter(MessageInterpreter):
def __init__(self):
MessageInterpreter.__init__(self)
def SHOW_GRID_DIALOG(self, message):
if DialogFactory.ready():
DialogFactory.instance().show(GridArrangeDialog)
def __calculateBoundingBoxOffset(self, nodeId):
"""
Calculates the vector from the location of the object in worldspace
to the center of it's bounding box
"""
node = Node.getNodeById(nodeId)
matrix = AffineMatrix()
node.getWorldTransform(matrix, True)
translate = Point(matrix.m[9], matrix.m[10], matrix.m[11])
bbox = ComputeBoundingBox([node])
if not bbox.isBounded():
return Vector(0.0, 0.0, 0.0)
boxCenter = bbox.mid()
return Vector(translate[0] - boxCenter[0],
translate[1] - boxCenter[1],
translate[2] - boxCenter[2])
def GRID_ARRANGE(self, message):
(objects, rows, columns, layout) = message.data
(rowVector, columnVector, gridCenter) = layout
currentRow = Vector(gridCenter)
rowStart = Vector(rowVector)
rowStart *= (rows - 1)/2.0
columnStart = Vector(columnVector)
columnStart *= (columns - 1)/2.0
currentRow -= rowStart
currentRow -= columnStart
currentColumn = Vector(currentRow)
for (i, objectID) in enumerate(objects):
boxOffset = self.__calculateBoundingBoxOffset(objectID)
boxOffset += currentColumn
self.sendMessage("TRANSLATE_WORLDSPACE",
(boxOffset[0], boxOffset[1], boxOffset[2], False, (objectID, )) )
currentColumn += columnVector
if (i + 1) % columns == 0:
currentRow += rowVector
currentColumn = Vector(currentRow)
SHOW_GRID_DIALOG_Doc = \
[(
"""
Show's the "Arrange Items in a Grid" dialog box.
"""
),
[],
]
GRID_ARRANGE_DIALOG_Doc = \
[(
"""
Arranges the specified nodes into the specified 2D grid layout.
The correct translation offset will be calculated so that each node's
bounding box will be at the center of its grid point.
"""
),
[[("objects"),("A list of node ids to arrange in the grid.")],
[("rows"), ("The number of rows in the grid.")],
[("columns"), ("The number of columns in the grid.")],
[("layout"), (
"""
Contains a tuple consisting of: the vector to add between rows, the vector to
add between columns, and a vector representing worldspace location of the
center of the grid.
""")]
]
]
messages = (
('SHOW_GRID_DIALOG', 0, (), SHOW_GRID_DIALOG_Doc ),
('GRID_ARRANGE', Message.kUndoable, (tuple, int, int, tuple), GRID_ARRANGE_DIALOG_Doc ),
)
for message in messages:
theMessageRegistry.register( message[0], message[2], message[1], message[3] )
def info():
customInfo = CustomInfo()
customInfo.vendor = 'Autodesk'
customInfo.version = '1.0'
customInfo.api = '2013'
customInfo.shortInfo = "Arrange selected items in grid patterns."
customInfo.longInfo = \
"""You will get a "Tools" menu added to the Showcase menu bar containing the "Arrange items in a \
grid..." menu item. This menu item opens a dialog box which allows the user to arrange selected \
items in grid patterns.
"""
return customInfo