mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
*** empty log message ***
This commit is contained in:
parent
cbb60ab16e
commit
2b13cd507b
@ -35,7 +35,7 @@ class DirectSession(PandaObject):
|
||||
self.drList = DisplayRegionList()
|
||||
self.iRayList = map(lambda x: x.iRay, self.drList)
|
||||
self.dr = self.drList[0]
|
||||
self.camera = self.dr.cam
|
||||
self.camera = base.cameraList[0]
|
||||
self.iRay = self.dr.iRay
|
||||
|
||||
self.cameraControl = DirectCameraControl()
|
||||
|
@ -4,6 +4,7 @@ from PGTop import *
|
||||
from PGButton import *
|
||||
from PGItem import *
|
||||
from PGFrameStyle import *
|
||||
import types
|
||||
import __builtin__
|
||||
|
||||
NORMAL = 'normal'
|
||||
@ -26,7 +27,9 @@ __builtin__.guiTop = aspect2d.attachNewNode(PGTop('DirectGuiTop'))
|
||||
guiTop.node().setMouseWatcher(base.mouseWatcher.node())
|
||||
|
||||
class DirectGuiObject(PandaObject):
|
||||
def __init__(self, optiondefs, **kw):
|
||||
def __init__(self, optiondefs, dynamicGroups, **kw):
|
||||
# Default id of all gui object, subclasses should override this
|
||||
self.guiId = 'guiObject'
|
||||
# Mapping from each megawidget option to a list of information
|
||||
# about the option
|
||||
# - default value
|
||||
@ -51,6 +54,10 @@ class DirectGuiObject(PandaObject):
|
||||
# - the name of the component group of this component, if any
|
||||
self.__componentInfo = {}
|
||||
|
||||
# Mapping from alias names to the names of components or
|
||||
# sub-components.
|
||||
self.__componentAliases = {}
|
||||
|
||||
# Contains information about the keywords provided to the
|
||||
# constructor. It is a mapping from the keyword to a tuple
|
||||
# containing:
|
||||
@ -65,9 +72,16 @@ class DirectGuiObject(PandaObject):
|
||||
# unused options given to the constructor.
|
||||
#
|
||||
# self._constructorKeywords = {}
|
||||
self.defineoptions(kw, optiondefs)
|
||||
|
||||
# List of dynamic component groups. If a group is included in
|
||||
# this list, then it not an error if a keyword argument for
|
||||
# the group is given to the constructor or to configure(), but
|
||||
# no components with this group have been created.
|
||||
# self._dynamicGroups = ()
|
||||
|
||||
self.defineoptions(kw, optiondefs, dynamicGroups)
|
||||
|
||||
def defineoptions(self, keywords, optionDefs):
|
||||
def defineoptions(self, keywords, optionDefs, dynamicGroups = ()):
|
||||
# Create options, providing the default value and the method
|
||||
# to call when the value is changed. If any option created by
|
||||
# base classes has the same name as one in <optionDefs>, the
|
||||
@ -79,9 +93,14 @@ class DirectGuiObject(PandaObject):
|
||||
if not hasattr(self, '_constructorKeywords'):
|
||||
tmp = {}
|
||||
for option, value in keywords.items():
|
||||
tmp[option] = value
|
||||
tmp[option] = [value, 0]
|
||||
self._constructorKeywords = tmp
|
||||
self._optionInfo = {}
|
||||
# Initialize dictionary of dynamic groups
|
||||
if not hasattr(self, '_dynamicGroups'):
|
||||
self._dynamicGroups = ()
|
||||
self._dynamicGroups = self._dynamicGroups + tuple(dynamicGroups)
|
||||
# Reconcile command line and default options
|
||||
self.addoptions(optionDefs)
|
||||
|
||||
def addoptions(self, optionDefs):
|
||||
@ -105,7 +124,7 @@ class DirectGuiObject(PandaObject):
|
||||
if not optionInfo_has_key(name):
|
||||
if keywords_has_key(name):
|
||||
# Overridden by keyword, use keyword value
|
||||
value = keywords[name]
|
||||
value = keywords[name][0]
|
||||
optionInfo[name] = [default, value, function]
|
||||
del keywords[name]
|
||||
else:
|
||||
@ -127,8 +146,15 @@ class DirectGuiObject(PandaObject):
|
||||
unusedOptions = []
|
||||
keywords = self._constructorKeywords
|
||||
for name in keywords.keys():
|
||||
# This keyword argument has not been used.
|
||||
unusedOptions.append(name)
|
||||
print name
|
||||
used = keywords[name][1]
|
||||
if not used:
|
||||
# This keyword argument has not been used. If it
|
||||
# does not refer to a dynamic group, mark it as
|
||||
# unused.
|
||||
index = string.find(name, '_')
|
||||
if index < 0 or name[:index] not in self._dynamicGroups:
|
||||
unusedOptions.append(name)
|
||||
self._constructorKeywords = {}
|
||||
if len(unusedOptions) > 0:
|
||||
if len(unusedOptions) == 1:
|
||||
@ -195,6 +221,8 @@ class DirectGuiObject(PandaObject):
|
||||
optionInfo_has_key = optionInfo.has_key
|
||||
componentInfo = self.__componentInfo
|
||||
componentInfo_has_key = componentInfo.has_key
|
||||
componentAliases = self.__componentAliases
|
||||
componentAliases_has_key = componentAliases.has_key
|
||||
VALUE = _OPT_VALUE
|
||||
FUNCTION = _OPT_FUNCTION
|
||||
|
||||
@ -227,17 +255,38 @@ class DirectGuiObject(PandaObject):
|
||||
# This option may be of the form <component>_<option>.
|
||||
component = option[:index]
|
||||
componentOption = option[(index + 1):]
|
||||
|
||||
# Expand component alias
|
||||
if componentAliases_has_key(component):
|
||||
component, subComponent = componentAliases[component]
|
||||
if subComponent is not None:
|
||||
componentOption = subComponent + '_' \
|
||||
+ componentOption
|
||||
|
||||
# Expand option string to write on error
|
||||
option = component + '_' + componentOption
|
||||
|
||||
# Does this component exist
|
||||
if componentInfo_has_key(component):
|
||||
# Get the configure func for the named component
|
||||
componentConfigFunc = componentInfo[component][1]
|
||||
componentConfigFuncs = [componentInfo[component][1]]
|
||||
else:
|
||||
componentConfigFunc = None
|
||||
raise KeyError, 'Unknown option "' + option + \
|
||||
'" for ' + self.__class__.__name__
|
||||
# Check if this is a group name and configure all
|
||||
# components in the group.
|
||||
componentConfigFuncs = []
|
||||
for info in componentInfo.values():
|
||||
if info[4] == component:
|
||||
componentConfigFuncs.append(info[1])
|
||||
|
||||
# Add the configure method and option/value to dictionary.
|
||||
if componentConfigFunc:
|
||||
if len(componentConfigFuncs) == 0 and \
|
||||
component not in self._dynamicGroups:
|
||||
raise KeyError, 'Unknown option "' + option + \
|
||||
'" for ' + self.__class__.__name__
|
||||
|
||||
# Add the configure method(s) (may be more than
|
||||
# one if this is configuring a component group)
|
||||
# and option/value to dictionary.
|
||||
for componentConfigFunc in componentConfigFuncs:
|
||||
if not indirectOptions_has_key(componentConfigFunc):
|
||||
indirectOptions[componentConfigFunc] = {}
|
||||
indirectOptions[componentConfigFunc][componentOption] \
|
||||
@ -273,10 +322,27 @@ class DirectGuiObject(PandaObject):
|
||||
component = option[:index]
|
||||
componentOption = option[(index + 1):]
|
||||
|
||||
# Expand component alias
|
||||
if self.__componentAliases.has_key(component):
|
||||
component, subComponent = self.__componentAliases[
|
||||
component]
|
||||
if subComponent is not None:
|
||||
componentOption = subComponent + '_' + componentOption
|
||||
|
||||
# Expand option string to write on error
|
||||
option = component + '_' + componentOption
|
||||
|
||||
if self.__componentInfo.has_key(component):
|
||||
# Call cget on the component.
|
||||
componentCget = self.__componentInfo[component][3]
|
||||
return componentCget(componentOption)
|
||||
else:
|
||||
# If this is a group name, call cget for one of
|
||||
# the components in the group.
|
||||
for info in self.__componentInfo.values():
|
||||
if info[4] == component:
|
||||
componentCget = info[3]
|
||||
return componentCget(componentOption)
|
||||
|
||||
# Option not found
|
||||
raise KeyError, 'Unknown option "' + option + \
|
||||
@ -285,7 +351,8 @@ class DirectGuiObject(PandaObject):
|
||||
# Allow index style refererences
|
||||
__getitem__ = cget
|
||||
|
||||
def createcomponent(self, componentName, widgetClass, *widgetArgs, **kw):
|
||||
def createcomponent(self, componentName, componentAliases, componentGroup,
|
||||
widgetClass, *widgetArgs, **kw):
|
||||
"""Create a component (during construction or later)."""
|
||||
# Check for invalid component name
|
||||
if '_' in componentName:
|
||||
@ -296,6 +363,29 @@ class DirectGuiObject(PandaObject):
|
||||
keywords = self._constructorKeywords
|
||||
else:
|
||||
keywords = {}
|
||||
|
||||
for alias, component in componentAliases:
|
||||
# Create aliases to the component and its sub-components.
|
||||
index = string.find(component, '_')
|
||||
if index < 0:
|
||||
self.__componentAliases[alias] = (component, None)
|
||||
else:
|
||||
mainComponent = component[:index]
|
||||
subComponent = component[(index + 1):]
|
||||
self.__componentAliases[alias] = (mainComponent, subComponent)
|
||||
|
||||
# Remove aliases from the constructor keyword arguments by
|
||||
# replacing any keyword arguments that begin with *alias*
|
||||
# with corresponding keys beginning with *component*.
|
||||
|
||||
alias = alias + '_'
|
||||
aliasLen = len(alias)
|
||||
for option in keywords.keys():
|
||||
if len(option) > aliasLen and option[:aliasLen] == alias:
|
||||
newkey = component + '_' + option[aliasLen:]
|
||||
keywords[newkey] = keywords[option]
|
||||
del keywords[option]
|
||||
|
||||
# Find any keyword arguments for this component
|
||||
componentPrefix = componentName + '_'
|
||||
nameLen = len(componentPrefix)
|
||||
@ -303,9 +393,22 @@ class DirectGuiObject(PandaObject):
|
||||
if len(option) > nameLen and option[:nameLen] == componentPrefix:
|
||||
# The keyword argument refers to this component, so add
|
||||
# this to the options to use when constructing the widget.
|
||||
kw[option[nameLen:]] = keywords[option]
|
||||
kw[option[nameLen:]] = keywords[option][0]
|
||||
# And delete it from main construction keywords
|
||||
del keywords[option]
|
||||
else:
|
||||
# Check if this keyword argument refers to the group
|
||||
# of this component. If so, add this to the options
|
||||
# to use when constructing the widget. Mark the
|
||||
# keyword argument as being used, but do not remove it
|
||||
# since it may be required when creating another
|
||||
# component.
|
||||
index = string.find(option, '_')
|
||||
if index >= 0 and componentGroup == option[:index]:
|
||||
rest = option[(index + 1):]
|
||||
kw[rest] = keywords[option][0]
|
||||
keywords[option][1] = 1
|
||||
|
||||
# Return None if no widget class is specified
|
||||
if widgetClass is None:
|
||||
return None
|
||||
@ -319,7 +422,7 @@ class DirectGuiObject(PandaObject):
|
||||
widget = apply(widgetClass, widgetArgs, kw)
|
||||
componentClass = widget.__class__.__name__
|
||||
self.__componentInfo[componentName] = (widget, widget.configure,
|
||||
componentClass, widget.cget)
|
||||
componentClass, widget.cget, componentGroup)
|
||||
return widget
|
||||
|
||||
def component(self, name):
|
||||
@ -337,6 +440,16 @@ class DirectGuiObject(PandaObject):
|
||||
component = name[:index]
|
||||
remainingComponents = name[(index + 1):]
|
||||
|
||||
# Expand component alias
|
||||
if self.__componentAliases.has_key(component):
|
||||
component, subComponent = self.__componentAliases[component]
|
||||
if subComponent is not None:
|
||||
if remainingComponents is None:
|
||||
remainingComponents = subComponent
|
||||
else:
|
||||
remainingComponents = subComponent + '_' \
|
||||
+ remainingComponents
|
||||
|
||||
widget = self.__componentInfo[component][0]
|
||||
if remainingComponents is None:
|
||||
return widget
|
||||
@ -367,10 +480,10 @@ class DirectGuiObject(PandaObject):
|
||||
self._optionInfo = {}
|
||||
|
||||
def bind(self, sequence, command):
|
||||
self.accept(self.idString + '_' + sequence, command)
|
||||
self.accept(sequence + '-' + self.guiId, command)
|
||||
|
||||
def unbind(self, sequence):
|
||||
self.ignore(self.idString + '_' + sequence)
|
||||
self.ignore(sequence + '-' + self.guiId)
|
||||
|
||||
class DirectButton(DirectGuiObject, NodePath):
|
||||
def __init__(self, parent = guiTop, **kw):
|
||||
@ -386,22 +499,25 @@ class DirectButton(DirectGuiObject, NodePath):
|
||||
# - a VBase4(L,R,B,T)
|
||||
# - a bounding box object
|
||||
optiondefs = (
|
||||
('image', None, self.setImage),
|
||||
('geom', None, self.setGeom),
|
||||
('text', '', self.setText),
|
||||
('geom', None, None),
|
||||
('image', None, None),
|
||||
('command', None, self.setCommand),
|
||||
('relief', FLAT, self.setRelief),
|
||||
('frameColor', (1,1,1,1), self.setFrameColor),
|
||||
('borderWidth', (.1,.1), self.setBorderWidth),
|
||||
('frameSize', None, self.setFrameSize),
|
||||
('pressEffect', 1, None),
|
||||
('padSX', 1.2, None),
|
||||
('padSZ', 1.1, None),
|
||||
('pos', None, None),
|
||||
('scale', None, None),
|
||||
('state', NORMAL, self.setState),
|
||||
('command', None, None),
|
||||
('rolloverSound', None, None),
|
||||
('clickSound', None, None),
|
||||
)
|
||||
# Update options to reflect keyword parameters
|
||||
apply(DirectGuiObject.__init__, (self, optiondefs), kw)
|
||||
apply(DirectGuiObject.__init__, (self, optiondefs, ('text',)), kw)
|
||||
# Initialize the superclass
|
||||
NodePath.__init__(self)
|
||||
# Create a button
|
||||
@ -415,18 +531,26 @@ class DirectButton(DirectGuiObject, NodePath):
|
||||
self.stateNodePath = []
|
||||
for i in range(4):
|
||||
self.stateNodePath.append(NodePath(self.guiItem.getStateDef(i)))
|
||||
# Adjust frame
|
||||
self.frameStyle = [PGFrameStyle(),
|
||||
PGFrameStyle(),
|
||||
PGFrameStyle(),
|
||||
PGFrameStyle()]
|
||||
if self['pressEffect']:
|
||||
np = self.stateNodePath[1].attachNewNode('pressEffect')
|
||||
np.setScale(0.98)
|
||||
self.stateNodePath[1] = np
|
||||
# Initialize frame style
|
||||
self.frameStyle = []
|
||||
for i in range(4):
|
||||
self.frameStyle.append(PGFrameStyle())
|
||||
# For holding bounds info
|
||||
self.ll = Point3(0)
|
||||
self.ur = Point3(0)
|
||||
# Call initialization functions if necessary
|
||||
# To avoid doing things redundantly
|
||||
self.fInit = 1
|
||||
# Call initialization functions if necessary
|
||||
self.initialiseoptions(DirectButton)
|
||||
self.fInit = 0
|
||||
# Allow changes to take effect
|
||||
self.updateFrameStyle()
|
||||
self.setFrameSize()
|
||||
if not self['frameSize']:
|
||||
self.setFrameSize()
|
||||
# Update pose
|
||||
if self['pos']:
|
||||
if type(self['pos']) == type(()):
|
||||
@ -463,15 +587,32 @@ class DirectButton(DirectGuiObject, NodePath):
|
||||
if not self.fInit:
|
||||
self.updateFrameStyle()
|
||||
|
||||
def setFrameSize(self):
|
||||
def resetFrameSize(self):
|
||||
self.setFrameSize(fClearFrame = 1)
|
||||
|
||||
def setFrameSize(self, fClearFrame = 0):
|
||||
if self['frameSize']:
|
||||
# Use user specified bounds
|
||||
bounds = self['frameSize']
|
||||
self.guiItem.setFrame(bounds[0], bounds[1],
|
||||
bounds[2], bounds[3])
|
||||
else:
|
||||
bounds = self.component('text0').textNode.getCardActual()
|
||||
self.guiItem.setFrame(bounds[0] - 0.4, bounds[1] + 0.4,
|
||||
bounds[2] - 0.15, bounds[3] + 0.15)
|
||||
# Use ready state to compute bounds
|
||||
frameType = self.frameStyle[0].getType()
|
||||
if fClearFrame and (frameType != PGFrameStyle.TNone):
|
||||
self.frameStyle[0].setType(PGFrameStyle.TNone)
|
||||
self.guiItem.setFrameStyle(0, self.frameStyle[0])
|
||||
# To force an update of the button
|
||||
self.guiItem.getStateDef(0)
|
||||
# Clear out frame before computing bounds
|
||||
self.stateNodePath[0].calcTightBounds(self.ll, self.ur)
|
||||
# Scale bounds to give a pad around graphics
|
||||
bounds = (self.ll[0] * self['padSX'], self.ur[0] * self['padSX'],
|
||||
self.ll[2] * self['padSZ'], self.ur[2] * self['padSZ'])
|
||||
# Restore frame style if necessary
|
||||
if (frameType != PGFrameStyle.TNone):
|
||||
self.frameStyle[0].setType(frameType)
|
||||
self.guiItem.setFrameStyle(0, self.frameStyle[0])
|
||||
# Set frame to new dimensions
|
||||
self.guiItem.setFrame(bounds[0], bounds[1],bounds[2], bounds[3])
|
||||
|
||||
def setFrameColor(self):
|
||||
color = self['frameColor']
|
||||
@ -488,6 +629,11 @@ class DirectButton(DirectGuiObject, NodePath):
|
||||
self.updateFrameStyle()
|
||||
|
||||
def setText(self):
|
||||
if not self['text']:
|
||||
print "No Text"
|
||||
return
|
||||
else:
|
||||
print "SetText"
|
||||
if ((type(self['text']) == type(())) or
|
||||
(type(self['text']) == type([]))):
|
||||
text = self['text']
|
||||
@ -497,13 +643,59 @@ class DirectButton(DirectGuiObject, NodePath):
|
||||
component = 'text' + `i`
|
||||
if not self.hascomponent(component):
|
||||
self.createcomponent(
|
||||
component, OnscreenText.OnscreenText,
|
||||
component, (), 'text',
|
||||
OnscreenText.OnscreenText,
|
||||
(), parent = self.stateNodePath[i],
|
||||
text = text[i], scale = 1,
|
||||
mayChange = 1)
|
||||
else:
|
||||
self[component + '_text'] = text[i]
|
||||
|
||||
def setGeom(self):
|
||||
if not self['geom']:
|
||||
print "No Geom"
|
||||
return
|
||||
else:
|
||||
print "SetGeom"
|
||||
if ((type(self['geom']) == type(())) or
|
||||
(type(self['geom']) == type([]))):
|
||||
geom = self['geom']
|
||||
else:
|
||||
geom = (self['geom'],) * 4
|
||||
for i in range(4):
|
||||
component = 'geom' + `i`
|
||||
if not self.hascomponent(component):
|
||||
self.createcomponent(
|
||||
component, (), 'geom',
|
||||
OnscreenGeom,
|
||||
(), parent = self.stateNodePath[i],
|
||||
geom = geom[i], scale = 1)
|
||||
else:
|
||||
self[component + '_geom'] = geom[i]
|
||||
|
||||
def setImage(self):
|
||||
if not self['image']:
|
||||
print "No Image"
|
||||
return
|
||||
else:
|
||||
print "SetImage"
|
||||
if ((type(self['image']) == type(())) or
|
||||
(type(self['image']) == type([]))):
|
||||
if len(self['image']) == 4:
|
||||
image = self['image']
|
||||
else:
|
||||
image = (self['image'],) * 4
|
||||
for i in range(4):
|
||||
component = 'image' + `i`
|
||||
if not self.hascomponent(component):
|
||||
self.createcomponent(
|
||||
component, (), 'image',
|
||||
OnscreenImage,
|
||||
(), parent = self.stateNodePath[i],
|
||||
image = image[i], scale = 1)
|
||||
else:
|
||||
self[component + '_image'] = image[i]
|
||||
|
||||
def setState(self):
|
||||
if type(self['state']) == type(0):
|
||||
self.guiItem.setActive(self['state'])
|
||||
@ -511,12 +703,12 @@ class DirectButton(DirectGuiObject, NodePath):
|
||||
self.guiItem.setActive(1)
|
||||
else:
|
||||
self.guiItem.setActive(0)
|
||||
|
||||
def setImage(self):
|
||||
pass
|
||||
def setGeom(self):
|
||||
pass
|
||||
|
||||
def setCommand(self):
|
||||
self.unbind('click')
|
||||
if self['command']:
|
||||
self.bind('click', self['command'])
|
||||
|
||||
class DirectLabel(DirectGuiObject, PGItem):
|
||||
def __init__(self, parent = None, **kw):
|
||||
# Pass in a background texture, and/or a geometry object,
|
||||
@ -536,7 +728,7 @@ class DirectLabel(DirectGuiObject, PGItem):
|
||||
('textPos', (0,0,0), self.setTextPos),
|
||||
('textScale', (1,1,1), self.setTextPos),
|
||||
)
|
||||
apply(DirectGuiObject.__init__, (self, optiondefs), kw)
|
||||
apply(DirectGuiObject.__init__, (self, optiondefs, ()), kw)
|
||||
self.initialiseoptions(DirectLabel)
|
||||
|
||||
def setImage(self):
|
||||
@ -566,3 +758,262 @@ class DirectLabel(DirectGuiObject, PGItem):
|
||||
def setState(self):
|
||||
pass
|
||||
|
||||
|
||||
class OnscreenGeom(PandaObject, NodePath):
|
||||
def __init__(self, geom = None,
|
||||
pos = None,
|
||||
hpr = None,
|
||||
scale = None,
|
||||
color = None,
|
||||
parent = aspect2d):
|
||||
"""__init__(self, ...)
|
||||
|
||||
Make a geom node from string or a node path,
|
||||
put it into the 2d sg and set it up with all the indicated parameters.
|
||||
|
||||
The parameters are as follows:
|
||||
|
||||
geom: the actual geometry to display or a file name.
|
||||
This may be omitted and specified later via setGeom()
|
||||
if you don't have it available.
|
||||
|
||||
pos: the x, y, z position of the geometry on the screen.
|
||||
This maybe a 3-tuple of floats or a vector.
|
||||
y should be zero
|
||||
|
||||
hpr: the h,p,r of the geometry on the screen.
|
||||
This maybe a 3-tuple of floats or a vector.
|
||||
|
||||
scale: the size of the geometry. This may either be a single
|
||||
float, a 3-tuple of floats, or a vector, specifying a
|
||||
different x, y, z scale. y should be 1
|
||||
|
||||
color: the (r, g, b, a) color of the geometry. This is
|
||||
normally a 4-tuple of floats or ints.
|
||||
|
||||
parent: the NodePath to parent the geometry to initially.
|
||||
"""
|
||||
# We ARE a node path. Initially, we're an empty node path.
|
||||
NodePath.__init__(self)
|
||||
# Assign geometry
|
||||
if isinstance(geom, NodePath):
|
||||
self.assign(geom.copyTo(parent))
|
||||
elif type(geom) == type(''):
|
||||
self.assign(loader.loadModelCopy(geom))
|
||||
self.reparentTo(parent)
|
||||
|
||||
# Adjust pose
|
||||
# Set pos
|
||||
if (isinstance(pos, types.TupleType) or
|
||||
isinstance(pos, types.ListType)):
|
||||
apply(self.setPos, pos)
|
||||
elif isinstance(pos, VBase3):
|
||||
self.setPos(pos)
|
||||
# Hpr
|
||||
if (isinstance(hpr, types.TupleType) or
|
||||
isinstance(hpr, types.ListType)):
|
||||
apply(self.setHpr, hpr)
|
||||
elif isinstance(hpr, VBase3):
|
||||
self.setPos(hpr)
|
||||
# Scale
|
||||
if (isinstance(scale, types.TupleType) or
|
||||
isinstance(scale, types.ListType)):
|
||||
apply(self.setScale, scale)
|
||||
elif isinstance(scale, VBase3):
|
||||
self.setPos(scale)
|
||||
elif (isinstance(scale, types.FloatType) or
|
||||
isinstance(scale, types.IntType)):
|
||||
self.setScale(scale)
|
||||
|
||||
# Set color
|
||||
if color:
|
||||
# Set color, if specified
|
||||
self.setColor(color[0], color[1], color[2], color[3])
|
||||
|
||||
def setGeom(self, geom):
|
||||
# Assign geometry
|
||||
self.removeNode()
|
||||
# Assign geometry
|
||||
if isinstance(geom, NodePath):
|
||||
self.assign(geom.copyTo(parent))
|
||||
elif type(geom) == type(''):
|
||||
self.assign(loader.loadModelCopy(geom))
|
||||
self.reparentTo(parent)
|
||||
|
||||
def getGeom(self):
|
||||
return self
|
||||
|
||||
def configure(self, option=None, **kw):
|
||||
for option, value in kw.items():
|
||||
# Use option string to access setter function
|
||||
try:
|
||||
setter = eval('self.set' +
|
||||
string.upper(option[0]) + option[1:])
|
||||
if (((setter == self.setPos) or
|
||||
(setter == self.setHpr) or
|
||||
(setter == self.setScale)) and
|
||||
(isinstance(value, types.TupleType) or
|
||||
isinstance(value, types.ListType))):
|
||||
apply(setter,value)
|
||||
else:
|
||||
setter(value)
|
||||
except AttributeError:
|
||||
print 'OnscreenText.configure: invalid option:', option
|
||||
|
||||
# Allow index style references
|
||||
def __setitem__(self, key, value):
|
||||
apply(self.configure, (), {key: value})
|
||||
|
||||
def cget(self, option):
|
||||
# Get current configuration setting.
|
||||
# This is for compatability with DirectGui functions
|
||||
getter = eval('self.get' + string.upper(option[0]) + option[1:])
|
||||
return getter()
|
||||
|
||||
# Allow index style refererences
|
||||
__getitem__ = cget
|
||||
|
||||
|
||||
|
||||
class OnscreenImage(PandaObject, NodePath):
|
||||
def __init__(self, image = None,
|
||||
pos = None,
|
||||
hpr = None,
|
||||
scale = None,
|
||||
color = None,
|
||||
parent = aspect2d):
|
||||
"""__init__(self, ...)
|
||||
|
||||
Make a image node from string or a node path,
|
||||
put it into the 2d sg and set it up with all the indicated parameters.
|
||||
|
||||
The parameters are as follows:
|
||||
|
||||
image: the actual geometry to display or a file name.
|
||||
This may be omitted and specified later via setImage()
|
||||
if you don't have it available.
|
||||
|
||||
pos: the x, y, z position of the geometry on the screen.
|
||||
This maybe a 3-tuple of floats or a vector.
|
||||
y should be zero
|
||||
|
||||
hpr: the h,p,r of the geometry on the screen.
|
||||
This maybe a 3-tuple of floats or a vector.
|
||||
|
||||
scale: the size of the geometry. This may either be a single
|
||||
float, a 3-tuple of floats, or a vector, specifying a
|
||||
different x, y, z scale. y should be 1
|
||||
|
||||
color: the (r, g, b, a) color of the geometry. This is
|
||||
normally a 4-tuple of floats or ints.
|
||||
|
||||
parent: the NodePath to parent the geometry to initially.
|
||||
"""
|
||||
# We ARE a node path. Initially, we're an empty node path.
|
||||
NodePath.__init__(self)
|
||||
# Assign geometry
|
||||
if isinstance(image, NodePath):
|
||||
self.assign(image.copyTo(parent))
|
||||
elif type(image) == type(()):
|
||||
model = loader.loadModelOnce(image[0])
|
||||
self.assign(model.find(image[1]))
|
||||
self.reparentTo(parent)
|
||||
model.removeNode()
|
||||
|
||||
# Adjust pose
|
||||
# Set pos
|
||||
if (isinstance(pos, types.TupleType) or
|
||||
isinstance(pos, types.ListType)):
|
||||
apply(self.setPos, pos)
|
||||
elif isinstance(pos, VBase3):
|
||||
self.setPos(pos)
|
||||
# Hpr
|
||||
if (isinstance(hpr, types.TupleType) or
|
||||
isinstance(hpr, types.ListType)):
|
||||
apply(self.setHpr, hpr)
|
||||
elif isinstance(hpr, VBase3):
|
||||
self.setPos(hpr)
|
||||
# Scale
|
||||
if (isinstance(scale, types.TupleType) or
|
||||
isinstance(scale, types.ListType)):
|
||||
apply(self.setScale, scale)
|
||||
elif isinstance(scale, VBase3):
|
||||
self.setPos(scale)
|
||||
elif (isinstance(scale, types.FloatType) or
|
||||
isinstance(scale, types.IntType)):
|
||||
self.setScale(scale)
|
||||
|
||||
# Set color
|
||||
if color:
|
||||
# Set color, if specified
|
||||
self.setColor(color[0], color[1], color[2], color[3])
|
||||
|
||||
def setImage(self, image):
|
||||
# Assign geometry
|
||||
self.removeNode()
|
||||
if isinstance(image, NodePath):
|
||||
self.assign(image.copyTo(parent))
|
||||
elif type(image) == type(()):
|
||||
model = loader.loadModelOnce(image[0])
|
||||
self.assign(model.find(image[1]))
|
||||
self.reparentTo(parent)
|
||||
model.removeNode()
|
||||
|
||||
def getImage(self):
|
||||
return self
|
||||
|
||||
def configure(self, option=None, **kw):
|
||||
for option, value in kw.items():
|
||||
# Use option string to access setter function
|
||||
try:
|
||||
setter = eval('self.set' +
|
||||
string.upper(option[0]) + option[1:])
|
||||
if (((setter == self.setPos) or
|
||||
(setter == self.setHpr) or
|
||||
(setter == self.setScale)) and
|
||||
(isinstance(value, types.TupleType) or
|
||||
isinstance(value, types.ListType))):
|
||||
apply(setter,value)
|
||||
else:
|
||||
setter(value)
|
||||
except AttributeError:
|
||||
print 'OnscreenText.configure: invalid option:', option
|
||||
|
||||
# Allow index style references
|
||||
def __setitem__(self, key, value):
|
||||
apply(self.configure, (), {key: value})
|
||||
|
||||
def cget(self, option):
|
||||
# Get current configuration setting.
|
||||
# This is for compatability with DirectGui functions
|
||||
getter = eval('self.get' + string.upper(option[0]) + option[1:])
|
||||
return getter()
|
||||
|
||||
# Allow index style refererences
|
||||
__getitem__ = cget
|
||||
|
||||
|
||||
|
||||
"""
|
||||
EXAMPLE CODE
|
||||
import DirectButton
|
||||
smiley = loader.loadModel('models/directmodels/smiley')
|
||||
db = DirectButton.DirectButton(geom = smiley, text = 'hi',
|
||||
scale = .15, relief = 'raised')
|
||||
db['text_pos'] = (.8, -.8)
|
||||
db['text_scale'] = .5
|
||||
db['geom1_color'] = VBase4(1,0,0,1)
|
||||
db['text2_text'] = 'bye'
|
||||
|
||||
def dummyCmd():
|
||||
print 'Amazing!'
|
||||
|
||||
db['command'] = dummyCmd
|
||||
|
||||
rolloverSmiley = db.component('geom2')
|
||||
def shrink():
|
||||
rolloverSmiley.setScale(1)
|
||||
rolloverSmiley.lerpScale(.1,.1,.1, 1.0, blendType = 'easeInOut',
|
||||
task = 'shrink')
|
||||
db.bind('enter', shrink)
|
||||
"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user