seLights.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. #################################################################
  2. # seLights.py
  3. # Written by Yi-Hong Lin, [email protected], 2004
  4. #################################################################
  5. from direct.showbase.DirectObject import *
  6. from string import lower
  7. from direct.directtools import DirectUtil
  8. from pandac.PandaModules import *
  9. import string
  10. class seLight(NodePath):
  11. #################################################################
  12. # seLight(NodePath)
  13. # This is an object for keeping light data and let we can manipulate
  14. # lights as otherNopaths.
  15. # This idea basically is from directLight.
  16. # But the way directLight object worked is not we want in our
  17. # sceneEditor. So, we wrote one by ourself.
  18. #################################################################
  19. def __init__(self, light, parent, type,
  20. lightcolor=VBase4(0.3,0.3,0.3,1),
  21. specularColor = VBase4(1),
  22. position = Point3(0,0,0),
  23. orientation = Vec3(1,0,0),
  24. constant = 1.0,
  25. linear = 0.0,
  26. quadratic = 0.0,
  27. exponent = 0.0,
  28. tag="",
  29. lence = None):
  30. #################################################################
  31. # __init__(self, light, parent, type,
  32. # lightcolor=VBase4(0.3,0.3,0.3,1),
  33. # specularColor = VBase4(1),
  34. # position = Point3(0,0,0),
  35. # orientation = Vec3(1,0,0),
  36. # constant = 1.0,
  37. # linear = 0.0,
  38. # quadratic = 0.0,
  39. # exponent = 0.0,
  40. # tag="",
  41. # lence = None):
  42. # This constructor will create a light node inside it and upcast
  43. # this light node to itself as a nodePath.
  44. # Also, it will load a model as a reference to itself on the secene so that
  45. # user can easily recognize where is the light and can easily manipulate
  46. # by mouse picking and widget control.
  47. #################################################################
  48. # Initialize the super class
  49. NodePath.__init__(self)
  50. # Initialize and save values
  51. self.light = light
  52. self.type = type
  53. self.lightcolor=lightcolor
  54. self.specularColor = specularColor
  55. self.position = position
  56. self.orientation = orientation
  57. self.constant = constant
  58. self.linear = linear
  59. self.quadratic = quadratic
  60. self.exponent = exponent
  61. self.lence = lence
  62. self.active = True
  63. if isinstance(light, Spotlight):
  64. node = light.upcastToLensNode()
  65. else:
  66. node = light.upcastToPandaNode()
  67. # Attach node to self
  68. self.LightNode=parent.attachNewNode(node)
  69. self.LightNode.setTag("Metadata",tag)
  70. if(self.type=='spot'):
  71. self.LightNode.setHpr(self.orientation)
  72. self.LightNode.setPos(self.position)
  73. else:
  74. self.LightNode.setHpr(self.orientation)
  75. self.LightNode.setPos(self.position)
  76. self.assign(self.LightNode)
  77. if(self.type=='spot'):
  78. self.helpModel = loader.loadModel( "models/misc/Spotlight" )
  79. elif(self.type=='point'):
  80. self.helpModel = loader.loadModel( "models/misc/Pointlight" )
  81. elif(self.type=='directional'):
  82. self.helpModel = loader.loadModel( "models/misc/Dirlight" )
  83. else:
  84. self.helpModel = loader.loadModel( "models/misc/sphere" )
  85. self.helpModel.setColor(self.lightcolor)
  86. self.helpModel.reparentTo(self)
  87. DirectUtil.useDirectRenderStyle(self.helpModel)
  88. if not ((self.type == 'directional')or(self.type == 'point')or(self.type == 'spot')):
  89. self.helpModel.hide()
  90. def getLight(self):
  91. #################################################################
  92. # getLight(self)
  93. # This function will return the light object it contains.
  94. #################################################################
  95. return self.light
  96. def getLightColor(self):
  97. #################################################################
  98. # getLightColor(self)
  99. # This function will return the color of the light color of this light node.
  100. #################################################################
  101. return self.lightcolor
  102. def getName(self):
  103. #################################################################
  104. # getName(self)
  105. # This function will return the name of this light.
  106. #################################################################
  107. return self.light.getName()
  108. def rename(self,name):
  109. #################################################################
  110. # rename(self, name)
  111. # User should specify a string object, name, as the new name of this
  112. # light node. This function will rename itself and light object
  113. # to this new name.
  114. #################################################################
  115. self.light.setName(name)
  116. self.setName(name)
  117. def getType(self):
  118. #################################################################
  119. # getType(self)
  120. # This function will return a string which is the type of this
  121. # light node. (We only have four types of light)
  122. #################################################################
  123. return self.type
  124. def setColor(self,color):
  125. #################################################################
  126. # setColor(self, color)
  127. # This function takes one input parameter, color, which is a
  128. # VBase4 object. This function will simply set this object into
  129. # light node it has to change the property of light.
  130. # Also, if the light type is either "directional" or "point", which
  131. # means it has a reference model with it, this function will also
  132. # change the reference model's color to input value.
  133. #################################################################
  134. self.light.setColor(color)
  135. self.lightcolor = color
  136. if (self.type == 'directional')or(self.type == 'point'):
  137. self.helpModel.setColor(self.lightcolor)
  138. return
  139. def getSpecColor(self):
  140. #################################################################
  141. # getSpecColor(self)
  142. # This function will return the specular color of the light.
  143. # Although you can call this function for all kinds of light,
  144. # it will only meanful if this light is not a ambient light.
  145. #################################################################
  146. return self.specularColor
  147. def setSpecColor(self,color):
  148. #################################################################
  149. # setSpecColor(self, color)
  150. # This function can be used to set the specular color of the light.
  151. # Although you can call this function for all kinds of light,
  152. # it will only meanful if the light type is not "ambient"
  153. #################################################################
  154. self.light.setSpecularColor(color)
  155. self.specularcolor = color
  156. return
  157. def getPosition(self):
  158. #################################################################
  159. # getPosition(self)
  160. # getPosition(self)
  161. # This functioln will return a Point3 object which contains
  162. # the x, y, z position data of this light node.
  163. # It only has meaning for "point Light" and "Directional light"
  164. #################################################################
  165. self.position = self.LightNode.getPos()
  166. return self.position
  167. def setPosition(self, pos):
  168. #################################################################
  169. # setPosition(self, pos)
  170. # This function will take a Point3 object as a input.
  171. # Then, this function will set the itself andd light node to the
  172. # target point.
  173. #################################################################
  174. self.LightNode.setPos(pos)
  175. self.position = pos
  176. return
  177. def getOrientation(self):
  178. #################################################################
  179. # getOrientation(self)
  180. # This function will return a Vec3-type object which contains the
  181. # orientation data of this light node
  182. #
  183. # This function will only have meaning for point light and directional light.
  184. #
  185. #################################################################
  186. self.orientation = self.LightNode.getHpr()
  187. return self.orientation
  188. def setOrientation(self,orient):
  189. #################################################################
  190. # setOrientation(self, orient)
  191. # This funtction will take a Vec3-type object as an input.
  192. # Then this function will set itself nad light node to face
  193. # the target orientation.
  194. #
  195. # This function only has meaning for point light and directional light
  196. # type of lights.
  197. #
  198. #################################################################
  199. self.LightNode.setHpr(orient)
  200. self.orientation = orient
  201. return
  202. def getAttenuation(self):
  203. #################################################################
  204. # getAttenuation(self)
  205. # This function will return a Vec3 type of object which contains
  206. # the constant, linear and quadratic attenuation for this light node.
  207. #
  208. # This function will only have meaning for point light and spot light
  209. # tyoe of lights.
  210. #
  211. #################################################################
  212. return Vec3(self.constant,self.linear,self.quadratic)
  213. def setConstantAttenuation(self, value):
  214. #################################################################
  215. # setConstantAttenuation(self, value)
  216. # This function will take a float number as an input.
  217. # Then, this function will set the Constant Atenuation value
  218. # to this number.
  219. #################################################################
  220. self.light.setAttenuation(Vec3(value, self.linear, self.quadratic))
  221. self.constant = value
  222. return
  223. def setLinearAttenuation(self, value):
  224. #################################################################
  225. # setLinearAttenuation(self, value)
  226. # This function will take a float number as an input.
  227. # Then, this function will set the Linear Atenuation value
  228. # to this number.
  229. #################################################################
  230. self.light.setAttenuation(Vec3(self.constant, value, self.quadratic))
  231. self.linear = value
  232. return
  233. def setQuadraticAttenuation(self, value):
  234. #################################################################
  235. # setQuadraticAttenuation(self, value)
  236. # This function will take a float number as an input.
  237. # Then, this function will set the Quadratic Atenuation value
  238. # to this number.
  239. #################################################################
  240. self.light.setAttenuation(Vec3(self.constant, self.linear, value))
  241. self.quadratic = value
  242. return
  243. def getExponent(self):
  244. #################################################################
  245. # getExponent(self)
  246. # This function will return the value of the Exponent Attenuation
  247. # of this light node. (float)
  248. #################################################################
  249. return self.exponent
  250. def setExponent(self, value):
  251. #################################################################
  252. # setExponent(self, value)
  253. # This function will take a float number as an input.
  254. # Then, this function will set the Exponent Atenuation value
  255. # to this number.
  256. #################################################################
  257. self.light.setExponent(value)
  258. self.exponent = value
  259. return
  260. class seLightManager(NodePath):
  261. #################################################################
  262. # seLightManager(NodePath)
  263. # This is the class we used to control al lightings in our sceneEditor.
  264. #################################################################
  265. def __init__(self):
  266. # Initialize the superclass
  267. NodePath.__init__(self)
  268. # Create a node for the lights
  269. self.lnode=render.attachNewNode('Lights')
  270. self.assign(self.lnode)
  271. # Create a light attrib
  272. self.lightAttrib = LightAttrib.makeAllOff()
  273. self.lightDict = {}
  274. self.ambientCount = 0
  275. self.directionalCount = 0
  276. self.pointCount = 0
  277. self.spotCount = 0
  278. # Originally, we don't do this load model thing.
  279. # But the problem is, if we don't, then it will cause some
  280. # Bounding calculation error...
  281. self.helpModel = loader.loadModel( "models/misc/sphere" )
  282. self.helpModel.reparentTo(self)
  283. self.helpModel.hide()
  284. def create(self, type = 'ambient',
  285. lightcolor=VBase4(0.3,0.3,0.3,1),
  286. specularColor = VBase4(1),
  287. position = Point3(0,0,0),
  288. orientation = Vec3(1,0,0),
  289. constant = 1.0,
  290. linear = 0.0,
  291. quadratic = 0.0,
  292. exponent = 0.0,
  293. tag= "",
  294. name='DEFAULT_NAME'):
  295. #################################################################
  296. # create(self, type = 'ambient',
  297. # lightcolor=VBase4(0.3,0.3,0.3,1),
  298. # specularColor = VBase4(1),
  299. # position = Point3(0,0,0),
  300. # orientation = Vec3(1,0,0),
  301. # constant = 1.0,
  302. # linear = 0.0,
  303. # quadratic = 0.0,
  304. # exponent = 0.0,
  305. # tag= "",
  306. # name='DEFAULT_NAME')
  307. # As you can see, once user call this function and specify those
  308. # variables, this function will create a seLight node.
  309. # In the default, the light which just has been created will be
  310. # set to off.
  311. #################################################################
  312. ### create the light
  313. lence = None
  314. if type == 'ambient':
  315. self.ambientCount += 1
  316. if(name=='DEFAULT_NAME'):
  317. light = AmbientLight('ambient_' + `self.ambientCount`)
  318. else:
  319. light = AmbientLight(name)
  320. light.setColor(lightcolor)
  321. elif type == 'directional':
  322. self.directionalCount += 1
  323. if(name=='DEFAULT_NAME'):
  324. light = DirectionalLight('directional_' + `self.directionalCount`)
  325. else:
  326. light = DirectionalLight(name)
  327. light.setColor(lightcolor)
  328. light.setSpecularColor(specularColor)
  329. elif type == 'point':
  330. self.pointCount += 1
  331. if(name=='DEFAULT_NAME'):
  332. light = PointLight('point_' + `self.pointCount`)
  333. else:
  334. light = PointLight(name)
  335. light.setColor(lightcolor)
  336. light.setSpecularColor(specularColor)
  337. light.setAttenuation(Vec3(constant, linear, quadratic))
  338. elif type == 'spot':
  339. self.spotCount += 1
  340. if(name=='DEFAULT_NAME'):
  341. light = Spotlight('spot_' + `self.spotCount`)
  342. else:
  343. light = Spotlight(name)
  344. light.setColor(lightcolor)
  345. lence = PerspectiveLens()
  346. light.setLens(lence)
  347. light.setSpecularColor(specularColor)
  348. light.setAttenuation(Vec3(constant, linear, quadratic))
  349. light.setExponent(exponent)
  350. else:
  351. print 'Invalid light type'
  352. return None
  353. # Create the seLight objects and put the light object we just created into it.
  354. lightNode = seLight(light,self,type,
  355. lightcolor=lightcolor,
  356. specularColor = specularColor,
  357. position = position,
  358. orientation = orientation,
  359. constant = constant,
  360. linear = linear,
  361. quadratic = quadratic,
  362. exponent = exponent,
  363. tag=tag,
  364. lence = lence
  365. )
  366. self.lightDict[light.getName()] = lightNode
  367. self.setOn(lightNode)
  368. return self.lightDict.keys(),lightNode
  369. def addLight(self, light):
  370. #################################################################
  371. # addLight(self, light)
  372. # This function will put light in and save its properties in to a seLight Node
  373. # Attention!!
  374. # only Spotlight obj nneds to be specified a lens node first. i.e. setLens() first!
  375. #################################################################
  376. type = lower(light.getType().getName())
  377. light.upcastToNamable()
  378. specularColor = VBase4(1)
  379. position = Point3(0,0,0)
  380. orientation = Vec3(1,0,0)
  381. constant = 1.0
  382. linear = 0.0
  383. quadratic = 0.0
  384. exponent = 0.0
  385. lence = None
  386. lightcolor = light.getColor()
  387. if type == 'ambientlight':
  388. type = 'ambient'
  389. self.ambientCount += 1
  390. elif type == 'directionallight':
  391. type = 'directional'
  392. self.directionalCount += 1
  393. orientation = light.getDirection()
  394. position = light.getPoint()
  395. specularColor = light.getSpecularColor()
  396. elif type == 'pointlight':
  397. type = 'point'
  398. self.pointCount += 1
  399. position = light.getPoint()
  400. specularColor = light.getSpecularColor()
  401. Attenuation = light.getAttenuation()
  402. constant = Attenuation.getX()
  403. linear = Attenuation.getY()
  404. quadratic = Attenuation.getZ()
  405. elif type == 'spotlight':
  406. type = 'spot'
  407. self.spotCount += 1
  408. specularColor = light.getSpecularColor()
  409. Attenuation = light.getAttenuation()
  410. constant = Attenuation.getX()
  411. linear = Attenuation.getY()
  412. quadratic = Attenuation.getZ()
  413. exponent = light.getExponent()
  414. else:
  415. print 'Invalid light type'
  416. return None
  417. lightNode = seLight(light,self,type,
  418. lightcolor=lightcolor,
  419. specularColor = specularColor,
  420. position = position,
  421. orientation = orientation,
  422. constant = constant,
  423. linear = linear,
  424. quadratic = quadratic,
  425. exponent = exponent,
  426. lence = lence)
  427. self.lightDict[light.getName()] = lightNode
  428. self.setOn(lightNode)
  429. return self.lightDict.keys(),lightNode
  430. def delete(self, name, removeEntry = True):
  431. #################################################################
  432. # delete(self, name, removeEntry = True)
  433. # This function will remove light node had the same name with user input.
  434. # Also, you can specify the removeEntry to decide to remove the entry from the lightDict or not.
  435. # Normaly, you alway want to remove the entry from the dictionary. Thsi is only used for "deleteAll" function.
  436. #################################################################
  437. type = self.lightDict[name].getType()
  438. if type == 'ambient':
  439. self.ambientCount -= 1
  440. elif type == 'directional':
  441. self.directionalCount -= 1
  442. elif type == 'point':
  443. self.pointCount -= 1
  444. elif type == 'spot':
  445. self.spotCount -= 1
  446. self.setOff(self.lightDict[name])
  447. self.lightDict[name].removeChildren()
  448. self.lightDict[name].removeNode()
  449. if removeEntry:
  450. del self.lightDict[name]
  451. return self.lightDict.keys()
  452. def deleteAll(self):
  453. #################################################################
  454. # deleteAll(self)
  455. # This function will keep calling delete and put exist lights in
  456. # until all lights have been eliminated.
  457. #################################################################
  458. for name in self.lightDict:
  459. self.delete(name, removeEntry = False)
  460. self.lightDict.clear()
  461. def isLight(self,name):
  462. #################################################################
  463. # isLight(self.name)
  464. # Use a string as a index to check if there existing a light named "name"
  465. #################################################################
  466. return self.lightDict.has_key(name)
  467. def rename(self,oName,nName):
  468. #################################################################
  469. # rename(self, oName, nName)
  470. # This function will reanem the light named "oName(String)" to
  471. # nName(String)
  472. #################################################################
  473. if self.isLight(oName):
  474. lightNode = self.lightDict[oName]
  475. self.lightDict[nName] = lightNode
  476. lightNode.rename(nName)
  477. del self.lightDict[oName]
  478. return self.lightDict.keys(),lightNode
  479. else:
  480. print '----Light Mnager: No such Light!'
  481. def getLightNodeList(self):
  482. #################################################################
  483. # getLightNodeList(self)
  484. # Return a list which contains all seLight nodes
  485. #################################################################
  486. list = []
  487. for name in self.lightDict:
  488. list.append(self.lightDict[name])
  489. return list
  490. def getLightNodeDict(self):
  491. #################################################################
  492. # getLightNodeDict(self)
  493. # Return the light dictionary itself.
  494. #
  495. # Attention!
  496. # Because it doesn't make a copy when you return a dictionary, it
  497. # means when you can change the value from outside and that change
  498. # will directly reflect back to here.
  499. #
  500. #################################################################
  501. return self.lightDict
  502. def getLightList(self):
  503. #################################################################
  504. # getLightList(self)
  505. # Return a list which contains names of all lights.
  506. #################################################################
  507. list = []
  508. for name in self.lightDict:
  509. list.append(name)
  510. return list
  511. def getLightNode(self,lightName):
  512. #################################################################
  513. # getLightNode(self, lightName)
  514. # This function will return a seLight Node using a string, lightName. as a index.
  515. #################################################################
  516. if lightName in self.lightDict:
  517. return self.lightDict[lightName]
  518. def allOn(self):
  519. #################################################################
  520. # allOb(self)
  521. # Enable the lighting system.
  522. #################################################################
  523. # Turn on all lighting
  524. render.node().setAttrib(self.lightAttrib)
  525. # Make sure there is a default material
  526. render.setMaterial(Material())
  527. def allOff(self):
  528. #################################################################
  529. # allOff(self)
  530. # Disable whole lighting system
  531. #################################################################
  532. # Turn off all lighting
  533. render.node().clearAttrib(LightAttrib.getClassType())
  534. def toggle(self):
  535. #################################################################
  536. # toggle(self)
  537. # Toggles light attribute, but doesn't toggle individual lights
  538. #################################################################
  539. if render.node().hasAttrib(LightAttrib.getClassType()):
  540. self.allOff()
  541. else:
  542. self.allOn()
  543. def setOn(self, lightNode):
  544. #################################################################
  545. # setOn(lightNode)
  546. # This function will enable the input seLight node.
  547. # If the light system itself is down, activate it.
  548. #################################################################
  549. self.lightAttrib = self.lightAttrib.addLight(lightNode.getLight())
  550. lightNode.active = True
  551. if render.node().hasAttrib(LightAttrib.getClassType()):
  552. render.node().setAttrib(self.lightAttrib)
  553. def setOff(self, lightNode):
  554. #################################################################
  555. # setOff(self, lightNode)
  556. # This function will disable the input seLight node
  557. # If the light system itself is down, activate it.
  558. #################################################################
  559. lightNode.active = False
  560. self.lightAttrib = self.lightAttrib.removeLight(lightNode.getLight())
  561. if render.node().hasAttrib(LightAttrib.getClassType()):
  562. render.node().setAttrib(self.lightAttrib)
  563. def getList(self):
  564. #################################################################
  565. # getList(self)
  566. # This function actually has the same functionality with getLightList(),
  567. # but this one should be more efficient.
  568. #################################################################
  569. return self.lightDict.keys()