DirectFrame.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. from DirectGuiBase import *
  2. class DirectFrame(DirectGuiWidget):
  3. def __init__(self, parent = aspect2d, **kw):
  4. # Inherits from DirectGuiWidget
  5. # A Direct Frame can have:
  6. # - A background texture (pass in path to image, or Texture Card)
  7. # - A midground geometry item (pass in geometry)
  8. # - A foreground text Node (pass in text string or Onscreen Text)
  9. # Each of these has 1 or more states
  10. # The same object can be used for all states or each
  11. # state can have a different text/geom/image (for radio button
  12. # and check button indicators, for example
  13. optiondefs = (
  14. # Define type of DirectGuiWidget
  15. ('pgFunc', PGItem, None),
  16. ('numStates', 1, None),
  17. ('state', self.inactiveInitState, None),
  18. # Frame can have:
  19. # A background texture
  20. ('image', None, self.setImage),
  21. # A midground geometry item
  22. ('geom', None, self.setGeom),
  23. # A foreground text node
  24. ('text', None, self.setText),
  25. ('textMayChange', 1, None),
  26. )
  27. # Merge keyword options with default options
  28. self.defineoptions(kw, optiondefs,
  29. dynamicGroups = ('text', 'geom', 'image'))
  30. # Initialize superclasses
  31. DirectGuiWidget.__init__(self, parent)
  32. # Call option initialization functions
  33. self.initialiseoptions(DirectFrame)
  34. def setText(self):
  35. # Determine if user passed in single string or a sequence
  36. if self['text'] == None:
  37. textList = (None,) * self['numStates']
  38. elif type(self['text']) == types.StringType:
  39. # If just passing in a single string, make a tuple out of it
  40. textList = (self['text'],) * self['numStates']
  41. else:
  42. # Otherwise, hope that the user has passed in a tuple/list
  43. textList = self['text']
  44. # Create/destroy components
  45. for i in range(self['numStates']):
  46. component = 'text' + `i`
  47. # If fewer items specified than numStates,
  48. # just repeat last item
  49. try:
  50. text = textList[i]
  51. except IndexError:
  52. text = textList[-1]
  53. if self.hascomponent(component):
  54. if text == None:
  55. # Destroy component
  56. self.destroycomponent(component)
  57. else:
  58. self[component + '_text'] = text
  59. else:
  60. if text == None:
  61. return
  62. else:
  63. from OnscreenText import OnscreenText
  64. self.createcomponent(
  65. component, (), 'text',
  66. OnscreenText,
  67. (), parent = self.stateNodePath[i],
  68. text = text, scale = 1,
  69. sort = TEXT_SORT_INDEX,
  70. mayChange = self['textMayChange'],
  71. )
  72. def setGeom(self):
  73. # Determine argument type
  74. if self['geom'] == None:
  75. # Passed in None
  76. geomList = (None,) * self['numStates']
  77. elif isinstance(self['geom'], NodePath):
  78. # Passed in a single node path, make a tuple out of it
  79. geomList = (self['geom'],) * self['numStates']
  80. else:
  81. # Otherwise, hope that the user has passed in a tuple/list
  82. geomList = self['geom']
  83. # Create/destroy components
  84. for i in range(self['numStates']):
  85. component = 'geom' + `i`
  86. # If fewer items specified than numStates,
  87. # just repeat last item
  88. try:
  89. geom = geomList[i]
  90. except IndexError:
  91. geom = geomList[-1]
  92. if self.hascomponent(component):
  93. if geom == None:
  94. # Destroy component
  95. self.destroycomponent(component)
  96. else:
  97. self[component + '_geom'] = geom
  98. else:
  99. if geom == None:
  100. return
  101. else:
  102. self.createcomponent(
  103. component, (), 'geom',
  104. OnscreenGeom,
  105. (), parent = self.stateNodePath[i],
  106. geom = geom, scale = 1,
  107. sort = GEOM_SORT_INDEX)
  108. def setImage(self):
  109. # Determine argument type
  110. arg = self['image']
  111. if arg == None:
  112. # Passed in None
  113. imageList = (None,) * self['numStates']
  114. elif isinstance(arg, NodePath):
  115. imageList = (arg,) * self['numStates']
  116. elif type(arg) == types.StringType:
  117. # Passed in a single node path, make a tuple out of it
  118. imageList = (arg,) * self['numStates']
  119. else:
  120. # Otherwise, hope that the user has passed in a tuple/list
  121. if ((len(arg) == 2) and
  122. (type(arg[0]) == types.StringType) and
  123. (type(arg[1]) == types.StringType)):
  124. # Its a model/node pair of strings
  125. imageList = (arg,) * self['numStates']
  126. else:
  127. # Assume its a list of node paths
  128. imageList = arg
  129. # Create/destroy components
  130. for i in range(self['numStates']):
  131. component = 'image' + `i`
  132. # If fewer items specified than numStates,
  133. # just repeat last item
  134. try:
  135. image = imageList[i]
  136. except IndexError:
  137. image = imageList[-1]
  138. if self.hascomponent(component):
  139. if image == None:
  140. # Destroy component
  141. self.destroycomponent(component)
  142. else:
  143. self[component + '_image'] = image
  144. else:
  145. if image == None:
  146. return
  147. else:
  148. self.createcomponent(
  149. component, (), 'image',
  150. OnscreenImage,
  151. (), parent = self.stateNodePath[i],
  152. image = image, scale = 1,
  153. sort = IMAGE_SORT_INDEX)