seLights.py 26 KB

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