more files from CMU

This commit is contained in:
David Rose 2004-08-06 22:22:50 +00:00
parent 207239935d
commit 8618f4d3f8
70 changed files with 27166 additions and 0 deletions

View File

@ -0,0 +1,80 @@
import pandac.AudioSound
import pandac.AudioManager
class Audio3DManager:
def __init__(self, audio_manager, listener_target = None):
self.audio_manager = audio_manager
self.listener_target = listener_target
self.sound_dict = {}
def attachSoundToObject(self, sound, object):
# sound is an AudioSound
# object is any Panda object with coordinates
for known_object in self.sound_dict.keys():
if sound_dict[known_object].count(sound):
# This sound is already attached to something
return 0
if not self.sound_dict.has_key(object):
self.sound_dict[object] = []
self.sound_dict[object].append(sound)
return 1
def detachSound(self, sound):
for known_object in self.sound_dict.keys():
if sound_dict[known_object].count(sound):
self.sound_dict[known_object].remove()
if len(sound_dict[known_object]) == 0:
# if there are no other sounds, don't track
# the object any more
del self.sound_dict[known_object]
return 1
return 0
def getSoundsOnObject(self, object):
if not self.sound_dict.has_key(object):
return []
sound_list = []
sound_list.extend(self.sound_dict[object])
return sound_list
def attachListener(self, object):
self.listener_target = object
return 1
def detachListener(self):
self.listener_target = None
return 1
def update(self):
# Update the positions of all sounds based on the objects
# to which they are attached
for known_object in self.sound_dict.keys():
tracked_sound = 0
while tracked_sound < len(self.sound_dict[known_object]):
sound = self.sound_dict[known_object][tracked_sound]
if self.listener_target:
pos = known_object.getPos(self.listener_target)
else:
pos = known_object.getPos()
sound.set3dAttributes(pos[0], pos[1], pos[2], 0,0,0)
tracked_sound += 1
# Update the position of the listener based on the object
# to which it is attached
if self.listener_target:
pos = self.listener_target.getPos()
self.audio_manager.audio3dSetListenerAttributes(pos[0], pos[1], pos[2], 0,0,0, 0,1,0, 0,0,1)
else:
self.audio_manager.audio3dSetListenerAttributes(0,0,0, 0,0,0, 0,1,0, 0,0,1)
self.audio_manager.audio3dUpdate()
return 1

11
doc/.project Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>panda</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
</buildSpec>
<natures>
</natures>
</projectDescription>

11
doc/SceneEditor/.project Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>SceneEditor</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
</buildSpec>
<natures>
</natures>
</projectDescription>

View File

@ -0,0 +1,188 @@
#################################################################
# AlignTool.py
# Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#################################################################
from AppShell import *
from TkGlobal import *
class AlignTool(AppShell):
#################################################################
# AlignTool(AppShell)
#################################################################
appversion = '1.0'
appname = 'Align Tool'
frameWidth = 220
frameHeight = 330
frameIniPosX = 250
frameIniPosY = 250
padx = 0
pady = 0
def __init__(self, list = [], parent = None, nodePath = None, **kw):
# Keep nodePath Data
self.nodePath = nodePath
self.targetList = list
self.targetName = None
# Rename App
self.appname += (' '+self.nodePath.getName())
# Define the megawidget options.
optiondefs = (
('title', self.appname, None),
)
self.defineoptions(kw, optiondefs)
if parent == None:
self.parent = Toplevel()
AppShell.__init__(self, self.parent)
self.parent.geometry('%dx%d+%d+%d' % (self.frameWidth, self.frameHeight,self.frameIniPosX,self.frameIniPosY))
self.initialiseoptions(AlignTool)
self.parent.resizable(False,False) ## Disable the ability to resize for this Window.
def appInit(self):
return
def createInterface(self):
# The interior of the toplevel panel
interior = self.interior()
mainFrame = Frame(interior)
frame = Frame(mainFrame)
self.nameBox = self.createcomponent(
'Align Target', (), None,
Pmw.ComboBox, (frame,),
labelpos = W, label_text='Target Node:', entry_width = 20, entry_state = DISABLED,
selectioncommand = self.setTargetNode,
scrolledlist_items = self.targetList)
self.nameBox.pack(side=LEFT)
frame.pack(side=TOP, fill = X, expand = 1,pady=5)
group = Pmw.Group(mainFrame, tag_text = 'Setting')
group.pack(side=TOP, fill = 'both', expand = 1,pady=5)
groupFrame = group.interior()
# X and H checkbox
frame = Frame(groupFrame)
self.alignXVar = IntVar()
self.alignXVar.set(False)
self.alignXButton = Checkbutton(
frame,
text = ': Align X',
variable = self.alignXVar)
self.alignXButton.pack(side=LEFT, expand=False)
self.alignHVar = IntVar()
self.alignHVar.set(False)
self.alignHButton = Checkbutton(
frame,
text = ': Align H',
variable = self.alignHVar)
self.alignHButton.pack(side=RIGHT, expand=False)
frame.pack(side=TOP, fill = X, expand = 1,pady=5)
groupFrame.pack(side=TOP, fill = 'both', expand = 1,padx=5,pady=5)
frame = Frame(mainFrame)
Button(frame, text='Align', width = 13, command=self.Align_press).pack(side=LEFT)
Button(frame, text='OK', width = 13, command=self.ok_press).pack(side=RIGHT)
frame.pack(side=BOTTOM, fill = X, expand = 1,pady=5)
# Y and P checkbox
frame = Frame(groupFrame)
self.alignYVar = IntVar()
self.alignYVar.set(False)
self.alignYButton = Checkbutton(
frame,
text = ': Align Y',
variable = self.alignYVar)
self.alignYButton.pack(side=LEFT, expand=False)
self.alignPVar = IntVar()
self.alignPVar.set(False)
self.alignPButton = Checkbutton(
frame,
text = ': Align P',
variable = self.alignPVar)
self.alignPButton.pack(side=RIGHT, expand=False)
frame.pack(side=TOP, fill = X, expand = 1,pady=5)
# Z and R checkbox
frame = Frame(groupFrame)
self.alignZVar = IntVar()
self.alignZVar.set(False)
self.alignZButton = Checkbutton(
frame,
text = ': Align Z',
variable = self.alignZVar)
self.alignZButton.pack(side=LEFT, expand=False)
self.alignRVar = IntVar()
self.alignRVar.set(False)
self.alignRButton = Checkbutton(
frame,
text = ': Align R',
variable = self.alignRVar)
self.alignRButton.pack(side=RIGHT, expand=False)
frame.pack(side=TOP, fill = X, expand = 1,pady=5)
# Scale
frame = Frame(groupFrame)
Label(frame,text='Align Scale:').pack(side=LEFT)
frame.pack(side=TOP, fill = X, expand = 1,pady=5)
frame = Frame(groupFrame)
self.alignSXVar = IntVar()
self.alignSXVar.set(False)
self.alignSXButton = Checkbutton(
frame,
text = ': X',
variable = self.alignSXVar)
self.alignSXButton.pack(side=LEFT, expand=False)
self.alignSYVar = IntVar()
self.alignSYVar.set(False)
self.alignSYButton = Checkbutton(
frame,
text = ': Y',
variable = self.alignSYVar)
self.alignSYButton.pack(side=LEFT, expand=False)
frame.pack(side=TOP, fill = X, expand = 1,pady=5)
self.alignSZVar = IntVar()
self.alignSZVar.set(False)
self.alignSZButton = Checkbutton(
frame,
text = ': Z',
variable = self.alignSZVar)
self.alignSZButton.pack(side=LEFT, expand=False)
frame.pack(side=TOP, fill = X, expand = 1,pady=5)
mainFrame.pack(fill = 'both', expand = 1,padx=7,pady=7)
def createMenuBar(self):
self.menuBar.destroy()
def onDestroy(self, event):
messenger.send('ALW_close', [self.nodePath.getName()])
'''
If you have open any thing, please rewrite here!
'''
pass
###############################
def ok_press(self):
#################################################################
# ok_press(self)
# Callback function
# This function will be called when user click on the "OK" button on the window.
#################################################################
self.quit()
def Align_press(self):
list = [self.alignXVar.get(), self.alignYVar.get(), self.alignZVar.get(),
self.alignHVar.get(), self.alignPVar.get(), self.alignRVar.get(),
self.alignSXVar.get(), self.alignSYVar.get(), self.alignSZVar.get()]
if self.targetName != None:
messenger.send('ALW_align', [self.nodePath, self.targetName, list])
return
def setTargetNode(self,name=None):
self.targetName = name
return

View File

@ -0,0 +1,575 @@
<CoordinateSystem> { Z-Up }
<Comment> {
"MaxEggPlugin nul.max -o 'E:\sshadhan\Desktop\Dirlight.egg'"
}
<Texture> Tex1 {
"DirLight.tif"
<Scalar> format { rgb }
<Scalar> wrapu { repeat }
<Scalar> wrapv { repeat }
<Scalar> minfilter { linear_mipmap_linear }
<Scalar> magfilter { linear }
}
<Group> Box03 {
<Transform> {
<Matrix4> {
0.204526 0 0 0
0 3.98227e-008 0.204526 0
0 -0.204526 3.98227e-008 0
0 0 0 1
}
}
<VertexPool> Box03.verts {
<Vertex> 1 {
-1.02263 -0.00012118 -1.02263
<Normal> { 0 -0.204526 3.98227e-008 }
<UV> { 0.537617 0.269239 }
}
<Vertex> 2 {
1.02263 -0.00012118 -1.02263
<Normal> { 0 -0.204526 3.98227e-008 }
<UV> { 0.769888 0.269239 }
}
<Vertex> 3 {
1.02263 -0.000120782 1.02263
<Normal> { 0 -0.204526 3.98227e-008 }
<UV> { 0.769888 0.501509 }
}
<Vertex> 4 {
-1.02263 -0.000120782 1.02263
<Normal> { 0 -0.204526 3.98227e-008 }
<UV> { 0.537617 0.501509 }
}
<Vertex> 5 {
-1.02263 3.06777 -1.02263
<Normal> { 0 -3.98227e-008 -0.204526 }
<UV> { 0.516079 0.378406 }
}
<Vertex> 6 {
1.02263 3.06777 -1.02263
<Normal> { 0 -3.98227e-008 -0.204526 }
<UV> { 0.283808 0.378406 }
}
<Vertex> 7 {
1.02263 -0.00012118 -1.02263
<Normal> { 0 -3.98227e-008 -0.204526 }
<UV> { 0.283808 0.03 }
}
<Vertex> 8 {
-1.02263 -0.00012118 -1.02263
<Normal> { 0 -3.98227e-008 -0.204526 }
<UV> { 0.516079 0.03 }
}
<Vertex> 9 {
1.02263 3.06777 -1.02263
<Normal> { 0.204526 0 0 }
<UV> { 0.516079 0.759119 }
}
<Vertex> 10 {
1.02263 3.06777 1.02263
<Normal> { 0.204526 0 0 }
<UV> { 0.283808 0.759119 }
}
<Vertex> 11 {
1.02263 -0.000120782 1.02263
<Normal> { 0.204526 0 0 }
<UV> { 0.283808 0.410713 }
}
<Vertex> 12 {
1.02263 -0.00012118 -1.02263
<Normal> { 0.204526 0 0 }
<UV> { 0.516079 0.410713 }
}
<Vertex> 13 {
1.02263 3.06777 1.02263
<Normal> { 0 3.98227e-008 0.204526 }
<UV> { 0.262271 0.759119 }
}
<Vertex> 14 {
-1.02263 3.06777 1.02263
<Normal> { 0 3.98227e-008 0.204526 }
<UV> { 0.03 0.759119 }
}
<Vertex> 15 {
-1.02263 -0.000120782 1.02263
<Normal> { 0 3.98227e-008 0.204526 }
<UV> { 0.03 0.410713 }
}
<Vertex> 16 {
1.02263 -0.000120782 1.02263
<Normal> { 0 3.98227e-008 0.204526 }
<UV> { 0.262271 0.410713 }
}
<Vertex> 17 {
-1.02263 3.06777 1.02263
<Normal> { -0.204526 0 0 }
<UV> { 0.262271 0.378406 }
}
<Vertex> 18 {
-1.02263 3.06777 -1.02263
<Normal> { -0.204526 0 0 }
<UV> { 0.03 0.378406 }
}
<Vertex> 19 {
-1.02263 -0.00012118 -1.02263
<Normal> { -0.204526 0 0 }
<UV> { 0.03 0.03 }
}
<Vertex> 20 {
-1.02263 -0.000120782 1.02263
<Normal> { -0.204526 0 0 }
<UV> { 0.262271 0.03 }
}
<Vertex> 21 {
-1.02263 3.06777 -1.02263
<Normal> { 0 0.204526 -3.98227e-008 }
<UV> { 0.537617 0.262271 }
}
<Vertex> 22 {
-1.02263 3.06777 1.02263
<Normal> { 0 0.204526 -3.98227e-008 }
<UV> { 0.537617 0.03 }
}
<Vertex> 23 {
-0.0931723 3.06777 0.0931723
<Normal> { 0 0.204526 -3.98227e-008 }
<UV> { 0.643171 0.135554 }
}
<Vertex> 24 {
-0.0931723 3.06777 -0.0931723
<Normal> { 0 0.204526 -3.98227e-008 }
<UV> { 0.643171 0.156716 }
}
<Vertex> 25 {
1.02263 3.06777 1.02263
<Normal> { 0 0.204526 -3.98227e-008 }
<UV> { 0.769888 0.03 }
}
<Vertex> 26 {
0.0931723 3.06777 0.0931723
<Normal> { 0 0.204526 -3.98227e-008 }
<UV> { 0.664333 0.135554 }
}
<Vertex> 27 {
1.02263 3.06777 -1.02263
<Normal> { 0 0.204526 -3.98227e-008 }
<UV> { 0.769888 0.262271 }
}
<Vertex> 28 {
0.0931723 3.06777 -0.0931723
<Normal> { 0 0.204526 -3.98227e-008 }
<UV> { 0.664333 0.156716 }
}
<Vertex> 29 {
-0.0931723 3.06777 -0.0931723
<Normal> { -0.204526 0 0 }
<UV> { 0.700095 0.508478 }
}
<Vertex> 30 {
-0.0931723 3.06777 0.0931723
<Normal> { -0.204526 0 0 }
<UV> { 0.721257 0.508478 }
}
<Vertex> 31 {
-0.0931723 7.13171 0.0931715
<Normal> { -0.204526 0 0 }
<UV> { 0.721257 0.97 }
}
<Vertex> 32 {
-0.0931723 7.13171 -0.0931731
<Normal> { -0.204526 0 0 }
<UV> { 0.700095 0.97 }
}
<Vertex> 33 {
-0.0931723 3.06777 0.0931723
<Normal> { 0 3.98227e-008 0.204526 }
<UV> { 0.653846 0.508478 }
}
<Vertex> 34 {
0.0931723 3.06777 0.0931723
<Normal> { 0 3.98227e-008 0.204526 }
<UV> { 0.675008 0.508478 }
}
<Vertex> 35 {
0.0931723 7.13171 0.0931715
<Normal> { 0 3.98227e-008 0.204526 }
<UV> { 0.675008 0.97 }
}
<Vertex> 36 {
-0.0931723 7.13171 0.0931715
<Normal> { 0 3.98227e-008 0.204526 }
<UV> { 0.653846 0.97 }
}
<Vertex> 37 {
0.0931723 3.06777 0.0931723
<Normal> { 0.204526 0 0 }
<UV> { 0.676971 0.508478 }
}
<Vertex> 38 {
0.0931723 3.06777 -0.0931723
<Normal> { 0.204526 0 0 }
<UV> { 0.698133 0.508478 }
}
<Vertex> 39 {
0.0931723 7.13171 -0.0931731
<Normal> { 0.204526 0 0 }
<UV> { 0.698133 0.97 }
}
<Vertex> 40 {
0.0931723 7.13171 0.0931715
<Normal> { 0.204526 0 0 }
<UV> { 0.676971 0.97 }
}
<Vertex> 41 {
0.0931723 3.06777 -0.0931723
<Normal> { 0 -3.98227e-008 -0.204526 }
<UV> { 0.72322 0.508478 }
}
<Vertex> 42 {
-0.0931723 3.06777 -0.0931723
<Normal> { 0 -3.98227e-008 -0.204526 }
<UV> { 0.744382 0.508478 }
}
<Vertex> 43 {
-0.0931723 7.13171 -0.0931731
<Normal> { 0 -3.98227e-008 -0.204526 }
<UV> { 0.744382 0.97 }
}
<Vertex> 44 {
0.0931723 7.13171 -0.0931731
<Normal> { 0 -3.98227e-008 -0.204526 }
<UV> { 0.72322 0.97 }
}
<Vertex> 45 {
-0.0931723 7.13171 -0.0931731
<Normal> { -0.0336239 -0.201743 3.92809e-008 }
<UV> { 0.819457 0.311841 }
}
<Vertex> 46 {
-0.0931723 7.13171 0.0931715
<Normal> { -0.0336239 -0.201743 3.92809e-008 }
<UV> { 0.819457 0.333003 }
}
<Vertex> 47 {
-0.468305 7.19423 0.468304
<Normal> { -0.0336239 -0.201743 3.92809e-008 }
<UV> { 0.776855 0.375605 }
}
<Vertex> 48 {
-0.468305 7.19423 -0.468306
<Normal> { -0.0336239 -0.201743 3.92809e-008 }
<UV> { 0.776855 0.269239 }
}
<Vertex> 49 {
-0.0931723 7.13171 0.0931715
<Normal> { 0 -0.201743 0.033624 }
<UV> { 0.819457 0.333003 }
}
<Vertex> 50 {
0.0931723 7.13171 0.0931715
<Normal> { 0 -0.201743 0.033624 }
<UV> { 0.84062 0.333003 }
}
<Vertex> 51 {
0.468305 7.19423 0.468304
<Normal> { 0 -0.201743 0.033624 }
<UV> { 0.883222 0.375605 }
}
<Vertex> 52 {
-0.468305 7.19423 0.468304
<Normal> { 0 -0.201743 0.033624 }
<UV> { 0.776855 0.375605 }
}
<Vertex> 53 {
0.0931723 7.13171 0.0931715
<Normal> { 0.0336239 -0.201743 3.92809e-008 }
<UV> { 0.84062 0.333003 }
}
<Vertex> 54 {
0.0931723 7.13171 -0.0931731
<Normal> { 0.0336239 -0.201743 3.92809e-008 }
<UV> { 0.84062 0.311841 }
}
<Vertex> 55 {
0.468305 7.19423 -0.468306
<Normal> { 0.0336239 -0.201743 3.92809e-008 }
<UV> { 0.883222 0.269239 }
}
<Vertex> 56 {
0.468305 7.19423 0.468304
<Normal> { 0.0336239 -0.201743 3.92809e-008 }
<UV> { 0.883222 0.375605 }
}
<Vertex> 57 {
0.0931723 7.13171 -0.0931731
<Normal> { 0 -0.201743 -0.0336239 }
<UV> { 0.84062 0.311841 }
}
<Vertex> 58 {
-0.0931723 7.13171 -0.0931731
<Normal> { 0 -0.201743 -0.0336239 }
<UV> { 0.819457 0.311841 }
}
<Vertex> 59 {
-0.468305 7.19423 -0.468306
<Normal> { 0 -0.201743 -0.0336239 }
<UV> { 0.776855 0.269239 }
}
<Vertex> 60 {
0.468305 7.19423 -0.468306
<Normal> { 0 -0.201743 -0.0336239 }
<UV> { 0.883222 0.269239 }
}
<Vertex> 61 {
-0.468305 7.19423 -0.468306
<Normal> { -0.18883 0.0785766 -1.52994e-008 }
<UV> { 0.537617 0.508478 }
}
<Vertex> 62 {
-0.468305 7.19423 0.468304
<Normal> { -0.18883 0.0785766 -1.52994e-008 }
<UV> { 0.643983 0.508478 }
}
<Vertex> 63 {
0 8.31963 -1.02257e-006
<Normal> { -0.18883 0.0785766 -1.52994e-008 }
<UV> { 0.5908 0.646908 }
}
<Vertex> 64 {
-0.468305 7.19423 0.468304
<Normal> { 0 0.0785766 0.18883 }
<UV> { 0.776855 0.03 }
}
<Vertex> 65 {
0.468305 7.19423 0.468304
<Normal> { 0 0.0785766 0.18883 }
<UV> { 0.883222 0.03 }
}
<Vertex> 66 {
0 8.31963 -1.02257e-006
<Normal> { 0 0.0785766 0.18883 }
<UV> { 0.830039 0.16843 }
}
<Vertex> 67 {
0.468305 7.19423 0.468304
<Normal> { 0.18883 0.0785766 -1.52994e-008 }
<UV> { 0.03 0.791425 }
}
<Vertex> 68 {
0.468305 7.19423 -0.468306
<Normal> { 0.18883 0.0785766 -1.52994e-008 }
<UV> { 0.136366 0.791425 }
}
<Vertex> 69 {
0 8.31963 -1.02257e-006
<Normal> { 0.18883 0.0785766 -1.52994e-008 }
<UV> { 0.0831832 0.929855 }
}
<Vertex> 70 {
0.468305 7.19423 -0.468306
<Normal> { 0 0.0785765 -0.18883 }
<UV> { 0.283808 0.791425 }
}
<Vertex> 71 {
-0.468305 7.19423 -0.468306
<Normal> { 0 0.0785765 -0.18883 }
<UV> { 0.390175 0.791425 }
}
<Vertex> 72 {
0 8.31963 -1.02257e-006
<Normal> { 0 0.0785765 -0.18883 }
<UV> { 0.336992 0.929855 }
}
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 1 2 3 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 3 4 1 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 5 6 7 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 7 8 5 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 9 10 11 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 11 12 9 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 13 14 15 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 15 16 13 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 17 18 19 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 19 20 17 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 21 22 23 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 23 24 21 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 22 25 26 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 26 23 22 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 25 27 28 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 28 26 25 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 27 21 24 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 24 28 27 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 29 30 31 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 31 32 29 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 33 34 35 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 35 36 33 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 37 38 39 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 39 40 37 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 41 42 43 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 43 44 41 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 45 46 47 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 47 48 45 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 49 50 51 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 51 52 49 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 53 54 55 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 55 56 53 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 57 58 59 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 59 60 57 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 61 62 63 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 64 65 66 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 67 68 69 <Ref> { Box03.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 70 71 72 <Ref> { Box03.verts } }
}
}

View File

@ -0,0 +1,59 @@
from AppShell import *
from TkGlobal import *
class MetadataPanel(AppShell,Pmw.MegaWidget):
appversion = '1.0'
appname = 'Metadata Panel'
frameWidth = 400
frameHeight = 400
padx = 0
pady = 0
usecommandarea = 0
usestatusarea = 0
Metatag=""
Metanode=None
tag_text=None
def __init__(self,nodePath,parent=None,**kw):
# Initialise superclass
Pmw.MegaWidget.__init__(self, parent)
# Define the megawidget options.
optiondefs = (
('title', self.appname, None),
)
self.defineoptions(kw, optiondefs)
self.Metanode=nodePath
if(nodePath.hasTag("Metadata")):
self.Metatag=self.Metanode.getTag("Metadata")
if parent == None:
self.parent = Toplevel()
AppShell.__init__(self, self.parent)
self.parent.resizable(False,False)
def appInit(self):
print "Metadata Panel"
def createInterface(self):
interior = self.interior()
mainFrame = Frame(interior)
tag_label=Label (mainFrame,text="Enter Metadata",font=('MSSansSerif', 15),
relief = RIDGE, borderwidth=5)
tag_label.pack()
source=StringVar()
source.set(self.Metatag)
self.tag_text=Entry(mainFrame, width=10,textvariable=source)
self.tag_text.pack()
set_button=Button(mainFrame, text='Set Metadata',font=('MSSansSerif', 15),
relief = RIDGE, borderwidth=5, command= lambda:self.SetIt())
set_button.pack()
mainFrame.pack(fill = 'both', expand = 1)
def SetIt(self):
self.Metanode.setTag("Metadata",self.tag_text.get())

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,991 @@
#################################################################
# seSession.py
# Originally from DirectSession.py
# Altered by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#
# We took out a lot of stuff we don't need in the sceneeditor.
# This is also the main reason we didn't just inherite the original directSession.
# Also, the way of selecting, renaming and some hot-key controls are changed.
#
#################################################################
from PandaObject import *
from DirectGlobals import *
from DirectUtil import*
from intervalGlobal import *
from seCameraControl import *
from seManipulation import *
from seSelection import *
from seGrid import *
from seGeometry import *
import Placer
import Slider
import OnscreenText
import types
import string
import Loader
class SeSession(PandaObject): ### Customized DirectSession
def __init__(self):
# Establish a global pointer to the direct object early on
# so dependant classes can access it in their code
__builtins__["SEditor"] = self
# These come early since they are used later on
self.group = render.attachNewNode('SEditor')
self.font = TextNode.getDefaultFont()
self.fEnabled = 0
self.drList = DisplayRegionList()
self.iRayList = map(lambda x: x.iRay, self.drList)
self.dr = self.drList[0]
self.camera = base.camera
self.trueCamera = self.camera
self.iRay = self.dr.iRay
self.coaMode = COA_ORIGIN
self.enableAutoCamera = True
self.cameraControl = DirectCameraControl()
self.manipulationControl = DirectManipulationControl()
self.useObjectHandles()
self.grid = DirectGrid()
self.grid.disable()
# Initialize the collection of selected nodePaths
self.selected = SelectedNodePaths()
# Ancestry of currently selected object
self.ancestry = []
self.ancestryIndex = 0
self.activeParent = None
self.selectedNPReadout = OnscreenText.OnscreenText(
pos = (-1.0, -0.9), bg=Vec4(1,1,1,1),
scale = 0.05, align = TextNode.ALeft,
mayChange = 1, font = self.font)
# Make sure readout is never lit or drawn in wireframe
useDirectRenderStyle(self.selectedNPReadout)
self.selectedNPReadout.reparentTo(hidden)
self.activeParentReadout = OnscreenText.OnscreenText(
pos = (-1.0, -0.975), bg=Vec4(1,1,1,1),
scale = 0.05, align = TextNode.ALeft,
mayChange = 1, font = self.font)
# Make sure readout is never lit or drawn in wireframe
useDirectRenderStyle(self.activeParentReadout)
self.activeParentReadout.reparentTo(hidden)
self.directMessageReadout = OnscreenText.OnscreenText(
pos = (-1.0, 0.9), bg=Vec4(1,1,1,1),
scale = 0.05, align = TextNode.ALeft,
mayChange = 1, font = self.font)
# Make sure readout is never lit or drawn in wireframe
useDirectRenderStyle(self.directMessageReadout)
self.directMessageReadout.reparentTo(hidden)
self.fControl = 0
self.fAlt = 0
self.fShift = 0
self.pos = VBase3()
self.hpr = VBase3()
self.scale = VBase3()
self.hitPt = Point3(0.0)
# Lists for managing undo/redo operations
self.undoList = []
self.redoList = []
# One run through the context task to init everything
self.drList.updateContext()
for dr in self.drList:
dr.camUpdate()
self.modifierEvents = ['control', 'control-up',
'shift', 'shift-up',
'alt', 'alt-up',
]
self.keyEvents = ['escape', 'delete', 'page_up', 'page_down',
'[', '{', ']', '}',
'shift-a', 'b', 'control-f',
'l', 'shift-l', 'o', 'p', 'r',
'shift-r', 's', 't', 'v', 'w']
self.mouseEvents = ['mouse1', 'mouse1-up',
'shift-mouse1', 'shift-mouse1-up',
'control-mouse1', 'control-mouse1-up',
'alt-mouse1', 'alt-mouse1-up',
'mouse2', 'mouse2-up',
'shift-mouse2', 'shift-mouse2-up',
'control-mouse2', 'control-mouse2-up',
'alt-mouse2', 'alt-mouse2-up',
'mouse3', 'mouse3-up',
'shift-mouse3', 'shift-mouse3-up',
'control-mouse3', 'control-mouse3-up',
'alt-mouse3', 'alt-mouse3-up',
]
def enable(self):
if self.fEnabled:
return
# Make sure old tasks are shut down
self.disable()
# Start all display region context tasks
self.drList.spawnContextTask()
# Turn on mouse Flying
self.cameraControl.enableMouseFly()
# Turn on object manipulation
self.manipulationControl.enableManipulation()
# Make sure list of selected items is reset
self.selected.reset()
# Accept appropriate hooks
self.enableKeyEvents()
self.enableModifierEvents()
self.enableMouseEvents()
# Set flag
self.fEnabled = 1
if self.enableAutoCamera:
self.accept('DH_LoadingComplete', self.autoCameraMove)
def disable(self):
# Shut down all display region context tasks
self.drList.removeContextTask()
# Turn off camera fly
self.cameraControl.disableMouseFly()
# Turn off object manipulation
self.manipulationControl.disableManipulation()
self.disableKeyEvents()
self.disableModifierEvents()
self.disableMouseEvents()
self.ignore('DH_LoadingComplete')
# Kill tasks
taskMgr.remove('flashNodePath')
taskMgr.remove('hideDirectMessage')
taskMgr.remove('hideDirectMessageLater')
# Set flag
self.fEnabled = 0
def minimumConfiguration(self):
# Remove context task
self.drList.removeContextTask()
# Turn off camera fly
self.cameraControl.disableMouseFly()
# Ignore keyboard and action events
self.disableKeyEvents()
self.disableActionEvents()
# But let mouse events pass through
self.enableMouseEvents()
self.enableModifierEvents()
def oobe(self):
# If oobeMode was never set, set it to false and create the
# structures we need to implement OOBE.
try:
self.oobeMode
except:
self.oobeMode = 0
self.oobeCamera = hidden.attachNewNode('oobeCamera')
self.oobeVis = loader.loadModelOnce('models/misc/camera')
if self.oobeVis:
self.oobeVis.node().setFinal(1)
if self.oobeMode:
# Position a target point to lerp the oobe camera to
self.cameraControl.camManipRef.iPosHpr(self.trueCamera)
t = self.oobeCamera.lerpPosHpr(
Point3(0), Vec3(0), 2.0,
other = self.cameraControl.camManipRef,
task = 'manipulateCamera',
blendType = 'easeInOut')
# When move is done, switch to oobe mode
t.uponDeath = self.endOOBE
else:
# Place camera marker at true camera location
self.oobeVis.reparentTo(self.trueCamera)
# Remove any transformation on the models arc
self.oobeVis.clearMat()
# Make oobeCamera be a sibling of wherever camera is now.
cameraParent = self.camera.getParent()
# Prepare oobe camera
self.oobeCamera.reparentTo(cameraParent)
self.oobeCamera.iPosHpr(self.trueCamera)
# Put camera under new oobe camera
base.cam.reparentTo(self.oobeCamera)
# Position a target point to lerp the oobe camera to
self.cameraControl.camManipRef.setPos(
self.trueCamera, Vec3(-2,-20, 5))
self.cameraControl.camManipRef.lookAt(self.trueCamera)
t = self.oobeCamera.lerpPosHpr(
Point3(0), Vec3(0), 2.0,
other = self.cameraControl.camManipRef,
task = 'manipulateCamera',
blendType = 'easeInOut')
# When move is done, switch to oobe mode
t.uponDeath = self.beginOOBE
def beginOOBE(self, state):
# Make sure we've reached our final destination
self.oobeCamera.iPosHpr(self.cameraControl.camManipRef)
self.camera = self.oobeCamera
self.oobeMode = 1
def endOOBE(self, state):
# Make sure we've reached our final destination
self.oobeCamera.iPosHpr(self.trueCamera)
# Disable OOBE mode.
base.cam.reparentTo(self.trueCamera)
self.camera = self.trueCamera
# Get rid of ancillary node paths
self.oobeVis.reparentTo(hidden)
self.oobeCamera.reparentTo(hidden)
self.oobeMode = 0
def destroy(self):
self.disable()
def reset(self):
self.enable()
# EVENT FUNCTIONS
def enableModifierEvents(self):
for event in self.modifierEvents:
self.accept(event, self.inputHandler, [event])
def enableKeyEvents(self):
for event in self.keyEvents:
self.accept(event, self.inputHandler, [event])
def enableMouseEvents(self):
for event in self.mouseEvents:
self.accept(event, self.inputHandler, [event])
def disableModifierEvents(self):
for event in self.modifierEvents:
self.ignore(event)
def disableKeyEvents(self):
for event in self.keyEvents:
self.ignore(event)
def disableMouseEvents(self):
for event in self.mouseEvents:
self.ignore(event)
def inputHandler(self, input):
# Deal with keyboard and mouse input
if input == 'mouse1-up':
messenger.send('DIRECT-mouse1Up')
if SEditor.widget.fActive:
messenger.send('shift-f')
elif input.find('mouse1') != -1:
modifiers = self.getModifiers(input, 'mouse1')
messenger.send('DIRECT-mouse1', sentArgs = [modifiers])
elif input == 'mouse2-up':
messenger.send('DIRECT-mouse2Up')
if SEditor.widget.fActive:
messenger.send('shift-f')
elif input.find('mouse2') != -1:
modifiers = self.getModifiers(input, 'mouse2')
messenger.send('DIRECT-mouse2', sentArgs = [modifiers])
elif input == 'mouse3-up':
messenger.send('DIRECT-mouse3Up')
if SEditor.widget.fActive:
messenger.send('shift-f')
elif input.find('mouse3') != -1:
modifiers = self.getModifiers(input, 'mouse3')
messenger.send('DIRECT-mouse3', sentArgs = [modifiers])
elif input == 'shift':
self.fShift = 1
elif input == 'shift-up':
self.fShift = 0
elif input == 'control':
self.fControl = 1
elif input == 'control-up':
self.fControl = 0
elif input == 'alt':
self.fAlt = 1
elif input == 'alt-up':
self.fAlt = 0
elif input == 'page_up':
self.upAncestry()
elif input == 'page_down':
self.downAncestry()
elif input == 'escape':
self.deselectAll()
elif input == 'delete':
taskMgr.remove('followSelectedNodePath')
#self.removeAllSelected()
messenger.send('SGE_Remove',[None])
self.deselectAll()
elif input == 'v':
messenger.send('SEditor-ToggleWidgetVis')
self.toggleWidgetVis()
if SEditor.widget.fActive:
messenger.send('shift-f')
elif input == 'b':
messenger.send('SEditor-ToggleBackface')
base.toggleBackface()
#elif input == 'control-f':
# self.flash(last)
elif input == 'shift-l':
self.cameraControl.toggleCOALock()
elif input == 'o':
self.oobe()
elif input == 'p':
if self.selected.last:
self.setActiveParent(self.selected.last)
elif input == 'r':
# Do wrt reparent
if self.selected.last:
self.reparent(self.selected.last, fWrt = 1)
elif input == 'shift-r':
# Do regular reparent
if self.selected.last:
self.reparent(self.selected.last)
elif input == 's':
if self.selected.last:
self.select(self.selected.last)
elif input == 't':
messenger.send('SEditor-ToggleTexture')
base.toggleTexture()
elif input == 'shift-a':
self.selected.toggleVisAll()
elif input == 'w':
messenger.send('SEditor-ToggleWireframe')
base.toggleWireframe()
elif (input == '[') or (input == '{'):
self.undo()
elif (input == ']') or (input == '}'):
self.redo()
def getModifiers(self, input, base):
modifiers = DIRECT_NO_MOD
modifierString = input[: input.find(base)]
if modifierString.find('shift') != -1:
modifiers |= DIRECT_SHIFT_MOD
if modifierString.find('control') != -1:
modifiers |= DIRECT_CONTROL_MOD
if modifierString.find('alt') != -1:
modifiers |= DIRECT_ALT_MOD
return modifiers
def gotShift(self, modifiers):
return modifiers & DIRECT_SHIFT_MOD
def gotControl(self, modifiers):
return modifiers & DIRECT_CONTROL_MOD
def gotAlt(self, modifiers):
return modifiers & DIRECT_ALT_MOD
def select(self, nodePath, fMultiSelect = 0, fResetAncestry = 1, callback=False):
dnp = self.selected.select(nodePath, fMultiSelect)
if dnp:
messenger.send('DIRECT_preSelectNodePath', [dnp])
if fResetAncestry:
# Update ancestry
self.ancestry = dnp.getAncestry()
self.ancestry.reverse()
self.ancestryIndex = 0
# Update the selectedNPReadout
self.selectedNPReadout.reparentTo(aspect2d)
self.selectedNPReadout.setText(
'Selected:' + dnp.getName())
# Show the manipulation widget
self.widget.showWidget()
# Update camera controls coa to this point
# Coa2Camera = Coa2Dnp * Dnp2Camera
mCoa2Camera = dnp.mCoa2Dnp * dnp.getMat(self.camera)
row = mCoa2Camera.getRow(3)
coa = Vec3(row[0], row[1], row[2])
self.cameraControl.updateCoa(coa)
# Adjust widgets size
# This uses the additional scaling factor used to grow and
# shrink the widget
self.widget.setScalingFactor(dnp.getRadius())
# Spawn task to have object handles follow the selected object
taskMgr.remove('followSelectedNodePath')
t = Task.Task(self.followSelectedNodePathTask)
t.dnp = dnp
taskMgr.add(t, 'followSelectedNodePath')
# Send an message marking the event
messenger.send('DIRECT_selectedNodePath', [dnp])
if callback:
messenger.send('se_selectedNodePath', [dnp, False])
else:
messenger.send('se_selectedNodePath', [dnp])
self.upAncestry()
if SEditor.widget.fActive:
messenger.send('shift-f')
def followSelectedNodePathTask(self, state):
mCoa2Render = state.dnp.mCoa2Dnp * state.dnp.getMat(render)
decomposeMatrix(mCoa2Render,
self.scale,self.hpr,self.pos,
CSDefault)
self.widget.setPosHpr(self.pos,self.hpr)
return Task.cont
def deselect(self, nodePath):
dnp = self.selected.deselect(nodePath)
if dnp:
# Hide the manipulation widget
self.widget.hideWidget()
self.selectedNPReadout.reparentTo(hidden)
self.selectedNPReadout.setText(' ')
taskMgr.remove('followSelectedNodePath')
self.ancestry = []
# Send an message marking the event
messenger.send('DIRECT_deselectedNodePath', [dnp])
def deselectAll(self):
self.selected.deselectAll()
# Hide the manipulation widget
self.widget.hideWidget()
self.selectedNPReadout.reparentTo(hidden)
self.selectedNPReadout.setText(' ')
taskMgr.remove('followSelectedNodePath')
messenger.send('se_deselectedAll')
def setActiveParent(self, nodePath = None):
# Record new parent
self.activeParent = nodePath
# Update the activeParentReadout
self.activeParentReadout.reparentTo(aspect2d)
self.activeParentReadout.setText(
'Active Reparent Target:' + nodePath.getName())
# Alert everyone else
self.activeParentReadout.show()
def reparent(self, nodePath = None, fWrt = 0):
if (nodePath and self.activeParent and
self.isNotCycle(nodePath, self.activeParent)):
oldParent = nodePath.getParent()
if fWrt:
nodePath.wrtReparentTo(self.activeParent)
else:
nodePath.reparentTo(self.activeParent)
# Alert everyone else
messenger.send('DIRECT_reparent',
[nodePath, oldParent, self.activeParent])
messenger.send('SGE_Update Explorer',[render])
self.activeParentReadout.hide()
def isNotCycle(self, nodePath, parent):
if nodePath.id() == parent.id():
print 'DIRECT.reparent: Invalid parent'
return 0
elif parent.hasParent():
return self.isNotCycle(nodePath, parent.getParent())
else:
return 1
def fitOnNodePath(self, nodePath = 'None Given'):
if nodePath == 'None Given':
# If nothing specified, try selected node path
nodePath = self.selected.last
SEditor.select(nodePath)
def fitTask(state, self = self):
self.cameraControl.fitOnWidget()
return Task.done
taskMgr.doMethodLater(0.1, fitTask, 'manipulateCamera')
def isolate(self, nodePath = 'None Given'):
""" Show a node path and hide its siblings """
# First kill the flashing task to avoid complications
taskMgr.remove('flashNodePath')
# Use currently selected node path if node selected
if nodePath == 'None Given':
nodePath = self.selected.last
# Do we have a node path?
if nodePath:
# Yes, show everything in level
self.showAllDescendants(nodePath.getParent())
# Now hide all of this node path's siblings
nodePath.hideSiblings()
def toggleVis(self, nodePath = 'None Given'):
""" Toggle visibility of node path """
# First kill the flashing task to avoid complications
taskMgr.remove('flashNodePath')
if nodePath == 'None Given':
# If nothing specified, try selected node path
nodePath = self.selected.last
if nodePath:
# Now toggle node path's visibility state
nodePath.toggleVis()
def removeNodePath(self, nodePath = 'None Given'):
if nodePath == 'None Given':
# If nothing specified, try selected node path
nodePath = self.selected.last
if nodePath:
nodePath.remove()
def removeAllSelected(self):
self.selected.removeAll()
def showAllDescendants(self, nodePath = render):
""" Show the level and its descendants """
nodePath.showAllDescendants()
nodePath.hideCS()
def upAncestry(self):
if self.ancestry:
l = len(self.ancestry)
i = self.ancestryIndex + 1
if i < l:
np = self.ancestry[i]
name = np.getName()
if i>0:
type = self.ancestry[i-1].node().getType().getName()
else:
type = self.ancestry[0].node().getType().getName()
ntype = np.node().getType().getName()
if (name != 'render') and (name != 'renderTop')and(self.checkTypeNameForAncestry(type, ntype)):
self.ancestryIndex = i
self.select(np, 0, 0, True)
def checkTypeNameForAncestry(self, type, nextType ):
if (type=='ModelRoot'):
if (nextType=='AmbientLight')or(nextType=='PointLight')or(nextType=='DirectionalLight')or(nextType=='Spotlight'):
return True
return False
elif (type=='ModelNode'):
if (nextType=='ModelNode'):
return True
return False
elif (type=='CollisionNode'):
return False
elif (type=='ActorNode'):
return False
elif (type=='AmbientLight')or(type=='PointLight')or(type=='DirectionalLight')or(type=='Spotlight'):
return False
else:
return True
def downAncestry(self):
if self.ancestry:
l = len(self.ancestry)
i = self.ancestryIndex - 1
if i >= 0:
np = self.ancestry[i]
name = np.getName()
if (name != 'render') and (name != 'renderTop'):
self.ancestryIndex = i
self.select(np, 0, 0, True)
def getAndSetName(self, nodePath):
""" Prompt user for new node path name """
from tkSimpleDialog import askstring
newName = askstring('Node Path: ' + nodePath.getName(),
'Enter new name:')
if newName:
nodePath.setName(newName)
messenger.send('DIRECT_nodePathSetName', [nodePath, newName])
# UNDO REDO FUNCTIONS
def pushUndo(self, nodePathList, fResetRedo = 1):
# Assemble group of changes
undoGroup = []
for nodePath in nodePathList:
t = nodePath.getTransform()
undoGroup.append([nodePath, t])
# Now record group
self.undoList.append(undoGroup)
# Truncate list
self.undoList = self.undoList[-25:]
# Alert anyone who cares
messenger.send('DIRECT_pushUndo')
if fResetRedo and (nodePathList != []):
self.redoList = []
messenger.send('DIRECT_redoListEmpty')
def popUndoGroup(self):
# Get last item
undoGroup = self.undoList[-1]
# Strip last item off of undo list
self.undoList = self.undoList[:-1]
# Update state of undo button
if not self.undoList:
messenger.send('DIRECT_undoListEmpty')
# Return last item
return undoGroup
def pushRedo(self, nodePathList):
# Assemble group of changes
redoGroup = []
for nodePath in nodePathList:
t = nodePath.getTransform()
redoGroup.append([nodePath, t])
# Now record redo group
self.redoList.append(redoGroup)
# Truncate list
self.redoList = self.redoList[-25:]
# Alert anyone who cares
messenger.send('DIRECT_pushRedo')
def popRedoGroup(self):
# Get last item
redoGroup = self.redoList[-1]
# Strip last item off of redo list
self.redoList = self.redoList[:-1]
# Update state of redo button
if not self.redoList:
messenger.send('DIRECT_redoListEmpty')
# Return last item
return redoGroup
def undo(self):
if self.undoList:
# Get last item off of redo list
undoGroup = self.popUndoGroup()
# Record redo information
nodePathList = map(lambda x: x[0], undoGroup)
self.pushRedo(nodePathList)
# Now undo xform for group
for pose in undoGroup:
# Undo xform
pose[0].setTransform(pose[1])
# Alert anyone who cares
messenger.send('DIRECT_undo')
def redo(self):
if self.redoList:
# Get last item off of redo list
redoGroup = self.popRedoGroup()
# Record undo information
nodePathList = map(lambda x: x[0], redoGroup)
self.pushUndo(nodePathList, fResetRedo = 0)
# Redo xform
for pose in redoGroup:
pose[0].setTransform(pose[1])
# Alert anyone who cares
messenger.send('DIRECT_redo')
# UTILITY FUNCTIONS
def message(self, text):
taskMgr.remove('hideDirectMessage')
taskMgr.remove('hideDirectMessageLater')
self.directMessageReadout.reparentTo(aspect2d)
self.directMessageReadout.setText(text)
self.hideDirectMessageLater()
def hideDirectMessageLater(self):
taskMgr.doMethodLater(3.0, self.hideDirectMessage, 'hideDirectMessage')
def hideDirectMessage(self, state):
self.directMessageReadout.reparentTo(hidden)
return Task.done
def useObjectHandles(self):
self.widget = self.manipulationControl.objectHandles
self.widget.reparentTo(SEditor.group)
def hideSelectedNPReadout(self):
self.selectedNPReadout.reparentTo(hidden)
def hideActiveParentReadout(self):
self.activeParentReadout.reparentTo(hidden)
def toggleWidgetVis(self):
self.widget.toggleWidget()
def setCOAMode(self, mode):
self.coaMode = mode
def isEnabled(self):
return self.fEnabled
def addUnpickable(self, item):
for iRay in self.iRayList:
iRay.addUnpickable(item)
def removeUnpickable(self, item):
for iRay in self.iRayList:
iRay.removeUnpickable(item)
def toggleAutoCamera(self):
self.enableAutoCamera = (self.enableAutoCamera+1)%2
if self.enableAutoCamera==1:
self.accept('DH_LoadingComplete', self.autoCameraMove)
else:
self.ignore('DH_LoadingComplete')
return
def autoCameraMove(self, nodePath):
time = 1
node = DirectNodePath(nodePath)
radius = node.getRadius()
center = node.getCenter()
node.dehighlight()
posB = base.camera.getPos()
hprB = base.camera.getHpr()
posE = Point3((radius*-1.41)+center.getX(), (radius*-1.41)+center.getY(), (radius*1.41)+center.getZ())
hprE = Point3(-45, -38, 0)
print posB, hprB
print posE, hprE
posInterval1 = base.camera.posInterval(time, posE, bakeInStart = 1)
posInterval2 = base.camera.posInterval(time, posB, bakeInStart = 1)
hprInterval1 = base.camera.hprInterval(time, hprE, bakeInStart = 1)
hprInterval2 = base.camera.hprInterval(time, hprB, bakeInStart = 1)
parallel1 = Parallel(posInterval1, hprInterval1)
parallel2 = Parallel(posInterval2, hprInterval2)
Sequence(Wait(7), parallel1, Wait(1), parallel2).start()
return
class DisplayRegionContext(PandaObject):
regionCount = 0
def __init__(self, cam):
self.cam = cam
self.camNode = self.cam.node()
self.camLens = self.camNode.getLens()
# set lens change callback
changeEvent = 'dr%d-change-event' % DisplayRegionContext.regionCount
DisplayRegionContext.regionCount += 1
self.camLens.setChangeEvent(changeEvent)
self.accept(changeEvent, self.camUpdate)
self.iRay = SelectionRay(self.cam)
self.nearVec = Vec3(0)
self.mouseX = 0.0
self.mouseY = 0.0
# A Camera node can have more than one display region
# associated with it. Here I assume that there is only
# one display region per camera, since we are defining a
# display region on a per-camera basis. See note in
# DisplayRegionList.__init__()
try:
self.dr = self.camNode.getDr(0)
except:
self.dr = self.camNode.getDisplayRegion(0)
left = self.dr.getLeft()
right = self.dr.getRight()
bottom = self.dr.getBottom()
top = self.dr.getTop()
self.originX = left+right-1
self.originY = top+bottom-1
self.scaleX = 1.0/(right-left)
self.scaleY = 1.0/(top-bottom)
self.setOrientation()
self.camUpdate()
def __getitem__(self,key):
return self.__dict__[key]
def setOrientation(self):
# MRM This assumes orientation is set on transform above cam
hpr = self.cam.getHpr()
if hpr[2] < 135 and hpr[2]>45 or hpr[2]>225 and hpr[2]<315:
self.isSideways = 1
elif hpr[2] > -135 and hpr[2] < -45 or hpr[2] < -225 and hpr[2] > -315:
self.isSideways = 1
else:
self.isSideways = 0
# The following take into consideration sideways displays
def getHfov(self):
if self.isSideways:
return self.camLens.getVfov()
else:
return self.camLens.getHfov()
def getVfov(self):
if self.isSideways:
return self.camLens.getHfov()
else:
return self.camLens.getVfov()
def setHfov(self,hfov):
if self.isSideways:
self.camLens.setFov(self.camLens.getHfov(), hfov)
else:
self.camLens.setFov(hfov, self.camLens.getVfov())
def setVfov(self,vfov):
if self.isSideways:
self.camLens.setFov(vfov, self.camLens.getVfov())
else:
self.camLens.setFov(self.camLens.getHfov(), vfov)
def setFov(self,hfov,vfov):
if self.isSideways:
self.camLens.setFov(vfov, hfov)
else:
self.camLens.setFov(hfov, vfov)
def getWidth(self):
prop = base.win.getProperties()
if prop.hasSize():
return prop.getXSize()
else:
return 640
def getHeight(self):
prop = base.win.getProperties()
if prop.hasSize():
return prop.getYSize()
else:
return 480
def camUpdate(self, lens = None):
# Window Data
self.near = self.camLens.getNear()
self.far = self.camLens.getFar()
self.fovH = self.camLens.getHfov()
self.fovV = self.camLens.getVfov()
self.nearWidth = math.tan(deg2Rad(self.fovH * 0.5)) * self.near * 2.0
self.nearHeight = math.tan(deg2Rad(self.fovV * 0.5)) * self.near * 2.0
self.left = -self.nearWidth * 0.5
self.right = self.nearWidth * 0.5
self.top = self.nearHeight * 0.5
self.bottom = -self.nearHeight * 0.5
def mouseUpdate(self):
# Mouse Data
# Last frame
self.mouseLastX = self.mouseX
self.mouseLastY = self.mouseY
# Values for this frame
# This ranges from -1 to 1
if (base.mouseWatcherNode.hasMouse()):
self.mouseX = base.mouseWatcherNode.getMouseX()
self.mouseY = base.mouseWatcherNode.getMouseY()
self.mouseX = (self.mouseX-self.originX)*self.scaleX
self.mouseY = (self.mouseY-self.originY)*self.scaleY
# Delta percent of window the mouse moved
self.mouseDeltaX = self.mouseX - self.mouseLastX
self.mouseDeltaY = self.mouseY - self.mouseLastY
self.nearVec.set((self.nearWidth*0.5) * self.mouseX,
self.near,
(self.nearHeight*0.5) * self.mouseY)
class DisplayRegionList(PandaObject):
def __init__(self):
self.displayRegionList = []
i = 0
# Things are funky if we are oobe
if (hasattr(base, 'oobeMode') and base.oobeMode):
# assume we only have one cam at this point
drc = DisplayRegionContext(base.cam)
self.displayRegionList.append(drc)
else:
# MRM: Doesn't properly handle multiple camera groups anymore
# Assumes everything is under main camera
# This is following the old way of setting up
# display regions. A display region is set up for
# each camera node in the scene graph. This was done
# so that only display regions in the scene graph are
# considered. The right way to do this is to set up
# a display region for each real display region, and then
# keep track of which are currently active (e.g. use a flag)
# processing only them.
for camIndex in range(len(base.camList)):
cam = base.camList[camIndex]
if cam.getName()=='<noname>':
cam.setName('Camera%d' % camIndex)
drc = DisplayRegionContext(cam)
self.displayRegionList.append(drc)
self.accept("DIRECT-mouse1",self.mouseUpdate)
self.accept("DIRECT-mouse2",self.mouseUpdate)
self.accept("DIRECT-mouse3",self.mouseUpdate)
self.accept("DIRECT-mouse1Up",self.mouseUpdate)
self.accept("DIRECT-mouse2Up",self.mouseUpdate)
self.accept("DIRECT-mouse3Up",self.mouseUpdate)
def __getitem__(self, index):
return self.displayRegionList[index]
def __len__(self):
return len(self.displayRegionList)
def updateContext(self):
self.contextTask(None)
def setNearFar(self, near, far):
for dr in self.displayRegionList:
dr.camLens.setNearFar(near, far)
def setNear(self, near):
for dr in self.displayRegionList:
dr.camLens.setNear(near)
def setFar(self, far):
for dr in self.displayRegionList:
dr.camLens.setFar(far)
def setFov(self, hfov, vfov):
for dr in self.displayRegionList:
dr.setFov(hfov, vfov)
def setHfov(self, fov):
for dr in self.displayRegionList:
dr.setHfov(fov)
def setVfov(self, fov):
for dr in self.displayRegionList:
dr.setVfov(fov)
def mouseUpdate(self, modifiers = DIRECT_NO_MOD):
for dr in self.displayRegionList:
dr.mouseUpdate()
SEditor.dr = self.getCurrentDr()
def getCurrentDr(self):
for dr in self.displayRegionList:
if (dr.mouseX >= -1.0 and dr.mouseX <= 1.0 and
dr.mouseY >= -1.0 and dr.mouseY <= 1.0):
return dr
return self.displayRegionList[0]
def start(self):
# First shutdown any existing task
self.stop()
# Start a new context task
self.spawnContextTask()
def stop(self):
# Kill the existing context task
taskMgr.remove('DIRECTContextTask')
def spawnContextTask(self):
taskMgr.add(self.contextTask, 'DIRECTContextTask')
def removeContextTask(self):
taskMgr.remove('DIRECTContextTask')
def contextTask(self, state):
# Window Data
self.mouseUpdate()
# hack to test movement
return Task.cont
# Create one
#__builtins__['direct'] = base.direct = DirectSession()

View File

@ -0,0 +1,459 @@
#################################################################
# sideWindow.py
# Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#################################################################
from AppShell import *
from TkGlobal import *
import seSceneGraphExplorer
import Floater
import Slider
import VectorWidgets
class sideWindow(AppShell):
#################################################################
# sideWindow(AppShell)
# This class will open a side window wich contains a scene graph and
# a world setting page.
#################################################################
appversion = '1.0'
appname = 'Navigation Window'
frameWidth = 325
frameHeight = 580
frameIniPosX = 0
frameIniPosY = 110
padx = 0
pady = 0
lightEnable = 0
ParticleEnable = 0
basedriveEnable = 0
collision = 0
backface = 0
texture = 1
wireframe = 0
enableBaseUseDrive = 0
def __init__(self, worldColor,lightEnable,ParticleEnable, basedriveEnable,collision,
backface, texture, wireframe, grid, widgetVis, enableAutoCamera, parent = None, nodePath = render, **kw):
self.worldColor = worldColor
self.lightEnable = lightEnable
self.ParticleEnable = ParticleEnable
self.basedriveEnable = basedriveEnable
self.collision = collision
self.backface = backface
self.texture = texture
self.wireframe = wireframe
self.grid = grid
self.enableAutoCamera = enableAutoCamera
self.widgetVis = widgetVis
# Define the megawidget options.
optiondefs = (
('title', self.appname, None),
)
self.defineoptions(kw, optiondefs)
if parent == None:
self.parent = Toplevel()
else:
self.parent = parent
AppShell.__init__(self, self.parent)
self.parent.geometry('%dx%d+%d+%d' % (self.frameWidth, self.frameHeight,self.frameIniPosX,self.frameIniPosY))
self.parent.resizable(False,False) ## Disable the ability to resize for this Window.
def appInit(self):
print '----SideWindow is Initialized!!'
def createInterface(self):
# The interior of the toplevel panel
interior = self.interior()
mainFrame = Frame(interior)
## Creat NoteBook
self.notebookFrame = Pmw.NoteBook(mainFrame)
self.notebookFrame.pack(fill=BOTH,expand=1)
sgePage = self.notebookFrame.add('Tree Graph')
envPage = self.notebookFrame.add('World Setting')
self.notebookFrame['raisecommand'] = self.updateInfo
## Tree Grapgh Page
self.SGE = seSceneGraphExplorer.seSceneGraphExplorer(
sgePage, nodePath = render,
scrolledCanvas_hull_width = 270,
scrolledCanvas_hull_height = 570)
self.SGE.pack(fill = BOTH, expand = 0)
## World Setting Page
envPage = Frame(envPage)
pageFrame = Frame(envPage)
self.LightingVar = IntVar()
self.LightingVar.set(self.lightEnable)
self.LightingButton = Checkbutton(
pageFrame,
text = 'Enable Lighting',
variable = self.LightingVar,
command = self.toggleLights)
self.LightingButton.pack(side=LEFT, expand=False)
pageFrame.pack(side=TOP, fill=X, expand=True)
pageFrame = Frame(envPage)
self.CollisionVar = IntVar()
self.CollisionVar.set(self.collision)
self.CollisionButton = Checkbutton(
pageFrame,
text = 'Show Collision Object',
variable = self.CollisionVar,
command = self.showCollision)
self.CollisionButton.pack(side=LEFT, expand=False)
pageFrame.pack(side=TOP, fill=X, expand=True)
pageFrame = Frame(envPage)
self.ParticleVar = IntVar()
self.ParticleVar.set(self.ParticleEnable)
self.ParticleButton = Checkbutton(
pageFrame,
text = 'Show Particle Dummy',
variable = self.ParticleVar,
command = self.enableParticle)
self.ParticleButton.pack(side=LEFT, expand=False)
pageFrame.pack(side=TOP, fill=X, expand=True)
pageFrame = Frame(envPage)
self.baseUseDriveVar = IntVar()
self.baseUseDriveVar.set(self.basedriveEnable)
self.baseUseDriveButton = Checkbutton(
pageFrame,
text = 'Enable base.usedrive',
variable = self.baseUseDriveVar,
command = self.enablebaseUseDrive)
self.baseUseDriveButton.pack(side=LEFT, expand=False)
pageFrame.pack(side=TOP, fill=X, expand=True)
pageFrame = Frame(envPage)
self.backfaceVar = IntVar()
self.backfaceVar.set(self.backface)
self.backfaceButton = Checkbutton(
pageFrame,
text = 'Enable BackFace',
variable = self.backfaceVar,
command = self.toggleBackface)
self.backfaceButton.pack(side=LEFT, expand=False)
pageFrame.pack(side=TOP, fill=X, expand=True)
pageFrame = Frame(envPage)
self.textureVar = IntVar()
self.textureVar.set(self.texture)
self.textureButton = Checkbutton(
pageFrame,
text = 'Enable Texture',
variable = self.textureVar,
command = self.toggleTexture)
self.textureButton.pack(side=LEFT, expand=False)
pageFrame.pack(side=TOP, fill=X, expand=True)
pageFrame = Frame(envPage)
self.wireframeVar = IntVar()
self.wireframeVar.set(self.wireframe)
self.wireframeButton = Checkbutton(
pageFrame,
text = 'Enable Wireframe',
variable = self.wireframeVar,
command = self.toggleWireframe)
self.wireframeButton.pack(side=LEFT, expand=False)
pageFrame.pack(side=TOP, fill=X, expand=True)
pageFrame = Frame(envPage)
self.gridVar = IntVar()
self.gridVar.set(self.grid)
self.gridButton = Checkbutton(
pageFrame,
text = 'Enable Grid',
variable = self.gridVar,
command = self.toggleGrid)
self.gridButton.pack(side=LEFT, expand=False)
pageFrame.pack(side=TOP, fill=X, expand=True)
pageFrame = Frame(envPage)
self.widgetVisVar = IntVar()
self.widgetVisVar.set(self.widgetVis)
self.widgetVisButton = Checkbutton(
pageFrame,
text = 'Enable WidgetVisible',
variable = self.widgetVisVar,
command = self.togglewidgetVis)
self.widgetVisButton.pack(side=LEFT, expand=False)
pageFrame.pack(side=TOP, fill=X, expand=True)
pageFrame = Frame(envPage)
self.enableAutoCameraVar = IntVar()
self.enableAutoCameraVar.set(self.enableAutoCamera)
self.enableAutoCameraButton = Checkbutton(
pageFrame,
text = 'Enable Auto Camera Movement for Loading Objects',
variable = self.enableAutoCameraVar,
command = self.toggleAutoCamera)
self.enableAutoCameraButton.pack(side=LEFT, expand=False)
pageFrame.pack(side=TOP, fill=X, expand=True)
pageFrame = Frame(envPage)
self.backgroundColor = VectorWidgets.ColorEntry(
pageFrame, text = 'BG Color', value=self.worldColor)
self.backgroundColor['command'] = self.setBackgroundColorVec
self.backgroundColor['resetValue'] = [0,0,0,0]
self.backgroundColor.pack(side=LEFT, expand=False)
self.bind(self.backgroundColor, 'Set background color')
pageFrame.pack(side=TOP, fill=X, expand=True)
envPage.pack(expand=False)
## Set all stuff done
self.notebookFrame.setnaturalsize()
mainFrame.pack(fill = 'both', expand = 1)
def createMenuBar(self):
# We don't need menu bar here.
self.menuBar.destroy()
def onDestroy(self, event):
#################################################################
# onDestroy(self, event)
# This function will be called when user closed the side window.
# Here we will send out a message with whole data set we will need
# for the next time user open the side window.
#################################################################
messenger.send('SW_close',[self.worldColor,
self.lightEnable,
self.ParticleEnable,
self.basedriveEnable,
self.collision,
self.backface,
self.texture,
self.wireframe,
self.grid,
self.widgetVis,
self.enableAutoCamera])
'''
If you have open any thing, please rewrite here!
'''
pass
###############################
def updateInfo(self, page = 'Tree Graph'):
#################################################################
# updateInfo(self, page = 'Tree Graph')
# This function will be called when each time user change the main
# page of the window.
# What it dose is to call right function to restore the data for current selected page.
#################################################################
if page=='Tree Graph':
self.updateTreeGraph()
elif page == 'World Setting':
self.updateWorldSetting()
def updateTreeGraph(self):
#################################################################
# updateTreeGraph(self)
# When scene graoh page has been opend, call sceneGraphExplorer to
# updata the tree.
#################################################################
self.SGE.update()
pass
def updateWorldSetting(self):
#################################################################
# updateWorldSetting(self)
# When world setting page has been selected, this function will
# reset those check box in the page to reflect the current world setting.
#################################################################
self.LightingVar.set(self.lightEnable)
self.CollisionVar.set(self.collision)
self.ParticleVar.set(self.ParticleEnable)
self.baseUseDriveVar.set(self.basedriveEnable)
self.backgroundColor.set(value = self.worldColor)
pass
def toggleLights(self):
#################################################################
# toggleLights(self)
# send out a message to let sceneEditor know we need to toggle the light.
# Then, sceneEditor will pass the message to dataHolder to disable/enable
# the lights. (lightManager is inside the dataHolder)
#################################################################
self.lightEnable = (self.lightEnable+1)%2
messenger.send('SW_lightToggle')
pass
def showCollision(self):
#################################################################
# showCollision(self)
# This function will send out a message to sceneEditor to toggle
# the visibility of collision objects.
#################################################################
self.collision = (self.collision+1)%2
messenger.send('SW_collisionToggle', [self.collision])
pass
def enableParticle(self):
#################################################################
# enableParticle(self)
# This function will send out a message to sceneEditor to toggle
# the visibility of particle objects.
#################################################################
self.ParticleEnable = (self.ParticleEnable+1)%2
messenger.send('SW_particleToggle', [self.ParticleEnable])
pass
def enablebaseUseDrive(self):
#################################################################
# enablebaseUseDrive(self)
# This function will toggle the usage of base.useDrive.
# Well, it may not usefull at all.
#
# We won't send out any message in this time to notice
# the sceneEditor this event happend.
# In the other hand, we will restore it back when
# the side window has been closed.
#
#################################################################
if self.enableBaseUseDrive==0:
print 'Enabled'
base.useDrive()
self.enableBaseUseDrive = 1
else:
print 'disabled'
#base.useTrackball()
base.disableMouse()
self.enableBaseUseDrive = 0
self.basedriveEnable = (self.basedriveEnable+1)%2
pass
def toggleBackface(self):
#################################################################
# toggleBackface(self)
# This function will toggle the back face setting. so it will
# render the polygon with two sides.
#################################################################
base.toggleBackface()
self.backface = (self.backface+1)%2
return
def toggleBackfaceFromMainW(self):
#################################################################
# toggleBackfaceFromMainW(self)
# This function is called by sceneEditor when user used hot key
# to toggle the back face setting in the main panda window.
# In here we will only reset the flag and reset the state of
# check box
#################################################################
self.backface = (self.backface+1)%2
self.backfaceButton.toggle()
return
def toggleTexture(self):
#################################################################
# toggleTexture(self)
# This function will toggle the txture using option for the whole scene.
#################################################################
base.toggleTexture()
self.texture = (self.texture+1)%2
return
def toggleTextureFromMainW(self):
#################################################################
# toggleTextureFromMainW(self)
# This function is called by sceneEditor when user used hot key
# to toggle the texture usage from the main panda window.
# In here we will only reset the flag and reset the state of
# check box
#################################################################
self.texture = (self.texture+1)%2
self.textureButton.toggle()
return
def toggleWireframe(self):
#################################################################
# toggleWireframe(self)
# This function will toggle the wire frame mode.
#################################################################
base.toggleWireframe()
self.wireframe = (self.wireframe+1)%2
return
def toggleWireframeFromMainW(self):
#################################################################
# toggleWireframeFromMainW(self)
# This function is called by sceneEditor when user used hot key
# to toggle the wire frame mode in the main panda window.
# In here we will only reset the flag and reset the state of
# check box
#################################################################
self.wireframe = (self.wireframe+1)%2
self.wireframeButton.toggle()
return
def toggleGrid(self):
#################################################################
# toggleGrid(self)
# This function will toggle the usage of the grid.
#################################################################
self.grid = (self.grid+1)%2
if self.grid==1:
SEditor.grid.enable()
else:
SEditor.grid.disable()
def togglewidgetVis(self):
#################################################################
# togglewidgetVis(self)
# This function will toggle the visibility of the widget of the grid.
#################################################################
self.widgetVis = (self.widgetVis+1)%2
SEditor.toggleWidgetVis()
if SEditor.widget.fActive:
messenger.send('shift-f')
return
def toggleWidgetVisFromMainW(self):
#################################################################
# toggleWidgetVisFromMainW(self)
# This function is called by sceneEditor when user used hot key
# to toggle the visibility of widgets ('v') from the main panda window.
# In here we will only reset the flag and reset the state of
# check box
#################################################################
self.widgetVis = (self.widgetVis+1)%2
self.widgetVisButton.toggle()
return
def setBackgroundColorVec(self,color):
#################################################################
# setBackgroundColorVec(self,color)
# Call back function
# This will be called from the colorEntry on the world setting page.
# The "color" here is a list containing three integer data, R, G and B.
#################################################################
base.setBackgroundColor(color[0]/255.0,
color[1]/255.0,
color[2]/255.0)
self.worldColor = [color[0],color[1],color[2],0]
def toggleAutoCamera(self):
#################################################################
# toggleAutoCamera(self)
# This function will toggle the usage of the auto-camera movement
# when user loaded model or actor into the scene.
#################################################################
self.enableAutoCamera = (self.enableAutoCamera+1)%2
SEditor.toggleAutoCamera()
return
def selectPage(self,page='Tree Graph'):
#################################################################
#################################################################
self.notebookFrame.selectpage(page)

View File

@ -0,0 +1,870 @@
<CoordinateSystem> { Z-Up }
<Comment> {
"MaxEggPlugin nul.max -o 'E:\sshadhan\Desktop\Spotlight.egg'"
}
<Texture> Tex1 {
"Spotlight.tif"
<Scalar> format { rgb }
<Scalar> wrapu { repeat }
<Scalar> wrapv { repeat }
<Scalar> minfilter { linear_mipmap_linear }
<Scalar> magfilter { linear }
}
<Group> Cone01 {
<Transform> {
<Matrix4> {
0.0976066 0 0 0
0 1.90047e-008 0.0976066 0
0 -0.0976066 1.90047e-008 0
0 0 0 1
}
}
<VertexPool> Cone01.verts {
<Vertex> 1 {
2.26078 5.50627 -1.06759e-013
<Normal> { 0.0849605 0.0480494 -7.35668e-009 }
<UV> { 0.701375 0.870481 }
}
<Vertex> 2 {
1.82901 5.50627 1.32885
<Normal> { 0.0687345 0.0480495 0.0499385 }
<UV> { 0.592975 0.870481 }
}
<Vertex> 3 {
0 -3.8396e-005 1.07212e-006
<Normal> { 0.0864707 -0.0355031 0.0280961 }
<UV> { 0.701375 0.421306 }
}
<Vertex> 4 {
0 -3.8396e-005 1.07212e-006
<Normal> { 0.0864707 -0.0355031 -0.028096 }
<UV> { 0.701375 0.421306 }
}
<Vertex> 5 {
1.82901 5.50627 1.32885
<Normal> { 0.0687345 0.0480495 0.0499385 }
<UV> { 0.328401 0.97 }
}
<Vertex> 6 {
0.698618 5.50627 2.15013
<Normal> { 0.0262543 0.0480495 0.0808022 }
<UV> { 0.23619 0.97 }
}
<Vertex> 7 {
0 -3.8396e-005 1.07212e-006
<Normal> { 0.0534418 -0.0355031 0.0735564 }
<UV> { 0.1792 0.520825 }
}
<Vertex> 8 {
0 -3.8396e-005 1.07212e-006
<Normal> { 0.0864707 -0.0355031 0.0280961 }
<UV> { 0.1792 0.520825 }
}
<Vertex> 9 {
-0.698619 5.50627 2.15013
<Normal> { -0.0262543 0.0480495 0.0808023 }
<UV> { 0.122211 0.97 }
}
<Vertex> 10 {
0 -3.8396e-005 1.07212e-006
<Normal> { 0 -0.0355031 0.0909207 }
<UV> { 0.1792 0.520825 }
}
<Vertex> 11 {
-1.82901 5.50627 1.32885
<Normal> { -0.0687345 0.0480495 0.0499385 }
<UV> { 0.03 0.97 }
}
<Vertex> 12 {
0 -3.8396e-005 1.07212e-006
<Normal> { -0.0534418 -0.0355031 0.0735564 }
<UV> { 0.1792 0.520825 }
}
<Vertex> 13 {
-1.82901 5.50627 1.32885
<Normal> { -0.0687345 0.0480495 0.0499385 }
<UV> { 0.572872 0.870481 }
}
<Vertex> 14 {
-2.26078 5.50627 -1.97643e-007
<Normal> { -0.0849605 0.0480494 -2.11178e-008 }
<UV> { 0.464471 0.870481 }
}
<Vertex> 15 {
0 -3.8396e-005 1.07212e-006
<Normal> { -0.0864707 -0.0355031 0.028096 }
<UV> { 0.464471 0.421306 }
}
<Vertex> 16 {
0 -3.8396e-005 1.07212e-006
<Normal> { -0.0534418 -0.0355031 0.0735564 }
<UV> { 0.464471 0.421306 }
}
<Vertex> 17 {
-1.82901 5.50627 -1.32885
<Normal> { -0.0687345 0.0480494 -0.0499386 }
<UV> { 0.356071 0.870481 }
}
<Vertex> 18 {
0 -3.8396e-005 1.07212e-006
<Normal> { -0.0864707 -0.0355031 -0.028096 }
<UV> { 0.464471 0.421306 }
}
<Vertex> 19 {
-1.82901 5.50627 -1.32885
<Normal> { -0.0687345 0.0480494 -0.0499386 }
<UV> { 0.328401 0.479175 }
}
<Vertex> 20 {
-0.698618 5.50627 -2.15013
<Normal> { -0.0262542 0.0480494 -0.0808023 }
<UV> { 0.23619 0.479175 }
}
<Vertex> 21 {
0 -3.8396e-005 1.07212e-006
<Normal> { -0.0534418 -0.0355031 -0.0735564 }
<UV> { 0.1792 0.03 }
}
<Vertex> 22 {
0 -3.8396e-005 1.07212e-006
<Normal> { -0.0864707 -0.0355031 -0.028096 }
<UV> { 0.1792 0.03 }
}
<Vertex> 23 {
0.698619 5.50627 -2.15013
<Normal> { 0.0262543 0.0480494 -0.0808023 }
<UV> { 0.122211 0.479175 }
}
<Vertex> 24 {
0 -3.8396e-005 1.07212e-006
<Normal> { 1.21144e-008 -0.0355031 -0.0909207 }
<UV> { 0.1792 0.03 }
}
<Vertex> 25 {
1.82901 5.50627 -1.32885
<Normal> { 0.0687345 0.0480495 -0.0499385 }
<UV> { 0.03 0.479175 }
}
<Vertex> 26 {
0 -3.8396e-005 1.07212e-006
<Normal> { 0.0534418 -0.0355031 -0.0735564 }
<UV> { 0.1792 0.03 }
}
<Vertex> 27 {
1.82901 5.50627 -1.32885
<Normal> { 0.0687345 0.0480495 -0.0499385 }
<UV> { 0.809776 0.870481 }
}
<Vertex> 28 {
0 -3.8396e-005 1.07212e-006
<Normal> { 0.0534418 -0.0355031 -0.0735564 }
<UV> { 0.701375 0.421306 }
}
<Vertex> 29 {
0.0729454 8.46019 -0.224503
<Normal> { 0.023082 0.0628309 -0.071039 }
<UV> { 0.396217 0.36432 }
}
<Vertex> 30 {
-0.0729452 8.46019 -0.224503
<Normal> { -0.023082 0.062831 -0.0710389 }
<UV> { 0.408118 0.36432 }
}
<Vertex> 31 {
-0.190973 8.46019 -0.138751
<Normal> { -0.0604293 0.062831 -0.0439046 }
<UV> { 0.417746 0.371315 }
}
<Vertex> 32 {
-0.236056 8.46019 -4.5556e-007
<Normal> { -0.0746948 0.062831 -5.86065e-008 }
<UV> { 0.421423 0.382634 }
}
<Vertex> 33 {
-0.190973 8.46019 0.13875
<Normal> { -0.0604293 0.062831 0.0439045 }
<UV> { 0.417746 0.393952 }
}
<Vertex> 34 {
-0.0729453 8.46019 0.224502
<Normal> { -0.0230819 0.062831 0.0710389 }
<UV> { 0.408118 0.400947 }
}
<Vertex> 35 {
0.0729452 8.46019 0.224502
<Normal> { 0.0230819 0.062831 0.0710389 }
<UV> { 0.396217 0.400947 }
}
<Vertex> 36 {
0.190973 8.46019 0.13875
<Normal> { 0.0604293 0.062831 0.0439046 }
<UV> { 0.386589 0.393952 }
}
<Vertex> 37 {
0.236056 8.46019 -6.38597e-007
<Normal> { 0.0746948 0.062831 2.14833e-008 }
<UV> { 0.382911 0.382634 }
}
<Vertex> 38 {
0.190973 8.46019 -0.138751
<Normal> { 0.0604294 0.062831 -0.0439045 }
<UV> { 0.386588 0.371315 }
}
<Vertex> 39 {
0 -3.8396e-005 1.07212e-006
<Normal> { 0.0534418 -0.0355031 0.0735564 }
<UV> { 0.701375 0.421306 }
}
<Vertex> 40 {
0 -3.8396e-005 1.07212e-006
<Normal> { 0 -0.0355031 0.0909207 }
<UV> { 0.701375 0.421306 }
}
<Vertex> 41 {
0 -3.8396e-005 1.07212e-006
<Normal> { -0.0534418 -0.0355031 0.0735564 }
<UV> { 0.701375 0.421306 }
}
<Vertex> 42 {
0 -3.8396e-005 1.07212e-006
<Normal> { -0.0864707 -0.0355031 0.028096 }
<UV> { 0.701375 0.421306 }
}
<Vertex> 43 {
0 -3.8396e-005 1.07212e-006
<Normal> { -0.0864707 -0.0355031 -0.028096 }
<UV> { 0.701375 0.421306 }
}
<Vertex> 44 {
0 -3.8396e-005 1.07212e-006
<Normal> { -0.0534418 -0.0355031 -0.0735564 }
<UV> { 0.701375 0.421306 }
}
<Vertex> 45 {
0 -3.8396e-005 1.07212e-006
<Normal> { 1.21144e-008 -0.0355031 -0.0909207 }
<UV> { 0.701375 0.421306 }
}
<Vertex> 46 {
1.82901 5.50627 1.32885
<Normal> { 0.0687345 0.0480495 0.0499385 }
<UV> { 0.639867 0.363622 }
}
<Vertex> 47 {
2.26078 5.50627 -1.06759e-013
<Normal> { 0.0849605 0.0480494 -7.35668e-009 }
<UV> { 0.531466 0.398844 }
}
<Vertex> 48 {
0.236056 5.50627 -6.34468e-008
<Normal> { 0.0606261 0.0764952 -9.18613e-009 }
<UV> { 0.531466 0.233678 }
}
<Vertex> 49 {
0.190973 5.50627 0.13875
<Normal> { 0.0490475 0.0764952 0.0356352 }
<UV> { 0.542785 0.23 }
}
<Vertex> 50 {
1.82901 5.50627 -1.32885
<Normal> { 0.0687345 0.0480495 -0.0499385 }
<UV> { 0.423066 0.363622 }
}
<Vertex> 51 {
0.190973 5.50627 -0.13875
<Normal> { 0.0490476 0.0764952 -0.0356351 }
<UV> { 0.520148 0.23 }
}
<Vertex> 52 {
0.698619 5.50627 -2.15013
<Normal> { 0.0262543 0.0480494 -0.0808023 }
<UV> { 0.356071 0.271411 }
}
<Vertex> 53 {
0.0729454 5.50627 -0.224503
<Normal> { 0.0187345 0.0764952 -0.0576588 }
<UV> { 0.513153 0.220372 }
}
<Vertex> 54 {
-0.698618 5.50627 -2.15013
<Normal> { -0.0262542 0.0480494 -0.0808023 }
<UV> { 0.356071 0.157432 }
}
<Vertex> 55 {
-0.0729452 5.50627 -0.224502
<Normal> { -0.0187345 0.0764952 -0.0576589 }
<UV> { 0.513153 0.208471 }
}
<Vertex> 56 {
-1.82901 5.50627 -1.32885
<Normal> { -0.0687345 0.0480494 -0.0499386 }
<UV> { 0.423066 0.0652215 }
}
<Vertex> 57 {
-0.190973 5.50627 -0.13875
<Normal> { -0.0490475 0.0764952 -0.0356352 }
<UV> { 0.520148 0.198843 }
}
<Vertex> 58 {
-2.26078 5.50627 -1.97643e-007
<Normal> { -0.0849605 0.0480494 -2.11178e-008 }
<UV> { 0.531466 0.03 }
}
<Vertex> 59 {
-0.236056 5.50627 1.1959e-007
<Normal> { -0.0606261 0.0764952 -3.15091e-008 }
<UV> { 0.531466 0.195166 }
}
<Vertex> 60 {
-1.82901 5.50627 1.32885
<Normal> { -0.0687345 0.0480495 0.0499385 }
<UV> { 0.639867 0.0652214 }
}
<Vertex> 61 {
-0.190973 5.50627 0.13875
<Normal> { -0.0490475 0.0764952 0.0356351 }
<UV> { 0.542785 0.198843 }
}
<Vertex> 62 {
-0.698619 5.50627 2.15013
<Normal> { -0.0262543 0.0480495 0.0808023 }
<UV> { 0.706862 0.157432 }
}
<Vertex> 63 {
-0.0729453 5.50627 0.224502
<Normal> { -0.0187344 0.0764952 0.0576589 }
<UV> { 0.54978 0.208471 }
}
<Vertex> 64 {
0.698618 5.50627 2.15013
<Normal> { 0.0262543 0.0480495 0.0808022 }
<UV> { 0.706862 0.271411 }
}
<Vertex> 65 {
0.0729452 5.50627 0.224502
<Normal> { 0.0187345 0.0764952 0.0576589 }
<UV> { 0.54978 0.220372 }
}
<Vertex> 66 {
0.190973 5.50627 0.13875
<Normal> { 0.0490475 0.0764952 0.0356352 }
<UV> { 0.829879 0.684615 }
}
<Vertex> 67 {
0.236056 5.50627 -6.34468e-008
<Normal> { 0.0606261 0.0764952 -9.18613e-009 }
<UV> { 0.841198 0.684615 }
}
<Vertex> 68 {
0.236056 8.46019 -6.38597e-007
<Normal> { 0.0746948 0.062831 2.14833e-008 }
<UV> { 0.841198 0.92558 }
}
<Vertex> 69 {
0.190973 8.46019 0.13875
<Normal> { 0.0604293 0.062831 0.0439046 }
<UV> { 0.829879 0.92558 }
}
<Vertex> 70 {
0.190973 5.50627 -0.13875
<Normal> { 0.0490476 0.0764952 -0.0356351 }
<UV> { 0.852516 0.684615 }
}
<Vertex> 71 {
0.190973 8.46019 -0.138751
<Normal> { 0.0604294 0.062831 -0.0439045 }
<UV> { 0.852516 0.92558 }
}
<Vertex> 72 {
0.190973 5.50627 -0.13875
<Normal> { 0.0490476 0.0764952 -0.0356351 }
<UV> { 0.728225 0.03 }
}
<Vertex> 73 {
0.0729454 5.50627 -0.224503
<Normal> { 0.0187345 0.0764952 -0.0576588 }
<UV> { 0.737853 0.03 }
}
<Vertex> 74 {
0.0729454 8.46019 -0.224503
<Normal> { 0.023082 0.0628309 -0.071039 }
<UV> { 0.737853 0.270965 }
}
<Vertex> 75 {
0.190973 8.46019 -0.138751
<Normal> { 0.0604294 0.062831 -0.0439045 }
<UV> { 0.728225 0.270965 }
}
<Vertex> 76 {
-0.0729452 5.50627 -0.224502
<Normal> { -0.0187345 0.0764952 -0.0576589 }
<UV> { 0.749754 0.03 }
}
<Vertex> 77 {
-0.0729452 8.46019 -0.224503
<Normal> { -0.023082 0.062831 -0.0710389 }
<UV> { 0.749754 0.270965 }
}
<Vertex> 78 {
-0.190973 5.50627 -0.13875
<Normal> { -0.0490475 0.0764952 -0.0356352 }
<UV> { 0.759382 0.03 }
}
<Vertex> 79 {
-0.190973 8.46019 -0.138751
<Normal> { -0.0604293 0.062831 -0.0439046 }
<UV> { 0.759382 0.270965 }
}
<Vertex> 80 {
-0.190973 5.50627 -0.13875
<Normal> { -0.0490475 0.0764952 -0.0356352 }
<UV> { 0.762271 0.03 }
}
<Vertex> 81 {
-0.236056 5.50627 1.1959e-007
<Normal> { -0.0606261 0.0764952 -3.15091e-008 }
<UV> { 0.77359 0.03 }
}
<Vertex> 82 {
-0.236056 8.46019 -4.5556e-007
<Normal> { -0.0746948 0.062831 -5.86065e-008 }
<UV> { 0.77359 0.270965 }
}
<Vertex> 83 {
-0.190973 8.46019 -0.138751
<Normal> { -0.0604293 0.062831 -0.0439046 }
<UV> { 0.762271 0.270965 }
}
<Vertex> 84 {
-0.190973 5.50627 0.13875
<Normal> { -0.0490475 0.0764952 0.0356351 }
<UV> { 0.784908 0.03 }
}
<Vertex> 85 {
-0.190973 8.46019 0.13875
<Normal> { -0.0604293 0.062831 0.0439045 }
<UV> { 0.784908 0.270965 }
}
<Vertex> 86 {
-0.190973 5.50627 0.13875
<Normal> { -0.0490475 0.0764952 0.0356351 }
<UV> { 0.829879 0.421306 }
}
<Vertex> 87 {
-0.0729453 5.50627 0.224502
<Normal> { -0.0187344 0.0764952 0.0576589 }
<UV> { 0.839507 0.421306 }
}
<Vertex> 88 {
-0.0729453 8.46019 0.224502
<Normal> { -0.0230819 0.062831 0.0710389 }
<UV> { 0.839507 0.662271 }
}
<Vertex> 89 {
-0.190973 8.46019 0.13875
<Normal> { -0.0604293 0.062831 0.0439045 }
<UV> { 0.829879 0.662271 }
}
<Vertex> 90 {
0.0729452 5.50627 0.224502
<Normal> { 0.0187345 0.0764952 0.0576589 }
<UV> { 0.851408 0.421306 }
}
<Vertex> 91 {
0.0729452 8.46019 0.224502
<Normal> { 0.0230819 0.062831 0.0710389 }
<UV> { 0.851408 0.662271 }
}
<Vertex> 92 {
0.190973 5.50627 0.13875
<Normal> { 0.0490475 0.0764952 0.0356352 }
<UV> { 0.861036 0.421306 }
}
<Vertex> 93 {
0.190973 8.46019 0.13875
<Normal> { 0.0604293 0.062831 0.0439046 }
<UV> { 0.861036 0.662271 }
}
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 1 2 3 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 3 4 1 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 5 6 7 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 7 8 5 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 6 9 10 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 10 7 6 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 9 11 12 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 12 10 9 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 13 14 15 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 15 16 13 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 14 17 18 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 18 15 14 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 19 20 21 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 21 22 19 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 20 23 24 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 24 21 20 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 23 25 26 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 26 24 23 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 27 1 4 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 4 28 27 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 29 30 31 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 31 32 33 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 33 34 35 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 35 36 37 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 33 35 37 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 31 33 37 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 29 31 37 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 38 29 37 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 3 39 40 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 40 41 42 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 42 43 44 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 44 45 28 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 42 44 28 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 40 42 28 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 3 40 28 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 4 3 28 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 46 47 48 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 48 49 46 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 47 50 51 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 51 48 47 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 50 52 53 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 53 51 50 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 52 54 55 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 55 53 52 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 54 56 57 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 57 55 54 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 56 58 59 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 59 57 56 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 58 60 61 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 61 59 58 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 60 62 63 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 63 61 60 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 62 64 65 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 65 63 62 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 64 46 49 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 49 65 64 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 66 67 68 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 68 69 66 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 67 70 71 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 71 68 67 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 72 73 74 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 74 75 72 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 73 76 77 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 77 74 73 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 76 78 79 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 79 77 76 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 80 81 82 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 82 83 80 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 81 84 85 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 85 82 81 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 86 87 88 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 88 89 86 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 87 90 91 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 91 88 87 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 90 92 93 <Ref> { Cone01.verts } }
}
<Polygon> {
<RGBA> { 1 1 1 1 }
<TRef> { Tex1 }
<VertexRef> { 93 91 90 <Ref> { Cone01.verts } }
}
}

View File

@ -0,0 +1,302 @@
#################################################################
# collisionWindow.py
# Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#################################################################
# Import Tkinter, Pmw, and the floater code from this directory tree.
from AppShell import *
from TkGlobal import *
from seColorEntry import *
import VectorWidgets
import Floater
import Slider
import string
import math
import types
class collisionWindow(AppShell):
#################################################################
# This will open a talk window for user to set the collision object
# In here, we won't finish the whole process to generate the
# collision object, half of process will be finished by dataHolder.
#################################################################
# Override class variables
appname = 'Creating Collision Object'
frameWidth = 600
frameHeight = 300
widgetsDict = {}
# Define the types of collision we take care here
collisionType = ['collisionPolygon',
'collisionSphere',
'collisionSegment',
'collisionRay']
def __init__(self, nodePath, parent = None, **kw):
self.nodePath = nodePath
self.objType = 'collisionSphere' # set default type to Collision Sphere
INITOPT = Pmw.INITOPT
optiondefs = (
('title', self.appname, None),
)
self.defineoptions(kw, optiondefs)
# Initialize the superclass
AppShell.__init__(self)
# Execute option callbacks
self.initialiseoptions(collisionWindow)
self.parent.resizable(False,False) ## Disable the ability to resize for this Window.
def createInterface(self):
# Handle to the toplevels interior
interior = self.interior()
menuBar = self.menuBar
self.menuBar.destroy()
# Create a frame to hold all stuff
mainFrame = Frame(interior)
frame = Frame(mainFrame)
self.collisionTypeEntry = self.createcomponent(
'Collision Type', (), None,
Pmw.ComboBox, (frame,),
labelpos = W, label_text='Collision Object Type:', entry_width = 20,
selectioncommand = self.setObjectType,
scrolledlist_items = self.collisionType)
self.collisionTypeEntry.pack(side=LEFT, padx=3)
label = Label(frame, text='Parent NodePath: '+ self.nodePath.getName(), font=('MSSansSerif', 12),
relief = RIDGE)
label.pack(side=LEFT,expand=0,fill=X, padx=20)
frame.pack(side=TOP, fill=X, expand=True, padx=3)
self.collisionTypeEntry.selectitem('collisionSphere', setentry=True)
self.inputZone = Pmw.Group(mainFrame, tag_pyclass = None)
self.inputZone.pack(fill='both',expand=1)
settingFrame = self.inputZone.interior()
############################################
# Notebook pages for specific object setting
############################################
self.objNotebook = Pmw.NoteBook(settingFrame, tabpos = None,
borderwidth = 0)
PolygonPage = self.objNotebook.add('Polygon')
SpherePage = self.objNotebook.add('Sphere')
SegmentPage = self.objNotebook.add('Segment')
RayPage = self.objNotebook.add('Ray')
self.objNotebook.selectpage('Sphere')
# Put this here so it isn't called right away
self.objNotebook['raisecommand'] = self.updateObjInfo
# Polygon object setting
Interior = Frame(PolygonPage)
label = Label(Interior, text='Attention! All Coordinates Are Related To Its Parent Node!')
label.pack(side=LEFT,expand=0,fill=X, padx=1)
Interior.pack(side=TOP, expand=0,fill=X)
self.createPosEntry(PolygonPage, catagory='Polygon', id='Point A')
self.createPosEntry(PolygonPage, catagory='Polygon', id='Point B')
self.createPosEntry(PolygonPage, catagory='Polygon', id='Point C')
# Sphere object setting
Interior = Frame(SpherePage)
label = Label(Interior, text='Attention! All Coordinates Are Related To Its Parent Node!')
label.pack(side=LEFT,expand=0,fill=X, padx=1)
Interior.pack(side=TOP, expand=0,fill=X)
self.createPosEntry(SpherePage, catagory='Sphere', id='Center Point')
self.createEntryField(SpherePage,catagory='Sphere', id='Size',
value = 1.0,
command = None,
initialState='normal',
side = 'top')
# Segment object setting
Interior = Frame(SegmentPage)
label = Label(Interior, text='Attention! All Coordinates Are Related To Its Parent Node!')
label.pack(side=LEFT,expand=0,fill=X, padx=1)
Interior.pack(side=TOP, expand=0,fill=X)
self.createPosEntry(SegmentPage, catagory='Segment', id='Point A')
self.createPosEntry(SegmentPage, catagory='Segment', id='Point B')
# Ray object setting
Interior = Frame(RayPage)
label = Label(Interior, text='Attention! All Coordinates Are Related To Its Parent Node!')
label.pack(side=LEFT,expand=0,fill=X, padx=1)
Interior.pack(side=TOP, expand=0,fill=X)
self.createPosEntry(RayPage, catagory='Ray', id='Origin')
self.createPosEntry(RayPage, catagory='Ray', id='Direction')
self.objNotebook.setnaturalsize()
self.objNotebook.pack(expand = 1, fill = BOTH)
self.okButton = Button(mainFrame, text="OK", command=self.okPress,width=10)
self.okButton.pack(fill=BOTH,expand=0,side=RIGHT)
mainFrame.pack(expand=1, fill = BOTH)
def onDestroy(self, event):
messenger.send('CW_close')
'''
If you have open any thing, please rewrite here!
'''
pass
def setObjectType(self, typeName = 'collisionSphere'):
#################################################################
# setObjectType(self, typeName = 'collisionSphere')
# Call back function
# This function will be called when user select target collision
# type on the combo box on the panel.
# Basically, this function's job is to switch the notebook page to right one.
#################################################################
self.objType = typeName
if self.objType=='collisionPolygon':
self.objNotebook.selectpage('Polygon')
elif self.objType=='collisionSphere':
self.objNotebook.selectpage('Sphere')
elif self.objType=='collisionSegment':
self.objNotebook.selectpage('Segment')
elif self.objType=='collisionRay':
self.objNotebook.selectpage('Ray')
return
def updateObjInfo(self, page=None):
#################################################################
# Nothing. Unlike in the lighting panel, we don't have to keep data
# once user switch the page.
#################################################################
return
def okPress(self):
#################################################################
# okPress(self)
# This function will be called when user click on the Ok button.
# Then this function will collect all parameters that we need to create
# a collision Object from the panel and generate the colision Object.
# In the last, it will send the object out with a message to dataHolder to
# put the object into a CollisionNode and attach it to the target nodePath
#################################################################
collisionObject = None
print self.objType
if self.objType=='collisionPolygon':
pointA = Point3(float(self.widgetDict['PolygonPoint A'][0]._entry.get()),
float(self.widgetDict['PolygonPoint A'][1]._entry.get()),
float(self.widgetDict['PolygonPoint A'][2]._entry.get()))
pointB = Point3(float(self.widgetDict['PolygonPoint B'][0]._entry.get()),
float(self.widgetDict['PolygonPoint B'][1]._entry.get()),
float(self.widgetDict['PolygonPoint B'][2]._entry.get()))
pointC = Point3(float(self.widgetDict['PolygonPoint C'][0]._entry.get()),
float(self.widgetDict['PolygonPoint C'][1]._entry.get()),
float(self.widgetDict['PolygonPoint C'][2]._entry.get()))
collisionObject = CollisionPolygon(pointA, pointB, pointC)
elif self.objType=='collisionSphere':
collisionObject = CollisionSphere(float(self.widgetDict['SphereCenter Point'][0]._entry.get()),
float(self.widgetDict['SphereCenter Point'][1]._entry.get()),
float(self.widgetDict['SphereCenter Point'][2]._entry.get()),
float(self.widgetDict['SphereSize'].getvalue()))
elif self.objType=='collisionSegment':
pointA = Point3(float(self.widgetDict['SegmentPoint A'][0]._entry.get()),
float(self.widgetDict['SegmentPoint A'][1]._entry.get()),
float(self.widgetDict['SegmentPoint A'][2]._entry.get()))
pointB = Point3(float(self.widgetDict['SegmentPoint B'][0]._entry.get()),
float(self.widgetDict['SegmentPoint B'][1]._entry.get()),
float(self.widgetDict['SegmentPoint B'][2]._entry.get()))
collisionObject = CollisionSegment()
collisionObject.setPointA(pointA)
collisionObject.setFromLens(base.cam.node(), Point2( -1, 1 )) ## You must set up the camera lensNode before you set point B....
collisionObject.setPointB(pointB)
elif self.objType=='collisionRay':
point = Point3(float(self.widgetDict['RayOrigin'][0]._entry.get()),
float(self.widgetDict['RayOrigin'][1]._entry.get()),
float(self.widgetDict['RayOrigin'][2]._entry.get()))
vector = Vec3(float(self.widgetDict['RayDirection'][0]._entry.get()),
float(self.widgetDict['RayDirection'][1]._entry.get()),
float(self.widgetDict['RayDirection'][2]._entry.get()))
print vector, point
collisionObject = CollisionRay()
collisionObject.setOrigin(point)
collisionObject.setDirection(vector)
#collisionObject.setFromLens(base.cam.node(), Point2( -1, 1 )) ## You must set up the camera lensNode before you set up others...
if self.objType=='collisionPolygon':
messenger.send('CW_addCollisionObj', [collisionObject, self.nodePath, pointA, pointB, pointC])
else:
messenger.send('CW_addCollisionObj', [collisionObject, self.nodePath])
self.quit()
return
def createPosEntry(self, contentFrame, catagory, id):
posInterior = Frame(contentFrame)
label = Label(posInterior, text=id+':')
label.pack(side=LEFT,expand=0,fill=X, padx=1)
self.posX = self.createcomponent('posX'+catagory+id, (), None,
Floater.Floater, (posInterior,),
text = 'X', relief = FLAT,
value = 0.0,
entry_width = 6)
self.posX.pack(side=LEFT,expand=0,fill=X, padx=1)
self.posY = self.createcomponent('posY'+catagory+id, (), None,
Floater.Floater, (posInterior,),
text = 'Y', relief = FLAT,
value = 0.0,
entry_width = 6)
self.posY.pack(side=LEFT, expand=0,fill=X, padx=1)
self.posZ = self.createcomponent('posZ'+catagory+id, (), None,
Floater.Floater, (posInterior,),
text = 'Z', relief = FLAT,
value = 0.0,
entry_width = 6)
self.posZ.pack(side=LEFT, expand=0,fill=X, padx=1)
self.widgetDict[catagory+id]=[self.posX, self.posY, self.posZ]
posInterior.pack(side=TOP, expand=0,fill=X, padx=3, pady=3)
return
def createEntryField(self, parent, catagory, id, value,
command, initialState, labelWidth = 6,
side = 'left', fill = X, expand = 0,
validate = None,
defaultButton = False, buttonText = 'Default',defaultFunction = None ):
frame = Frame(parent)
widget = Pmw.EntryField(frame, labelpos='w', label_text = id+':',
value = value, entry_font=('MSSansSerif', 10),label_font=('MSSansSerif', 10),
modifiedcommand=command, validate = validate,
label_width = labelWidth)
widget.configure(entry_state = initialState)
widget.pack(side=LEFT)
self.widgetDict[catagory+id] = widget
if defaultButton and (defaultFunction!=None):
widget = Button(frame, text=buttonText, font=('MSSansSerif', 10), command = defaultFunction)
widget.pack(side=LEFT, padx=3)
self.widgetDict[catagory+id+'-'+'DefaultButton']=widget
frame.pack(side = side, fill = fill, expand = expand,pady=3)

View File

@ -0,0 +1,697 @@
#################################################################
# controllerWindow.py
# Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#################################################################
# Import Tkinter, Pmw, and the floater code from this directory tree.
from AppShell import *
from TkGlobal import *
import VectorWidgets
import Floater
import string
# Define the Category
KEYBORAD = 'Keyboard-'
TRACKER = 'Tarcker-'
class controllerWindow(AppShell):
#################################################################
# This will open a talk window for user to set the control mechanism
# In here, user can choose to control what object by keyboard or other inputs.
#################################################################
# Override class variables
appname = 'Controller Panel'
frameWidth = 500
frameHeight = 500
widgetsDict = {} # category-id : widget obj
# setup the type of controller we handle here.
controllerList = ['Keyboard',
'Tracker']
# Default Keyboard setting
keyboardMapDict = {}
keyboardSpeedDict = {}
def __init__(self, listOfObj, controlType , dataList, parent = None, **kw):
if controlType == 'Keyboard':
self.nodePath = dataList[0] # Default setting -> mainly used for Keyboard control now.
self.nameOfNode = self.nodePath.getName()
self.controllType = 'Keyboard'
self.keyboardMapDict.clear()
self.keyboardMapDict = dataList[1]
self.keyboardSpeedDict.clear()
self.keyboardSpeedDict = dataList[2]
self.listOfObj = listOfObj
self.keepControl = False
INITOPT = Pmw.INITOPT
optiondefs = (
('title', self.appname, None),
)
self.defineoptions(kw, optiondefs)
# Initialize the superclass
AppShell.__init__(self)
# Execute option callbacks
self.initialiseoptions(controllerWindow)
self.parent.resizable(False,False) ## Disable the ability to resize for this Window.
def createInterface(self):
# Handle to the toplevels interior
interior = self.interior()
menuBar = self.menuBar
# We don't need menu bar here
self.menuBar.destroy()
# Create a frame to hold all stuff
mainFrame = Frame(interior)
# A comboBox to switch the controller
frame = Frame(mainFrame)
self.cotrollerTypeEntry = self.createcomponent(
'Controller Type', (), None,
Pmw.ComboBox, (frame,),
labelpos = W, label_text='Controller Type:', entry_width = 20,entry_state = DISABLED,
selectioncommand = self.setControllerType,
scrolledlist_items = self.controllerList)
self.cotrollerTypeEntry.pack(side=LEFT)
frame.pack(side=TOP, fill=X, expand=False, pady = 3)
self.cotrollerTypeEntry.selectitem('Keyboard', setentry=True)
self.inputZone = Pmw.Group(mainFrame, tag_pyclass = None)
self.inputZone.pack(fill='both',expand=1)
settingFrame = self.inputZone.interior()
###################################################
# Notebook pages for specific controller setting #
###################################################
self.contentWidge = self.createcomponent(
'scrolledFrame',
(), None,
Pmw.ScrolledFrame, (settingFrame,),
hull_width = 200, hull_height = 300,
usehullsize = 1)
self.contentFrame = self.contentWidge.component('frame')
self.contentWidge.pack(fill = 'both', expand = 1,padx = 3, pady = 5)
self.objNotebook = Pmw.NoteBook(self.contentFrame, tabpos = None,
borderwidth = 0)
keyboardPage = self.objNotebook.add('Keyboard')
tarckerPage = self.objNotebook.add('Tracker')
self.objNotebook.selectpage('Keyboard')
self.objNotebook.pack(side = TOP, fill='both',expand=False)
# Put this here so it isn't called right away
self.objNotebook['raisecommand'] = self.updateControlInfo
# Keyboard setting
assignFrame = Frame(keyboardPage)
Interior = Frame(assignFrame)
widget = self.createcomponent(
'Target Type', (), None,
Pmw.ComboBox, (Interior,),
labelpos = W, label_text='Target Object:', entry_width = 20, entry_state = DISABLED,
selectioncommand = self.setTargetObj,
scrolledlist_items = self.listOfObj)
widget.pack(side=LEFT, padx=3)
Interior.pack(side=TOP, fill=X, expand=True, pady = 5)
widget.selectitem(self.nameOfNode, setentry=True)
self.widgetsDict[KEYBORAD+'ObjList'] = widget
inputZone = Pmw.Group(assignFrame, tag_pyclass = None)
inputZone.pack(fill='both',expand=1)
settingFrame = inputZone.interior()
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Assign a Key For:').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True,pady = 6 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Forward :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Forward key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyForward'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyForward'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Forward Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedForward'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedForward'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Backward :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Backward key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyBackward'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyBackward'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Backward Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedBackward'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedBackward'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Right :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Right key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyRight'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyRight'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Right Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedRight'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedRight'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Left :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Left key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyLeft'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyLeft'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Left Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedLeft'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedLeft'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Up :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Up key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyUp'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyUp'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Up Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedUp'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedUp'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Down :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Down key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyDown'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyDown'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Down Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedDown'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedDown'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Turn Right:', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Turn Right key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyTurnRight'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyTurnRight'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Turn Right Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedTurnRight'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedTurnRight'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Turn Left :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Turn Left key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyTurnLeft'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyTurnLeft'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Turn Left Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedTurnLeft'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedTurnLeft'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Turn UP :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Turn UP key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyTurnUp'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyTurnUp'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Turn UP Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedTurnUp'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedTurnUp'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Turn Down :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Turn Down key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyTurnDown'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyTurnDown'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Turn Down Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedTurnDown'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedTurnDown'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Roll Right:', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Roll Right key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyRollRight'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyRollRight'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Roll Right Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedRollRight'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedRollRight'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Roll Left :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Roll Left key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyRollLeft'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyRollLeft'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Roll Left Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedRollLeft'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedRollLeft'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Scale UP :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale UP key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyScaleUp'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyScaleUp'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale UP Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedScaleUp'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedScaleUp'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Scale Down:', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale Down key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyScaleDown'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyScaleDown'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale Down Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedScaleDown'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedScaleDown'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Scale X UP :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale X UP key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyScaleXUp'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyScaleXUp'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale X UP Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedScaleXUp'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedScaleXUp'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Scale X Down:', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale X Down key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyScaleXDown'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyScaleXDown'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale Down X Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedScaleXDown'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedScaleXDown'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Scale Y UP :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale Y UP key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyScaleYUp'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyScaleYUp'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale Y UP Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedScaleYUp'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedScaleYUp'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Scale Y Down:', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale Y Down key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyScaleYDown'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyScaleYDown'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale Down XY Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedScaleYDown'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedScaleYDown'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Scale Z UP :', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale Z UP key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyScaleZUp'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyScaleZUp'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale Z UP Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedScaleZUp'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedScaleZUp'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
Interior = Frame(settingFrame)
widget = Label(Interior, text = 'Scale Z Down:', width = 20, anchor = W).pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale Z Down key', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardMapDict['KeyScaleZDown'],
labelpos = W, label_text='Key :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'KeyScaleZDown'] = widget
widget = Label(Interior, text = ' ').pack(side=LEFT, expand = False)
widget = self.createcomponent(
'Scale Down Z Speed', (), None,
Pmw.EntryField, (Interior,),
value = self.keyboardSpeedDict['SpeedScaleZDown'],
labelpos = W, label_text='Speed :', entry_width = 10)
widget.pack(side=LEFT, expand = False)
self.widgetsDict[KEYBORAD+'SpeedScaleZDown'] = widget
widget = Label(Interior, text = 'Per Seceond').pack(side=LEFT, expand = False)
Interior.pack(side=TOP, fill=X, expand=True, pady = 4 )
assignFrame.pack(side=TOP, expand=True, fill = X)
keyboardPage.pack(side=TOP, expand=True, fill = X)
####################################################################
####################################################################
# End of Keyboard control page
####################################################################
####################################################################
# Pack the mainFrame
frame = Frame(mainFrame)
widget = Button(frame, text='OK', width = 13, command=self.ok_press).pack(side=RIGHT)
widget = Button(frame, text='Enable Control', width = 13, command=self.enableControl).pack(side=LEFT)
widget = Button(frame, text='Disable Control', width = 13, command=self.disableControl).pack(side=LEFT)
widget = Button(frame, text='Save & Keep', width = 13, command=self.saveKeepControl).pack(side=LEFT)
frame.pack(side = BOTTOM, expand=1, fill = X)
mainFrame.pack(expand=1, fill = BOTH)
def onDestroy(self, event):
# Check if user wish to keep the control after the window closed.
if not self.keepControl:
messenger.send('ControlW_controlDisable',[self.controllType])
messenger.send('ControlW_close')
'''
If you have open any thing, please rewrite here!
'''
pass
def ok_press(self):
####################################################################
# ok_press(self)
# After user clicked on "OK" button, this function will be called.
# This function will collect data from the panel and send it back to
# sceneEditor and close the window. It won't activate control at all.
####################################################################
if self.controllType=='Keyboard':
for index in self.keyboardMapDict:
self.keyboardMapDict[index] = self.widgetsDict['Keyboard-'+index].getvalue()
for index in self.keyboardSpeedDict:
self.keyboardSpeedDict[index] = float(self.widgetsDict['Keyboard-'+index].getvalue())
messenger.send('ControlW_controlSetting', ['Keyboard', [self.nodePath, self.keyboardMapDict, self.keyboardSpeedDict]])
self.quit()
return
def enableControl(self):
####################################################################
# enableControl(self)
# Call back function.
# THis function will be called each time when user clicks on the
# "Enable Control" button. This function will do pretty much
# the same thing with ok_press function, except that this function
# will activate the control process in sceneEditor.
# However, if user didn't click on the button "Keep ANd Save,"
# the control process will be terminated when user closed the panel.
####################################################################
if self.controllType=='Keyboard':
for index in self.keyboardMapDict:
self.keyboardMapDict[index] = self.widgetsDict['Keyboard-'+index].getvalue()
for index in self.keyboardSpeedDict:
self.keyboardSpeedDict[index] = float(self.widgetsDict['Keyboard-'+index].getvalue())
messenger.send('ControlW_controlEnable', ['Keyboard', [self.nodePath, self.keyboardMapDict, self.keyboardSpeedDict]])
return
def disableControl(self):
####################################################################
# disableControl(self)
# This function will send out a message to sceneEditor to stop the
# control task.
####################################################################
messenger.send('ControlW_controlDisable',[self.controllType])
return
def setControllerType(self, typeName = 'Keyboard'):
#################################################################
# setControllerType(self, typeName = 'Keyboard')
# Call back function
# This function will be called when user select the type of
# controller they want on the combo box on the panel.
# Basically, this function's job is to switch the notebook page to right one.
#################################################################
self.controllType = typeName
if self.controllType=='Keyboard':
self.objNotebook.selectpage('Keyboard')
elif self.controllType=='Tracker':
self.objNotebook.selectpage('Tracker')
return
def updateControlInfo(self, page=None):
#################################################################
# Nothing. Unlike in the lighting panel, we don't have to keep data
# once user switch the page.
#################################################################
return
def setTargetObj(self, name = None, tracker = None):
#################################################################
# setTargetObj(self, name = None)
# setup the target object we want to control
#################################################################
if tracker == None: # Call from Keyboard page.
if name=='camera':
self.nodePath = camera
else:
messenger.send('ControlW_require',[name])
return
def resetNameList(self, list, name = None, nodePath = None):
####################################################################
# resetNameList(self, list, name = None, nodePath = None)
# This function will be called be sceneEditor in order to reset the
# object list inside the panel.
# list here is a name list for all objects that can be set on control
# in the scene. If user has specify a name and a nodePath in, it will
# check if the name is equal to the name of current control target.
# If so, it will change the name showed on panel.
####################################################################
self.widgetsDict['Keyboard-ObjList'].setlist(list)
if name != None:
if self.nameOfNode == name:
self.nameOfNode = self.nodePath.getName()
self.widgetsDict['Keyboard-ObjList'].selectitem(self.nameOfNode, setentry=True)
return
def setNodePathIn(self, nodePath):
####################################################################
# setNodePathIn(self, nodePath)
# THis function will be called by sceneEditor.
# After we send out a message to sceneEditor in setTargetObj function,
# This function will be called by sceneEditor after we get the reference
# of target object from dataHolder.
# This function will keep the reference.
####################################################################
self.nodePath = nodePath
self.nameOfNode = self.nodePath.getName()
return
def saveKeepControl(self):
#################################################################
# saveKeepControl(self)
# When any time user has click on the "Save & Keep" button,
# This function will be called.
# This function will send out the message to sceneEditor to process
# the saving. Also, this function will change the "self.keepControl" flag.
# So, when user closes the window with control enabled, it will keep
# the control process runnning. otherwise program will disable the
# control automatically when panel has been closed.
#
# It doesn't mean that this function will automatically enable the
# control when user closed the window!!
# This flag will only decide that we will send out a "stopControl"
# message or not.
#
#################################################################
self.keepControl = True
if self.controllType=='Keyboard':
for index in self.keyboardMapDict:
self.keyboardMapDict[index] = self.widgetsDict['Keyboard-'+index].getvalue()
for index in self.keyboardSpeedDict:
self.keyboardSpeedDict[index] = float(self.widgetsDict['Keyboard-'+index].getvalue())
print self.nodePath
messenger.send('ControlW_saveSetting', ['Keyboard', [self.nodePath, self.keyboardMapDict, self.keyboardSpeedDict]])
return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,172 @@
#################################################################
# duplicateWindow.py
# Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#################################################################
from AppShell import *
from TkGlobal import *
import seSceneGraphExplorer
class duplicateWindow(AppShell):
#################################################################
# duplicateWindow(AppShell)
# This class is used to create a dialog window
# for handling the "dupicate" command from the sceneEditor
#
# Notice!
# The actual duplicating process is not happending here!
# The one handle the process is dataHolder...
#################################################################
appversion = '1.0'
appname = 'Duplication'
frameWidth = 450
frameHeight = 320
frameIniPosX = 250
frameIniPosY = 250
padx = 0
pady = 0
def __init__(self, parent = None, nodePath = None, **kw):
# Define the megawidget options.
optiondefs = (
('title', self.appname, None),
)
self.defineoptions(kw, optiondefs)
if parent == None:
self.parent = Toplevel()
AppShell.__init__(self, self.parent)
self.parent.geometry('%dx%d+%d+%d' % (self.frameWidth, self.frameHeight,self.frameIniPosX,self.frameIniPosY))
self.nodePath = nodePath
self.parent.resizable(False,False) ## Disable the ability to resize for this Window.
def appInit(self):
print '----SideWindow is Initialized!!'
def createInterface(self):
# The interior of the toplevel panel
interior = self.interior()
mainFrame = Frame(interior)
self.inputZone = Pmw.Group(mainFrame, tag_text='Offset setting')
self.inputZone.pack(fill='both',expand=1)
settingFrame = self.inputZone.interior()
Label(settingFrame,text=' X ').place(anchor=NW,x=110,y=15)
Label(settingFrame,text=' Y ').place(anchor=NW,x=205,y=15)
Label(settingFrame,text=' Z ').place(anchor=NW,x=295,y=15)
self.move_x = Pmw.EntryField(settingFrame,label_text='Move :',labelpos='w',value='0.0', validate=Pmw.realvalidator)
self.move_x.component('entry').config(width=10)
self.move_y = Pmw.EntryField(settingFrame,value='0.0', validate=Pmw.realvalidator)
self.move_y.component('entry').config(width=10)
self.move_z = Pmw.EntryField(settingFrame, value='0.0', validate=Pmw.realvalidator)
self.move_z.component('entry').config(width=10)
self.move_x.place(anchor=NW,x=50,y=40)
self.move_y.place(anchor=NW,x=185,y=40)
self.move_z.place(anchor=NW,x=275,y=40)
self.rotate_x = Pmw.EntryField(settingFrame,label_text='Rotate:',labelpos='w',value='0.0', validate=Pmw.realvalidator)
self.rotate_x.component('entry').config(width=10)
self.rotate_y = Pmw.EntryField(settingFrame,value='0.0', validate=Pmw.realvalidator)
self.rotate_y.component('entry').config(width=10)
self.rotate_z = Pmw.EntryField(settingFrame, value='0.0', validate=Pmw.realvalidator)
self.rotate_z.component('entry').config(width=10)
self.rotate_x.place(anchor=NW,x=50,y=70)
self.rotate_y.place(anchor=NW,x=185,y=70)
self.rotate_z.place(anchor=NW,x=275,y=70)
self.scale_x = Pmw.EntryField(settingFrame,label_text='Scale :',labelpos='w',value='1.0', validate=Pmw.realvalidator)
self.scale_x.component('entry').config(width=10)
self.scale_y = Pmw.EntryField(settingFrame,value='1.0', validate=Pmw.realvalidator)
self.scale_y.component('entry').config(width=10)
self.scale_z = Pmw.EntryField(settingFrame, value='1.0', validate=Pmw.realvalidator)
self.scale_z.component('entry').config(width=10)
self.scale_x.place(anchor=NW,x=52,y=100)
self.scale_y.place(anchor=NW,x=185,y=100)
self.scale_z.place(anchor=NW,x=275,y=100)
self.numberOfCopy = Pmw.EntryField(settingFrame,label_text='Number of Copy :',labelpos='w',value='1', validate=Pmw.integervalidator)
self.numberOfCopy.component('entry').config(width=15)
self.numberOfCopy.place(anchor=NW,x=52,y=150)
settingFrame.pack(fill=BOTH,expand=1,padx=7,pady=7)
self.button_ok = Button(mainFrame, text="OK", command=self.ok_press,width=10)
self.button_ok.pack(fill=BOTH,expand=0,side=RIGHT)
mainFrame.pack(fill = 'both', expand = 1,padx=7,pady=7)
def createMenuBar(self):
self.menuBar.destroy()
def onDestroy(self, event):
messenger.send('DW_close')
'''
If you have open any thing, please rewrite here!
'''
pass
###############################
def ok_press(self):
#################################################################
# ok_press(self)
# Callback function
# This function will be called when user click on the "OK" button on the window.
# After collect all data we need for the duplication process,
# this function will send out a message with all data.
# 'DW_duplicating'
# This message will be caught by sceneEditor.
#################################################################
if not self.allEntryValid():
print '---- Duplication Window: Invalid value!!'
return
x = self.move_x.getvalue()
y = self.move_y.getvalue()
z = self.move_z.getvalue()
pos=Vec3(FloatType(x),FloatType(y),FloatType(z))
x = self.rotate_x.getvalue()
y = self.rotate_y.getvalue()
z = self.rotate_z.getvalue()
hpr=Vec3(FloatType(x),FloatType(y),FloatType(z))
x = self.scale_x.getvalue()
y = self.scale_y.getvalue()
z = self.scale_z.getvalue()
scale=Vec3(FloatType(x),FloatType(y),FloatType(z))
num = int(self.numberOfCopy.getvalue())
messenger.send('DW_duplicating',[self.nodePath,pos,hpr,scale,num])
self.quit()
def allEntryValid(self):
#################################################################
# allEntryValid(self)
# This function is used to check all data in the input entries are valid.
#
# For example, none of entries contains blank data.
#
#################################################################
if not self.move_x.valid():
return False
elif not self.move_y.valid():
return False
elif not self.move_z.valid():
return False
elif not self.rotate_x.valid():
return False
elif not self.rotate_y.valid():
return False
elif not self.rotate_z.valid():
return False
elif not self.scale_x.valid():
return False
elif not self.scale_y.valid():
return False
elif not self.scale_z.valid():
return False
elif not self.numberOfCopy.valid():
return False
return True

View File

@ -0,0 +1,496 @@
#################################################################
# lightingPanel.py
# Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#################################################################
# Import Tkinter, Pmw, and the floater code from this directory tree.
from AppShell import *
from TkGlobal import *
from seColorEntry import *
import VectorWidgets
import Floater
import Slider
import string
import math
import types
class lightingPanel(AppShell):
#################################################################
# lightingPanel(AppShell)
# This will create a window to let user
# create any kinds of lighting into the scene
#################################################################
# Override class variables
appname = 'Lighting Panel'
frameWidth = 400
frameHeight = 400
currentLight = None
def __init__(self, lightList, parent = None, **kw):
self.lightList = lightList
self.lightColor = [0.3*255,0.3*255,0.3*255]
self.type = ''
INITOPT = Pmw.INITOPT
optiondefs = (
('title', self.appname, None),
)
self.defineoptions(kw, optiondefs)
# Initialize the superclass
AppShell.__init__(self)
# Execute option callbacks
self.initialiseoptions(lightingPanel)
self.parent.resizable(False,False) ## Disable the ability to resize for this Window.
def createInterface(self):
# Handle to the toplevels interior
interior = self.interior()
menuBar = self.menuBar
self.menuBar.destroy()
# Create a frame to hold all stuff
mainFrame = Frame(interior)
self.listZone = Pmw.Group(mainFrame,tag_pyclass = None)
self.listZone.pack(expand=0, fill=X,padx=3,pady=3)
listFrame = self.listZone.interior()
self.lightEntry = self.createcomponent(
'Lights List', (), None,
Pmw.ComboBox, (listFrame,),label_text='Light :',
labelpos = W, entry_width = 25, selectioncommand = self.selectLight,
scrolledlist_items = self.lightList)
self.lightEntry.pack(side=LEFT)
self.renameButton = self.createcomponent(
'Rename Light', (), None,
Button, (listFrame,),
text = ' Rename ',
command = self.renameLight)
self.renameButton.pack(side=LEFT)
self.addLighZone = Pmw.Group(listFrame,tag_pyclass = None)
self.addLighZone.pack(side=LEFT)
insideFrame = self.addLighZone.interior()
self.lightsButton = Menubutton(insideFrame, text = 'Add light',borderwidth = 3,
activebackground = '#909090')
lightsMenu = Menu(self.lightsButton)
lightsMenu.add_command(label = 'Add Ambient Light',
command = self.addAmbient)
lightsMenu.add_command(label = 'Add Directional Light',
command = self.addDirectional)
lightsMenu.add_command(label = 'Add Point Light',
command = self.addPoint)
lightsMenu.add_command(label = 'Add Spotlight',
command = self.addSpot)
self.lightsButton.pack(expand=0)
self.lightsButton['menu'] = lightsMenu
self.deleteButton = self.createcomponent(
'delete Light', (), None,
Button, (listFrame,),
text = ' Delete ',
command = self.deleteLight)
self.deleteButton.pack(side=LEFT)
self.lightColor = seColorEntry(
mainFrame, text = 'Light Color', value=self.lightColor)
self.lightColor['command'] = self.setLightingColorVec
self.lightColor['resetValue'] = [0.3*255,0.3*255,0.3*255,0]
self.lightColor.pack(fill=X,expand=0)
self.bind(self.lightColor, 'Set light color')
# Notebook pages for light specific controls
self.lightNotebook = Pmw.NoteBook(mainFrame, tabpos = None,
borderwidth = 0)
ambientPage = self.lightNotebook.add('Ambient')
directionalPage = self.lightNotebook.add('Directional')
pointPage = self.lightNotebook.add('Point')
spotPage = self.lightNotebook.add('Spot')
# Put this here so it isn't called right away
self.lightNotebook['raisecommand'] = self.updateLightInfo
# Directional light controls
self.dSpecularColor = seColorEntry(
directionalPage, text = 'Specular Color')
self.dSpecularColor['command'] = self.setSpecularColor
self.dSpecularColor.pack(fill = X, expand = 0)
self.bind(self.dSpecularColor,
'Set directional light specular color')
self.dPosition = VectorWidgets.Vector3Entry(
directionalPage, text = 'Position')
self.dPosition['command'] = self.setPosition
self.dPosition['resetValue'] = [0,0,0,0]
self.dPosition.pack(fill = X, expand = 0)
self.bind(self.dPosition, 'Set directional light position')
self.dOrientation = VectorWidgets.Vector3Entry(
directionalPage, text = 'Orientation')
self.dOrientation['command'] = self.setOrientation
self.dOrientation['resetValue'] = [0,0,0,0]
self.dOrientation.pack(fill = X, expand = 0)
self.bind(self.dOrientation, 'Set directional light orientation')
# Point light controls
self.pSpecularColor = seColorEntry(
pointPage, text = 'Specular Color')
self.pSpecularColor['command'] = self.setSpecularColor
self.pSpecularColor.pack(fill = X, expand = 0)
self.bind(self.pSpecularColor,
'Set point light specular color')
self.pPosition = VectorWidgets.Vector3Entry(
pointPage, text = 'Position')
self.pPosition['command'] = self.setPosition
self.pPosition['resetValue'] = [0,0,0,0]
self.pPosition.pack(fill = X, expand = 0)
self.bind(self.pPosition, 'Set point light position')
self.pConstantAttenuation = Slider.Slider(
pointPage,
text = 'Constant Attenuation',
max = 1.0,
resolution = 0.01,
value = 1.0)
self.pConstantAttenuation['command'] = self.setConstantAttenuation
self.pConstantAttenuation.pack(fill = X, expand = 0)
self.bind(self.pConstantAttenuation,
'Set point light constant attenuation')
self.pLinearAttenuation = Slider.Slider(
pointPage,
text = 'Linear Attenuation',
max = 1.0,
resolution = 0.01,
value = 0.0)
self.pLinearAttenuation['command'] = self.setLinearAttenuation
self.pLinearAttenuation.pack(fill = X, expand = 0)
self.bind(self.pLinearAttenuation,
'Set point light linear attenuation')
self.pQuadraticAttenuation = Slider.Slider(
pointPage,
text = 'Quadratic Attenuation',
max = 1.0,
resolution = 0.01,
value = 0.0)
self.pQuadraticAttenuation['command'] = self.setQuadraticAttenuation
self.pQuadraticAttenuation.pack(fill = X, expand = 0)
self.bind(self.pQuadraticAttenuation,
'Set point light quadratic attenuation')
# Spot light controls
self.sSpecularColor = seColorEntry(
spotPage, text = 'Specular Color')
self.sSpecularColor['command'] = self.setSpecularColor
self.sSpecularColor.pack(fill = X, expand = 0)
self.bind(self.sSpecularColor,
'Set spot light specular color')
self.sConstantAttenuation = Slider.Slider(
spotPage,
text = 'Constant Attenuation',
max = 1.0,
resolution = 0.01,
value = 1.0)
self.sConstantAttenuation['command'] = self.setConstantAttenuation
self.sConstantAttenuation.pack(fill = X, expand = 0)
self.bind(self.sConstantAttenuation,
'Set spot light constant attenuation')
self.sLinearAttenuation = Slider.Slider(
spotPage,
text = 'Linear Attenuation',
max = 1.0,
resolution = 0.01,
value = 0.0)
self.sLinearAttenuation['command'] = self.setLinearAttenuation
self.sLinearAttenuation.pack(fill = X, expand = 0)
self.bind(self.sLinearAttenuation,
'Set spot light linear attenuation')
self.sQuadraticAttenuation = Slider.Slider(
spotPage,
text = 'Quadratic Attenuation',
max = 1.0,
resolution = 0.01,
value = 0.0)
self.sQuadraticAttenuation['command'] = self.setQuadraticAttenuation
self.sQuadraticAttenuation.pack(fill = X, expand = 0)
self.bind(self.sQuadraticAttenuation,
'Set spot light quadratic attenuation')
self.sExponent = Slider.Slider(
spotPage,
text = 'Exponent',
max = 1.0,
resolution = 0.01,
value = 0.0)
self.sExponent['command'] = self.setExponent
self.sExponent.pack(fill = X, expand = 0)
self.bind(self.sExponent,
'Set spot light exponent')
# MRM: Add frustum controls
self.lightNotebook.setnaturalsize()
self.lightNotebook.pack(expand = 1, fill = BOTH)
mainFrame.pack(expand=1, fill = BOTH)
def onDestroy(self, event):
messenger.send('LP_close')
'''
If you have open any thing, please rewrite here!
'''
pass
def renameLight(self):
#################################################################
# renameLight(self)
# Call Back function
# This function will be called when user push
# the "Rename" button on the panel.
#
# Then, this function will collect data and send out them with a message
# "LP_rename"
# Which will be caught by sceneEditor and pass to dataHolder to
# complete the renaming.
#
#################################################################
oName = self.currentLight
nName = self.lightEntry.get()
messenger.send('LP_rename',[oName,nName])
return
def deleteLight(self):
#################################################################
# deleteLight(self)
# Call Back Function.
# This function will be called when user click on
# the "Delete" button on the panel.
#
# Then, this function will send out a message with current seleted light
# "LP_removeLight"
# Which will be caught by sceneEditor and pass to dataHolder to
# complete the delete process.
#
#################################################################
messenger.send('LP_removeLight',[self.currentLight])
return
def updateList(self, list, node=None):
#################################################################
# updataList(self, list, node = None)
# This function will take a list object which contains names of lights in the scene.
# Also, if user has put node as a parameter,
# this function will automatically select that node as the current working target.
#################################################################
self.lightList = list
self.lightEntry.setlist(list)
if node!=None:
self.lightEntry.selectitem(index=node.getName(), setentry=True )
self.updateDisplay(node)
elif len(list)>0:
self.lightEntry.selectitem(index=0, setentry=True )
self.selectLight(list[0])
else:
self.lightEntry.clear()
return
def selectLight(self, lightName):
#################################################################
# selectLight(self, lightName)
# This function will be called each time when
# user select a light from the list on the panel.
# Then, this function will send out the message,
# 'LP_selectLight' to sceneEditorand get the current light information from dataHolder.
#################################################################
if lightName in self.lightList:
messenger.send('LP_selectLight',[lightName])
return
def updateDisplay(self, lightNode):
#################################################################
# updateDisplay(self, lightNode)
# This function will update the information showing on the panel.
# For example, give a lightNode which is a Point Light.
# This function will switch the page to specify the type.
# Also, new node is the same type with the previous one,
# then this is function won't do the page switching,
# but will call other function to refresh the data to target node.
#################################################################
self.currentLight = lightNode
if self.currentLight != None:
color = lightNode.getLightColor()
self.lightColor.set([255*color.getX(),255*color.getY(),255*color.getZ()])
oldType = self.type
self.type = lightNode.getType()
else:
self.lightColor.set([255*0.3,255*0.3,255*0.3])
oldType = self.type
self.type = 'ambient'
if self.type=='ambient':
self.lightNotebook.selectpage('Ambient')
elif self.type =='directional':
self.lightNotebook.selectpage('Directional')
elif self.type =='point':
self.lightNotebook.selectpage('Point')
elif self.type =='spot':
self.lightNotebook.selectpage('Spot')
if oldType == self.type:
# The same type with previous one, call updateLightInfo to refresh the values.
self.updateLightInfo()
return
def updateLightInfo(self, page=None):
#################################################################
# updateLightInfo(self, page=None)
# This function will refresh the data we user have done any selection.
#################################################################
if self.currentLight != None:
light = self.currentLight.getLight()
if self.type != 'ambient':
specColor = light.getSpecularColor()
if self.type =='directional':
point = self.currentLight.getPosition()
dir = self.currentLight.getOrientation()
self.dSpecularColor.set([specColor.getX()*255,specColor.getY()*255,specColor.getZ()*255])
self.dPosition.set([point.getX(),point.getY(),point.getZ()])
self.dOrientation.set([dir.getX(),dir.getY(),dir.getZ()])
elif self.type =='point':
point = self.currentLight.getPosition()
attenuation = light.getAttenuation()
self.pSpecularColor.set([specColor.getX()*255,specColor.getY()*255,specColor.getZ()*255])
self.pPosition.set([point.getX(),point.getY(),point.getZ()])
self.pConstantAttenuation.set(attenuation.getX())
self.pLinearAttenuation.set(attenuation.getY())
self.pQuadraticAttenuation.set(attenuation.getZ())
elif self.type =='spot':
attenuation = light.getAttenuation()
expo = light.getExponent()
self.sSpecularColor.set([specColor.getX()*255,specColor.getY()*255,specColor.getZ()*255])
self.sConstantAttenuation.set(attenuation.getX())
self.sLinearAttenuation.set(attenuation.getY())
self.sQuadraticAttenuation.set(attenuation.getZ())
self.sExponent.set(expo)
return
def addAmbient(self):
#################################################################
# addAmbient(self)
# This function will send out a message to
# ask dataHolder to create a default ambient light
#################################################################
messenger.send('LP_addLight',['ambient'])
return
def addDirectional(self):
#################################################################
# addDirectional(self)
# This function will send out a message to
# sk dataHolder to create a default Directional light
#################################################################
messenger.send('LP_addLight',['directional'])
return
def addPoint(self):
#################################################################
# addPoint(self)
# This function will send out a message to
# ask dataHolder to create a default Point light
#################################################################
messenger.send('LP_addLight',['point'])
return
def addSpot(self):
#################################################################
# addSpot(self)
# This function will send out a message to
# ask dataHolder to create a default Spot light
#################################################################
messenger.send('LP_addLight',['spot'])
return
def setLightingColorVec(self,color):
#################################################################
# setLightingColorVec(self,color)
# Call Back function. This will be called
# when user try to change the color of light.
#################################################################
if self.currentLight==None:
return
self.currentLight.setColor(VBase4((color[0]/255),(color[1]/255),(color[2]/255),1))
return
def setSpecularColor(self,color):
#################################################################
# setSpecularColor(self,color)
# Call Back function. This will be called
# when user try to change the Specular color of light.
#################################################################
if self.currentLight==None:
return
self.currentLight.setSpecColor(VBase4((color[0]/255),(color[1]/255),(color[2]/255),1))
return
def setPosition(self,position):
#################################################################
# setPosition(self,position)
# Call Back function. This will be called
# when user try to change the position of light.
#################################################################
if self.currentLight==None:
return
self.currentLight.setPosition(Point3(position[0],position[1],position[2]))
return
def setOrientation(self, orient):
#################################################################
# setOrientation(self, orient)
# Call Back function. This will be called
# when user try to change the orientation of light.
#################################################################
if self.currentLight==None:
return
self.currentLight.setOrientation(Vec3(orient[0],orient[1],orient[2]))
return
def setConstantAttenuation(self, value):
#################################################################
# setConstantAttenuation(self, value)
# Call Back function. This will be called
# when user try to change the Constant Attenuation of light.
#################################################################
self.currentLight.setConstantAttenuation(value)
return
def setLinearAttenuation(self, value):
#################################################################
# setLinearAttenuation(self, value)
# Call Back function. This will be called
# when user try to change the Linear Attenuation of light.
#################################################################
self.currentLight.setLinearAttenuation(value)
return
def setQuadraticAttenuation(self, value):
#################################################################
# setQuadraticAttenuation(self, value)
# Call Back function. This will be called
# when user try to change the Quadratic Attenuation of light.
#################################################################
self.currentLight.setQuadraticAttenuation(value)
return
def setExponent(self, value):
#################################################################
# setExponent(self, value)
# Call Back function. This will be called
# when user try to change Exponent value of light.
#################################################################
self.currentLight.setExponent(value)
return

File diff suppressed because it is too large Load Diff

674
doc/SceneEditor/quad.py Normal file
View File

@ -0,0 +1,674 @@
#########################################################################################################################################
# This file implements a Quad View for the level editor
# This feature is not yet enabled in the level editor because picking objects in quad view doesnt work
# I have tried to send the picking function in seSelection.py the correct camera and mouse coordinates but something seems to be wron
# There are two classes in this file..the QuadView and the viewPort...there are four instances of viewport, one for each view in QuadView
#########################################################################################################################################
from ShowBaseGlobal import *
from intervalGlobal import *
import DirectObject
import math
from MouseWatcher import *
class ViewPort:
#########################################################################################################################################
# The ViewPort class has the camera and associated display region set up for actually rendering the four sub-views
# The constructor needs the bounds, window layer, camera, color, projection type, name and scene for the view
#########################################################################################################################################
def __init__(self,X1,X2,Y1,Y2,layer,cam,background=Vec4(0.3,0.3,0.3,1),projection="perspective",type="top",scene=render):
self.VPType=type
self.VP_X1=X1
self.VP_Y1=Y1
self.VP_X2=X2
self.VP_Y2=Y2
self.VP_width=self.VP_X2 - self.VP_X1
self.VP_height=self.VP_Y2 - self.VP_Y1
self.the_viewport=layer.makeDisplayRegion(self.VP_X1, self.VP_X2,self.VP_Y1, self.VP_Y2)
self.the_viewport.setCamera(cam)
self.the_viewport.setClearDepthActive(1)
self.the_viewport.setClearColorActive(1)
self.the_viewport.setClearColor(background)
self.cam=cam
# Set up the cameras to look in the right place.
if(type=="top"):
self.cam.setP(-90)
self.cam.setZ(-40)
elif(type=="left"):
self.cam.setH(-90)
self.cam.setX(10)
elif(type=="front"):
self.cam.setY(-10)
elif(type=="perspective"):
cam.setY(-100)
#cam.setX(10)
#cam.setZ(-10)
#cam.setH(45)
#cam.setP(-45)
#print "aa"
if(projection=="ortho"):
self.lens=OrthographicLens()
self.lens.setAspectRatio((self.VP_X2-self.VP_X1)/(self.VP_Y2-self.VP_Y1))
self.lens.setFilmSize(self.VP_width*200,self.VP_height*200)
#lens.setFilmOffset((self.VP_X2 + self.VP_X1) * 0.5, (self.VP_Y2 + self.VP_Y1) * 0.5)
self.lens.setNearFar(-1000, 1000)
self.cam.node().setLens(self.lens)
self.cam.node().setScene(scene)
elif(projection=="perspective"):
self.lens=base.cam.node().getLens()
self.lens.setAspectRatio((self.VP_X2-self.VP_X1)/(self.VP_Y2-self.VP_Y1))
self.cam.node().setLens(self.lens)
self.cam.node().setScene(scene)
self.the_viewport.setCamera(self.cam)
def resizeX(self,width_increment):
if(self.VPType=="top" or self.VPType=="left"):
self.the_viewport.setDimensions(self.VP_X1,self.VP_X2+width_increment,self.VP_Y1,self.VP_Y2)
elif(self.VPType=="perspective" or self.VPType=="front"):
self.the_viewport.setDimensions(self.VP_X1+width_increment,self.VP_X2,self.VP_Y1,self.VP_Y2)
def resizeY(self,height_increment,direction):
if(self.VPType=="left" or self.type=="perspective"):
self.the_viewport.setDimensions(self.VP_X1,self.VP_X2,self.VP_Y1,self.VP_Y2+height_increment)
else:
self.the_viewport.setDimensions(self.VP_X1,self.VP_X2,self.VP_Y1+height_increment,self.VP_Y2)
def AdjustAspect(self,x,y):
if (y==0):
y=1
self.lens.setAspectRatio(x/y)
self.cam.node().setLens(self.lens)
def resize(self,x,y):
if(self.VPType=="left"):
self.the_viewport.setDimensions(0,x,0,y)
w=abs(x-self.VP_X1)
h=abs(y-self.VP_Y1)
if(h==0):
h=1
self.lens.setAspectRatio(w/h)
self.cam.node().setLens(self.lens)
if(self.VPType=="top"):
self.the_viewport.setDimensions(0,x,y,1)
w=abs(x-self.VP_X1)
h=abs(self.VP_Y2-y)
if(h==0):
h=1
self.lens.setAspectRatio(w/h)
self.cam.node().setLens(self.lens)
if(self.VPType=="front"):
self.the_viewport.setDimensions(x,1,y,1)
w=abs(self.VP_X2-x)
h=abs(self.VP_Y2-y)
if(h==0):
h=1
self.lens.setAspectRatio(w/h)
self.cam.node().setLens(self.lens)
if(self.VPType=="perspective"):
self.the_viewport.setDimensions(x,1,0,y)
w=abs(self.VP_X2-x)
h=abs(y-self.VP_Y1)
if(h==0):
h=1
self.lens.setAspectRatio(w/h)
self.cam.node().setLens(self.lens)
def setScene(self,scene):
self.cam.node().setScene(scene)
def setDR(self,mouseWatcher):
#mouseWatcher.setDisplayRegion(self.the_viewport)
pass
def setCam(self):
#base.cam=self.cam
#base.cam.node().setLens(self.cam.node().getLens())
base.camNode=self.cam.node()
#base.camNode.setLens(self.cam.node().getLens())
#base.camLens=self.cam.node().getLens()
def getCam(self):
return self.cam
class QuadView(DirectObject.DirectObject):
#########################################################################################################################################
# This class sets up four cameras for the scene (ideally we want four instances of render too)
# and then instatiates a ViewPort class for each of them
#
#########################################################################################################################################
def __init__(self):
self.PTracker=1
self.ControlPressed=0
self.AltPressed=0
self.PanConstantX=50
self.PanConstantY=50
self.ZoomConstant=1
self.FrontWidth=100
self.FrontHeight=100
self.TopWidth=100
self.TopHeight=100
self.LeftWidth=100
self.LeftHeight=100
self.MouseButton=0
self.CurrentQuad=4
self.HorizontalAxis=0.0
self.VerticalAxis=0.0
#base.disableMouse()
self.MouseDragging=0
self.currX= 0
self.oldX=self.currX
self.currY= 0
self.oldY=self.currY
self.FrontTexture=1
self.LeftTexture=1
self.PerspectiveTexture=1
self.TopTexture=1
self.FrontWire=0
self.LeftWire=0
self.PerspectiveWire=0
self.TopWire=0
# Keep track of the currently selected window... values are 1-4 for four quadrants of a standard
# Cartesian coordinate system
# These are the orthographic cameras
# They will be restricted to panning and zooming i.e. no rotation
# Top could be flipped to back, left to right and front to back
self.topCam= render.attachNewNode(Camera('topCam'))
self.frontCam = render.attachNewNode(Camera('frontCam'))
self.leftCam= render.attachNewNode(Camera('leftCam'))
# This camera will have a trackball control since its perspective
self.perspectiveCam = render.attachNewNode(Camera('perspectiveCam'))
#self.toplens=OrthographicLens()
#self.leftLens=OrthographicLens()
#self.frontLens=OrthographicLens()
#self.perspectiveLens=base.cam.node().getLens()
# For now all lenses are same as that of base.cam
#self.topCamLens=OrthographicLens()
#self.frontCamLens= base.cam.node().getLens()
#self.leftCamLens= base.cam.node().getLens()
#self.perspectiveCamLens= base.cam.node().getLens()
# Manipulate lenses here if need be
#self.topCamLens.setFilmSize(250)
# Set the Lenses
#self.topCam.node().setLens(self.topCamLens)
#self.frontCam.node().setLens(self.frontCamLens)
#self.leftCam.node().setLens(self.leftCamLens)
#self.perspectiveCam.node().setLens(self.perspectiveCamLens)
#self.badwiz = loader.loadModel('badwizard1')
#self.badwiz.reparentTo(render)
# Create four separate display regions for the quad view.
# These will overlap the main display region
# To stack these overlapping DisplayRegions, we need a new layer. If
# they didn't overlap, we could put them in the same layer.
self.newLayer = base.win.getChannel(0).makeLayer()
self.PerspectiveScene=NodePath('PerspectiveScene')
self.FrontScene=NodePath('FrontScene')
self.TopScene=NodePath('TopScene')
self.LeftScene=NodePath('LeftScene')
self.SceneParent=NodePath('SceneParent')
#self.PerspectiveScene=render.copyTo(self.SceneParent)
#self.FrontScene=render.copyTo(self.SceneParent)
#self.TopScene=render.copyTo(self.SceneParent)
#self.LeftScene=render.copyTo(self.SceneParent)
self.PerspectiveScene=render
self.FrontScene=render
self.TopScene=render
self.LeftScene=render
#self.PerspectiveScene.reparentTo(self.SceneParent)
#self.FrontScene.reparentTo(self.SceneParent)
#self.TopScene.reparentTo(self.SceneParent)
#self.LeftScene.reparentTo(self.SceneParent)
self.Perspective=ViewPort(0.5,1.0,0.0,0.5,self.newLayer,self.perspectiveCam,Vec4(0.75,0.75,0.75,1),"perspective","perspective",self.PerspectiveScene)
self.Top=ViewPort(0.0,0.5,0.5,1.0,self.newLayer,self.topCam,Vec4(0.80,0.80,0.80,1),"ortho","top",self.TopScene)
self.Left=ViewPort(0.0,0.5,0.0,0.5,self.newLayer,self.leftCam,Vec4(0.85,0.85,0.85,1),"ortho","left",self.LeftScene)
self.Front=ViewPort(0.5,1.0,0.5,1.0,self.newLayer,self.frontCam,Vec4(0.85,0.85,0.85,1),"ortho","front",self.FrontScene)
#self.Perspective=None
#self.Top=None
#self.Front=None
#self.Left=None
#self.raycaster = RayCaster( camera )
#self.lastPickPoint = None
#base.useTrackball()
#self.dataRoot = NodePath('dataRoot')
# Cache the node so we do not ask for it every frame
#self.dataRootNode = self.dataRoot.node()
#self.dataUnused = NodePath('dataUnused')
#self.mak=None
#self.mak = self.dataRoot.attachNewNode(MouseAndKeyboard(base.win, 0, 'mak'))
#self.mak.node().setSource(base.win, 0)
self.mouseWatcherNode = MouseWatcher('mouseWatcher')
self.mouseWatcher = base.mak.attachNewNode(self.mouseWatcherNode)
#self.Perspective.setDR(self.mouseWatcherNode)
self.buttonThrower = self.mouseWatcher.attachNewNode(ButtonThrower('buttons'))
#ddr=DisplayRegionContext(self.Perspective.getCam())
#base.setMouseOnNode(self.smiley.node()) # Let Mouse Control Perspective View for now
#base.enableSoftwareMousePointer()
# Message Handlers
self.accept("a",self.setLeft)
self.accept("q",self.setTop)
self.accept("w",self.setFront)
self.accept("s",self.setPerspective)
self.accept("mouse1",self.MouseTell,[1])
self.accept("mouse2",self.MouseTell,[2])
self.accept("mouse3",self.MouseTell,[3])
self.accept("mouse1-up",self.MouseTellUp,[4])
self.accept("mouse2-up",self.MouseTellUp,[5])
self.accept("mouse3-up",self.MouseTellUp,[6])
self.accept("mouse2-scroll",self.resizedr)
self.accept("r",self.resizedr)
self.accept("alt",self.AltHandler)
self.accept("alt-up",self.AltUpHandler)
self.accept("alt-mouse1",self.AltDown)
self.accept("alt-mouse1-up",self.AltUp)
self.accept("control-mouse1",self.CtlDown)
self.accept("control-mouse1-up",self.CtlUp)
# Methods
#def setLastPickPoint( self ):
# mouseX, mouseY = self.mouseWatcherNode.getMouseX(), self.mouseWatcherNode.getMouseY()
# self.lastPickPoint = self.raycaster.pick( mouseX, mouseY )
# print self.lastPickPoint
def AltDown(self):
self.AltPressed=1
def AltUp(self):
self.AltPressed=0
def CtlDown(self):
self.ControlPressed=1
def CtlUp(self):
self.ControlPressed=0
def ToggleWire(self):
if (self.CurrentQuad==1): # Front View
if(self.FrontWire): # Wireframe is On so turn it off
self.FrontScene.setRenderModeWireframe(100);
self.FrontScene.setTwoSided(1);
self.FrontScene.setTextureOff(100)
self.FrontWire=0
else:
self.FrontScene.clearRenderMode()
#self.FrontScene.setTwoSided(not self.backfaceCullingEnabled)
if(self.FrontTexture):
self.FrontScene.clearTexture()
self.FrontWire=1
elif (self.CurrentQuad==2): # Front View
if(self.TopWire): # Wireframe is On so turn it off
self.TopScene.setRenderModeWireframe(100);
self.TopScene.setTwoSided(1);
self.TopScene.setTextureOff(100)
self.TopWire=0
else:
self.TopScene.clearRenderMode()
#self.TopScene.setTwoSided(not self.backfaceCullingEnabled)
if(self.TopTexture):
self.TopScene.clearTexture()
self.TopWire=1
elif (self.CurrentQuad==3): # Front View
if(self.LeftWire): # Wireframe is On so turn it off
self.LeftScene.setRenderModeWireframe(100);
self.LeftScene.setTwoSided(1);
self.LeftScene.setTextureOff(100)
self.LeftWire=0
else:
self.LeftScene.clearRenderMode()
#self.LeftScene.setTwoSided(not self.backfaceCullingEnabled)
if(self.LeftTexture):
self.LeftScene.clearTexture()
self.LeftWire=1
elif (self.CurrentQuad==4): # Front View
if(self.PerspectiveWire): # Wireframe is On so turn it off
self.PerspectiveScene.setRenderModeWireframe(100);
self.PerspectiveScene.setTwoSided(1);
self.PerspectiveScene.setTextureOff(100)
self.PerspectiveWire=0
else:
self.PerspectiveScene.clearRenderMode()
#self.PerspectiveScene.setTwoSided(not self.backfaceCullingEnabled)
if(self.PerspectiveTexture):
self.PerspectiveScene.clearTexture()
self.PerspectiveWire=1
def ToggleTexture(self):
if (self.CurrentQuad==1): # Front View
if(self.FrontTexture): # Texture is on so turn it off
self.FrontScene.setTextureOff(100)
self.FrontTexture=0;
else:
self.FrontScene.clearTexture()
self.FrontTexture=1
elif (self.CurrentQuad==2): # Top View
if(self.TopTexture): # Texture is on so turn it off
self.TopScene.setTextureOff(100)
self.TopTexture=0;
else:
self.TopScene.clearTexture()
self.TopTexture=1
elif (self.CurrentQuad==3): # Left View
if(self.LeftTexture): # Texture is on so turn it off
self.LeftScene.setTextureOff(100)
self.LeftTexture=0;
else:
self.LeftScene.clearTexture()
self.LeftTexture=1
elif (self.CurrentQuad==4): # Perspective View
if(self.PerspectiveTexture): # Texture is on so turn it off
self.PerspectiveScene.setTextureOff(100)
self.PerspectiveTexture=0;
else:
self.PerspectiveScene.clearTexture()
self.PerspectiveTexture=1
def reparenter(self):
#self.FrontScene.reparentTo(render)
#self.Front.setScene(render)
#self.Top.setScene(render)
#self.Left.setScene(render)
#self.Perspective.setScene(render)
pass
def unparenter(self):
#self.PerspectiveScene=render.copyTo(render)
#self.FrontScene=render.copyTo(render)
#self.TopScene=render.copyTo(render)
#self.LeftScene=render.copyTo(render)
#self.SceneParent.reparentTo(render)
#self.PerspectiveScene.reparentTo(self.SceneParent)
#self.FrontScene.reparentTo(self.SceneParent)
#self.TopScene.reparentTo(self.SceneParent)
#self.LeftScene.reparentTo(self.SceneParent)
pass
def AltHandler(self):
self.oldX=self.mouseWatcherNode.getMouseX()
if(self.oldX<-1 or self.oldX>1):
return
self.oldY=self.mouseWatcherNode.getMouseY()
if(self.oldY<-1 or self.oldY>1):
return
taskMgr.add(self.DragAction,'DragAction')
def AltUpHandler(self):
taskMgr.remove('DragAction')
def gridtoggle(self):
#grid=DirectGrid()
#grid.enable()
pass
def resizedr(self,x,y):
#print "X: " + str(x) + " Y: " + str(y)
x=(x+1)/2.0
y=(y+1)/2.0
self.Perspective.resize(x,y)
self.Top.resize(x,y)
self.Front.resize(x,y)
self.Left.resize(x,y)
def setAppropriateViewPort(self,x,y):
#print "SET APPROPRIATE:" + str(x) + " " + str(y)
if(x<self.VerticalAxis):
if(y<self.HorizontalAxis):
self.setLeft()
else:
self.setTop()
else:
if(y<self.HorizontalAxis):
self.setPerspective()
else:
self.setFront()
def MouseTell(self,buttonCode):
self.MouseButton=buttonCode
self.setAppropriateViewPort(self.mouseWatcherNode.getMouseX(),self.mouseWatcherNode.getMouseY())
x=base.mouseWatcherNode.getMouseX()
y=base.mouseWatcherNode.getMouseY()
#Perspective and Front
if(self.CurrentQuad==4 or self.CurrentQuad==1):
x1=abs(x-self.VerticalAxis)
w1=abs(1-self.VerticalAxis)
x2=x1*2.0/w1
ansX=-1+x2
#Left and top
if(self.CurrentQuad==2 or self.CurrentQuad==3):
x1=abs(x-(-1.0))
w1=abs(self.VerticalAxis-(-1.0))
x2=x1*2.0/w1
ansX=-1.0+x2
#Left and Perspective
if(self.CurrentQuad==4 or self.CurrentQuad==3):
y1=abs(y-(-1.0))
h1=abs(self.HorizontalAxis-(-1.0))
y2=y1*2.0/h1
ansY=-1.0+y2
#Front and top
if(self.CurrentQuad==1 or self.CurrentQuad==2):
y1=abs(y-self.HorizontalAxis)
h1=abs(1.0-self.HorizontalAxis)
y2=y1*2.0/h1
ansY=-1.0+y2
self.xy=[ansX,ansY]
print "Sent X:%f Sent Y:%f"%(ansX,ansY)
#SEditor.iRay.pick(render,self.xy)
SEditor.manipulationControl.manipulationStop(self.xy)
#print "MouseX " + str(base.mouseWatcherNode.getMouseX()) + "MouseY " + str(base.mouseWatcherNode.getMouseY()) + "\n"
#print "MouseX " + str(self.mouseWatcherNode.getMouseX()) + "MouseY " + str(self.mouseWatcherNode.getMouseY()) + "\n"
base.mouseWatcherNode=self.mouseWatcherNode
self.oldX=self.mouseWatcherNode.getMouseX()
if(self.oldX<-1 or self.oldX>1):
return
self.oldY=self.mouseWatcherNode.getMouseY()
if(self.oldY<-1 or self.oldY>1):
return
self.Mouse_Dragging=1
taskMgr.add(self.DragAction,'DragAction')
def MouseTellUp(self,buttoncode):
#self.MouseButton=0
self.PanConstantX= 50
self.PanConstantY= 50
self.ZoomConstant=1
taskMgr.remove('DragAction')
self.Mouse_Draggin=0
#print "Mouse Up"
def Max_Style_Mouse_View(self,buttoncode):
pass
def ChangeBaseDR(self):
dr=base.win.getDisplayRegion(0)
if(self.CurrentQuad==1): #Front
dr.setDimensions(0.5,1,0.5,1)
elif(self.CurrentQuad==2): #Top
dr.setDimensions(0,0.5,0.5,1)
elif(self.CurrentQuad==3): #Left
dr.setDimensions(0,0.5,0,0.5)
elif(self.CurrentQuad==4): #Perspective
dr.setDimensions(0.5,1,0,0.5)
def setLeft(self):
print "LEFT"
self.CurrentQuad=3
self.ChangeBaseDR()
self.Left.setCam()
#self.Left.setDR(self.mouseWatcherNode)
def setTop(self):
print "TOP"
self.CurrentQuad=2
self.ChangeBaseDR()
self.Top.setCam()
#self.Top.setDR(self.mouseWatcherNode)
def setPerspective(self):
print "PERSPECTIVE"
self.CurrentQuad=4
self.ChangeBaseDR()
self.Perspective.setCam()
#self.Perspective.setDR(self.mouseWatcherNode)
def setFront(self):
print "FRONT"
self.CurrentQuad=1
self.ChangeBaseDR()
self.Front.setCam()
#self.Front.setDR(self.mouseWatcherNode)
def DragAction(self,task):
#if(self.MouseDragging==1):
self.currX= self.mouseWatcherNode.getMouseX()
if(self.currX<-1 or self.currX>1):
return
self.currY= self.mouseWatcherNode.getMouseY()
if(self.currY<-1 or self.currY>1):
return
self.diffX=self.currX-self.oldX
self.diffY=self.currY-self.oldY
if(self.ControlPressed): # Change Size of the ViewPorts
#if(base.getControl()):
self.VerticalAxis=self.currX
self.HorizontalAxis=self.currY
if(self.HorizontalAxis<-1 or self.HorizontalAxis>1 or self.VerticalAxis<-1 or self.VerticalAxis>1):
return
self.resizedr(self.VerticalAxis,self.HorizontalAxis)
#if(self.AltPressed): # View Camera Transforms -> Maya style
elif(1):
#print "ALTPRESSED"
if(self.PanConstantX<4096):
self.PanConstantX= self.PanConstantX * 2
self.PanConstantY= self.PanConstantY * 2
self.ZoomConstant= self.ZoomConstant + 50
if(self.MouseButton==1): # TrackBall rotation only for Perspective View
if(self.CurrentQuad==4):
pass
elif(self.MouseButton==2): # Do Panning
if(self.CurrentQuad==1): # Y and Z values change meanings for different cameras
self.MoveCamera(-self.diffX*self.PanConstantX,0,-self.diffY*self.PanConstantY,self.CurrentQuad)
elif(self.CurrentQuad==2):
self.MoveCamera(-self.diffX*self.PanConstantX,-self.diffY*self.PanConstantY,0,self.CurrentQuad)
elif(self.CurrentQuad==3):
self.MoveCamera(0,self.diffX*self.PanConstantX,-self.diffY*self.PanConstantY,self.CurrentQuad)
elif(self.CurrentQuad==4):
pass
elif(self.MouseButton==3): # Do Zoom
if(self.CurrentQuad==1): # Y and Z values change meanings for different cameras
#lens = OrthographicLens()
#lens.setFilmSize(l,self.VP_height*200)
#lens.setFilmOffset((self.VP_X2 + self.VP_X1) * 0.5, (self.VP_Y2 + self.VP_Y1) * 0.5)
#lens.setNearFar(-1000, 1000)
self.FrontWidth= self.FrontWidth + self.diffX
self.FrontHeight= self.FrontHeight + self.diffX
self.FrontWidth= self.FrontWidth + self.diffY
self.FrontHeight= self.FrontHeight + self.diffY
if(self.FrontWidth<=0):
Frontwidth=1
if(self.FrontHeight<=0):
FrontHeight=1
self.frontCam.node().getLens().setFilmSize(self.FrontWidth,self.FrontHeight)
self.resizedr(self.VerticalAxis,self.HorizontalAxis)
elif(self.CurrentQuad==2):
self.TopWidth= self.TopWidth + self.diffX
self.TopHeight= self.TopHeight + self.diffX
self.TopWidth= self.TopWidth + self.diffY
self.TopHeight= self.TopHeight + self.diffY
self.topCam.node().getLens().setFilmSize(self.TopWidth,self.TopHeight)
self.resizedr(self.VerticalAxis,self.HorizontalAxis)
elif(self.CurrentQuad==3):
self.LeftWidth= self.LeftWidth + self.diffX
self.LeftHeight= self.LeftHeight + self.diffX
self.LeftWidth= self.LeftWidth + self.diffY
self.LeftHeight= self.LeftHeight + self.diffY
self.leftCam.node().getLens().setFilmSize(self.LeftWidth,self.LeftHeight)
self.resizedr(self.VerticalAxis,self.HorizontalAxis)
elif(self.CurrentQuad==4):
pass
else:
pass
self.oldX=self.currX
self.oldY=self.currY
return Task.cont
def MoveCamera(self,X_amt,Y_amt,Z_amt,quad):
if(quad==1):
self.frontCam.setPos(self.frontCam.getX()+X_amt,self.frontCam.getY()+Y_amt,self.frontCam.getZ()+Z_amt)
elif(quad==2):
self.topCam.setPos(self.topCam.getX()+X_amt,self.topCam.getY()+Y_amt,self.topCam.getZ()+Z_amt)
elif(quad==3):
self.leftCam.setPos(self.leftCam.getX()+X_amt,self.leftCam.getY()+Y_amt,self.leftCam.getZ()+Z_amt)
elif(quad==4):
self.perspectiveCam.setPos(self.perspectiveCam.getX()+X_amt,self.perspectiveCam.getY()+Y_amt,self.perspectiveCam.getZ()+Z_amt)
#View=QuadView()
#run()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,608 @@
#################################################################
# collisionWindow.py
# Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#################################################################
# Import Tkinter, Pmw, and the floater code from this directory tree.
from AppShell import *
from TkGlobal import *
from tkSimpleDialog import askfloat
import string
import math
import types
import Task
FRAMES = 0
SECONDS = 1
class AnimPanel(AppShell):
#################################################################
# This class will generate a animation panel for an actor
# which user assigned. Inside this panel, instead of using actorInterval
# or just simply calling the play function in Actor, we create a task to
# set animation frame by frame using setPose.
#################################################################
# Override class variables
appname = 'Anim Panel'
frameWidth = 575
frameHeight = 250
usecommandarea = 0
usestatusarea = 0
index = 0
dragMode = False
rateList= ['1/24.0', '0.1', '0.5', '1.0', '2.0', '5.0' , '10.0']
def __init__(self, aNode = None, parent = None, **kw):
INITOPT = Pmw.INITOPT
self.id = 'AnimPanel '+ aNode.getName()
self.appname = self.id
optiondefs = (
('title', self.appname, None),
('actor', aNode, None),
('animList', [], None),
)
self.defineoptions(kw, optiondefs)
self.frameHeight = 300
self.id = 'AnimPanel '+ aNode.getName()
self.nodeName = aNode.getName()
# Initialize the superclass
AppShell.__init__(self)
# Execute option callbacks
self.initialiseoptions(AnimPanel)
self.currTime = 0.0 # Initialize the start time
self.animName = None
self.parent.resizable(False,False) ## Disable the ability to resize for this Window.
def createInterface(self):
# Handle to the toplevels interior
interior = self.interior()
menuBar = self.menuBar
menuBar.addmenu('Anim', 'Anim Panel Operations')
# Reset all actor controls
menuBar.addmenuitem('File', 'command',
'Load Animation',
label = 'Load Animation',
command = self.loadAnimation)
menuBar.addmenuitem('Anim', 'command',
'Set actor controls to t = 0.0',
label = 'Jump all to zero',
command = self.resetAllToZero)
menuBar.addmenuitem('Anim', 'command',
'Set Actor controls to end time',
label = 'Jump all to end time',
command = self.resetAllToEnd)
menuBar.addmenuitem('Anim', 'separator')
menuBar.addmenuitem('Anim', 'command',
'Play Current Animation',
label = 'Play',
command = self.play)
menuBar.addmenuitem('Anim', 'command',
'Stop Current Animation',
label = 'stop',
command = self.stop)
# Create a frame to hold all the actor controls
actorFrame = Frame(interior)
name_label = Label(actorFrame, text= self.nodeName,font=('MSSansSerif', 16),
relief = SUNKEN, borderwidth=3)
name_label.place(x=5,y=5,anchor=NW)
Label(actorFrame, text= "Animation:", font=('MSSansSerif', 12)).place(x=140,y=5,anchor=NW)
Label(actorFrame, text= "Play Rate:", font=('MSSansSerif', 12)).place(x=140,y=35,anchor=NW)
self['animList'] = self['actor'].getAnimNames()
self.AnimEntry = self.createcomponent(
'AnimationMenu', (), None,
Pmw.ComboBox, (actorFrame,),
labelpos = W, entry_width = 20, selectioncommand = self.setAnimation,
scrolledlist_items = self['animList'])
self.AnimEntry.place(x=240,y=10,anchor=NW)
self.playRateEntry = self.createcomponent(
'playRateMenu', (), None,
Pmw.ComboBox, (actorFrame,),
labelpos = W, entry_width = 20, selectioncommand = self.setPlayRate,
scrolledlist_items = self.rateList)
self.playRateEntry.place(x=240,y=40,anchor=NW)
self.playRateEntry.selectitem('1.0')
### Loop checkbox
Label(actorFrame, text= "Loop:", font=('MSSansSerif', 12)).place(x=420,y=05,anchor=NW)
self.loopVar = IntVar()
self.loopVar.set(0)
self.loopButton = self.createcomponent(
'loopButton', (), None,
Checkbutton, (actorFrame,),
variable = self.loopVar)
self.loopButton.place(x=470,y=7,anchor=NW)
### Display Frames/Seconds
Label(actorFrame, text= "Frame/Second:", font=('MSSansSerif', 11)).place(x=5,y=75,anchor=NW)
self.unitsVar = IntVar()
self.unitsVar.set(FRAMES)
self.displayButton = self.createcomponent(
'displayButton', (), None,
Checkbutton, (actorFrame,),
command = self.updateDisplay,
variable = self.unitsVar)
self.displayButton.place(x=120,y=77,anchor=NW)
## scale control
frameFrame = Frame(actorFrame, relief = SUNKEN, bd = 1)
self.minLabel = self.createcomponent(
'minLabel', (), 'sLabel',
Label, (frameFrame,),
text = 0)
self.minLabel.pack(side = LEFT)
self.frameControl = self.createcomponent(
'scale', (), None,
Scale, (frameFrame,),
from_ = 0, to = 24, resolution = 1.0,
command = self.goTo, length = 500,
orient = HORIZONTAL, showvalue = 1)
self.frameControl.pack(side = LEFT, expand = 1)
self.frameControl.bind('<Button-1>', self.onPress)
self.frameControl.bind('<ButtonRelease-1>', self.onRelease)
self.maxLabel = self.createcomponent(
'maxLabel', (), 'sLabel',
Label, (frameFrame,),
text = 24)
self.maxLabel.pack(side = LEFT)
frameFrame.pack(side = LEFT, expand = 1, fill = X)
## button contorl
ButtomFrame = Frame(actorFrame, relief = SUNKEN, bd = 1,borderwidth=5)
self.toStartButton = self.createcomponent(
'toStart', (), None,
Button, (ButtomFrame,),
text = '<<',
width = 8,
command = self.resetAllToZero)
self.toStartButton.pack(side = LEFT, expand = 1, fill = X)
self.playButton = self.createcomponent(
'playButton', (), None,
Button, (ButtomFrame,),
text = 'Play', width = 8,
command = self.play)
self.playButton.pack(side = LEFT, expand = 1, fill = X)
self.stopButton = self.createcomponent(
'stopButton', (), None,
Button, (ButtomFrame,),
text = 'Stop', width = 8, state=DISABLED,
command = self.stop)
self.stopButton.pack(side = LEFT, expand = 1, fill = X)
self.toEndButton = self.createcomponent(
'toEnd', (), None,
Button, (ButtomFrame,),
text = '>>',
width = 8,
command = self.resetAllToEnd)
self.toEndButton.pack(side = LEFT, expand = 1, fill = X)
ButtomFrame.place(anchor=NW,x=5,y=165)
self.removeButton = self.createcomponent(
'Remove Animation', (), None,
Button, (actorFrame,),
text = 'Remove This Animation', width = 20,
command = self.removeAnim)
self.removeButton.place(anchor=NW,x=5,y=220)
self.loadButton = self.createcomponent(
'Load Animation', (), None,
Button, (actorFrame,),
text = 'Load New Animation', width = 20,
command = self.loadAnimation)
self.loadButton.place(anchor=NW,x=180,y=220)
# Now pack the actor frame
actorFrame.pack(expand = 1, fill = BOTH)
def updateList(self):
#################################################################
# updateList(self)
# This function will update the list of animations that the Actor
# currently has into the combo box widget.
#################################################################
self.ignore('DataH_loadFinish'+self.nodeName)
del self.loaderWindow
self['animList'] = self['actor'].getAnimNames()
animL = self['actor'].getAnimNames()
self.AnimEntry.setlist(animL)
def removeAnim(self):
#################################################################
# removeAnim(self)
# This function will stop the animation and get the name of animation
# which user wish to remove from the panel. Then, it will send out
# a message to dataHolder to remove the target animation.
# And in the same time, it will start waiting a return message to
# make sure that target animation has been removed.
#################################################################
name = self.AnimEntry.get()
if taskMgr.hasTaskNamed(self.id + '_UpdateTask'):
self.stop()
self.accept('DataH_removeAnimFinish'+self.nodeName,self.afterRemove)
messenger.send('AW_removeAnim',[self['actor'],name])
return
def afterRemove(self):
#################################################################
# afterRemove(self)
# This function will be called once panel has received the return
# message from dataHolder. This function will call setList to
# reset the list of Animations
#################################################################
self.ignore('DataH_removeAnimFinish'+self.nodeName)
self['animList'] = self['actor'].getAnimNames()
animL = self['actor'].getAnimNames()
self.AnimEntry.setlist(animL)
print '-----',animL
return
def loadAnimation(self):
#################################################################
# loadAnimation(self)
# This function will open a dialog window to require user to input
# the animation he wants to load in for this actor.
#################################################################
self.loaderWindow = LoadAnimPanel(aNode=self['actor'])
self.accept('DataH_loadFinish'+self.nodeName,self.updateList)
return
def play(self):
#################################################################
# play(self)
# This function will be called when user click on the "play" button.
# First, this function will initialize all parameter that the actual
# play task need to run and add the play task into the taskMgr.
#################################################################
self.animName = self.AnimEntry.get()
if self.animName in self['animList']:
animName = self.AnimEntry.get()
self.playButton.config(state=DISABLED)
self.lastT = globalClock.getFrameTime()
taskMgr.add(self.playTask, self.id + '_UpdateTask')
self.stopButton.config(state=NORMAL)
else:
print '----Illegal Animaion name!!', self.animName
return
def playTask(self, task):
#################################################################
# playTask(self, task)
# This task will record time by each frame
# In fact it is just a clock keeper.
# If the current frame time over the max long of the animation,
# it will reset the timer.
# Anyway, this function will call gotoT by each frame.
#################################################################
fLoop = self.loopVar.get()
currT = globalClock.getFrameTime()
deltaT = currT - self.lastT
self.lastT = currT
if self.dragMode:
return Task.cont
self.currTime = self.currTime + deltaT
if (self.currTime > self.maxSeconds):
if fLoop:
self.currTime = self.currTime%self.duration
self.gotoT(self.currTime)
else:
self.currTime = 0.0
self.gotoT(0.0)
self.playButton.config(state=NORMAL)
self.stopButton.config(state=DISABLED)
return Task.done
else:
self.gotoT(self.currTime)
return Task.cont
def stop(self):
#################################################################
# stop(self)
# This function will remove the play task from taskMgr when user
# click on the "Stop" button
#################################################################
taskMgr.remove(self.id + '_UpdateTask')
self.playButton.config(state=NORMAL)
self.stopButton.config(state=DISABLED)
return
def setAnimation(self, animation):
#################################################################
# setAnimation(self, animation)
# This function will be called each time when user change
# the current animation. Most important thing this function do is
# to recalculate all variables to fit the selected animation
#################################################################
self.animName = self.AnimEntry.get()
playRate = '%0.1f' % self['actor'].getPlayRate(self.animName)
if playRate not in self.rateList:
def strCmp(a, b):
return cmp(eval(a), eval(b))
self.rateList.append(playRate)
self.rateList.sort(strCmp)
self.playRateEntry.reset(self.rateList)
self.playRateEntry.selectitem(playRate)
self.currTime = 0.0
self.frameControl.set(0)
self.updateDisplay()
return
def setPlayRate(self,rate):
#################################################################
# setPlayRate(self, rate)
# This function will be called each time when user changes the current play rate.
#################################################################
self.animName = self.AnimEntry.get()
if self.animName in self['animList']:
self['actor'].setPlayRate(eval(rate), self.animName)
self.updateDisplay()
return
def updateDisplay(self):
#################################################################
# updateDisplay(self)
# This function will be called whenever something has been changed
# on the panel. In here we will re-new all widgets on the panel to
# correct value.
#################################################################
self.fps = self['actor'].getFrameRate(self.animName)
self.duration = self['actor'].getDuration(self.animName)
self.maxFrame = self['actor'].getNumFrames(self.animName) - 1
self.maxSeconds = self.duration
if self.unitsVar.get() == FRAMES:
fromFrame = 0
toFrame = self.maxFrame
self.minLabel['text'] = fromFrame
self.maxLabel['text'] = toFrame
self.frameControl.configure(from_ = fromFrame,
to = toFrame,
resolution = 1.0)
else:
self.minLabel['text'] = '0.0'
self.maxLabel['text'] = "%.2f" % self.duration
self.frameControl.configure(from_ = 0.0,
to = self.duration,
resolution = 0.01)
def gotoT(self,time):
#################################################################
# gotoT(self, time)
# calculate the right parameter which will be send to set Frame
# Control slider, which is the real place we play the animation.
#################################################################
if self.unitsVar.get() == FRAMES:
self.frameControl.set(time * self.fps)
else:
self.frameControl.set(time)
return
def goTo(self,frame):
#################################################################
# goto(self, frame)
# Call back function for the frame control slider.
# This function will set the animation by the value on the slider.
#
# This function is the real function we "play" the animation.
#
#################################################################
if self.animName in self['animList']:
# Convert scale value to float
frame = string.atof(frame)
# Now convert t to seconds for offset calculations
if self.unitsVar.get() == FRAMES:
frame = frame / self.fps
if self.dragMode:
# If user is clicking on the slider and is draging the bar, reset the global timer.
self.currTime = frame
self['actor'].pose(self.animName,
min(self.maxFrame, int(frame * self.fps)))
return
def onRelease(self,frame):
#################################################################
# onRelease(self, frame)
# disable the dragMode when user releases the bar on the slider.
#################################################################
self.dragMode = False
return
def onPress(self,frame):
#################################################################
# onPress(self, frame)
# enable the dragMode when user press the bar on the slider.
#################################################################
self.dragMode = True
return
def resetAllToZero(self):
#################################################################
# resetAllToZero(self)
# reset the global timer to zero and also move the slider to zero.
# This will also reset the actor to the zero frame of current animation
#################################################################
self.currTime = 0.0
self.gotoT(0)
return
def resetAllToEnd(self):
#################################################################
# resetAllToEnd(self)
# set the global timer to the end of current animation and
# also move the slider to the end.
#################################################################
self.currTime = self.maxSeconds
self.gotoT(self.duration)
return
def onDestroy(self, event):
if taskMgr.hasTaskNamed(self.id + '_UpdateTask'):
taskMgr.remove(self.id + '_UpdateTask')
self.ignore('DataH_loadFinish')
messenger.send('AW_close',[self.nodeName])
'''
If you have open any thing, please rewrite here!
'''
pass
class LoadAnimPanel(AppShell):
#################################################################
# LoadAnimPanel(AppShell)
# This class will open a dialog to ask user to input names and
# file paths of animations
#################################################################
# Override class variables
appname = 'Load Animation'
frameWidth = 575
frameHeight = 200
usecommandarea = 0
usestatusarea = 0
index = 0
## Anim name : File Path
def __init__(self, aNode = None, parent = None, **kw):
INITOPT = Pmw.INITOPT
self.id = 'Load Animation '+ aNode.getName()
self.appname = self.id
self.animDic = {}
self.animList = []
optiondefs = (
('title', self.appname, None),
)
self.defineoptions(kw, optiondefs)
self.frameHeight = 300
self.nodeName = aNode.getName()
self.Actor = aNode
# Initialize the superclass
AppShell.__init__(self)
# Execute option callbacks
self.initialiseoptions(LoadAnimPanel)
def createInterface(self):
self.menuBar.destroy()
interior = self.interior()
mainFrame = Frame(interior)
self.inputZone = Pmw.Group(mainFrame, tag_text='File Setting')
self.inputZone.pack(fill='both',expand=1)
settingFrame = self.inputZone.interior()
Label(settingFrame,text='Anim Name').place(anchor=NW,x=60,y=5)
Label(settingFrame,text='File Path').place(anchor=NW,x=205,y=5)
self.AnimName_1 = self.createcomponent(
'Anim Name List', (), None,
Pmw.ComboBox, (settingFrame,),label_text='Anim :',
labelpos = W, entry_width = 10, selectioncommand = self.selectAnim,
scrolledlist_items = self.animList)
self.AnimFile_1 = Pmw.EntryField(settingFrame,value='')
self.AnimFile_1.component('entry').config(width=20)
self.AnimName_1.place(anchor=NW,x=10,y=25)
self.AnimFile_1.place(anchor=NW,x=140,y=25)
self.Browse_1 = self.createcomponent(
'File Browser1', (), None,
Button, (mainFrame,),
text = 'Browse...',
command = self.Browse_1)
self.Browse_1.place(anchor=NW,x=270,y=38)
self.addIntoButton = self.createcomponent(
'Load Add', (), None,
Button, (mainFrame,),
text = 'Add to Load',
command = self.addIntoList)
self.addIntoButton.place(anchor=NW,x=345,y=38)
att_label = Label(mainFrame, font=('MSSansSerif', 10),
text= "Attention! Animations won't be loaded in before you press the 'OK' button below!")
att_label.place(anchor=NW,x=10,y=80)
self.button_ok = Button(mainFrame, text="OK", command=self.ok_press,width=10)
self.button_ok.pack(fill=BOTH,expand=0,side=RIGHT)
mainFrame.pack(expand = 1, fill = BOTH)
def onDestroy(self, event):
messenger.send('AWL_close',[self.nodeName])
'''
If you have open any thing, please rewrite here!
'''
pass
def selectAnim(self,name):
#################################################################
# selectAnim(self, name)
# This function will be called if user select an animation on the list.
#################################################################
if name in self.animDic:
self.AnimFile_1.setvalue = self.animDic[name]
return
def Browse_1(self):
#################################################################
# Browse_1(self)
# when the browse button pused, this function will be called.
# Do nothing but open a file dialog for user to set the path to target file
# Then, set the path back to the entry on the panel.
#################################################################
AnimFilename = askopenfilename(
defaultextension = '.egg',
filetypes = (('Egg Files', '*.egg'),
('Bam Files', '*.bam'),
('All files', '*')),
initialdir = '.',
title = 'File Path for Anim 1',
parent = self.parent)
if AnimFilename:
self.AnimFile_1.setvalue(AnimFilename)
return
def addIntoList(self):
#################################################################
# addIntoList(self)
# This function will be called each time when user click on the
# "Add to Load" button. This function will read the current data
# on the panel into a dictionary. then reset the list of the animation
# name list on this panel.(not the one in the animation panel...)
#
# This function won't load any animation....
#
#################################################################
name = self.AnimName_1.get()
self.animDic[name] = Filename.fromOsSpecific(self.AnimFile_1.getvalue()).getFullpath()
if name in self.animList:
pass
else:
self.animList.append(name)
self.AnimName_1.setlist(self.animList)
print self.animDic
return
def ok_press(self):
#################################################################
# ok_press(Self)
# This functiion will be called when user click on the "OK"
# button. This function will send a message along with the animation
# file we wish to load for this actor.
# Then, it will close the panel itself.
#################################################################
messenger.send('AW_AnimationLoad',[self.Actor,self.animDic])
#print self.animDic
self.quit()
return

View File

@ -0,0 +1,666 @@
#################################################################
# collisionWindow.py
# Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#################################################################
# Import Tkinter, Pmw, and the floater code from this directory tree.
from AppShell import *
from TkGlobal import *
from tkSimpleDialog import askfloat
import string
import math
import types
import Task
FRAMES = 0
SECONDS = 1
#####################################################################################
# BlendAnimPanel(AppShell)
# This Panel will allow user to blend tow animations
# that have already been loaded for this actor.
# user can play and manipulate this blended animation
# just like in the animation panel. And, they can save this blended animation.
#####################################################################################
class BlendAnimPanel(AppShell):
# Override class variables
appname = 'Blend Anim Panel'
frameWidth = 575
frameHeight = 450
usecommandarea = 0
usestatusarea = 0
index = 0
dragMode = False
blendRatio = 0
rateList= ['1/24.0', '0.1', '0.5', '1.0', '2.0', '5.0' , '10.0']
enableBlend = False
currentBlendName = None
def __init__(self, aNode = None, blendDict={}, parent = None, **kw):
INITOPT = Pmw.INITOPT
self.id = 'BlendAnimPanel '+ aNode.getName()
self.appname = self.id
self.actorNode = aNode
self.blendDict = blendDict.copy()
if len(blendDict)>0:
self.blendList = blendDict.keys()
else:
self.blendList = []
optiondefs = (
('title', self.appname, None),
('actor', aNode, None),
('animList', [], None),
('blendAnimList', self.blendList, None),
)
self.defineoptions(kw, optiondefs)
self.id = 'Blend AnimPanel '+ aNode.getName()
self.nodeName = aNode.getName()
# Initialize the superclass
AppShell.__init__(self)
# Execute option callbacks
self.initialiseoptions(BlendAnimPanel)
self.currTime = 0.0
self.animNameA = None
self.animNameB = None
self.parent.resizable(False,False) ## Disable the ability to resize for this Window.
def createInterface(self):
# Handle to the toplevels interior
interior = self.interior()
self.menuBar.destroy()
# show the actor's name
actorFrame = Frame(interior)
name_label = Label(actorFrame, text= self.nodeName,font=('MSSansSerif', 14),
relief = SUNKEN, borderwidth=3)
name_label.pack(side = TOP, expand = False)
actorFrame.pack(side = TOP, expand = False, fill = X)
# Create a frame to show is there any ore-blended animation and save, edit, rename button.
group = Pmw.Group(interior, tag_pyclass=None)
actorFrame = group.interior()
group.pack(side = TOP, expand = False, fill = X)
Label(actorFrame, text= "Blended:", font=('MSSansSerif', 10)).pack(side=LEFT)
self.blendAnimEntry = self.createcomponent(
'Blended Animation', (), None,
Pmw.ComboBox, (actorFrame,),
labelpos = W, entry_width = 20, selectioncommand = self.setBlendAnim,
scrolledlist_items = self['blendAnimList'])
self.blendAnimEntry.pack(side=LEFT)
Label(actorFrame, text= " ", font=('MSSansSerif', 10)).pack(side=LEFT)
button = Button(actorFrame, text="Save", font=('MSSansSerif', 10),width = 12,
command = self.saveButtonPushed).pack(side=LEFT)
button = Button(actorFrame, text="Remove", font=('MSSansSerif', 10),width = 12,
command = self.removeButtonPushed).pack(side=LEFT)
button = Button(actorFrame, text="Rename", font=('MSSansSerif', 10),width = 12,
command = self.renameButtonPushed).pack(side=LEFT)
actorFrame.pack(side = TOP, expand = False, fill = X)
# Create a frame to hold all the animation setting
group = Pmw.Group(interior, tag_pyclass=None)
actorFrame = group.interior()
group.pack(side = TOP, expand = False, fill = X)
Label(actorFrame, text= "Animation A:", font=('MSSansSerif', 10)).pack(side=LEFT)
self['animList'] = self['actor'].getAnimNames()
self.AnimEntryA = self.createcomponent(
'AnimationMenuA', (), None,
Pmw.ComboBox, (actorFrame,),
labelpos = W, entry_width = 20, entry_state = DISABLED,
selectioncommand = lambda name, a = 'a' : self.setAnimation(name, AB=a),
scrolledlist_items = self['animList'])
self.AnimEntryA.pack(side=LEFT)
Label(actorFrame, text= " ", font=('MSSansSerif', 10)).pack(side=LEFT,)
Label(actorFrame, text= "Animation B:", font=('MSSansSerif', 10)).pack(side=LEFT)
self['animList'] = self['actor'].getAnimNames()
self.AnimEntryB = self.createcomponent(
'AnimationMenuB', (), None,
Pmw.ComboBox, (actorFrame,),
labelpos = W, entry_width = 20, entry_state = DISABLED,
selectioncommand = lambda name, a = 'b' : self.setAnimation(name, AB=a),
scrolledlist_items = self['animList'])
self.AnimEntryB.pack(side=LEFT)
actorFrame.pack(side = TOP, expand = False, fill = X)
### Blend Enable checkbox
actorFrame = Frame(interior, relief = SUNKEN, bd = 1)
Label(actorFrame, text= "Enable Blending:", font=('MSSansSerif', 10)).pack(side=LEFT,)
self.blendVar = IntVar()
self.blendVar.set(0)
self.blendButton = self.createcomponent(
'blendButton', (), None,
Checkbutton, (actorFrame,),
variable = self.blendVar,
command = self.toggleBlend)
self.blendButton.pack(side=LEFT)
actorFrame.pack(side = TOP, expand = False, fill = X)
## Ratio control
actorFrame = Frame(interior)
frameFrame = Frame(actorFrame, relief = SUNKEN, bd = 1)
minRatioLabel = self.createcomponent(
'minRatioLabel', (), 'sLabel',
Label, (frameFrame,),
text = 0.00)
minRatioLabel.pack(side = LEFT)
self.ratioControl = self.createcomponent(
'ratio', (), None,
Scale, (frameFrame,),
from_ = 0.0, to = 1.0, resolution = 0.01,
command = self.setRatio, length = 500,
orient = HORIZONTAL, showvalue = 1)
self.ratioControl.pack(side = LEFT, expand = 1)
self.ratioControl.set(1.0)
self.maxRatioLabel = self.createcomponent(
'maxRatioLabel', (), 'sLabel',
Label, (frameFrame,),
text = 1.00)
self.maxRatioLabel.pack(side = LEFT)
frameFrame.pack(side = LEFT, expand = 1, fill = X)
actorFrame.pack(side = TOP, expand = True, fill = X)
###################################################################################
###################################################################################
actorFrame = Frame(interior)
Label(actorFrame, text= "Play Rate:", font=('MSSansSerif', 10)).pack(side=LEFT)
self.playRateEntry = self.createcomponent(
'playRateMenu', (), None,
Pmw.ComboBox, (actorFrame,),
labelpos = W, entry_width = 20, selectioncommand = self.setPlayRate,
scrolledlist_items = self.rateList)
self.playRateEntry.pack(side=LEFT)
self.playRateEntry.selectitem('1.0')
### Loop checkbox
Label(actorFrame, text= " ", font=('MSSansSerif', 10)).pack(side=LEFT,)
Label(actorFrame, text= "Loop:", font=('MSSansSerif', 10)).pack(side=LEFT,)
self.loopVar = IntVar()
self.loopVar.set(0)
self.loopButton = self.createcomponent(
'loopButton', (), None,
Checkbutton, (actorFrame,),
variable = self.loopVar)
self.loopButton.pack(side=LEFT)
actorFrame.pack(side = TOP, expand = True, fill = X)
### Display Frames/Seconds
actorFrame = Frame(interior)
Label(actorFrame, text= "Frame/Second:", font=('MSSansSerif', 10)).pack(side=LEFT)
self.unitsVar = IntVar()
self.unitsVar.set(FRAMES)
self.displayButton = self.createcomponent(
'displayButton', (), None,
Checkbutton, (actorFrame,),
command = self.updateDisplay,
variable = self.unitsVar)
self.displayButton.pack(side=LEFT)
actorFrame.pack(side = TOP, expand = True, fill = X)
## scale control
actorFrame = Frame(interior)
frameFrame = Frame(actorFrame, relief = SUNKEN, bd = 1)
self.minLabel = self.createcomponent(
'minLabel', (), 'sLabel',
Label, (frameFrame,),
text = 0)
self.minLabel.pack(side = LEFT)
self.frameControl = self.createcomponent(
'scale', (), None,
Scale, (frameFrame,),
from_ = 0, to = 24, resolution = 1.0,
command = self.goTo, length = 500,
orient = HORIZONTAL, showvalue = 1)
self.frameControl.pack(side = LEFT, expand = 1)
self.frameControl.bind('<Button-1>', self.onPress)
self.frameControl.bind('<ButtonRelease-1>', self.onRelease)
self.maxLabel = self.createcomponent(
'maxLabel', (), 'sLabel',
Label, (frameFrame,),
text = 24)
self.maxLabel.pack(side = LEFT)
frameFrame.pack(side = LEFT, expand = 1, fill = X)
actorFrame.pack(side = TOP, expand = True, fill = X)
## button contorl
actorFrame = Frame(interior)
ButtomFrame = Frame(actorFrame, relief = SUNKEN, bd = 1,borderwidth=5)
self.toStartButton = self.createcomponent(
'toStart', (), None,
Button, (ButtomFrame,),
text = '<<',
width = 8,
command = self.resetAllToZero)
self.toStartButton.pack(side = LEFT, expand = 1, fill = X)
self.playButton = self.createcomponent(
'playButton', (), None,
Button, (ButtomFrame,),
text = 'Play', width = 8,
command = self.play)
self.playButton.pack(side = LEFT, expand = 1, fill = X)
self.stopButton = self.createcomponent(
'stopButton', (), None,
Button, (ButtomFrame,),
text = 'Stop', width = 8, state=DISABLED,
command = self.stop)
self.stopButton.pack(side = LEFT, expand = 1, fill = X)
self.toEndButton = self.createcomponent(
'toEnd', (), None,
Button, (ButtomFrame,),
text = '>>',
width = 8,
command = self.resetAllToEnd)
self.toEndButton.pack(side = LEFT, expand = 1, fill = X)
ButtomFrame.pack(side = TOP, expand = True, fill = X)
actorFrame.pack(expand = 1, fill = BOTH)
def updateList(self):
#################################################################
# updateList(self)
# This will reset the list of all animations that this actor has
# to the animation entry A and B.
#################################################################
self['animList'] = self['actor'].getAnimNames()
animL = self['actor'].getAnimNames()
self.AnimEntryA.setlist(animL)
self.AnimEntryB.setlist(animL)
def play(self):
#################################################################
# play(self)
# It works pretty much like what we have in the Animation Panel.
# The only different now is that we set two "pose" here.
# When you do the blending animation by setPose, you don't have
# to set them simultaneously.
#################################################################
self.animNameA = self.AnimEntryA.get()
self.animNameB = self.AnimEntryB.get()
if (self.animNameA in self['animList'])and(self.animNameB in self['animList']):
self.playButton.config(state=DISABLED)
self.lastT = globalClock.getFrameTime()
taskMgr.add(self.playTask, self.id + '_UpdateTask')
self.stopButton.config(state=NORMAL)
else:
print '----Illegal Animaion name!!', self.animNameA + ', '+ self.animNameB
return
def playTask(self, task):
#################################################################
# playTask(self, task)
# see play(self)
#################################################################
fLoop = self.loopVar.get()
currT = globalClock.getFrameTime()
deltaT = currT - self.lastT
self.lastT = currT
if self.dragMode:
return Task.cont
self.currTime = self.currTime + deltaT
if (self.currTime > self.maxSeconds):
if fLoop:
self.currTime = self.currTime%self.duration
self.gotoT(self.currTime)
else:
self.currTime = 0.0
self.gotoT(0.0)
self.playButton.config(state=NORMAL)
self.stopButton.config(state=DISABLED)
return Task.done
else:
self.gotoT(self.currTime)
return Task.cont
def stop(self):
#################################################################
# stop(self)
# see play(self)
#################################################################
taskMgr.remove(self.id + '_UpdateTask')
self.playButton.config(state=NORMAL)
self.stopButton.config(state=DISABLED)
return
def setAnimation(self, animation, AB = 'a'):
#################################################################
# setAnimation(self, animation, AB = 'a')
# see play(self)
#################################################################
print 'OK!!!'
if AB == 'a':
if self.animNameA != None:
self['actor'].setControlEffect(self.animNameA, 1.0, 'modelRoot','lodRoot')
self.animNameA = self.AnimEntryA.get()
else:
if self.animNameB != None:
self['actor'].setControlEffect(self.animNameB, 1.0, 'modelRoot','lodRoot')
self.animNameB = self.AnimEntryB.get()
self.currTime = 0.0
self.frameControl.set(0)
self.updateDisplay()
self.setRatio(self.blendRatio)
return
def setPlayRate(self,rate):
#################################################################
# setPlayRate(self,rate)
# see play(self)
#################################################################
self.animNameA = self.AnimEntryA.get()
if self.animNameA in self['animList']:
self['actor'].setPlayRate(eval(rate), self.animNameA)
self.updateDisplay()
if self.animNameB in self['animList']:
self['actor'].setPlayRate(eval(rate), self.animNameB)
self.updateDisplay()
return
def updateDisplay(self):
#################################################################
# updateDisplay(self)
# see play(self)
#################################################################
if not (self.animNameA in self['animList']):
return
self.fps = self['actor'].getFrameRate(self.animNameA)
self.duration = self['actor'].getDuration(self.animNameA)
self.maxFrame = self['actor'].getNumFrames(self.animNameA) - 1
if not (self.animNameB in self['animList']):
return
if self.duration > self['actor'].getDuration(self.animNameB):
self.duration = self['actor'].getDuration(self.animNameB)
if self.maxFrame > self['actor'].getNumFrames(self.animNameB) - 1:
self.maxFrame = self['actor'].getNumFrames(self.animNameB) - 1
self.maxSeconds = self.duration
if self.unitsVar.get() == FRAMES:
fromFrame = 0
toFrame = self.maxFrame
self.minLabel['text'] = fromFrame
self.maxLabel['text'] = toFrame
self.frameControl.configure(from_ = fromFrame,
to = toFrame,
resolution = 1.0)
else:
self.minLabel['text'] = '0.0'
self.maxLabel['text'] = "%.2f" % self.duration
self.frameControl.configure(from_ = 0.0,
to = self.duration,
resolution = 0.01)
def gotoT(self,time):
#################################################################
# gotoT(self,time)
# see play(self)
#################################################################
if self.unitsVar.get() == FRAMES:
self.frameControl.set(time * self.fps)
else:
self.frameControl.set(time)
return
def goTo(self,frame):
#################################################################
# goTo(self,frame)
# see play(self)
#################################################################
if (self.animNameA in self['animList'])and(self.animNameB in self['animList']):
# Convert scale value to float
frame = string.atof(frame)
# Now convert t to seconds for offset calculations
if self.unitsVar.get() == FRAMES:
frame = frame / self.fps
if self.dragMode:
self.currTime = frame
self['actor'].pose(self.animNameA,
min(self.maxFrame, int(frame * self.fps)))
self['actor'].pose(self.animNameB,
min(self.maxFrame, int(frame * self.fps)))
return
def onRelease(self,frame):
#################################################################
# onRelease(self,frame)
# see play(self)
#################################################################
self.dragMode = False
return
def onPress(self,frame):
#################################################################
# onPress(self,frame)
# see play(self)
#################################################################
self.dragMode = True
return
def resetAllToZero(self):
#################################################################
# resetAllToZero(self)
# see play(self)
#################################################################
self.currTime = 0.0
self.gotoT(0)
return
def resetAllToEnd(self):
#################################################################
# resetAllToEnd(self)
# see play(self)
#################################################################
self.currTime = self.maxSeconds
self.gotoT(self.duration)
return
def toggleBlend(self):
#################################################################
# toggleBlend(self)
# This function will enable the blending option for the actor.
# and call set ratio function to set the blending animation mixing in
# current ratio.
#
# This blending enable will not be keep when you close the window!
#
#################################################################
if self.blendVar.get():
self.enableBlend = True
self['actor'].enableBlend()
self.setRatio(self.blendRatio)
else:
self.enableBlend = False
self['actor'].disableBlend()
return
def setRatio(self, ratio):
#################################################################
# setRatio(self, ratio)
# callback funtion
# This one will be called each time when user drag the blend ratio
# slider on the panel. This will set the blening ratio to both animation.
# (Which is "setControlEffect")
#################################################################
self.blendRatio = float(ratio)
if self.enableBlend:
if self.animNameA in self['animList']:
self['actor'].setControlEffect(self.animNameA, self.blendRatio, 'modelRoot','lodRoot')
if self.animNameB in self['animList']:
self['actor'].setControlEffect(self.animNameB, 1-self.blendRatio, 'modelRoot','lodRoot')
return
def setBlendAnim(self, name):
#################################################################
# setBlendAnim(self, name)
# This function will be called each time when user try to select
# a existing blending animation from the comboBox on the panel
# This function will re-set every varaibles on the panel to what
# it should be. For example, when user choose blending anim "R,"
# which was blended by anim "a" and "b" with ratio "c,"
# then this function will set Animation A to "a" and animation B
# to "b" and set the ratio slider to "c" position.
#################################################################
if self.blendDict.has_key(name):
self.currentBlendName = name
animA = self.blendDict[name][0]
animB = self.blendDict[name][1]
ratio = self.blendDict[name][2]
self.AnimEntryA.selectitem(animA)
self.AnimEntryB.selectitem(animB)
self.setAnimation(animA, AB = 'a')
self.setAnimation(animB, AB = 'b')
self.ratioControl.set(ratio)
return
def setBlendAnimList(self, dict, select=False):
#################################################################
# setBlendAnimList(self, dict, select=False)
# This function will be called when we need to reset the dropdown list
# of "Blend Anim."
# About "selec" option, this now is mainly used when we remove
# a blended animation from the actor. When it has been specified to True,
# the function will not only reset the list, but will also automatically
# select one from the top of list, if it is not empty.
#################################################################
self.blendDict.clear()
del self.blendDict
self.blendDict = dict.copy()
print self.blendDict
if len(self.blendDict)>0:
self.blendList = self.blendDict.keys()
else:
self.blendList = []
self.blendAnimEntry.setlist(self.blendList)
if select:
if len(self.blendList)>0:
self.blendAnimEntry.selectitem(self.blendList[0])
self.setBlendAnim(self.blendList[0])
self.currentBlendName = self.blendList[0]
else:
self.blendAnimEntry.clear()
self.currentBlendName = None
return
def saveButtonPushed(self):
#################################################################
# saveButtonPushed(self)
# This function will be called when user clicked on the "Save" button
# This functiont will collect all data on the panel and send them with
# a message to sceneEditor to save the current blending animation
# into the dataHolder.
#################################################################
name = self.blendAnimEntry.get()
if name=='':
Pmw.MessageDialog(None, title='Caution!',
message_text = 'You have to give the blending animation a name first!',
iconpos='s',
defaultbutton = 'Close'
)
return
elif (not(self.animNameA in self['animList']))or(not(self.animNameB in self['animList'])):
Pmw.MessageDialog(None, title='Caution!',
message_text = 'The Animations you have selected are not exist!',
iconpos='s',
defaultbutton = 'Close'
)
return
else:
messenger.send('BAW_saveBlendAnim', [self['actor'].getName(),
name,
self.animNameA,
self.animNameB,
self.blendRatio])
self.currentBlendName = name
return
def removeButtonPushed(self):
#################################################################
# removeButtonPushed(self)
# remove the current seleted blended animation from the actor.
# This will send out a message to sceneEditor to delete the data inside
# the dataHolder and then reset the list of here.
#################################################################
name = self.blendAnimEntry.get()
messenger.send('BAW_removeBlendAnim', [self['actor'].getName(),name])
return
def renameButtonPushed(self):
#################################################################
# renameButtonPushed(self)
# this function will be called when user click on the "Rename" button.
# This function will collect all data on the panel and send them out
# with a message to sceneEditor to rename and re-save all setting about
# current animation.
#################################################################
oName = self.currentBlendName
name = self.blendAnimEntry.get()
if self.currentBlendName == None:
Pmw.MessageDialog(None, title='Caution!',
message_text = "You haven't select any blended animation!!",
iconpos='s',
defaultbutton = 'Close'
)
return
elif name=='':
Pmw.MessageDialog(None, title='Caution!',
message_text = 'You have to give the blending animation a name first!',
iconpos='s',
defaultbutton = 'Close'
)
return
elif (not(self.animNameA in self['animList']))or(not(self.animNameB in self['animList'])):
Pmw.MessageDialog(None, title='Caution!',
message_text = 'The Animations you have selected are not exist!',
iconpos='s',
defaultbutton = 'Close'
)
return
else:
messenger.send('BAW_renameBlendAnim', [self['actor'].getName(),
name,
oName,
self.animNameA,
self.animNameB,
self.blendRatio]
)
self.currentBlendName = name
return
def onDestroy(self, event):
#################################################################
# onDestroy(self, event)
# This function will be call when user try to close the window.
# In here we will stop all tasks we have opend and disable the
# blend setting of actor.
# If we didn't disable the blend option, the next time you play
# the animation via animation panel will cause some error.
#################################################################
if taskMgr.hasTaskNamed(self.id + '_UpdateTask'):
taskMgr.remove(self.id + '_UpdateTask')
messenger.send('BAW_close',[self.nodeName])
self.actorNode.setControlEffect(self.animNameA, 1.0, 'modelRoot','lodRoot')
self.actorNode.setControlEffect(self.animNameB, 1.0, 'modelRoot','lodRoot')
self.actorNode.disableBlend()
'''
If you have open any thing, please rewrite here!
'''
pass

View File

@ -0,0 +1,670 @@
#################################################################
# seCameraControl.py
# Originally from DirectCameraControl.py
# Altered by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#
# We didn't change anything essential.
# Just because we customized the seSession from DirectSession,
# So we need related files can follow the change.
# However, we don't want to change anything inside the original directool
# to let them can work with our scene editor.
# (If we do change original directools, it will force user has to install the latest version of OUR Panda)
#
#################################################################
from PandaObject import *
from DirectUtil import *
from seGeometry import *
from DirectGlobals import *
import Task
CAM_MOVE_DURATION = 1.2
COA_MARKER_SF = 0.0075
Y_AXIS = Vec3(0,1,0)
class DirectCameraControl(PandaObject):
def __init__(self):
# Create the grid
self.startT = 0.0
self.startF = 0
self.orthoViewRoll = 0.0
self.lastView = 0
self.coa = Point3(0,100,0)
self.coaMarker = loader.loadModel('models/misc/sphere')
self.coaMarker.setName('DirectCameraCOAMarker')
self.coaMarker.setTransparency(1)
self.coaMarker.setColor(1,0,0,0)
self.coaMarker.setPos(0,100,0)
useDirectRenderStyle(self.coaMarker)
self.coaMarkerPos = Point3(0)
self.fLockCOA = 0
self.nullHitPointCount = 0
self.cqEntries = []
self.coaMarkerRef = SEditor.group.attachNewNode('coaMarkerRef')
self.camManipRef = SEditor.group.attachNewNode('camManipRef')
t = CAM_MOVE_DURATION
self.actionEvents = [
['DIRECT-mouse2', self.mouseFlyStart],
['DIRECT-mouse2Up', self.mouseFlyStop],
]
self.keyEvents = [
['c', self.centerCamIn, 0.5],
['f', self.fitOnWidget],
['h', self.homeCam],
['shift-v', self.toggleMarkerVis],
['m', self.moveToFit],
['n', self.pickNextCOA],
['u', self.orbitUprightCam],
['shift-u', self.uprightCam],
[`1`, self.spawnMoveToView, 1],
[`2`, self.spawnMoveToView, 2],
[`3`, self.spawnMoveToView, 3],
[`4`, self.spawnMoveToView, 4],
[`5`, self.spawnMoveToView, 5],
[`6`, self.spawnMoveToView, 6],
[`7`, self.spawnMoveToView, 7],
[`8`, self.spawnMoveToView, 8],
['9', self.swingCamAboutWidget, -90.0, t],
['0', self.swingCamAboutWidget, 90.0, t],
['`', self.removeManipulateCameraTask],
['=', self.zoomCam, 0.5, t],
['+', self.zoomCam, 0.5, t],
['-', self.zoomCam, -2.0, t],
['_', self.zoomCam, -2.0, t],
]
def toggleMarkerVis(self):
if SEditor.cameraControl.coaMarker.isHidden():
SEditor.cameraControl.coaMarker.show()
else:
SEditor.cameraControl.coaMarker.hide()
def mouseFlyStart(self, modifiers):
# Record undo point
SEditor.pushUndo([SEditor.camera])
# Where are we in the display region?
if ((abs(SEditor.dr.mouseX) < 0.9) and (abs(SEditor.dr.mouseY) < 0.9)):
# MOUSE IS IN CENTRAL REGION
# Hide the marker for this kind of motion
self.coaMarker.hide()
# Record time of start of mouse interaction
self.startT= globalClock.getFrameTime()
self.startF = globalClock.getFrameCount()
# Start manipulation
self.spawnXZTranslateOrHPanYZoom()
# END MOUSE IN CENTRAL REGION
else:
if ((abs(SEditor.dr.mouseX) > 0.9) and
(abs(SEditor.dr.mouseY) > 0.9)):
# Mouse is in corners, spawn roll task
self.spawnMouseRollTask()
else:
# Mouse is in outer frame, spawn mouseRotateTask
self.spawnMouseRotateTask()
def mouseFlyStop(self):
taskMgr.remove('manipulateCamera')
stopT = globalClock.getFrameTime()
deltaT = stopT - self.startT
stopF = globalClock.getFrameCount()
deltaF = stopF - self.startF
if (deltaT <= 0.25) or (deltaF <= 1):
# Check for a hit point based on
# current mouse position
# Allow intersection with unpickable objects
# And then spawn task to determine mouse mode
# Don't intersect with hidden or backfacing objects
skipFlags = SKIP_HIDDEN | SKIP_BACKFACE
# Skip camera (and its children), unless control key is pressed
skipFlags |= SKIP_CAMERA * (1 - base.getControl())
self.computeCOA(SEditor.iRay.pickGeom(skipFlags = skipFlags))
# Record reference point
self.coaMarkerRef.iPosHprScale(base.cam)
# Record entries
self.cqEntries = []
for i in range(SEditor.iRay.getNumEntries()):
self.cqEntries.append(SEditor.iRay.getEntry(i))
# Show the marker
self.coaMarker.show()
# Resize it
self.updateCoaMarkerSize()
def spawnXZTranslateOrHPanYZoom(self):
# Kill any existing tasks
taskMgr.remove('manipulateCamera')
# Spawn the new task
t = Task.Task(self.XZTranslateOrHPanYZoomTask)
# For HPanYZoom
t.zoomSF = Vec3(self.coaMarker.getPos(SEditor.camera)).length()
taskMgr.add(t, 'manipulateCamera')
def spawnXZTranslateOrHPPan(self):
# Kill any existing tasks
taskMgr.remove('manipulateCamera')
# Spawn new task
taskMgr.add(self.XZTranslateOrHPPanTask,
'manipulateCamera')
def spawnXZTranslate(self):
# Kill any existing tasks
taskMgr.remove('manipulateCamera')
# Spawn new task
taskMgr.add(self.XZTranslateTask, 'manipulateCamera')
def spawnHPanYZoom(self):
# Kill any existing tasks
taskMgr.remove('manipulateCamera')
# Spawn new task
t = Task.Task(self.HPanYZoomTask)
t.zoomSF = Vec3(self.coaMarker.getPos(SEditor.camera)).length()
taskMgr.add(t, 'manipulateCamera')
def spawnHPPan(self):
# Kill any existing tasks
taskMgr.remove('manipulateCamera')
# Spawn new task
taskMgr.add(self.HPPanTask, 'manipulateCamera')
def XZTranslateOrHPanYZoomTask(self, state):
if SEditor.fShift:
return self.XZTranslateTask(state)
else:
return self.HPanYZoomTask(state)
def XZTranslateOrHPPanTask(self, state):
if SEditor.fShift:
# Panning action
return self.HPPanTask(state)
else:
# Translation action
return self.XZTranslateTask(state)
def XZTranslateTask(self,state):
coaDist = Vec3(self.coaMarker.getPos(SEditor.camera)).length()
xlateSF = (coaDist / SEditor.dr.near)
SEditor.camera.setPos(SEditor.camera,
(-0.5 * SEditor.dr.mouseDeltaX *
SEditor.dr.nearWidth *
xlateSF),
0.0,
(-0.5 * SEditor.dr.mouseDeltaY *
SEditor.dr.nearHeight *
xlateSF))
return Task.cont
def HPanYZoomTask(self,state):
if SEditor.fControl:
moveDir = Vec3(self.coaMarker.getPos(SEditor.camera))
# If marker is behind camera invert vector
if moveDir[1] < 0.0:
moveDir.assign(moveDir * -1)
moveDir.normalize()
else:
moveDir = Vec3(Y_AXIS)
moveDir.assign(moveDir * (-1.0 * SEditor.dr.mouseDeltaY *
state.zoomSF))
if SEditor.dr.mouseDeltaY > 0.0:
moveDir.setY(moveDir[1] * 1.0)
SEditor.camera.setPosHpr(SEditor.camera,
moveDir[0],
moveDir[1],
moveDir[2],
(0.5 * SEditor.dr.mouseDeltaX *
SEditor.dr.fovH),
0.0, 0.0)
return Task.cont
def HPPanTask(self, state):
SEditor.camera.setHpr(SEditor.camera,
(0.5 * SEditor.dr.mouseDeltaX *
SEditor.dr.fovH),
(-0.5 * SEditor.dr.mouseDeltaY *
SEditor.dr.fovV),
0.0)
return Task.cont
def spawnMouseRotateTask(self):
# Kill any existing tasks
taskMgr.remove('manipulateCamera')
# Set at markers position in render coordinates
self.camManipRef.setPos(self.coaMarkerPos)
self.camManipRef.setHpr(SEditor.camera, ZERO_POINT)
t = Task.Task(self.mouseRotateTask)
if abs(SEditor.dr.mouseX) > 0.9:
t.constrainedDir = 'y'
else:
t.constrainedDir = 'x'
taskMgr.add(t, 'manipulateCamera')
def mouseRotateTask(self, state):
# If moving outside of center, ignore motion perpendicular to edge
if ((state.constrainedDir == 'y') and (abs(SEditor.dr.mouseX) > 0.9)):
deltaX = 0
deltaY = SEditor.dr.mouseDeltaY
elif ((state.constrainedDir == 'x') and (abs(SEditor.dr.mouseY) > 0.9)):
deltaX = SEditor.dr.mouseDeltaX
deltaY = 0
else:
deltaX = SEditor.dr.mouseDeltaX
deltaY = SEditor.dr.mouseDeltaY
if SEditor.fShift:
SEditor.camera.setHpr(SEditor.camera,
(deltaX * SEditor.dr.fovH),
(-deltaY * SEditor.dr.fovV),
0.0)
self.camManipRef.setPos(self.coaMarkerPos)
self.camManipRef.setHpr(SEditor.camera, ZERO_POINT)
else:
wrt = SEditor.camera.getTransform( self.camManipRef )
self.camManipRef.setHpr(self.camManipRef,
(-1 * deltaX * 180.0),
(deltaY * 180.0),
0.0)
SEditor.camera.setTransform(self.camManipRef, wrt)
return Task.cont
def spawnMouseRollTask(self):
# Kill any existing tasks
taskMgr.remove('manipulateCamera')
# Set at markers position in render coordinates
self.camManipRef.setPos(self.coaMarkerPos)
self.camManipRef.setHpr(SEditor.camera, ZERO_POINT)
t = Task.Task(self.mouseRollTask)
t.coaCenter = getScreenXY(self.coaMarker)
t.lastAngle = getCrankAngle(t.coaCenter)
# Store the camera/manipRef offset transform
t.wrt = SEditor.camera.getTransform( self.camManipRef )
taskMgr.add(t, 'manipulateCamera')
def mouseRollTask(self, state):
wrt = state.wrt
angle = getCrankAngle(state.coaCenter)
deltaAngle = angle - state.lastAngle
state.lastAngle = angle
if base.config.GetBool('temp-hpr-fix',0):
self.camManipRef.setHpr(self.camManipRef, 0, 0, deltaAngle)
else:
self.camManipRef.setHpr(self.camManipRef, 0, 0, -deltaAngle)
SEditor.camera.setTransform(self.camManipRef, wrt)
return Task.cont
def lockCOA(self):
self.fLockCOA = 1
SEditor.message('COA Lock On')
def unlockCOA(self):
self.fLockCOA = 0
SEditor.message('COA Lock Off')
def toggleCOALock(self):
self.fLockCOA = 1 - self.fLockCOA
if self.fLockCOA:
SEditor.message('COA Lock On')
else:
SEditor.message('COA Lock Off')
def pickNextCOA(self):
""" Cycle through collision handler entries """
if self.cqEntries:
# Get next entry and rotate entries
entry = self.cqEntries[0]
self.cqEntries = self.cqEntries[1:] + self.cqEntries[:1]
# Filter out object's under camera
nodePath = entry.getIntoNodePath()
if SEditor.camera not in nodePath.getAncestry():
# Compute new hit point
hitPt = entry.getFromIntersectionPoint()
# Move coa marker to new point
self.updateCoa(hitPt, ref = self.coaMarkerRef)
else:
# Remove offending entry
self.cqEntries = self.cqEntries[:-1]
self.pickNextCOA()
def computeCOA(self, entry):
coa = Point3(0)
dr = SEditor.drList.getCurrentDr()
if self.fLockCOA:
# COA is locked, use existing point
# Use existing point
coa.assign(self.coaMarker.getPos(SEditor.camera))
# Reset hit point count
self.nullHitPointCount = 0
elif entry:
# Got a hit point (hit point is in camera coordinates)
# Set center of action
hitPt = entry.getFromIntersectionPoint()
hitPtDist = Vec3(hitPt).length()
coa.assign(hitPt)
# Handle case of bad coa point (too close or too far)
if ((hitPtDist < (1.1 * dr.near)) or
(hitPtDist > dr.far)):
# Just use existing point
coa.assign(self.coaMarker.getPos(SEditor.camera))
# Reset hit point count
self.nullHitPointCount = 0
else:
# Increment null hit point count
self.nullHitPointCount = (self.nullHitPointCount + 1) % 7
# No COA lock and no intersection point
# Use a point out in front of camera
# Distance to point increases on multiple null hit points
# MRM: Would be nice to be able to control this
# At least display it
dist = pow(10.0, self.nullHitPointCount)
SEditor.message('COA Distance: ' + `dist`)
coa.set(0,dist,0)
# Compute COA Dist
coaDist = Vec3(coa - ZERO_POINT).length()
if coaDist < (1.1 * dr.near):
coa.set(0,100,0)
coaDist = 100
# Update coa and marker
self.updateCoa(coa, coaDist = coaDist)
def updateCoa(self, ref2point, coaDist = None, ref = None):
self.coa.set(ref2point[0], ref2point[1], ref2point[2])
if not coaDist:
coaDist = Vec3(self.coa - ZERO_POINT).length()
# Place the marker in render space
if ref == None:
# KEH: use the current display region
# ref = base.cam
ref = SEditor.drList.getCurrentDr().cam
self.coaMarker.setPos(ref, self.coa)
pos = self.coaMarker.getPos()
self.coaMarker.setPosHprScale(pos, Vec3(0), Vec3(1))
# Resize it
self.updateCoaMarkerSize(coaDist)
# Record marker pos in render space
self.coaMarkerPos.assign(self.coaMarker.getPos())
def updateCoaMarkerSizeOnDeath(self, state):
# Needed because tasks pass in state as first arg
self.updateCoaMarkerSize()
def updateCoaMarkerSize(self, coaDist = None):
if not coaDist:
coaDist = Vec3(self.coaMarker.getPos( SEditor.camera )).length()
# KEH: use current display region for fov
# sf = COA_MARKER_SF * coaDist * math.tan(deg2Rad(SEditor.dr.fovV))
sf = COA_MARKER_SF * coaDist * math.tan(deg2Rad(SEditor.drList.getCurrentDr().fovV))
if sf == 0.0:
sf = 0.1
self.coaMarker.setScale(sf)
# Lerp color to fade out
self.coaMarker.lerpColor(VBase4(1,0,0,1), VBase4(1,0,0,0), 3.0,
task = 'fadeAway')
def homeCam(self):
# Record undo point
SEditor.pushUndo([SEditor.camera])
SEditor.camera.reparentTo(render)
SEditor.camera.clearMat()
# Resize coa marker
self.updateCoaMarkerSize()
def uprightCam(self):
taskMgr.remove('manipulateCamera')
# Record undo point
SEditor.pushUndo([SEditor.camera])
# Pitch camera till upright
currH = SEditor.camera.getH()
SEditor.camera.lerpHpr(currH, 0, 0,
CAM_MOVE_DURATION,
other = render,
blendType = 'easeInOut',
task = 'manipulateCamera')
def orbitUprightCam(self):
taskMgr.remove('manipulateCamera')
# Record undo point
SEditor.pushUndo([SEditor.camera])
# Transform camera z axis to render space
mCam2Render = Mat4()
mCam2Render.assign(SEditor.camera.getMat(render))
zAxis = Vec3(mCam2Render.xformVec(Z_AXIS))
zAxis.normalize()
# Compute rotation angle needed to upright cam
orbitAngle = rad2Deg(math.acos(CLAMP(zAxis.dot(Z_AXIS),-1,1)))
# Check angle
if orbitAngle < 0.1:
# Already upright
return
# Compute orthogonal axis of rotation
rotAxis = Vec3(zAxis.cross(Z_AXIS))
rotAxis.normalize()
# Find angle between rot Axis and render X_AXIS
rotAngle = rad2Deg(math.acos(CLAMP(rotAxis.dot(X_AXIS),-1,1)))
# Determine sign or rotation angle
if rotAxis[1] < 0:
rotAngle *= -1
# Position ref CS at coa marker with xaxis aligned with rot axis
self.camManipRef.setPos(self.coaMarker, Vec3(0))
self.camManipRef.setHpr(render, rotAngle, 0, 0)
# Reparent Cam to ref Coordinate system
parent = SEditor.camera.getParent()
SEditor.camera.wrtReparentTo(self.camManipRef)
# Rotate ref CS to final orientation
t = self.camManipRef.lerpHpr(rotAngle, orbitAngle, 0,
CAM_MOVE_DURATION,
other = render,
blendType = 'easeInOut',
task = 'manipulateCamera')
# Upon death, reparent Cam to parent
t.parent = parent
t.uponDeath = self.reparentCam
def centerCam(self):
self.centerCamIn(1.0)
def centerCamNow(self):
self.centerCamIn(0.)
def centerCamIn(self, t):
taskMgr.remove('manipulateCamera')
# Record undo point
SEditor.pushUndo([SEditor.camera])
# Determine marker location
markerToCam = self.coaMarker.getPos( SEditor.camera )
dist = Vec3(markerToCam - ZERO_POINT).length()
scaledCenterVec = Y_AXIS * dist
delta = markerToCam - scaledCenterVec
self.camManipRef.setPosHpr(SEditor.camera, Point3(0), Point3(0))
t = SEditor.camera.lerpPos(Point3(delta),
CAM_MOVE_DURATION,
other = self.camManipRef,
blendType = 'easeInOut',
task = 'manipulateCamera')
t.uponDeath = self.updateCoaMarkerSizeOnDeath
def zoomCam(self, zoomFactor, t):
taskMgr.remove('manipulateCamera')
# Record undo point
SEditor.pushUndo([SEditor.camera])
# Find a point zoom factor times the current separation
# of the widget and cam
zoomPtToCam = self.coaMarker.getPos(SEditor.camera) * zoomFactor
# Put a target nodePath there
self.camManipRef.setPos(SEditor.camera, zoomPtToCam)
# Move to that point
t = SEditor.camera.lerpPos(ZERO_POINT,
CAM_MOVE_DURATION,
other = self.camManipRef,
blendType = 'easeInOut',
task = 'manipulateCamera')
t.uponDeath = self.updateCoaMarkerSizeOnDeath
def spawnMoveToView(self, view):
# Kill any existing tasks
taskMgr.remove('manipulateCamera')
# Record undo point
SEditor.pushUndo([SEditor.camera])
# Calc hprOffset
hprOffset = VBase3()
if view == 8:
# Try the next roll angle
self.orthoViewRoll = (self.orthoViewRoll + 90.0) % 360.0
# but use the last view
view = self.lastView
else:
self.orthoViewRoll = 0.0
# Adjust offset based on specified view
if view == 1:
hprOffset.set(180., 0., 0.)
elif view == 2:
hprOffset.set(0., 0., 0.)
elif view == 3:
hprOffset.set(90., 0., 0.)
elif view == 4:
hprOffset.set(-90., 0., 0.)
elif view == 5:
hprOffset.set(0., -90., 0.)
elif view == 6:
hprOffset.set(0., 90., 0.)
elif view == 7:
hprOffset.set(135., -35.264, 0.)
# Position target
self.camManipRef.setPosHpr(self.coaMarker, ZERO_VEC,
hprOffset)
# Scale center vec by current distance to target
offsetDistance = Vec3(SEditor.camera.getPos(self.camManipRef) -
ZERO_POINT).length()
scaledCenterVec = Y_AXIS * (-1.0 * offsetDistance)
# Now put the camManipRef at that point
self.camManipRef.setPosHpr(self.camManipRef,
scaledCenterVec,
ZERO_VEC)
# Record view for next time around
self.lastView = view
t = SEditor.camera.lerpPosHpr(ZERO_POINT,
VBase3(0,0,self.orthoViewRoll),
CAM_MOVE_DURATION,
other = self.camManipRef,
blendType = 'easeInOut',
task = 'manipulateCamera')
t.uponDeath = self.updateCoaMarkerSizeOnDeath
def swingCamAboutWidget(self, degrees, t):
# Remove existing camera manipulation task
taskMgr.remove('manipulateCamera')
# Record undo point
SEditor.pushUndo([SEditor.camera])
# Coincident with widget
self.camManipRef.setPos(self.coaMarker, ZERO_POINT)
# But aligned with render space
self.camManipRef.setHpr(ZERO_POINT)
parent = SEditor.camera.getParent()
SEditor.camera.wrtReparentTo(self.camManipRef)
manipTask = self.camManipRef.lerpHpr(VBase3(degrees,0,0),
CAM_MOVE_DURATION,
blendType = 'easeInOut',
task = 'manipulateCamera')
# Upon death, reparent Cam to parent
manipTask.parent = parent
manipTask.uponDeath = self.reparentCam
def reparentCam(self, state):
SEditor.camera.wrtReparentTo(state.parent)
self.updateCoaMarkerSize()
def fitOnWidget(self, nodePath = 'None Given'):
# Fit the node on the screen
# stop any ongoing tasks
taskMgr.remove('manipulateCamera')
# How big is the node?
nodeScale = SEditor.widget.scalingNode.getScale(render)
maxScale = max(nodeScale[0],nodeScale[1],nodeScale[2])
maxDim = min(SEditor.dr.nearWidth, SEditor.dr.nearHeight)
# At what distance does the object fill 30% of the screen?
# Assuming radius of 1 on widget
camY = SEditor.dr.near * (2.0 * maxScale)/(0.3 * maxDim)
# What is the vector through the center of the screen?
centerVec = Y_AXIS * camY
# Where is the node relative to the viewpoint
vWidget2Camera = SEditor.widget.getPos(SEditor.camera)
# How far do you move the camera to be this distance from the node?
deltaMove = vWidget2Camera - centerVec
# Move a target there
self.camManipRef.setPos(SEditor.camera, deltaMove)
parent = SEditor.camera.getParent()
SEditor.camera.wrtReparentTo(self.camManipRef)
fitTask = SEditor.camera.lerpPos(Point3(0,0,0),
CAM_MOVE_DURATION,
blendType = 'easeInOut',
task = 'manipulateCamera')
# Upon death, reparent Cam to parent
fitTask.parent = parent
fitTask.uponDeath = self.reparentCam
def moveToFit(self):
# How bit is the active widget?
widgetScale = SEditor.widget.scalingNode.getScale(render)
maxScale = max(widgetScale[0], widgetScale[1], widgetScale[2])
# At what distance does the widget fill 50% of the screen?
camY = ((2 * SEditor.dr.near * (1.5 * maxScale)) /
min(SEditor.dr.nearWidth, SEditor.dr.nearHeight))
# Find a point this distance along the Y axis
# MRM: This needs to be generalized to support non uniform frusta
centerVec = Y_AXIS * camY
# Before moving, record the relationship between the selected nodes
# and the widget, so that this can be maintained
SEditor.selected.getWrtAll()
# Push state onto undo stack
SEditor.pushUndo(SEditor.selected)
# Remove the task to keep the widget attached to the object
taskMgr.remove('followSelectedNodePath')
# Spawn a task to keep the selected objects with the widget
taskMgr.add(self.stickToWidgetTask, 'stickToWidget')
# Spawn a task to move the widget
t = SEditor.widget.lerpPos(Point3(centerVec),
CAM_MOVE_DURATION,
other = SEditor.camera,
blendType = 'easeInOut',
task = 'moveToFitTask')
t.uponDeath = lambda state: taskMgr.remove('stickToWidget')
def stickToWidgetTask(self, state):
# Move the objects with the widget
SEditor.selected.moveWrtWidgetAll()
# Continue
return Task.cont
def enableMouseFly(self, fKeyEvents = 1):
# disable C++ fly interface
base.disableMouse()
# Enable events
for event in self.actionEvents:
self.accept(event[0], event[1], extraArgs = event[2:])
if fKeyEvents:
for event in self.keyEvents:
self.accept(event[0], event[1], extraArgs = event[2:])
# Show marker
self.coaMarker.reparentTo(SEditor.group)
def disableMouseFly(self):
# Hide the marker
self.coaMarker.reparentTo(hidden)
# Ignore events
for event in self.actionEvents:
self.ignore(event[0])
for event in self.keyEvents:
self.ignore(event[0])
# Kill tasks
self.removeManipulateCameraTask()
taskMgr.remove('stickToWidget')
base.enableMouse()
def removeManipulateCameraTask(self):
taskMgr.remove('manipulateCamera')

View File

@ -0,0 +1,51 @@
#################################################################
# seColorEntry.py
# Originally from VectorWidgets.py
# Altered by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#
# Here we need some widget to handle some color input.
# There is some colorEntry in the VectorWidgets.py, but they didn't
# work as we need (we don't need alpha here. so the dim option should be set to 3).
# So we make one from them.
#
#################################################################
from TkGlobal import *
import Valuator
import Floater
import Slider
import string
import tkColorChooser
from VectorWidgets import VectorEntry
class seColorEntry(VectorEntry):
def __init__(self, parent = None, **kw):
# Initialize options for the class (overriding some superclass options)
optiondefs = (
('dim', 3, Pmw.INITOPT),
('type', 'slider', Pmw.INITOPT),
('fGroup_labels', ('R','G','B'), None),
('min', 0.0, None),
('max', 255.0, None),
('nuDigits', 0, None),
('valuator_resolution', 1.0, None),
)
self.defineoptions(kw, optiondefs)
# Initialize the superclass, make sure dim makes it to superclass
VectorEntry.__init__(self, parent, dim = self['dim'])
# Add menu item to popup color picker
self.addMenuItem(
'Popup color picker',
command = lambda s = self: s.popupColorPicker())
# Needed because this method checks if self.__class__ is myClass
# where myClass is the argument passed into inialiseoptions
self.initialiseoptions(seColorEntry)
def popupColorPicker(self):
# Can pass in current color with: color = (255, 0, 0)
color = tkColorChooser.askcolor(
parent = self.interior(),
# Initialize it to current color
initialcolor = tuple(self.get()[:3]))[0]
if color:
self.set((color[0], color[1], color[2]))

View File

@ -0,0 +1,913 @@
####################################################################################################################################################
# File Saving
# This code saves the scene out as python code... the scene is stored in the various dictionaries in "dataHolder.py" ...the class "AllScene"
#
####################################################################################################################################################
from PandaModules import *
from ShowBaseGlobal import *
import os
import shutil
from EggData import *
import string
####################################################################################################################################################
#### These modules are modified versions of Disney's equivalent modules
#### We need to figure out a way to inherit their modules and overwrite what we need changed
import seParticlePanel
import seParticles
import seParticleEffect
import seForceGroup
####################################################################################################################################################
class FileSaver:
####################################################################################################################################################
# This class saves out the scene built with the scene editor as python code
# There are dictionaries saved out to save the state of the scene for reloading it with the editor
# Currently saving is supported for Models, Animations, Lights, Dummy Nodes
# Attributes like parenting are also saved out
# This class is actually instantiated in sceneEditor.py in the saveScene() method
####################################################################################################################################################
def __init(self):
pass
def SaveFile(self,AllScene,filename,dirname,reSaveFlag=0):
################################################################################################################################################
# This function takes the "dataHolder" instance "AllScene" which has dictionaries containing scene information
# The filename is where the scene will be written to
################################################################################################################################################
i1=" " # indentation
i2=i1+i1 # double indentation
out_file = open(filename,"w")
print "dirname:" + dirname
if( not os.path.isdir(dirname)):
os.mkdir(dirname)
savepathname=Filename(filename)
self.savepath=savepathname.getBasenameWoExtension()
out_file.write("##########################################################################################################\n")
out_file.write("# Auto Generated Code by Scene Editor\n")
out_file.write("# Edit with caution\n")
out_file.write("# Using this file in your code:\n")
out_file.write("# For example, if you have named this file as \"myscene.py\"\n")
out_file.write("# Do the following:\n")
out_file.write("# from myscene import * \n")
out_file.write("# theScene=SavedScene() #instantiate the class\n")
out_file.write("# IMPORTANT: All the documentation below refers to \"theScene\" as the instance of SavedScene()\n")
out_file.write("##########################################################################################################\n\n")
out_file.write("##########################################################################################################\n")
out_file.write("# Import Panda Modules\n")
out_file.write("##########################################################################################################\n")
out_file.write("from ShowBaseGlobal import * # Core functionality for running the \"show\"\n")
out_file.write("import Actor # Importing models with animations\n")
out_file.write("import Mopath # Motion Paths\n")
out_file.write("import MopathInterval # Motion Paths\n")
out_file.write("from IntervalGlobal import * # Intervals for interpolation, sequencing and parallelization\n")
out_file.write("import ParticleEffect # Particle Systems\n")
out_file.write("import ForceGroup # Forces acting on Particles\n")
out_file.write("import Particles\n\n")
out_file.write("##########################################################################################################\n")
out_file.write("# This class stores the entire scene\n")
out_file.write("##########################################################################################################\n\n")
out_file.write("class SavedScene(DirectObject): # We inherit from DirectObject so that we can use self.accept method to catch messages\n")
out_file.write("\n")
out_file.write(i1+"# These dictionaries are required for re-loading a scene in the editor\n")
out_file.write(i1+"# They can be used to access the objects as well\n\n")
out_file.write(i1+"ModelDic={}# Stores all the models and static geometry\n")
out_file.write(i1+"ModelRefDic={}# Stores the paths to the models\n")
out_file.write("\n")
out_file.write(i1+"ActorDic={}# Stores all the actors\n")
out_file.write(i1+"ActorRefDic={}# Stores the paths to the actors\n")
out_file.write(i1+"ActorAnimsDic={}# Stores the animations for each actor\n")
out_file.write(i1+"blendAnimDict={}# Stores all the blended animations\n")
out_file.write("\n")
out_file.write(i1+"LightDict={}# Stores all the lights\n")
out_file.write(i1+"LightTypes={}# Stores types for the lights\n")
out_file.write(i1+"LightNodes={}# Stores the actual nodes for the lights\n")
out_file.write("\n")
out_file.write(i1+"dummyDict={}# Stores dummies\n")
out_file.write("\n")
out_file.write(i1+"collisionDict={}# Stores Collision information\n")
out_file.write("\n")
out_file.write(i1+"curveDict={}# Stores Mopath information\n")
out_file.write(i1+"curveIntervals=[]# Stores list of mopath intervals\n")
out_file.write(i1+"curveRefColl=[]# Stores paths to mopaths\n")
out_file.write(i1+"curveIntervalsDict={}# Stores mopath intervals\n")
out_file.write("\n")
out_file.write(i1+"particleDict={}# Stores particles\n")
out_file.write(i1+"particleNodes={}# Stores particle nodes\n")
out_file.write("\n")
out_file.write(i1+"#Light Count\n")
out_file.write(i1+"ambientCount=0\n")
out_file.write(i1+"directionalCount=0\n")
out_file.write(i1+"pointCount=0\n")
out_file.write(i1+"spotCount=0\n")
out_file.write("\n")
out_file.write(i1+"#Lighting Attribute\n")
out_file.write(i1+"lightAttrib = LightAttrib.makeAllOff()# Initialize lighting\n")
out_file.write("\n")
out_file.write(i1+"CollisionHandler=CollisionHandlerEvent()# Setup a Collision Handler\n")
out_file.write(i1+"##########################################################################################################\n")
out_file.write(i1+"# Constructor: this is run first when you instantiate the SavedScene class\n")
out_file.write(i1+"##########################################################################################################\n")
out_file.write(i1+"def __init__(self,loadmode=1,seParticleEffect=None,seParticles=None,executionpath=None):# loadmode 0 specifies that this file is being loaded by the scene editor and it passes its own versions of the particle fx modules\n")
out_file.write("\n")
out_file.write(i2+"self.loadmode=loadmode\n")
out_file.write(i2+"self.seParticleEffect=seParticleEffect\n")
out_file.write(i2+"self.seParticles=seParticles\n")
out_file.write(i2+"self.executionpath=executionpath\n")
out_file.write("\n")
out_file.write(i2+"base.enableParticles()# Enable Particle effects\n")
out_file.write("\n")
out_file.write(i2+"self.cTrav = CollisionTraverser() # Setup a traverser for collisions\n")
out_file.write(i2+"base.cTrav = self.cTrav\n")
out_file.write(i2+"self.CollisionHandler.setInPattern(\"enter%in\")# The message to be raised when something enters a collision node\n")
out_file.write(i2+"self.CollisionHandler.setOutPattern(\"exit%in\")# The message to be raised when something exits a collision node\n")
out_file.write("\n")
####################################################################################################################################################
# Save Models
####################################################################################################################################################
out_file.write(i2+"##########################################################################################################\n")
out_file.write(i2+"# Code for all the models\n")
out_file.write(i2+"# To access these models:\n")
out_file.write(i2+"# theScene.ModelDic[\"'Model_Name\"']\n")
out_file.write(i2+"# where theScene is the SavedScene class instance\n")
out_file.write(i2+"# Properties saved include:\n")
out_file.write(i2+"# Transformations\n")
out_file.write(i2+"# Alpha and color\n")
out_file.write(i2+"# Parent and child information\n")
out_file.write(i2+"##########################################################################################################\n")
for model in AllScene.ModelDic:
out_file.write("\n")
modelS=str(model)
if(1): # This is kept for now... perhaps later some sort of check might have to be enforced based on loadMode
#Loading Code
out_file.write(i2+"# Loading model's egg file\n")
#out_file.write(i2+ "self."+ modelS + "=loader.loadModel(\'" + AllScene.ModelRefDic[model].getFullpath() + "\')\n")#Absolute Paths
newpath = dirname + "/" + AllScene.ModelRefDic[model].getBasename()
newpathF=Filename(newpath)
newpathSpecific=newpathF.toOsSpecific()
# Copy all the textures referenced by this file over to the relative directory
fnamelist=[]
modelData=EggData()
modelData.read(AllScene.ModelRefDic[model])
textures=EggTextureCollection()
textures.findUsedTextures(modelData)
for index in range(textures.getNumTextures()):
texture=textures.getTexture(index)
texfilename=texture.getFilename()
fnamelist.append(texfilename.getFullpath())
oldFilename=Filename(Filename(AllScene.ModelRefDic[model].getDirname()),texfilename)
if(not oldFilename.isRegularFile()):
if(texfilename.resolveFilename(getTexturePath(),"")):
oldFilename=texfilename
oldtexpath=oldFilename.toOsSpecific();
newtexpath=dirname + "/" + texfilename.getBasename()
newtexpathF=Filename(newtexpath)
newtexpathSpecific=newtexpathF.toOsSpecific()
print "TEXTURE SAVER:: copying" + oldtexpath + " to " + newtexpathSpecific
if(oldtexpath != newtexpathSpecific):
shutil.copyfile(oldtexpath,newtexpathSpecific)
# Copy the file over to the relative directory
oldModelpath=AllScene.ModelRefDic[model].toOsSpecific()
print "FILESAVER:: copying from " + AllScene.ModelRefDic[model].toOsSpecific() + "to" + newpathSpecific
if(oldModelpath!=newpathSpecific):
shutil.copyfile(oldModelpath,newpathSpecific)
e=EggData()
e.read(AllScene.ModelRefDic[model])
etc=EggTextureCollection()
etc.extractTextures(e)
for index in range(len(fnamelist)):
print fnamelist[index]
tex=etc.findFilename(Filename(fnamelist[index]))
fn=Filename(tex.getFilename())
fn.setDirname("")
tex.setFilename(fn)
e.writeEgg(Filename.fromOsSpecific(newpathSpecific))
out_file.write(i2+"if(self.loadmode==1):\n")
out_file.write(i2+i1+ "self."+ modelS + "=loader.loadModel(\'" + self.savepath + "/" + AllScene.ModelRefDic[model].getBasename() + "')\n")#Relative Path
out_file.write(i2+"else:\n")
out_file.write(i2+i1+ "self."+ modelS + "=loader.loadModel(self.executionpath + \'/" + AllScene.ModelRefDic[model].getBasename() + "')\n")#Relative Path with execution point specified by the invoking-level-editor
#Transformation Code
out_file.write("\n")
out_file.write(i2+"# Transforming the model\n")
out_file.write(i2+ "self."+ modelS + ".setPosHprScale(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)\n"% (AllScene.ModelDic[model].getX(),AllScene.ModelDic[model].getY(),AllScene.ModelDic[model].getZ(),AllScene.ModelDic[model].getH(),AllScene.ModelDic[model].getP(),AllScene.ModelDic[model].getR(),AllScene.ModelDic[model].getSx(),AllScene.ModelDic[model].getSy(),AllScene.ModelDic[model].getSz()))
if(AllScene.ModelDic[model].hasTransparency()):
out_file.write("\n")
out_file.write(i2+"# Alpha\n")
out_file.write(i2+ "self."+ modelS + ".setTransparency(1)\n")
clr=AllScene.ModelDic[model].getColor()
out_file.write(i2+ "self."+ modelS + ".setColor(%.4f,%.4f,%.4f,%.4f)\n"%(clr.getX(),clr.getY(),clr.getZ(),clr.getW()))
out_file.write("\n")
out_file.write(i2+ "# Reparent To Render for now and later we update all the parentings\n")
out_file.write(i2+ "self."+ modelS + ".reparentTo(render)\n")
out_file.write("\n")
out_file.write(i2+ "# Save Metadata...can be retrieved by doing theScene.ModelDic[\"Model_Name\"].getTag(\"Metadata\")\n")
out_file.write(i2+ "self."+ modelS + ".setTag(\"Metadata\",\"" + AllScene.ModelDic[model].getTag("Metadata") + "\")\n")
out_file.write("\n")
out_file.write(i2+ "# Fill in the dictionaries which are used by level Ed to reload state\n")
out_file.write(i2+ "self.ModelDic[\'" + modelS + "\']=self." + AllScene.ModelDic[model].getName()+"\n")
#out_file.write(i2+ "self.ModelRefDic[\'" + modelS + "\']=Filename(\'"+ AllScene.ModelRefDic[model].getFullpath() +"\')\n")# The old Absolute Path way
out_file.write(i2+ "self.ModelRefDic[\'" + modelS + "\']=\'"+ AllScene.ModelRefDic[model].getBasename() +"\'\n")# Relative paths
out_file.write(i2+ "self.ModelDic[\'"+ modelS + "\'].setName(\'"+ modelS +"\')\n")
out_file.write("\n")
####################################################################################################################################################
# Save Dummies
####################################################################################################################################################
out_file.write(i2+"##########################################################################################################\n")
out_file.write(i2+"# Code for all the Dummy Objects\n")
out_file.write(i2+"# To access the dummies\n")
out_file.write(i2+"# theScene.dummyDict['Dummy_Name']\n")
out_file.write(i2+"##########################################################################################################\n")
for dummy in AllScene.dummyDict:
out_file.write("\n")
dummyS=str(dummy)
if(1): # This is kept for now... perhaps later some sort of check might have to be enforced based on loadMode
out_file.write(i2+ "self."+ dummyS + "=loader.loadModelCopy(\"misc/sphere\")\n")
#Transformation Code
out_file.write(i2+"# Transforming the Dummy\n")
out_file.write(i2+ "self."+ dummyS + ".setPosHprScale(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)\n"% (AllScene.dummyDict[dummy].getX(),AllScene.dummyDict[dummy].getY(),AllScene.dummyDict[dummy].getZ(),AllScene.dummyDict[dummy].getH(),AllScene.dummyDict[dummy].getP(),AllScene.dummyDict[dummy].getR(),AllScene.dummyDict[dummy].getSx(),AllScene.dummyDict[dummy].getSy(),AllScene.dummyDict[dummy].getSz()))
out_file.write("\n")
out_file.write(i2+ "# Fill in the dictionaries which are used by level Ed to reload state\n")
out_file.write(i2+ "self.dummyDict[\'" + dummyS + "\']=self." + AllScene.dummyDict[dummy].getName()+"\n")
out_file.write(i2+ "self.dummyDict[\'"+ dummyS + "\'].setName(\'"+ dummyS +"\')\n")
out_file.write("\n")
out_file.write(i2+ "# Save Metadata...can be retrieved by doing theScene.dummyDict[\"Dummy_Name\"].getTag(\"Metadata\")\n")
out_file.write(i2+ "self."+ dummyS + ".setTag(\"Metadata\",\"" + AllScene.dummyDict[dummy].getTag("Metadata") + "\")\n")
out_file.write("\n")
####################################################################################################################################################
# Saving Actors and their animations
####################################################################################################################################################
out_file.write(i2+"##########################################################################################################\n")
out_file.write(i2+"# Code for all the Actors and animations\n")
out_file.write(i2+"# To access the Actors\n")
out_file.write(i2+"# theScene.ActorDic[\'Actor_Name\']\n")
out_file.write(i2+"# theScene.ActorDic[\'Actor_Name\'].play(\'Animation_Name\')\n")
out_file.write(i2+"##########################################################################################################\n")
for actor in AllScene.ActorDic:
out_file.write("\n")
actorS=str(actor)
if(1): # This is kept for now... perhaps later some sort of check might have to be enforced based on loadMode
#out_file.write(i2+ "self."+ actorS + "=Actor.Actor(\'"+ AllScene.ActorRefDic[actor].getFullpath() + "\')\n")# The old way with absolute paths
newpath = dirname + "/" + AllScene.ActorRefDic[actor].getBasename()
newpathF=Filename(newpath)
newpathSpecific=newpathF.toOsSpecific()
# Copy all the textures referenced by this file over to the relative directory
actorfnamelist=[]
actorData=EggData()
actorData.read(AllScene.ActorRefDic[actor])
textures=EggTextureCollection()
textures.findUsedTextures(actorData)
for index in range(textures.getNumTextures()):
texture=textures.getTexture(index)
texfilename=texture.getFilename()
actorfnamelist.append(texfilename.getFullpath())
oldFilename=Filename(Filename(AllScene.ActorRefDic[actor].getDirname()),texfilename)
if(not oldFilename.isRegularFile()):
if(texfilename.resolveFilename(getTexturePath(),"")):
oldFilename=texfilename
oldtexpath=oldFilename.toOsSpecific();
newtexpath=dirname + "/" + texfilename.getBasename()
newtexpathF=Filename(newtexpath)
newtexpathSpecific=newtexpathF.toOsSpecific()
print "TEXTURE SAVER:: copying" + oldtexpath + " to " + newtexpathSpecific
if(oldtexpath != newtexpathSpecific):
shutil.copyfile(oldtexpath,newtexpathSpecific)
# Copy the file over to the relative directory
oldActorpath=AllScene.ActorRefDic[actor].toOsSpecific()
print "FILESAVER:: copying from " + AllScene.ActorRefDic[actor].toOsSpecific() + "to" + newpathSpecific
if(oldActorpath!=newpathSpecific):
shutil.copyfile(oldActorpath,newpathSpecific)
e=EggData()
e.read(AllScene.ActorRefDic[actor])
etc=EggTextureCollection()
etc.extractTextures(e)
for index in range(len(actorfnamelist)):
print actorfnamelist[index]
tex=etc.findFilename(Filename(actorfnamelist[index]))
fn=Filename(tex.getFilename())
fn.setDirname("")
tex.setFilename(fn)
e.writeEgg(Filename.fromOsSpecific(newpathSpecific))
out_file.write(i2+"if(self.loadmode==1):\n")
out_file.write(i2+i1+ "self."+ actorS + "=Actor.Actor(\'" + self.savepath + "/" + AllScene.ActorRefDic[actor].getBasename() + "')\n")#Relative Path
out_file.write(i2+"else:\n")
out_file.write(i2+i1+ "self."+ actorS + "=Actor.Actor(self.executionpath + \'/" + AllScene.ActorRefDic[actor].getBasename() + "')\n")#Relative Path with execution point specified by the invoking-level-editor
#Transformation Code
out_file.write(i2+"# Transforming the Actor\n")
out_file.write(i2+ "self."+ actorS + ".setPosHprScale(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)\n"% (AllScene.ActorDic[actor].getX(),AllScene.ActorDic[actor].getY(),AllScene.ActorDic[actor].getZ(),AllScene.ActorDic[actor].getH(),AllScene.ActorDic[actor].getP(),AllScene.ActorDic[actor].getR(),AllScene.ActorDic[actor].getSx(),AllScene.ActorDic[actor].getSy(),AllScene.ActorDic[actor].getSz()))
if(AllScene.ActorDic[actor].hasTransparency()):
out_file.write(i2+"# Alpha\n")
out_file.write(i2+ "self."+ actorS + ".setTransparency(1)\n")
clr=AllScene.ActorDic[actor].getColor()
out_file.write(i2+ "self."+ actorS + ".setColor(%.4f,%.4f,%.4f,%.4f)\n"%(clr.getX(),clr.getY(),clr.getZ(),clr.getW()))
out_file.write(i2+ "self."+ actorS + ".reparentTo(render)\n")
out_file.write("\n")
out_file.write(i2+ "# Save Metadata...can be retrieved by doing theScene.ActorDic[\"Actor_Name\"].getTag(\"Metadata\")\n")
out_file.write(i2+ "self."+ actorS + ".setTag(\"Metadata\",\"" + AllScene.ActorDic[actor].getTag("Metadata") + "\")\n")
out_file.write("\n")
out_file.write(i2+ "# Fill in the dictionaries which are used by level Ed to reload state\n")
ActorAnimations=AllScene.getAnimationDictFromActor(actor)
ActorAnimationsInvoke={}
if(ActorAnimations!={}): #Check if a dictionary of animations exists for this actor
for animation in ActorAnimations:
#out_file.write(i2+ "self."+ actorS + ".loadAnims(" + str(ActorAnimations) +")\n") # Old way with absolute paths
print "ACTOR ANIMATIONS" + ActorAnimations[animation]
oldAnimPath=Filename(ActorAnimations[animation])
oldAnim=oldAnimPath.toOsSpecific()
dirOS=Filename(dirname)
newAnim=dirOS.toOsSpecific() + "\\" + oldAnimPath.getBasename()
print "ACTOR ANIM SAVER:: Comparing" + oldAnim +"and" + newAnim
if(oldAnim!=newAnim):
shutil.copyfile(oldAnim,newAnim)
newAnimF=Filename.fromOsSpecific(newAnim)
ActorAnimationsInvoke[animation]="self.executionpath +" + "/" +newAnimF.getBasename()
ActorAnimations[animation]= self.savepath + "/" + newAnimF.getBasename()
out_file.write(i2+"if(self.loadmode==1):\n")
out_file.write(i2+ i1+"self."+ actorS + ".loadAnims(" + str(ActorAnimations) +")\n") # Now with new relative paths
out_file.write(i2+"else:\n")
theloadAnimString=str(ActorAnimationsInvoke)# We hack the "self.executionpath" part into the dictionary as a variable using string replace
print "LOAD ANIM STRING BEFORE" + theloadAnimString
theloadAnimString=theloadAnimString.replace('\'self.executionpath +','self.executionpath + \'')
print "LOAD ANIM STRING AFTER" + theloadAnimString
out_file.write(i2+ i1+"self."+ actorS + ".loadAnims(" + theloadAnimString +")\n") # Now with new relative paths based on editor invocation
out_file.write(i2+ "self.ActorDic[\'" + actorS + "\']=self." + AllScene.ActorDic[actor].getName()+"\n")
#out_file.write(i2+ "self.ActorRefDic[\'" + actorS + "\']=Filename(\'"+AllScene.ActorRefDic[actor].getFullpath() +"\')\n") # Old way with absolute paths
out_file.write(i2+ "self.ActorRefDic[\'" + actorS + "\']=\'"+ AllScene.ActorRefDic[actor].getBasename() +"\'\n")# Relative paths
out_file.write(i2+ "self.ActorDic[\'"+ actorS + "\'].setName(\'"+ actorS +"\')\n")
if(AllScene.blendAnimDict.has_key(actor)): # Check if a dictionary of blended animations exists
out_file.write(i2+ "self.blendAnimDict[\"" + actorS +"\"]=" + str(AllScene.blendAnimDict[actor]) + "\n")
out_file.write("\n")
####################################################################################################################################################
# Collsion Node Saving
####################################################################################################################################################
out_file.write(i2+"##########################################################################################################\n")
out_file.write(i2+"# Code for setting up Collision Nodes\n")
out_file.write(i2+"# To use collision detection:\n")
out_file.write(i2+"# You must set up your own bitmasking and event handlers, the traverser \"cTrav\" is created for you at the top\n")
out_file.write(i2+"# The collision nodes are stored in collisionDict\n")
out_file.write(i2+"##########################################################################################################\n\n")
for collnode in AllScene.collisionDict:
collnodeS=str(collnode)
solid=AllScene.collisionDict[collnode].node().getSolid(0)
nodetype=solid.getType().getName()
if(nodetype=="CollisionSphere"): #Save Collison Sphere
out_file.write(i2+"collSolid=CollisionSphere(%.3f,%.3f,%.3f,%.3f)\n"%(solid.getCenter().getX(),solid.getCenter().getY(),solid.getCenter().getZ(),solid.getRadius()))
pass
elif(nodetype=="CollisionPolygon"): #Save Collison Polygon
ax=AllScene.collisionDict[collnode].getTag("A_X")
ay=AllScene.collisionDict[collnode].getTag("A_Y")
az=AllScene.collisionDict[collnode].getTag("A_Z")
bx=AllScene.collisionDict[collnode].getTag("B_X")
by=AllScene.collisionDict[collnode].getTag("B_Y")
bz=AllScene.collisionDict[collnode].getTag("B_Z")
cx=AllScene.collisionDict[collnode].getTag("C_X")
cy=AllScene.collisionDict[collnode].getTag("C_Y")
cz=AllScene.collisionDict[collnode].getTag("C_Z")
out_file.write(i2+"pointA = Point3(" + ax + "," + ay + "," + az + ")\n")
out_file.write(i2+"pointB = Point3(" + bx + "," + by + "," + bz + ")\n")
out_file.write(i2+"pointC = Point3(" + cx + "," + cy + "," + cz + ")\n")
out_file.write(i2+"collSolid=CollisionPolygon(pointA, pointB, pointC)\n")
pass
elif(nodetype=="CollisionSegment"): #Save Collison Segment
A=AllScene.collisionDict[collnode].node().getSolid(0).getPointA()
B=AllScene.collisionDict[collnode].node().getSolid(0).getPointB()
out_file.write(i2+"pointA = Point3(%.3f,%.3f,%.3f)\n"%(A.getX(),A.getY(),A.getZ()))
out_file.write(i2+"pointB = Point3(%.3f,%.3f,%.3f)\n"%(B.getX(),B.getY(),B.getZ()))
out_file.write(i2+"collSolid=CollisionSegment()\n")
out_file.write(i2+"collSolid.setPointA(pointA)\n")
out_file.write(i2+"collSolid.setFromLens(base.cam.node(),Point2(-1,1))\n")
out_file.write(i2+"collSolid.setPointB(pointB)\n")
pass
elif(nodetype=="CollisionRay"): #Save Collison Ray
P = AllScene.collisionDict[collnode].node().getSolid(0).getOrigin()
V = AllScene.collisionDict[collnode].node().getSolid(0).getDirection()
out_file.write(i2+"point=Point3(%.3f,%.3f,%.3f)\n"%(P.getX(),P.getY(),P.getZ()))
out_file.write(i2+"vector=Vec3(%.3f,%.3f,%.3f)\n"%(V.getX(),V.getY(),V.getZ()))
out_file.write(i2+"collSolid=CollisionRay()\n")
out_file.write(i2+"collSolid.setOrigin(point)\n")
out_file.write(i2+"collSolid.setDirection(vector)\n")
pass
else:
print "Invalid Collision Node: " + nodetype
out_file.write("\n")
out_file.write(i2+"self." + collnodeS + "_Node" + "=CollisionNode(\""+collnodeS+"\")\n")
out_file.write(i2+"self." + collnodeS + "_Node" + ".addSolid(collSolid)\n")
out_file.write(i2+"base.cTrav.addCollider(self." + collnodeS + "_Node,self.CollisionHandler)\n")
out_file.write("\n")
####################################################################################################################################################
# Light Saving
####################################################################################################################################################
out_file.write(i2+"##########################################################################################################\n")
out_file.write(i2+"# Code for Lighting\n")
out_file.write(i2+"# To manipulated lights:\n")
out_file.write(i2+"# Manipulate the light node in theScene.LightNodes[\'Light_Name\']\n")
out_file.write(i2+"##########################################################################################################\n\n")
LightList=AllScene.lightManager.getLightNodeList()
for light in LightList:
type = light.getType()
if type == 'ambient':
out_file.write(i2+"# Ambient Light\n")
out_file.write (i2+ "self.ambientCount += 1\n")
out_file.write (i2+ "alight = AmbientLight(\'"+ light.getName() +"\')\n")
out_file.write (i2+ "alight.setColor(VBase4("+ str(light.getLightColor().getX())+ "," + str(light.getLightColor().getY())+ "," + str(light.getLightColor().getZ()) + "," + str(light.getLightColor().getW()) + "))\n")
out_file.write (i2+ "self.lightAttrib=self.lightAttrib.addLight(alight)\n")
out_file.write (i2+ "self."+light.getName()+"= render.attachNewNode(alight.upcastToPandaNode())\n")
out_file.write (i2+ "self."+light.getName()+".setTag(\"Metadata\",\"" + light.getTag("Metadata") + "\")\n")
out_file.write (i2+ "self.LightDict[\'" + light.getName() + "\']=alight\n")
out_file.write (i2+ "self.LightTypes[\'" + light.getName() + "\']=\'" + type + "\'\n")
out_file.write (i2+ "self.LightNodes[\'" + light.getName() + "\']=self." + light.getName() + "\n")
out_file.write ("\n")
elif type == 'directional':
out_file.write(i2+"# Directional Light\n")
out_file.write (i2+ "self.directionalCount += 1\n")
out_file.write (i2+ "alight = DirectionalLight(\'"+ light.getName() + "\')\n")
out_file.write (i2+ "alight.setColor(VBase4("+ str(light.getLightColor().getX())+ "," + str(light.getLightColor().getY())+ "," + str(light.getLightColor().getZ()) + "," + str(light.getLightColor().getW()) + "))\n")
#out_file.write (i2+ "alight.setDirection(Vec3("+ str(light.getH())+ "," + str(light.getP())+ "," + str(light.getR()) + "))\n")
#out_file.write (i2+ "alight.setPoint(Point3(" + str(light.getX()) + "," + str(light.getY()) + "," + str(light.getZ()) + "))\n")
out_file.write (i2+ "alight.setSpecularColor(Vec4(" + str(light.getSpecColor().getX()) + "," + str(light.getSpecColor().getY()) + "," + str(light.getSpecColor().getZ()) + "," + str(light.getSpecColor().getW()) + "))\n")
out_file.write (i2+ "self.lightAttrib=self.lightAttrib.addLight(alight)\n")
out_file.write (i2+ "self."+light.getName()+ "= render.attachNewNode(alight.upcastToPandaNode())\n")
out_file.write (i2+ "self."+light.getName()+ ".setPos(Point3(" + str(light.getX()) + "," + str(light.getY()) + "," + str(light.getZ()) + "))\n")
out_file.write (i2+ "self."+light.getName()+ ".setHpr(Vec3("+ str(light.getH())+ "," + str(light.getP())+ "," + str(light.getR()) + "))\n")
out_file.write (i2+ "self."+light.getName()+ ".setTag(\"Metadata\",\"" + light.getTag("Metadata") + "\")\n")
#out_file.write (i2+ "alight.setPos
out_file.write (i2+ "self.LightDict[\'" + light.getName() + "\']=alight\n")
out_file.write (i2+ "self.LightTypes[\'" + light.getName() + "\']=\'" + type + "\'\n")
out_file.write (i2+ "self.LightNodes[\'" + light.getName() + "\']=self." + light.getName() + "\n")
out_file.write ("\n")
elif type == 'point':
out_file.write(i2+"# Point Light\n")
out_file.write (i2+ "self.pointCount += 1\n")
out_file.write (i2+ "alight = PointLight(\'"+ light.getName() +"\')\n")
out_file.write (i2+ "alight.setColor(VBase4("+ str(light.getLightColor().getX())+ "," + str(light.getLightColor().getY())+ "," + str(light.getLightColor().getZ()) + "," + str(light.getLightColor().getW()) + "))\n")
#out_file.write (i2+ "alight.setPoint(Point3(" + str(light.getX()) + "," + str(light.getY()) + "," + str(light.getZ()) + "))\n")
out_file.write (i2+ "alight.setSpecularColor(Vec4(" + str(light.getSpecColor().getX()) + "," + str(light.getSpecColor().getY()) + "," + str(light.getSpecColor().getZ()) + "," + str(light.getSpecColor().getW()) + "))\n")
out_file.write (i2+ "alight.setAttenuation(Vec3("+ str(light.getAttenuation().getX()) + "," + str(light.getAttenuation().getY()) + "," + str(light.getAttenuation().getZ()) + "))\n")
out_file.write (i2+ "self.lightAttrib=self.lightAttrib.addLight(alight)\n")
out_file.write (i2+ "self."+light.getName()+ "= render.attachNewNode(alight.upcastToPandaNode())\n")
out_file.write (i2+ "self."+light.getName()+ ".setTag(\"Metadata\",\"" + light.getTag("Metadata") + "\")\n")
out_file.write (i2+ "self."+light.getName()+ ".setPos(Point3(" + str(light.getX()) + "," + str(light.getY()) + "," + str(light.getZ()) + "))\n")
out_file.write (i2+ "self.LightDict[\'" + light.getName() + "\']=alight\n")
out_file.write (i2+ "self.LightTypes[\'" + light.getName() + "\']=\'" + type + "\'\n")
out_file.write (i2+ "self.LightNodes[\'" + light.getName() + "\']=self." + light.getName() + "\n")
out_file.write ("\n")
elif type == 'spot':
out_file.write(i2+"# Spot Light\n")
out_file.write (i2+ "self.spotCount += 1\n")
out_file.write (i2+ "alight = Spotlight(\'"+ light.getName() + "\')\n")
out_file.write (i2+ "alight.setColor(VBase4("+ str(light.getLightColor().getX())+ "," + str(light.getLightColor().getY())+ "," + str(light.getLightColor().getZ()) + "," + str(light.getLightColor().getW()) + "))\n")
out_file.write (i2+ "alens = PerspectiveLens()\n")
out_file.write (i2+ "alight.setLens(alens)\n")
out_file.write (i2+ "alight.setSpecularColor(Vec4(" + str(light.getSpecColor().getX()) + "," + str(light.getSpecColor().getY()) + "," + str(light.getSpecColor().getZ()) + "," + str(light.getSpecColor().getW()) + "))\n")
out_file.write (i2+ "alight.setAttenuation(Vec3("+ str(light.getAttenuation().getX()) + "," + str(light.getAttenuation().getY()) + "," + str(light.getAttenuation().getZ()) + "))\n")
out_file.write (i2+ "alight.setExponent(" +str(light.getExponent()) +")\n")
out_file.write (i2+ "self.lightAttrib=self.lightAttrib.addLight(alight)\n")
out_file.write (i2+ "self."+light.getName()+ "= render.attachNewNode(alight.upcastToLensNode())\n")
out_file.write (i2+ "self."+light.getName()+ ".setTag(\"Metadata\",\"" + light.getTag("Metadata") + "\")\n")
out_file.write (i2+ "self."+light.getName()+ ".setPos(Point3(" + str(light.getX()) + "," + str(light.getY()) + "," + str(light.getZ()) + "))\n")
out_file.write (i2+ "self."+light.getName()+ ".setHpr(Vec3("+ str(light.getH())+ "," + str(light.getP())+ "," + str(light.getR()) + "))\n")
out_file.write (i2+ "self.LightDict[\'" + light.getName() + "\']=alight\n")
out_file.write (i2+ "self.LightTypes[\'" + light.getName() + "\']=\'" + type + "\'\n")
out_file.write (i2+ "self.LightNodes[\'" + light.getName() + "\']=self." + light.getName() + "\n")
out_file.write ("\n")
else:
out_file.write (i2+ "print \'Invalid light type\'")
out_file.write (i2+ "return None")
out_file.write("\n")
####################################################################################################################################################
# Enable Lighting
####################################################################################################################################################
out_file.write(i2+ "# Enable Ligthing\n")
out_file.write(i2+ "render.node().setAttrib(self.lightAttrib)\n")
out_file.write("\n")
####################################################################################################################################################
# Initialize Particles for non scene editor mode
####################################################################################################################################################
out_file.write(i2+"# Load Particle Effects. The parameters to this function are to allow us to use our modified versions of the Particle Effects modules when loading this file with the level editor\n")
out_file.write(i2+"self.starteffects(self.loadmode,self.seParticleEffect,self.seParticles)\n")
out_file.write("\n")
####################################################################################################################################################
# Save Camera Settings
####################################################################################################################################################
out_file.write("\n")
out_file.write(i2+ "# Save Camera Settings\n")
out_file.write(i2+ "camera.setX(" + str(camera.getX()) + ")\n")
out_file.write(i2+ "camera.setY(" + str(camera.getY()) + ")\n")
out_file.write(i2+ "camera.setZ(" + str(camera.getZ()) + ")\n")
out_file.write(i2+ "camera.setH(" + str(camera.getH()) + ")\n")
out_file.write(i2+ "camera.setP(" + str(camera.getP()) + ")\n")
out_file.write(i2+ "camera.setR(" + str(camera.getR()) + ")\n")
out_file.write(i2+ "camera.getChild(0).node().getLens().setNear(" + str(camera.getChild(0).node().getLens().getNear()) + ")\n")
out_file.write(i2+ "camera.getChild(0).node().getLens().setFar(" + str(camera.getChild(0).node().getLens().getFar()) + ")\n")
out_file.write(i2+ "camera.getChild(0).node().getLens().setFov(VBase2(%.5f,%.5f))\n"% (camera.getChild(0).node().getLens().getHfov(),camera.getChild(0).node().getLens().getVfov()))
FilmSize=camera.getChild(0).node().getLens().getFilmSize()
out_file.write(i2+ "camera.getChild(0).node().getLens().setFilmSize(%.3f,%.3f)\n"%(FilmSize.getX(),FilmSize.getY()))
out_file.write(i2+ "camera.getChild(0).node().getLens().setFocalLength(" + str(camera.getChild(0).node().getLens().getFocalLength()) + ")\n")
out_file.write(i2+ "camera.setTag(\"Metadata\",\"" + camera.getTag("Metadata") + "\")\n")
out_file.write(i2+ "camera.reparentTo(render)\n")
out_file.write(i2+ "base.disableMouse()\n")
self.bgColor=base.getBackgroundColor()
out_file.write(i2+ "base.setBackgroundColor(%.3f,%.3f,%.3f)\n"%(self.bgColor.getX(),self.bgColor.getY(),self.bgColor.getZ()))
out_file.write("\n")
####################################################################################################################################################
# Mopath Saving
####################################################################################################################################################
out_file.write(i2+"##########################################################################################################\n")
out_file.write(i2+"# Motion Paths\n")
out_file.write(i2+"# Using Mopaths:\n")
out_file.write(i2+"# theScene.curveIntervals[0].start() or .loop() will play curve with index 0\n")
out_file.write(i2+"##########################################################################################################\n\n")
for node in AllScene.curveDict:
curveCollection=AllScene.curveDict[node]
curvenumber=0
for curve in curveCollection:
filestring=dirname+ "\\" + str(node)+"_curve_"+str(curvenumber)+".egg"
f=Filename.fromOsSpecific(filestring)
#filestring=f.getFullpath()# The old absolute path way
filestring=f.getBasename() # The new relative path way
curve.writeEgg(f)
out_file.write(i2+"m=Mopath.Mopath()\n")
out_file.write(i2+"if(self.loadmode==1):\n")
out_file.write(i2+i1+"m.loadFile(\"" + self.savepath +"/"+ filestring + "\")\n") # If just normally executed
out_file.write(i2+"else:\n")
out_file.write(i2+i1+"m.loadFile(self.executionpath + \"/"+ filestring + "\")\n") # If being invoked by level Ed
out_file.write(i2+"mp=MopathInterval(m,self." + str(node) + ")\n")
out_file.write(i2+"self.curveIntervals.append(mp)\n")
out_file.write(i2+"if(self.loadmode==1):\n")
out_file.write(i2+i1+"self.curveRefColl.append(\"" + self.savepath +"/"+ filestring +"\")\n")
out_file.write(i2+"else:\n")
out_file.write(i2+i1+"self.curveRefColl.append(self.executionpath + \"/"+ filestring +"\")\n")
curvenumber=curvenumber+1
out_file.write(i2+"self.curveIntervalsDict[\"" + str(node) + "\"]=self.curveIntervals\n")
out_file.write(i2+"self.curveDict[\"" + str(node) + "\"]=self.curveRefColl\n")
####################################################################################################################################################
# Lets do all the reparenting here so as to make sure everything that needed to load was loaded
####################################################################################################################################################
out_file.write(i2+"##########################################################################################################\n")
out_file.write(i2+"# Reparenting\n")
out_file.write(i2+"# A final pass is done on setting all the scenegraph hierarchy after all objects are laoded\n")
out_file.write(i2+"##########################################################################################################\n\n")
for model in AllScene.ModelDic:
modelS=str(model)
parent=AllScene.ModelDic[model].getParent().getName()
if(parent=="render" or parent=="camera"):
out_file.write(i2+ "self."+ modelS + ".reparentTo(" + parent + ")\n")
else:
if(AllScene.particleDict.has_key(parent)):
out_file.write(i2+ "self."+ modelS + ".reparentTo(self." + parent + ".getEffect())\n")
else:
out_file.write(i2+ "self."+ modelS + ".reparentTo(self." + parent + ")\n")
out_file.write(i2+ "self.ModelDic[\'" + modelS + "\']=self." + AllScene.ModelDic[model].getName()+"\n")
out_file.write(i2+"\n")
for dummy in AllScene.dummyDict:
dummyS=str(dummy)
parent=AllScene.dummyDict[dummy].getParent().getName()
if(parent=="render" or parent=="camera"):
out_file.write(i2+ "self."+ dummyS + ".reparentTo(" + parent + ")\n")
else:
if(AllScene.particleDict.has_key(parent)):
out_file.write(i2+ "self."+ dummyS + ".reparentTo(self." + parent + ".getEffect())\n")
else:
out_file.write(i2+ "self."+ dummyS + ".reparentTo(self." + parent + ")\n")
out_file.write(i2+ "self.dummyDict[\'" + dummyS + "\']=self." + AllScene.dummyDict[dummy].getName()+"\n")
out_file.write(i2+"\n")
for actor in AllScene.ActorDic:
actorS=str(actor)
parent=AllScene.ActorDic[actor].getParent().getName()
if(parent=="render" or parent=="camera"):
out_file.write(i2+ "self."+ actorS + ".reparentTo(" + parent + ")\n")
else:
if(AllScene.particleDict.has_key(parent)):
out_file.write(i2+ "self."+ actorS + ".reparentTo(self." + parent + ".getEffect())\n")
else:
out_file.write(i2+ "self."+ actorS + ".reparentTo(self." + parent + ")\n")
out_file.write(i2+ "self.ActorDic[\'" + actorS + "\']=self." + AllScene.ActorDic[actor].getName()+"\n")
out_file.write(i2+"\n")
for collnode in AllScene.collisionDict:
collnodeS=str(collnode)
solid=AllScene.collisionDict[collnode].node().getSolid(0)
nodetype=solid.getType().getName()
parentname=AllScene.collisionDict[collnode].getParent().getName()
if(parentname=="render" or parentname =="camera"):
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"]="+ parentname + ".attachNewNode(self." + collnodeS + "_Node)\n")
else:
if(AllScene.particleDict.has_key(parent)):
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"]=self."+ parentname + "getEffect().attachNewNode(self." + collnodeS + "_Node)\n")
else:
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"]=self."+ parentname + ".attachNewNode(self." + collnodeS + "_Node)\n")
dictelem=AllScene.collisionDict[collnode]
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"].setPosHprScale(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)\n"%(dictelem.getX(),dictelem.getY(),dictelem.getZ(),dictelem.getH(),dictelem.getP(),dictelem.getR(),dictelem.getSx(),dictelem.getSy(),dictelem.getSz()))
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"].setTag(\"Metadata\",\"" + AllScene.collisionDict[collnode].getTag("Metadata") + "\")\n")
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"].show()\n")
if(nodetype=="CollisionPolygon"): #Save Collison Polygon... the reason we need to use setTag here is because there is no inbuilt way of saving transforms for collision polys
ax=float(AllScene.collisionDict[collnode].getTag("A_X"))
ay=float(AllScene.collisionDict[collnode].getTag("A_Y"))
az=float(AllScene.collisionDict[collnode].getTag("A_Z"))
bx=float(AllScene.collisionDict[collnode].getTag("B_X"))
by=float(AllScene.collisionDict[collnode].getTag("B_Y"))
bz=float(AllScene.collisionDict[collnode].getTag("B_Z"))
cx=float(AllScene.collisionDict[collnode].getTag("C_X"))
cy=float(AllScene.collisionDict[collnode].getTag("C_Y"))
cz=float(AllScene.collisionDict[collnode].getTag("C_Z"))
out_file.write(i2+"pointA=Point3(%.3f,%.3f,%.3f)\n"%(ax,ay,az))
out_file.write(i2+"pointB=Point3(%.3f,%.3f,%.3f)\n"%(bx,by,bz))
out_file.write(i2+"pointC=Point3(%.3f,%.3f,%.3f)\n"%(cx,cy,cz))
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"].setTag('A_X','%f'%pointA.getX())\n")
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"].setTag('A_Y','%f'%pointA.getY())\n")
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"].setTag('A_Z','%f'%pointA.getZ())\n")
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"].setTag('B_X','%f'%pointB.getX())\n")
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"].setTag('B_Y','%f'%pointB.getY())\n")
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"].setTag('B_Z','%f'%pointB.getZ())\n")
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"].setTag('C_X','%f'%pointC.getX())\n")
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"].setTag('C_Y','%f'%pointC.getY())\n")
out_file.write(i2+"self.collisionDict[\"" + collnodeS + "\"].setTag('C_Z','%f'%pointC.getZ())\n")
out_file.write(i2+"\n")
for effect in AllScene.particleDict:
parent=AllScene.particleNodes[effect].getParent().getName()
if(parent=="render" or parent=="camera"):
out_file.write(i2+"self.particleDict[\""+ str(effect) +"\"].reparentTo(" + parent + ")\n")
else:
out_file.write(i2+"self.particleDict[\""+ str(effect) +"\"].reparentTo(self." + parent + ")\n")
out_file.write(i2+"\n")
####################################################################################################################################################
# Particle Saving
####################################################################################################################################################
out_file.write("\n")
out_file.write(i2+"##########################################################################################################\n")
out_file.write(i2+"# Particle Effects\n")
out_file.write(i2+"# Using Particles:\n")
out_file.write(i2+"# theScene.enableeffect(\"Effect_Name\")\n")
out_file.write(i2+"##########################################################################################################\n\n")
out_file.write(i1+"def starteffects(self,mode,seParticleEffect=None,seParticles=None):\n")
for effect in AllScene.particleDict:
effectS=str(effect)
out_file.write(i2+ "self." + effectS + "=" + effectS + "(mode,seParticleEffect,seParticles)\n")
out_file.write(i2+ "effect=self."+ effectS + ".getEffect()\n")
out_file.write(i2+ "self.particleDict[\"" + effectS + "\"]=effect\n")
out_file.write(i2+ "effect.reparentTo(render)\n")
thenode=AllScene.particleNodes[effect]
out_file.write(i2+ "self.particleDict[\"" + effectS + "\"].setPosHprScale(%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f)\n"%(thenode.getX(),thenode.getY(),thenode.getZ(),thenode.getH(),thenode.getP(),thenode.getR(),thenode.getSx(),thenode.getSy(),thenode.getSz()))
out_file.write("\n")
out_file.write(i2+"return\n")
out_file.write("\n")
out_file.write(i1+"def enableeffect(self,effect_name):\n")
out_file.write(i2+"self.particleDict[effect_name].enable()\n")
out_file.write(i2+"return\n")
out_file.write("\n")
out_file.write(i1+"def disableeffect(self,effect_name):\n")
out_file.write(i2+"self.particleDict[effect_name].disable()\n")
out_file.write(i2+"return\n")
out_file.write("\n")
####################################################################################################################################################
# Animation Blending Methods
####################################################################################################################################################
out_file.write("\n")
out_file.write(i2+"##########################################################################################################\n")
out_file.write(i2+"# Animation Blending\n")
out_file.write(i2+"# Using blending:\n")
out_file.write(i2+"# theScene.playBlendAnim(actor,blendname)\n")
out_file.write(i2+"# theScene.stopBlendAnim(actor,blendname)\n")
out_file.write(i2+"# theScene.changeBlendAnim(actor,blendname,blend_amount)\n")
out_file.write(i2+"##########################################################################################################\n\n")
out_file.write(i1+"def playBlendAnim(self,actor,blendName,loop=0):\n")
out_file.write(i2+"actor.enableBlend()\n")
out_file.write(i2+"blendDicts=self.blendAnimDict[actor.getName()]\n")
out_file.write(i2+"blendList=blendDicts[blendName]\n")
out_file.write(i2+"actor.setControlEffect(blendList[0],blendList[2])\n")
out_file.write(i2+"actor.setControlEffect(blendList[1],1.0-blendList[2])\n")
out_file.write(i2+"if(loop):\n")
out_file.write(i2+i1+"actor.loop(blendList[0])\n")
out_file.write(i2+i1+"actor.loop(blendList[1])\n")
out_file.write(i2+"else:\n")
out_file.write(i2+i1+"actor.start(blendList[0])\n")
out_file.write(i2+i1+"actor.start(blendList[1])\n")
out_file.write("\n")
out_file.write(i1+"def stopBlendAnim(self,actor,blendName):\n")
out_file.write(i2+"blendDicts=self.blendAnimDict[actor.getName()]\n")
out_file.write(i2+"blendList=blendDicts[blendName]\n")
out_file.write(i2+"actor.stop(blendList[0])\n")
out_file.write(i2+"actor.stop(blendList[1])\n")
out_file.write("\n")
out_file.write(i1+"def changeBlending(self,actor,blendName,blending):\n")
out_file.write(i2+"blendDicts=self.blendAnimDict[actor.getName()]\n")
out_file.write(i2+"blendList=blendDicts[blendName]\n")
out_file.write(i2+"blendList[2]=blending\n")
out_file.write(i2+"self.blendAnimDict[actor.getName()]={blendName:[blendList[0],blendList[1],blending]}\n")
out_file.write("\n")
####################################################################################################################################################
# Hide and Show Methods
####################################################################################################################################################
out_file.write("\n")
out_file.write(i2+"##########################################################################################################\n")
out_file.write(i2+"# Hide and Show Methods\n")
out_file.write(i2+"# These will help you hide/show dummies, collision solids, effect nodes etc.\n")
out_file.write(i2+"##########################################################################################################\n\n")
out_file.write("\n")
out_file.write(i1+"def hideDummies(self):\n")
out_file.write("\n")
out_file.write(i2+"for dummy in self.dummyDict:\n")
out_file.write(i2+i1+"self.dummyDict[dummy].reparentTo(hidden)\n")
out_file.write("\n")
out_file.write(i1+"def hideCollSolids(self):\n")
out_file.write("\n")
out_file.write(i2+"for collSolid in self.collisionDict:\n")
out_file.write(i2+i1+"self.collisionDict[collSolid].hide()\n")
out_file.write("\n")
out_file.write(i1+"def hideEffectNodes(self):\n")
out_file.write("\n")
out_file.write(i2+"for effectnode in self.particleNodes:\n")
out_file.write(i2+i1+"self.particleNodes[effectnode].hide()\n")
out_file.write("\n")
out_file.write(i1+"def showDummies(self):\n")
out_file.write("\n")
out_file.write(i2+"for dummy in self.dummyDict:\n")
out_file.write(i2+i1+"self.dummyDict[dummy].reparentTo(hidden)\n")
out_file.write("\n")
out_file.write(i1+"def showCollSolids(self):\n")
out_file.write("\n")
out_file.write(i2+"for collSolid in self.collisionDict:\n")
out_file.write(i2+i1+"self.collisionDict[collSolid].show()\n")
out_file.write("\n")
out_file.write(i1+"def showEffectNodes(self):\n")
out_file.write("\n")
out_file.write(i2+"for effectnode in self.particleNodes:\n")
out_file.write(i2+i1+"self.particleNodes[effectnode].show()\n\n")
##########################################################################################################
# Saving Particle Parameters as a Class
##########################################################################################################
out_file.write("\n")
out_file.write(i2+"##########################################################################################################\n")
out_file.write(i2+"# Particle Effects\n")
out_file.write(i2+"# This is where effect parameters are saved in a class\n")
out_file.write(i2+"# The class is then instantiated in the starteffects method and appended to the dictionaries\n")
out_file.write(i2+"##########################################################################################################\n\n")
for effect in AllScene.particleDict:
out_file.write("\n\n")
out_file.write("class " + str(effect) + ":\n")
out_file.write(i1+"def __init__(self,mode=1,seParticleEffect=None,seParticles=None):\n")
out_file.write(i2+"if(mode==0):\n")
out_file.write(i2+i1+"self.effect=seParticleEffect.ParticleEffect()\n")
out_file.write(i2+"else:\n")
out_file.write(i2+i1+"self.effect=ParticleEffect.ParticleEffect()\n")
AllScene.particleDict[effect].AppendConfig(out_file)
#out_file.write(i2+"return self.effect\n")
out_file.write("\n\n")
out_file.write(i1+"def starteffect(self):\n")
out_file.write(i2+"pass\n")
out_file.write("\n\n")
out_file.write(i1+"def stopeffect(self):\n")
out_file.write(i2+"pass\n\n")
out_file.write(i1+"def getEffect(self):\n")
out_file.write(i2+"return self.effect\n\n")
#Un-comment the lines below to make this a stand-alone file
#out_file.write("Scene=SavedScene()\n")
#out_file.write("run()\n")
out_file.close()

View File

@ -0,0 +1,139 @@
from PandaModules import *
from DirectObject import *
from PhysicsManagerGlobal import *
import ForceNode
import DirectNotifyGlobal
import sys
class ForceGroup(DirectObject):
notify = DirectNotifyGlobal.directNotify.newCategory('ForceGroup')
id = 1
def __init__(self, name=None):
"""__init__(self)"""
if (name == None):
self.name = 'ForceGroup-%d' % ForceGroup.id
ForceGroup.id += 1
else:
self.name = name
self.node = ForceNode.ForceNode(self.name)
self.nodePath = NodePath(self.node)
self.fEnabled = 0
self.particleEffect = None
def cleanup(self):
self.node.clear()
self.nodePath.removeNode()
del self.nodePath
del self.node
del self.particleEffect
def enable(self):
"""enable(self)
Convenience function to enable all forces in force group"""
for i in range(self.node.getNumForces()):
f = self.node.getForce(i)
f.setActive(1)
self.fEnabled = 1
def disable(self):
"""disable(self)
Convenience function to disable all forces in force group"""
for i in range(self.node.getNumForces()):
f = self.node.getForce(i)
f.setActive(0)
self.fEnabled = 0
def isEnabled(self):
return self.fEnabled
def addForce(self, force):
"""addForce(self, force)"""
self.node.addForce(force)
if (self.particleEffect):
self.particleEffect.addForce(force)
def removeForce(self, force):
"""removeForce(self, force)"""
self.node.removeForce(force)
if (self.particleEffect != None):
self.particleEffect.removeForce(force)
# Get/set
def getName(self):
"""getName(self)"""
return self.name
def getNode(self):
"""getNode(self)"""
return self.node
def getNodePath(self):
"""getNodePath(self)"""
return self.nodePath
# Utility functions
def __getitem__(self, index):
"""__getItem__(self, index)"""
numForces = self.node.getNumForces()
if ((index < 0) or (index >= numForces)):
raise IndexError
return self.node.getForce(index)
def __len__(self):
"""__len__(self)"""
return self.node.getNumForces()
def asList(self):
"""asList(self)"""
l = []
for i in range(self.node.getNumForces()):
l.append(self.node.getForce(i))
return l
def printParams(self, file = sys.stdout, targ = 'self'):
"""printParams(file, targ)"""
i1=" "
i2=i1+i1
file.write(i2+'# Force parameters\n')
for i in range(self.node.getNumForces()):
f = self.node.getForce(i)
fname = 'force%d' % i
if isinstance(f, LinearForce):
amplitude = f.getAmplitude()
massDependent = f.getMassDependent()
if isinstance(f, LinearCylinderVortexForce):
file.write(i2+fname + ' = LinearCylinderVortexForce(%.4f, %.4f, %.4f, %.4f, %d)\n' % (f.getRadius(), f.getLength(), f.getCoef(), amplitude, massDependent))
elif isinstance(f, LinearDistanceForce):
radius = f.getRadius()
falloffType = f.getFalloffType()
ftype = 'FTONEOVERR'
if (falloffType == LinearDistanceForce.FTONEOVERR):
ftype = 'FTONEOVERR'
elif (falloffType == LinearDistanceForce.FTONEOVERRSQUARED):
ftype = 'FTONEOVERRSQUARED'
elif (falloffType == LinearDistanceForce.FTONEOVERRCUBED):
ftype = 'FTONEOVERRCUBED'
forceCenter = f.getForceCenter()
if isinstance(f, LinearSinkForce):
file.write(i2+fname + ' = LinearSinkForce(Point3(%.4f, %.4f, %.4f), LinearDistanceForce.%s, %.4f, %.4f, %d)\n' % (forceCenter[0], forceCenter[1], forceCenter[2], ftype, radius, amplitude, massDependent))
elif isinstance(f, LinearSourceForce):
file.write(i2+fname + ' = LinearSourceForce(Point3(%.4f, %.4f, %.4f), LinearDistanceForce.%s, %.4f, %.4f, %d)\n' % (forceCenter[0], forceCenter[1], forceCenter[2], ftype, radius, amplitude, massDependent))
elif isinstance(f, LinearFrictionForce):
file.write(i2+fname + ' = LinearFrictionForce(%.4f, %.4f, %d)\n' % (f.getCoef(), amplitude, massDependent))
elif isinstance(f, LinearJitterForce):
file.write(i2+fname + ' = LinearJitterForce(%.4f, %d)\n' % (amplitude, massDependent))
elif isinstance(f, LinearNoiseForce):
file.write(i2+fname + ' = LinearNoiseForce(%.4f, %d)\n' % (amplitude, massDependent))
elif isinstance(f, LinearVectorForce):
vec = f.getLocalVector()
file.write(i2+fname + ' = LinearVectorForce(Vec3(%.4f, %.4f, %.4f), %.4f, %d)\n' % (vec[0], vec[1], vec[2], amplitude, massDependent))
elif isinstance(f, AngularForce):
if isinstance(f, AngularVectorForce):
vec = f.getLocalVector()
file.write(i2+fname + ' = AngularVectorForce(Vec3(%.4f, %.4f, %.4f))\n' % (vec[0], vec[1], vec[2]))
file.write(i2+fname + '.setActive(%d)\n' % f.getActive())
file.write(i2+targ + '.addForce(%s)\n' % fname)

View File

@ -0,0 +1,257 @@
#################################################################
# seGeometry.py
# Originally from DirectGeometry.py
# Altered by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#
# We didn't change anything essential.
# Just because we customized the seSession from DirectSession,
# So we need related files can follow the change.
# However, we don't want to change anything inside the original directool
# to let them can work with our scene editor.
# (If we do change original directools, it will force user has to install the latest version of OUR Panda)
#
#################################################################
from PandaModules import *
from PandaObject import *
from DirectGlobals import *
from DirectUtil import *
import math
class LineNodePath(NodePath):
def __init__(self, parent = None, name = None,
thickness = 1.0, colorVec = VBase4(1)):
# Initialize the superclass
NodePath.__init__(self)
if parent is None:
parent = hidden
# Attach a geomNode to the parent and set self to be
# the resulting node path
self.lineNode = GeomNode("lineNode")
self.assign(parent.attachNewNode( self.lineNode ))
if name:
self.setName(name)
# Create a lineSegs object to hold the line
ls = self.lineSegs = LineSegs()
# Initialize the lineSegs parameters
ls.setThickness(thickness)
ls.setColor(colorVec)
def moveTo( self, *_args ):
apply( self.lineSegs.moveTo, _args )
def drawTo( self, *_args ):
apply( self.lineSegs.drawTo, _args )
def create( self, frameAccurate = 0 ):
self.lineSegs.create( self.lineNode, frameAccurate )
def reset( self ):
self.lineSegs.reset()
self.lineNode.removeAllGeoms()
def isEmpty( self ):
return self.lineSegs.isEmpty()
def setThickness( self, thickness ):
self.lineSegs.setThickness( thickness )
def setColor( self, *_args ):
apply( self.lineSegs.setColor, _args )
def setVertex( self, *_args):
apply( self.lineSegs.setVertex, _args )
def setVertexColor( self, vertex, *_args ):
apply( self.lineSegs.setVertexColor, (vertex,) + _args )
def getCurrentPosition( self ):
return self.lineSegs.getCurrentPosition()
def getNumVertices( self ):
return self.lineSegs.getNumVertices()
def getVertex( self, index ):
return self.lineSegs.getVertex(index)
def getVertexColor( self ):
return self.lineSegs.getVertexColor()
def drawArrow(self, sv, ev, arrowAngle, arrowLength):
"""
Do the work of moving the cursor around to draw an arrow from
sv to ev. Hack: the arrows take the z value of the end point
"""
self.moveTo(sv)
self.drawTo(ev)
v = sv - ev
# Find the angle of the line
angle = math.atan2(v[1], v[0])
# Get the arrow angles
a1 = angle + deg2Rad(arrowAngle)
a2 = angle - deg2Rad(arrowAngle)
# Get the arrow points
a1x = arrowLength * math.cos(a1)
a1y = arrowLength * math.sin(a1)
a2x = arrowLength * math.cos(a2)
a2y = arrowLength * math.sin(a2)
z = ev[2]
self.moveTo(ev)
self.drawTo(Point3(ev + Point3(a1x, a1y, z)))
self.moveTo(ev)
self.drawTo(Point3(ev + Point3(a2x, a2y, z)))
def drawArrow2d(self, sv, ev, arrowAngle, arrowLength):
"""
Do the work of moving the cursor around to draw an arrow from
sv to ev. Hack: the arrows take the z value of the end point
"""
self.moveTo(sv)
self.drawTo(ev)
v = sv - ev
# Find the angle of the line
angle = math.atan2(v[2], v[0])
# Get the arrow angles
a1 = angle + deg2Rad(arrowAngle)
a2 = angle - deg2Rad(arrowAngle)
# Get the arrow points
a1x = arrowLength * math.cos(a1)
a1y = arrowLength * math.sin(a1)
a2x = arrowLength * math.cos(a2)
a2y = arrowLength * math.sin(a2)
self.moveTo(ev)
self.drawTo(Point3(ev + Point3(a1x, 0.0, a1y)))
self.moveTo(ev)
self.drawTo(Point3(ev + Point3(a2x, 0.0, a2y)))
def drawLines(self, lineList):
"""
Given a list of lists of points, draw a separate line for each list
"""
for pointList in lineList:
apply(self.moveTo, pointList[0])
for point in pointList[1:]:
apply(self.drawTo, point)
##
## Given a point in space, and a direction, find the point of intersection
## of that ray with a plane at the specified origin, with the specified normal
def planeIntersect (lineOrigin, lineDir, planeOrigin, normal):
t = 0
offset = planeOrigin - lineOrigin
t = offset.dot(normal) / lineDir.dot(normal)
hitPt = lineDir * t
return hitPt + lineOrigin
def getNearProjectionPoint(nodePath):
# Find the position of the projection of the specified node path
# on the near plane
origin = nodePath.getPos(SEditor.camera)
# project this onto near plane
if origin[1] != 0.0:
return origin * (SEditor.dr.near / origin[1])
else:
# Object is coplaner with camera, just return something reasonable
return Point3(0, SEditor.dr.near, 0)
def getScreenXY(nodePath):
# Where does the node path's projection fall on the near plane
nearVec = getNearProjectionPoint(nodePath)
# Clamp these coordinates to visible screen
nearX = CLAMP(nearVec[0], SEditor.dr.left, SEditor.dr.right)
nearY = CLAMP(nearVec[2], SEditor.dr.bottom, SEditor.dr.top)
# What percentage of the distance across the screen is this?
percentX = (nearX - SEditor.dr.left)/SEditor.dr.nearWidth
percentY = (nearY - SEditor.dr.bottom)/SEditor.dr.nearHeight
# Map this percentage to the same -1 to 1 space as the mouse
screenXY = Vec3((2 * percentX) - 1.0,nearVec[1],(2 * percentY) - 1.0)
# Return the resulting value
return screenXY
def getCrankAngle(center):
# Used to compute current angle of mouse (relative to the coa's
# origin) in screen space
x = SEditor.dr.mouseX - center[0]
y = SEditor.dr.mouseY - center[2]
return (180 + rad2Deg(math.atan2(y,x)))
def relHpr(nodePath, base, h, p, r):
# Compute nodePath2newNodePath relative to base coordinate system
# nodePath2base
mNodePath2Base = nodePath.getMat(base)
# delta scale, orientation, and position matrix
mBase2NewBase = Mat4()
composeMatrix(mBase2NewBase, UNIT_VEC, VBase3(h,p,r), ZERO_VEC,
CSDefault)
# base2nodePath
mBase2NodePath = base.getMat(nodePath)
# nodePath2 Parent
mNodePath2Parent = nodePath.getMat()
# Compose the result
resultMat = mNodePath2Base * mBase2NewBase
resultMat = resultMat * mBase2NodePath
resultMat = resultMat * mNodePath2Parent
# Extract and apply the hpr
hpr = Vec3(0)
decomposeMatrix(resultMat, VBase3(), hpr, VBase3(),
CSDefault)
nodePath.setHpr(hpr)
# Quaternion interpolation
def qSlerp(startQuat, endQuat, t):
startQ = Quat(startQuat)
destQuat = Quat.identQuat()
# Calc dot product
cosOmega = (startQ.getI() * endQuat.getI() +
startQ.getJ() * endQuat.getJ() +
startQ.getK() * endQuat.getK() +
startQ.getR() * endQuat.getR())
# If the above dot product is negative, it would be better to
# go between the negative of the initial and the final, so that
# we take the shorter path.
if ( cosOmega < 0.0 ):
cosOmega *= -1
startQ.setI(-1 * startQ.getI())
startQ.setJ(-1 * startQ.getJ())
startQ.setK(-1 * startQ.getK())
startQ.setR(-1 * startQ.getR())
if ((1.0 + cosOmega) > Q_EPSILON):
# usual case
if ((1.0 - cosOmega) > Q_EPSILON):
# usual case
omega = math.acos(cosOmega)
sinOmega = math.sin(omega)
startScale = math.sin((1.0 - t) * omega)/sinOmega
endScale = math.sin(t * omega)/sinOmega
else:
# ends very close
startScale = 1.0 - t
endScale = t
destQuat.setI(startScale * startQ.getI() +
endScale * endQuat.getI())
destQuat.setJ(startScale * startQ.getJ() +
endScale * endQuat.getJ())
destQuat.setK(startScale * startQ.getK() +
endScale * endQuat.getK())
destQuat.setR(startScale * startQ.getR() +
endScale * endQuat.getR())
else:
# ends nearly opposite
destQuat.setI(-startQ.getJ())
destQuat.setJ(startQ.getI())
destQuat.setK(-startQ.getR())
destQuat.setR(startQ.getK())
startScale = math.sin((0.5 - t) * math.pi)
endScale = math.sin(t * math.pi)
destQuat.setI(startScale * startQ.getI() +
endScale * endQuat.getI())
destQuat.setJ(startScale * startQ.getJ() +
endScale * endQuat.getJ())
destQuat.setK(startScale * startQ.getK() +
endScale * endQuat.getK())
return destQuat

170
doc/SceneEditor/seGrid.py Normal file
View File

@ -0,0 +1,170 @@
#################################################################
# seGrid.py
# Originally from DirectGrid.py
# Altered by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#
# We didn't change anything essential.
# Just because we customized the seSession from DirectSession,
# So we need related files can follow the change.
# However, we don't want to change anything inside the original directool
# to let them can work with our scene editor.
# (If we do change original directools, it will force user has to install the latest version of OUR Panda)
#
#################################################################
from PandaObject import *
from DirectUtil import *
from seGeometry import *
class DirectGrid(NodePath,PandaObject):
def __init__(self):
# Initialize superclass
NodePath.__init__(self)
self.assign(hidden.attachNewNode('DirectGrid'))
# Don't wireframe or light
useDirectRenderStyle(self)
# Load up grid parts to initialize grid object
# Polygon used to mark grid plane
self.gridBack = loader.loadModel('models/misc/gridBack')
self.gridBack.reparentTo(self)
self.gridBack.setColor(0.5,0.5,0.5,0.5)
# Grid Lines
self.lines = self.attachNewNode('gridLines')
self.minorLines = LineNodePath(self.lines)
self.minorLines.lineNode.setName('minorLines')
self.minorLines.setColor(VBase4(0.3,0.55,1,1))
self.minorLines.setThickness(1)
self.majorLines = LineNodePath(self.lines)
self.majorLines.lineNode.setName('majorLines')
self.majorLines.setColor(VBase4(0.3,0.55,1,1))
self.majorLines.setThickness(5)
self.centerLines = LineNodePath(self.lines)
self.centerLines.lineNode.setName('centerLines')
self.centerLines.setColor(VBase4(1,0,0,0))
self.centerLines.setThickness(3)
# Small marker to hilight snap-to-grid point
self.snapMarker = loader.loadModel('models/misc/sphere')
self.snapMarker.node().setName('gridSnapMarker')
self.snapMarker.reparentTo(self)
self.snapMarker.setColor(1,0,0,1)
self.snapMarker.setScale(0.3)
self.snapPos = Point3(0)
# Initialize Grid characteristics
self.fXyzSnap = 1
self.fHprSnap = 1
self.gridSize = 100.0
self.gridSpacing = 5.0
self.snapAngle = 15.0
self.enable()
def enable(self):
self.reparentTo(SEditor.group)
self.updateGrid()
self.fEnabled = 1
def disable(self):
self.reparentTo(hidden)
self.fEnabled = 0
def toggleGrid(self):
if self.fEnabled:
self.disable()
else:
self.enable()
def isEnabled(self):
return self.fEnabled
def updateGrid(self):
# Update grid lines based upon current grid spacing and grid size
# First reset existing grid lines
self.minorLines.reset()
self.majorLines.reset()
self.centerLines.reset()
# Now redraw lines
numLines = math.ceil(self.gridSize/self.gridSpacing)
scaledSize = numLines * self.gridSpacing
center = self.centerLines
minor = self.minorLines
major = self.majorLines
for i in range(-numLines,numLines + 1):
if i == 0:
center.moveTo(i * self.gridSpacing, -scaledSize, 0)
center.drawTo(i * self.gridSpacing, scaledSize, 0)
center.moveTo(-scaledSize, i * self.gridSpacing, 0)
center.drawTo(scaledSize, i * self.gridSpacing, 0)
else:
if (i % 5) == 0:
major.moveTo(i * self.gridSpacing, -scaledSize, 0)
major.drawTo(i * self.gridSpacing, scaledSize, 0)
major.moveTo(-scaledSize, i * self.gridSpacing, 0)
major.drawTo(scaledSize, i * self.gridSpacing, 0)
else:
minor.moveTo(i * self.gridSpacing, -scaledSize, 0)
minor.drawTo(i * self.gridSpacing, scaledSize, 0)
minor.moveTo(-scaledSize, i * self.gridSpacing, 0)
minor.drawTo(scaledSize, i * self.gridSpacing, 0)
center.create()
minor.create()
major.create()
self.gridBack.setScale(scaledSize)
def setXyzSnap(self, fSnap):
self.fXyzSnap = fSnap
def getXyzSnap(self):
return self.fXyzSnap
def setHprSnap(self, fSnap):
self.fHprSnap = fSnap
def getHprSnap(self):
return self.fHprSnap
def computeSnapPoint(self, point):
# Start of with current point
self.snapPos.assign(point)
# Snap if necessary
if self.fXyzSnap:
self.snapPos.set(
ROUND_TO(self.snapPos[0], self.gridSpacing),
ROUND_TO(self.snapPos[1], self.gridSpacing),
ROUND_TO(self.snapPos[2], self.gridSpacing))
# Move snap marker to this point
self.snapMarker.setPos(self.snapPos)
# Return the hit point
return self.snapPos
def computeSnapAngle(self, angle):
return ROUND_TO(angle, self.snapAngle)
def setSnapAngle(self, angle):
self.snapAngle = angle
def getSnapAngle(self):
return self.snapAngle
def setGridSpacing(self, spacing):
self.gridSpacing = spacing
self.updateGrid()
def getGridSpacing(self):
return self.gridSpacing
def setGridSize(self, size):
# Set size of grid back and redraw lines
self.gridSize = size
self.updateGrid()
def getGridSize(self):
return self.gridSize

632
doc/SceneEditor/seLights.py Normal file
View File

@ -0,0 +1,632 @@
#################################################################
# seLights.py
# Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#################################################################
from PandaObject import *
from string import lower
import DirectUtil
import string
class seLight(NodePath):
#################################################################
# seLight(NodePath)
# This is an object for keeping light data and let we can manipulate
# lights as otherNopaths.
# This idea basically is from directLight.
# But the way directLight object worked is not we want in our
# sceneEditor. So, we wrote one by ourself.
#################################################################
def __init__(self, light, parent, type,
lightcolor=VBase4(0.3,0.3,0.3,1),
specularColor = VBase4(1),
position = Point3(0,0,0),
orientation = Vec3(1,0,0),
constant = 1.0,
linear = 0.0,
quadratic = 0.0,
exponent = 0.0,
tag="",
lence = None):
#################################################################
# __init__(self, light, parent, type,
# lightcolor=VBase4(0.3,0.3,0.3,1),
# specularColor = VBase4(1),
# position = Point3(0,0,0),
# orientation = Vec3(1,0,0),
# constant = 1.0,
# linear = 0.0,
# quadratic = 0.0,
# exponent = 0.0,
# tag="",
# lence = None):
# This constructor will create a light node inside it and upcast
# this light node to itself as a nodePath.
# Also, it will load a model as a reference to itself on the secene so that
# user can easily recognize where is the light and can easily manipulate
# by mouse picking and widget control.
#################################################################
# Initialize the super class
NodePath.__init__(self)
# Initialize and save values
self.light = light
self.type = type
self.lightcolor=lightcolor
self.specularColor = specularColor
self.position = position
self.orientation = orientation
self.constant = constant
self.linear = linear
self.quadratic = quadratic
self.exponent = exponent
self.lence = lence
self.active = True
if isinstance(light, Spotlight):
node = light.upcastToLensNode()
else:
node = light.upcastToPandaNode()
# Attach node to self
self.LightNode=parent.attachNewNode(node)
self.LightNode.setTag("Metadata",tag)
if(self.type=='spot'):
self.LightNode.setHpr(self.orientation)
self.LightNode.setPos(self.position)
else:
self.LightNode.setHpr(self.orientation)
self.LightNode.setPos(self.position)
self.assign(self.LightNode)
if(self.type=='spot'):
self.helpModel = loader.loadModelCopy( "Spotlight" )
elif(self.type=='point'):
self.helpModel = loader.loadModelCopy( "Pointlight" )
elif(self.type=='directional'):
self.helpModel = loader.loadModelCopy( "Dirlight" )
else:
self.helpModel = loader.loadModelCopy( "misc/Sphere" )
self.helpModel.setColor(self.lightcolor)
self.helpModel.reparentTo(self)
DirectUtil.useDirectRenderStyle(self.helpModel)
if not ((self.type == 'directional')or(self.type == 'point')or(self.type == 'spot')):
self.helpModel.hide()
def getLight(self):
#################################################################
# getLight(self)
# This function will return the light object it contains.
#################################################################
return self.light
def getLightColor(self):
#################################################################
# getLightColor(self)
# This function will return the color of the light color of this light node.
#################################################################
return self.lightcolor
def getName(self):
#################################################################
# getName(self)
# This function will return the name of this light.
#################################################################
return self.light.getName()
def rename(self,name):
#################################################################
# rename(self, name)
# User should specify a string object, name, as the new name of this
# light node. This function will rename itself and light object
# to this new name.
#################################################################
self.light.setName(name)
self.setName(name)
def getType(self):
#################################################################
# getType(self)
# This function will return a string which is the type of this
# light node. (We only have four types of light)
#################################################################
return self.type
def setColor(self,color):
#################################################################
# setColor(self, color)
# This function takes one input parameter, color, which is a
# VBase4 object. This function will simply set this object into
# light node it has to change the property of light.
# Also, if the light type is either "directional" or "point", which
# means it has a reference model with it, this function will also
# change the reference model's color to input value.
#################################################################
self.light.setColor(color)
self.lightcolor = color
if (self.type == 'directional')or(self.type == 'point'):
self.helpModel.setColor(self.lightcolor)
return
def getSpecColor(self):
#################################################################
# getSpecColor(self)
# This function will return the specular color of the light.
# Although you can call this function for all kinds of light,
# it will only meanful if this light is not a ambient light.
#################################################################
return self.specularColor
def setSpecColor(self,color):
#################################################################
# setSpecColor(self, color)
# This function can be used to set the specular color of the light.
# Although you can call this function for all kinds of light,
# it will only meanful if the light type is not "ambient"
#################################################################
self.light.setSpecularColor(color)
self.specularcolor = color
return
def getPosition(self):
#################################################################
# getPosition(self)
# getPosition(self)
# This functioln will return a Point3 object which contains
# the x, y, z position data of this light node.
# It only has meaning for "point Light" and "Directional light"
#################################################################
self.position = self.LightNode.getPos()
return self.position
def setPosition(self, pos):
#################################################################
# setPosition(self, pos)
# This function will take a Point3 object as a input.
# Then, this function will set the itself andd light node to the
# target point.
#################################################################
self.LightNode.setPos(pos)
self.position = pos
return
def getOrientation(self):
#################################################################
# getOrientation(self)
# This function will return a Vec3-type object which contains the
# orientation data of this light node
#
# This function will only have meaning for point light and directional light.
#
#################################################################
self.orientation = self.LightNode.getHpr()
return self.orientation
def setOrientation(self,orient):
#################################################################
# setOrientation(self, orient)
# This funtction will take a Vec3-type object as an input.
# Then this function will set itself nad light node to face
# the target orientation.
#
# This function only has meaning for point light and directional light
# type of lights.
#
#################################################################
self.LightNode.setHpr(orient)
self.orientation = orient
return
def getAttenuation(self):
#################################################################
# getAttenuation(self)
# This function will return a Vec3 type of object which contains
# the constant, linear and quadratic attenuation for this light node.
#
# This function will only have meaning for point light and spot light
# tyoe of lights.
#
#################################################################
return Vec3(self.constant,self.linear,self.quadratic)
def setConstantAttenuation(self, value):
#################################################################
# setConstantAttenuation(self, value)
# This function will take a float number as an input.
# Then, this function will set the Constant Atenuation value
# to this number.
#################################################################
self.light.setAttenuation(Vec3(value, self.linear, self.quadratic))
self.constant = value
return
def setLinearAttenuation(self, value):
#################################################################
# setLinearAttenuation(self, value)
# This function will take a float number as an input.
# Then, this function will set the Linear Atenuation value
# to this number.
#################################################################
self.light.setAttenuation(Vec3(self.constant, value, self.quadratic))
self.linear = value
return
def setQuadraticAttenuation(self, value):
#################################################################
# setQuadraticAttenuation(self, value)
# This function will take a float number as an input.
# Then, this function will set the Quadratic Atenuation value
# to this number.
#################################################################
self.light.setAttenuation(Vec3(self.constant, self.linear, value))
self.quadratic = value
return
def getExponent(self):
#################################################################
# getExponent(self)
# This function will return the value of the Exponent Attenuation
# of this light node. (float)
#################################################################
return self.exponent
def setExponent(self, value):
#################################################################
# setExponent(self, value)
# This function will take a float number as an input.
# Then, this function will set the Exponent Atenuation value
# to this number.
#################################################################
self.light.setExponent(value)
self.exponent = value
return
class seLightManager(NodePath):
#################################################################
# seLightManager(NodePath)
# This is the class we used to control al lightings in our sceneEditor.
#################################################################
def __init__(self):
# Initialize the superclass
NodePath.__init__(self)
# Create a node for the lights
self.lnode=render.attachNewNode('Lights')
self.assign(self.lnode)
# Create a light attrib
self.lightAttrib = LightAttrib.makeAllOff()
self.lightDict = {}
self.ambientCount = 0
self.directionalCount = 0
self.pointCount = 0
self.spotCount = 0
# Originally, we don't do this load model thing.
# But the problem is, if we don't, then it will cause some
# Bounding calculation error...
self.helpModel = loader.loadModelCopy( "misc/sphere" )
self.helpModel.reparentTo(self)
self.helpModel.hide()
def create(self, type = 'ambient',
lightcolor=VBase4(0.3,0.3,0.3,1),
specularColor = VBase4(1),
position = Point3(0,0,0),
orientation = Vec3(1,0,0),
constant = 1.0,
linear = 0.0,
quadratic = 0.0,
exponent = 0.0,
tag= "",
name='DEFAULT_NAME'):
#################################################################
# create(self, type = 'ambient',
# lightcolor=VBase4(0.3,0.3,0.3,1),
# specularColor = VBase4(1),
# position = Point3(0,0,0),
# orientation = Vec3(1,0,0),
# constant = 1.0,
# linear = 0.0,
# quadratic = 0.0,
# exponent = 0.0,
# tag= "",
# name='DEFAULT_NAME')
# As you can see, once user call this function and specify those
# variables, this function will create a seLight node.
# In the default, the light which just has been created will be
# set to off.
#################################################################
### create the light
lence = None
if type == 'ambient':
self.ambientCount += 1
if(name=='DEFAULT_NAME'):
light = AmbientLight('ambient_' + `self.ambientCount`)
else:
light = AmbientLight(name)
light.setColor(lightcolor)
elif type == 'directional':
self.directionalCount += 1
if(name=='DEFAULT_NAME'):
light = DirectionalLight('directional_' + `self.directionalCount`)
else:
light = DirectionalLight(name)
light.setColor(lightcolor)
light.setSpecularColor(specularColor)
elif type == 'point':
self.pointCount += 1
if(name=='DEFAULT_NAME'):
light = PointLight('point_' + `self.pointCount`)
else:
light = PointLight(name)
light.setColor(lightcolor)
light.setSpecularColor(specularColor)
light.setAttenuation(Vec3(constant, linear, quadratic))
elif type == 'spot':
self.spotCount += 1
if(name=='DEFAULT_NAME'):
light = Spotlight('spot_' + `self.spotCount`)
else:
light = Spotlight(name)
light.setColor(lightcolor)
lence = PerspectiveLens()
light.setLens(lence)
light.setSpecularColor(specularColor)
light.setAttenuation(Vec3(constant, linear, quadratic))
light.setExponent(exponent)
else:
print 'Invalid light type'
return None
# Create the seLight objects and put the light object we just created into it.
lightNode = seLight(light,self,type,
lightcolor=lightcolor,
specularColor = specularColor,
position = position,
orientation = orientation,
constant = constant,
linear = linear,
quadratic = quadratic,
exponent = exponent,
tag=tag,
lence = lence
)
self.lightDict[light.getName()] = lightNode
self.setOn(lightNode)
return self.lightDict.keys(),lightNode
def addLight(self, light):
#################################################################
# addLight(self, light)
# This function will put light in and save its properties in to a seLight Node
# Attention!!
# only Spotlight obj nneds to be specified a lens node first. i.e. setLens() first!
#################################################################
type = lower(light.getType().getName())
light.upcastToNamable()
specularColor = VBase4(1)
position = Point3(0,0,0)
orientation = Vec3(1,0,0)
constant = 1.0
linear = 0.0
quadratic = 0.0
exponent = 0.0
lence = None
lightcolor = light.getColor()
if type == 'ambientlight':
type = 'ambient'
self.ambientCount += 1
elif type == 'directionallight':
type = 'directional'
self.directionalCount += 1
orientation = light.getDirection()
position = light.getPoint()
specularColor = light.getSpecularColor()
elif type == 'pointlight':
type = 'point'
self.pointCount += 1
position = light.getPoint()
specularColor = light.getSpecularColor()
Attenuation = light.getAttenuation()
constant = Attenuation.getX()
linear = Attenuation.getY()
quadratic = Attenuation.getZ()
elif type == 'spotlight':
type = 'spot'
self.spotCount += 1
specularColor = light.getSpecularColor()
Attenuation = light.getAttenuation()
constant = Attenuation.getX()
linear = Attenuation.getY()
quadratic = Attenuation.getZ()
exponent = light.getExponent()
else:
print 'Invalid light type'
return None
lightNode = seLight(light,self,type,
lightcolor=lightcolor,
specularColor = specularColor,
position = position,
orientation = orientation,
constant = constant,
linear = linear,
quadratic = quadratic,
exponent = exponent,
lence = lence)
self.lightDict[light.getName()] = lightNode
self.setOn(lightNode)
return self.lightDict.keys(),lightNode
def delete(self, name, removeEntry = True):
#################################################################
# delete(self, name, removeEntry = True)
# This function will remove light node had the same name with user input.
# Also, you can specify the removeEntry to decide to remove the entry from the lightDict or not.
# Normaly, you alway want to remove the entry from the dictionary. Thsi is only used for "deleteAll" function.
#################################################################
type = self.lightDict[name].getType()
if type == 'ambient':
self.ambientCount -= 1
elif type == 'directional':
self.directionalCount -= 1
elif type == 'point':
self.pointCount -= 1
elif type == 'spot':
self.spotCount -= 1
self.setOff(self.lightDict[name])
self.lightDict[name].removeChildren()
self.lightDict[name].removeNode()
if removeEntry:
del self.lightDict[name]
return self.lightDict.keys()
def deleteAll(self):
#################################################################
# deleteAll(self)
# This function will keep calling delete and put exist lights in
# until all lights have been eliminated.
#################################################################
for name in self.lightDict:
self.delete(name, removeEntry = False)
self.lightDict.clear()
def isLight(self,name):
#################################################################
# isLight(self.name)
# Use a string as a index to check if there existing a light named "name"
#################################################################
return self.lightDict.has_key(name)
def rename(self,oName,nName):
#################################################################
# rename(self, oName, nName)
# This function will reanem the light named "oName(String)" to
# nName(String)
#################################################################
if self.isLight(oName):
lightNode = self.lightDict[oName]
self.lightDict[nName] = lightNode
lightNode.rename(nName)
del self.lightDict[oName]
return self.lightDict.keys(),lightNode
else:
print '----Light Mnager: No such Light!'
def getLightNodeList(self):
#################################################################
# getLightNodeList(self)
# Return a list which contains all seLight nodes
#################################################################
list = []
for name in self.lightDict:
list.append(self.lightDict[name])
return list
def getLightNodeDict(self):
#################################################################
# getLightNodeDict(self)
# Return the light dictionary itself.
#
# Attention!
# Because it doesn't make a copy when you return a dictionary, it
# means when you can change the value from outside and that change
# will directly reflect back to here.
#
#################################################################
return self.lightDict
def getLightList(self):
#################################################################
# getLightList(self)
# Return a list which contains names of all lights.
#################################################################
list = []
for name in self.lightDict:
list.append(name)
return list
def getLightNode(self,lightName):
#################################################################
# getLightNode(self, lightName)
# This function will return a seLight Node using a string, lightName. as a index.
#################################################################
if lightName in self.lightDict:
return self.lightDict[lightName]
def allOn(self):
#################################################################
# allOb(self)
# Enable the lighting system.
#################################################################
# Turn on all lighting
render.node().setAttrib(self.lightAttrib)
# Make sure there is a default material
render.setMaterial(Material())
def allOff(self):
#################################################################
# allOff(self)
# Disable whole lighting system
#################################################################
# Turn off all lighting
render.node().clearAttrib(LightAttrib.getClassType())
def toggle(self):
#################################################################
# toggle(self)
# Toggles light attribute, but doesn't toggle individual lights
#################################################################
if render.node().hasAttrib(LightAttrib.getClassType()):
self.allOff()
else:
self.allOn()
def setOn(self, lightNode):
#################################################################
# setOn(lightNode)
# This function will enable the input seLight node.
# If the light system itself is down, activate it.
#################################################################
self.lightAttrib = self.lightAttrib.addLight(lightNode.getLight())
lightNode.active = True
if render.node().hasAttrib(LightAttrib.getClassType()):
render.node().setAttrib(self.lightAttrib)
def setOff(self, lightNode):
#################################################################
# setOff(self, lightNode)
# This function will disable the input seLight node
# If the light system itself is down, activate it.
#################################################################
lightNode.active = False
self.lightAttrib = self.lightAttrib.removeLight(lightNode.getLight())
if render.node().hasAttrib(LightAttrib.getClassType()):
render.node().setAttrib(self.lightAttrib)
def getList(self):
#################################################################
# getList(self)
# This function actually has the same functionality with getLightList(),
# but this one should be more efficient.
#################################################################
return self.lightDict.keys()

View File

@ -0,0 +1,956 @@
#################################################################
# seManipulation.py
# Originally from DirectManipulation.py
# Altered by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#
# We didn't change anything essential.
# Just because we customized the seSession from DirectSession,
# So we need related files can follow the change.
# However, we don't want to change anything inside the original directool
# to let them can work with our scene editor.
# (If we do change original directools, it will force user has to install the latest version of OUR Panda)
#
#################################################################
from PandaObject import *
from DirectGlobals import *
from DirectUtil import *
from seGeometry import *
import Task
class DirectManipulationControl(PandaObject):
def __init__(self):
# Create the grid
self.objectHandles = ObjectHandles()
self.hitPt = Point3(0)
self.prevHit = Vec3(0)
self.rotationCenter = Point3(0)
self.initScaleMag = 1
self.manipRef = SEditor.group.attachNewNode('manipRef')
self.hitPtDist = 0
self.constraint = None
self.rotateAxis = 'x'
self.lastCrankAngle = 0
self.fSetCoa = 0
self.fHitInit = 1
self.fScaleInit = 1
self.fWidgetTop = 0
self.fFreeManip = 1
self.fScaling = 0
self.mode = None
self.actionEvents = [
['DIRECT-mouse1', self.manipulationStart],
['DIRECT-mouse1Up', self.manipulationStop],
['tab', self.toggleObjectHandlesMode],
['.', self.objectHandles.multiplyScalingFactorBy, 2.0],
['>', self.objectHandles.multiplyScalingFactorBy, 2.0],
[',', self.objectHandles.multiplyScalingFactorBy, 0.5],
['<', self.objectHandles.multiplyScalingFactorBy, 0.5],
['shift-f', self.objectHandles.growToFit],
['i', self.plantSelectedNodePath],
]
def manipulationStart(self, modifiers):
# Start out in select mode
self.mode = 'select'
# Check for a widget hit point
entry = SEditor.iRay.pickWidget()
# Did we hit a widget?
if entry:
# Yes!
self.hitPt.assign(entry.getFromIntersectionPoint())
self.hitPtDist = Vec3(self.hitPt).length()
# Constraint determined by nodes name
self.constraint = entry.getIntoNodePath().getName()
else:
# Nope, off the widget, no constraint
self.constraint = None
# Check to see if we are moving the object
# We are moving the object if we either wait long enough
taskMgr.doMethodLater(MANIPULATION_MOVE_DELAY,
self.switchToMoveMode,
'manip-move-wait')
# Or we move far enough
self.moveDir = None
watchMouseTask = Task.Task(self.watchMouseTask)
watchMouseTask.initX = SEditor.dr.mouseX
watchMouseTask.initY = SEditor.dr.mouseY
taskMgr.add(watchMouseTask, 'manip-watch-mouse')
def switchToMoveMode(self, state):
taskMgr.remove('manip-watch-mouse')
self.mode = 'move'
self.manipulateObject()
return Task.done
def watchMouseTask(self, state):
if (((abs (state.initX - SEditor.dr.mouseX)) > 0.01) or
((abs (state.initY - SEditor.dr.mouseY)) > 0.01)):
taskMgr.remove('manip-move-wait')
self.mode = 'move'
self.manipulateObject()
return Task.done
else:
return Task.cont
def manipulationStop(self,xy=[]):
taskMgr.remove('manipulateObject')
taskMgr.remove('manip-move-wait')
taskMgr.remove('manip-watch-mouse')
# depending on flag.....
if self.mode == 'select':
# Check for object under mouse
# Don't intersect with hidden or backfacing objects
skipFlags = SKIP_HIDDEN | SKIP_BACKFACE
# Skip camera (and its children), unless control key is pressed
skipFlags |= SKIP_CAMERA * (1 - base.getControl())
entry = SEditor.iRay.pickGeom(skipFlags = skipFlags)
if entry:
# Record hit point information
self.hitPt.assign(entry.getFromIntersectionPoint())
self.hitPtDist = Vec3(self.hitPt).length()
# Select it
SEditor.select(entry.getIntoNodePath(), SEditor.fShift)
else:
SEditor.deselectAll()
else:
self.manipulateObjectCleanup()
def manipulateObjectCleanup(self):
if self.fScaling:
# We had been scaling, need to reset object handles
self.objectHandles.transferObjectHandlesScale()
self.fScaling = 0
SEditor.selected.highlightAll()
self.objectHandles.showAllHandles()
self.objectHandles.hideGuides()
# Restart followSelectedNodePath task
self.spawnFollowSelectedNodePathTask()
messenger.send('DIRECT_manipulateObjectCleanup')
def spawnFollowSelectedNodePathTask(self):
# If nothing selected, just return
if not SEditor.selected.last:
return
# Clear out old task to make sure
taskMgr.remove('followSelectedNodePath')
# Where are the object handles relative to the selected object
pos = VBase3(0)
hpr = VBase3(0)
decomposeMatrix(SEditor.selected.last.mCoa2Dnp,
VBase3(0), hpr, pos, CSDefault)
# Create the task
t = Task.Task(self.followSelectedNodePathTask)
# Update state variables
t.pos = pos
t.hpr = hpr
t.base = SEditor.selected.last
# Spawn the task
taskMgr.add(t, 'followSelectedNodePath')
def followSelectedNodePathTask(self, state):
SEditor.widget.setPosHpr(state.base, state.pos, state.hpr)
return Task.cont
def enableManipulation(self):
# Accept events
for event in self.actionEvents:
self.accept(event[0], event[1], extraArgs = event[2:])
def disableManipulation(self):
# Ignore events
for event in self.actionEvents:
self.ignore(event[0])
self.removeManipulateObjectTask()
taskMgr.remove('manipulateObject')
taskMgr.remove('manip-move-wait')
taskMgr.remove('manip-watch-mouse')
taskMgr.remove('highlightWidgetTask')
taskMgr.remove('resizeObjectHandles')
def toggleObjectHandlesMode(self):
self.fSetCoa = 1 - self.fSetCoa
if self.fSetCoa:
self.objectHandles.coaModeColor()
else:
self.objectHandles.manipModeColor()
def removeManipulateObjectTask(self):
taskMgr.remove('manipulateObject')
def manipulateObject(self):
# Only do this if something is selected
if SEditor.selected:
# Remove the task to keep the widget attached to the object
taskMgr.remove('followSelectedNodePath')
# and the task to highlight the widget
taskMgr.remove('highlightWidgetTask')
# Set manipulation flag
self.fManip = 1
# Record undo point
SEditor.pushUndo(SEditor.selected)
# Update object handles visibility
self.objectHandles.showGuides()
self.objectHandles.hideAllHandles()
self.objectHandles.showHandle(self.constraint)
# Record relationship between selected nodes and widget
SEditor.selected.getWrtAll()
# hide the bbox of the selected objects during interaction
SEditor.selected.dehighlightAll()
# Send event to signal start of manipulation
messenger.send('DIRECT_manipulateObjectStart')
# Manipulate the real object with the constraint
# The constraint is passed as the name of the node
self.spawnManipulateObjectTask()
def spawnManipulateObjectTask(self):
# reset hit-pt flag
self.fHitInit = 1
self.fScaleInit = 1
# record initial offset between widget and camera
t = Task.Task(self.manipulateObjectTask)
t.fMouseX = abs(SEditor.dr.mouseX) > 0.9
t.fMouseY = abs(SEditor.dr.mouseY) > 0.9
if t.fMouseX:
t.constrainedDir = 'y'
else:
t.constrainedDir = 'x'
# Compute widget's xy coords in screen space
t.coaCenter = getScreenXY(SEditor.widget)
# These are used to rotate about view vector
if t.fMouseX and t.fMouseY:
t.lastAngle = getCrankAngle(t.coaCenter)
taskMgr.add(t, 'manipulateObject')
def manipulateObjectTask(self, state):
# Widget takes precedence
if self.constraint:
type = self.constraint[2:]
if type == 'post':
self.xlate1D(state)
elif type == 'disc':
self.xlate2D(state)
elif type == 'ring':
self.rotate1D(state)
# No widget interaction, determine free manip mode
elif self.fFreeManip:
# If we've been scaling and changed modes, reset object handles
if 0 and self.fScaling and (not SEditor.fAlt):
self.objectHandles.transferObjectHandlesScale()
self.fScaling = 0
# Alt key switches to a scaling mode
if SEditor.fControl:
self.fScaling = 1
self.scale3D(state)
# Otherwise, manip mode depends on where you started
elif state.fMouseX and state.fMouseY:
# In the corner, spin around camera's axis
self.rotateAboutViewVector(state)
elif state.fMouseX or state.fMouseY:
# Mouse started elsewhere in the outer frame, rotate
self.rotate2D(state)
else:
# Mouse started in central region, xlate
# Mode depends on shift key
if SEditor.fShift or SEditor.fControl:
self.xlateCamXY(state)
else:
self.xlateCamXZ(state)
if self.fSetCoa:
# Update coa based on current widget position
SEditor.selected.last.mCoa2Dnp.assign(
SEditor.widget.getMat(SEditor.selected.last))
else:
# Move the objects with the widget
SEditor.selected.moveWrtWidgetAll()
# Continue
return Task.cont
### WIDGET MANIPULATION METHODS ###
def xlate1D(self, state):
# Constrained 1D Translation along widget axis
# Compute nearest hit point along axis and try to keep
# that point as close to the current mouse position as possible
# what point on the axis is the mouse pointing at?
self.hitPt.assign(self.objectHandles.getAxisIntersectPt(
self.constraint[:1]))
# use it to see how far to move the widget
if self.fHitInit:
# First time through, just record that point
self.fHitInit = 0
self.prevHit.assign(self.hitPt)
else:
# Move widget to keep hit point as close to mouse as possible
offset = self.hitPt - self.prevHit
SEditor.widget.setPos(SEditor.widget, offset)
def xlate2D(self, state):
# Constrained 2D (planar) translation
# Compute point of intersection of ray from eyepoint through cursor
# to one of the three orthogonal planes on the widget.
# This point tracks all subsequent mouse movements
self.hitPt.assign(self.objectHandles.getWidgetIntersectPt(
SEditor.widget, self.constraint[:1]))
# use it to see how far to move the widget
if self.fHitInit:
# First time through just record hit point
self.fHitInit = 0
self.prevHit.assign(self.hitPt)
else:
offset = self.hitPt - self.prevHit
SEditor.widget.setPos(SEditor.widget, offset)
def rotate1D(self, state):
# Constrained 1D rotation about the widget's main axis (X,Y, or Z)
# Rotation depends upon circular motion of the mouse about the
# projection of the widget's origin on the image plane
# A complete circle about the widget results in a change in
# orientation of 360 degrees.
# First initialize hit point/rotation angle
if self.fHitInit:
self.fHitInit = 0
self.rotateAxis = self.constraint[:1]
self.fWidgetTop = self.widgetCheck('top?')
self.rotationCenter = getScreenXY(SEditor.widget)
self.lastCrankAngle = getCrankAngle(self.rotationCenter)
# Rotate widget based on how far cursor has swung around origin
newAngle = getCrankAngle(self.rotationCenter)
deltaAngle = self.lastCrankAngle - newAngle
if self.fWidgetTop:
deltaAngle = -1 * deltaAngle
if self.rotateAxis == 'x':
SEditor.widget.setP(SEditor.widget, deltaAngle)
elif self.rotateAxis == 'y':
if base.config.GetBool('temp-hpr-fix',0):
SEditor.widget.setR(SEditor.widget, deltaAngle)
else:
SEditor.widget.setR(SEditor.widget, -deltaAngle)
elif self.rotateAxis == 'z':
SEditor.widget.setH(SEditor.widget, deltaAngle)
# Record crank angle for next time around
self.lastCrankAngle = newAngle
def widgetCheck(self,type):
# Utility to see if we are looking at the top or bottom of
# a 2D planar widget or if we are looking at a 2D planar widget
# edge on
# Based upon angle between view vector from eye through the
# widget's origin and one of the three principle axes
axis = self.constraint[:1]
# First compute vector from eye through widget origin
mWidget2Cam = SEditor.widget.getMat(SEditor.camera)
# And determine where the viewpoint is relative to widget
pos = VBase3(0)
decomposeMatrix(mWidget2Cam, VBase3(0), VBase3(0), pos,
CSDefault)
widgetDir = Vec3(pos)
widgetDir.normalize()
# Convert specified widget axis to view space
if axis == 'x':
widgetAxis = Vec3(mWidget2Cam.xformVec(X_AXIS))
elif axis == 'y':
widgetAxis = Vec3(mWidget2Cam.xformVec(Y_AXIS))
elif axis == 'z':
widgetAxis = Vec3(mWidget2Cam.xformVec(Z_AXIS))
widgetAxis.normalize()
if type == 'top?':
# Check sign of angle between two vectors
return (widgetDir.dot(widgetAxis) < 0.)
elif type == 'edge?':
# Checking to see if we are viewing edge-on
# Check angle between two vectors
return(abs(widgetDir.dot(widgetAxis)) < .2)
### FREE MANIPULATION METHODS ###
def xlateCamXZ(self, state):
"""Constrained 2D motion parallel to the camera's image plane
This moves the object in the camera's XZ plane"""
# reset fHitInit in case we later switch to manip mode
self.fHitInit = 1
# Reset scaling init flag
self.fScaleInit = 1
# Where is the widget relative to current camera view
vWidget2Camera = SEditor.widget.getPos(SEditor.camera)
x = vWidget2Camera[0]
y = vWidget2Camera[1]
z = vWidget2Camera[2]
# Move widget (and objects) based upon mouse motion
# Scaled up accordingly based upon widget distance
dr = SEditor.dr
SEditor.widget.setX(
SEditor.camera,
x + 0.5 * dr.mouseDeltaX * dr.nearWidth * (y/dr.near))
SEditor.widget.setZ(
SEditor.camera,
z + 0.5 * dr.mouseDeltaY * dr.nearHeight * (y/dr.near))
def xlateCamXY(self, state):
"""Constrained 2D motion perpendicular to camera's image plane
This moves the object in the camera's XY plane if shift is held
Moves object toward camera if control is held
"""
# Reset scaling init flag
self.fScaleInit = 1
# Now, where is the widget relative to current camera view
vWidget2Camera = SEditor.widget.getPos(SEditor.camera)
# If this is first time around, record initial y distance
if self.fHitInit:
self.fHitInit = 0
# Use distance to widget to scale motion along Y
self.xlateSF = Vec3(vWidget2Camera).length()
# Get widget's current xy coords in screen space
coaCenter = getNearProjectionPoint(SEditor.widget)
self.deltaNearX = coaCenter[0] - SEditor.dr.nearVec[0]
# Which way do we move the object?
if SEditor.fControl:
moveDir = Vec3(vWidget2Camera)
# If widget is behind camera invert vector
if moveDir[1] < 0.0:
moveDir.assign(moveDir * -1)
moveDir.normalize()
else:
moveDir = Vec3(Y_AXIS)
# Move selected objects
dr = SEditor.dr
# Scale move dir
moveDir.assign(moveDir * (2.0 * dr.mouseDeltaY * self.xlateSF))
# Add it to current widget offset
vWidget2Camera += moveDir
# The object, however, stays at the same relative point to mouse in X
vWidget2Camera.setX((dr.nearVec[0] + self.deltaNearX) *
(vWidget2Camera[1]/dr.near))
# Move widget
SEditor.widget.setPos(SEditor.camera, vWidget2Camera)
def rotate2D(self, state):
""" Virtual trackball rotation of widget """
# Reset init flag in case we switch to another mode
self.fHitInit = 1
# Reset scaling init flag
self.fScaleInit = 1
tumbleRate = 360
# If moving outside of center, ignore motion perpendicular to edge
if ((state.constrainedDir == 'y') and (abs(SEditor.dr.mouseX) > 0.9)):
deltaX = 0
deltaY = SEditor.dr.mouseDeltaY
elif ((state.constrainedDir == 'x') and (abs(SEditor.dr.mouseY) > 0.9)):
deltaX = SEditor.dr.mouseDeltaX
deltaY = 0
else:
deltaX = SEditor.dr.mouseDeltaX
deltaY = SEditor.dr.mouseDeltaY
# Mouse motion edge to edge of display region results in one full turn
relHpr(SEditor.widget, SEditor.camera, deltaX * tumbleRate,
-deltaY * tumbleRate, 0)
def rotateAboutViewVector(self, state):
# Reset init flag in case we switch to another mode
self.fHitInit = 1
# Reset scaling init flag
self.fScaleInit = 1
# Compute current angle
angle = getCrankAngle(state.coaCenter)
deltaAngle = angle - state.lastAngle
state.lastAngle = angle
# Mouse motion edge to edge of display region results in one full turn
if base.config.GetBool('temp-hpr-fix',0):
relHpr(SEditor.widget, SEditor.camera, 0, 0, -deltaAngle)
else:
relHpr(SEditor.widget, SEditor.camera, 0, 0, deltaAngle)
def scale3D(self, state):
# Scale the selected node based upon up down mouse motion
# Mouse motion from edge to edge results in a factor of 4 scaling
# From midpoint to edge doubles or halves objects scale
if self.fScaleInit:
self.fScaleInit = 0
self.manipRef.setPos(SEditor.widget, 0, 0, 0)
self.manipRef.setHpr(SEditor.camera, 0, 0, 0)
self.initScaleMag = Vec3(
self.objectHandles.getWidgetIntersectPt(
self.manipRef, 'y')).length()
# record initial scale
self.initScale = SEditor.widget.getScale()
# Reset fHitInitFlag
self.fHitInit = 1
# Begin
# Scale factor is ratio current mag with init mag
currScale = (
self.initScale *
(self.objectHandles.getWidgetIntersectPt(
self.manipRef, 'y').length() /
self.initScaleMag)
)
SEditor.widget.setScale(currScale)
## Utility functions ##
def plantSelectedNodePath(self):
""" Move selected object to intersection point of cursor on scene """
# Check for intersection
entry = SEditor.iRay.pickGeom(
skipFlags = SKIP_HIDDEN | SKIP_BACKFACE | SKIP_CAMERA)
# MRM: Need to handle moving COA
if (entry != None) and (SEditor.selected.last != None):
# Record undo point
SEditor.pushUndo(SEditor.selected)
# Record wrt matrix
SEditor.selected.getWrtAll()
# Move selected
SEditor.widget.setPos(
SEditor.camera,entry.getFromIntersectionPoint())
# Move all the selected objects with widget
# Move the objects with the widget
SEditor.selected.moveWrtWidgetAll()
# Let everyone know that something was moved
messenger.send('DIRECT_manipulateObjectCleanup')
class ObjectHandles(NodePath,PandaObject):
def __init__(self):
# Initialize the superclass
NodePath.__init__(self)
# Load up object handles model and assign it to self
self.assign(loader.loadModel('models/misc/objectHandles'))
self.setName('objectHandles')
self.scalingNode = self.getChild(0)
self.scalingNode.setName('ohScalingNode')
self.ohScalingFactor = 1.0
# To avoid recreating a vec every frame
self.hitPt = Vec3(0)
# Get a handle on the components
self.xHandles = self.find('**/X')
self.xPostGroup = self.xHandles.find('**/x-post-group')
self.xPostCollision = self.xHandles.find('**/x-post')
self.xRingGroup = self.xHandles.find('**/x-ring-group')
self.xRingCollision = self.xHandles.find('**/x-ring')
self.xDiscGroup = self.xHandles.find('**/x-disc-group')
self.xDisc = self.xHandles.find('**/x-disc-visible')
self.xDiscCollision = self.xHandles.find('**/x-disc')
self.yHandles = self.find('**/Y')
self.yPostGroup = self.yHandles.find('**/y-post-group')
self.yPostCollision = self.yHandles.find('**/y-post')
self.yRingGroup = self.yHandles.find('**/y-ring-group')
self.yRingCollision = self.yHandles.find('**/y-ring')
self.yDiscGroup = self.yHandles.find('**/y-disc-group')
self.yDisc = self.yHandles.find('**/y-disc-visible')
self.yDiscCollision = self.yHandles.find('**/y-disc')
self.zHandles = self.find('**/Z')
self.zPostGroup = self.zHandles.find('**/z-post-group')
self.zPostCollision = self.zHandles.find('**/z-post')
self.zRingGroup = self.zHandles.find('**/z-ring-group')
self.zRingCollision = self.zHandles.find('**/z-ring')
self.zDiscGroup = self.zHandles.find('**/z-disc-group')
self.zDisc = self.zHandles.find('**/z-disc-visible')
self.zDiscCollision = self.zHandles.find('**/z-disc')
# Adjust visiblity, colors, and transparency
self.xPostCollision.hide()
self.xRingCollision.hide()
self.xDisc.setColor(1,0,0,.2)
self.yPostCollision.hide()
self.yRingCollision.hide()
self.yDisc.setColor(0,1,0,.2)
self.zPostCollision.hide()
self.zRingCollision.hide()
self.zDisc.setColor(0,0,1,.2)
# Augment geometry with lines
self.createObjectHandleLines()
# Create long markers to help line up in world
self.createGuideLines()
self.hideGuides()
# Start with widget handles hidden
self.fActive = 1
self.toggleWidget()
# Make sure object handles are never lit or drawn in wireframe
useDirectRenderStyle(self)
def coaModeColor(self):
self.setColor(.5,.5,.5,1)
def manipModeColor(self):
self.clearColor()
def toggleWidget(self):
if self.fActive:
self.deactivate()
else:
self.activate()
def activate(self):
self.scalingNode.reparentTo(self)
self.fActive = 1
def deactivate(self):
self.scalingNode.reparentTo(hidden)
self.fActive = 0
def showWidgetIfActive(self):
if self.fActive:
self.reparentTo(SEditor.group)
def showWidget(self):
self.reparentTo(SEditor.group)
def hideWidget(self):
self.reparentTo(hidden)
def enableHandles(self, handles):
if type(handles) == types.ListType:
for handle in handles:
self.enableHandle(handle)
elif handles == 'x':
self.enableHandles(['x-post','x-ring','x-disc'])
elif handles == 'y':
self.enableHandles(['y-post','y-ring','y-disc'])
elif handles == 'z':
self.enableHandles(['z-post','z-ring','z-disc'])
elif handles == 'post':
self.enableHandles(['x-post','y-post','z-post'])
elif handles == 'ring':
self.enableHandles(['x-ring','y-ring','z-ring'])
elif handles == 'disc':
self.enableHandles(['x-disc','y-disc','z-disc'])
elif handles == 'all':
self.enableHandles(['x-post','x-ring','x-disc',
'y-post','y-ring','y-disc',
'z-post','z-ring','z-disc'])
def enableHandle(self, handle):
if handle == 'x-post':
self.xPostGroup.reparentTo(self.xHandles)
elif handle == 'x-ring':
self.xRingGroup.reparentTo(self.xHandles)
elif handle == 'x-disc':
self.xDiscGroup.reparentTo(self.xHandles)
if handle == 'y-post':
self.yPostGroup.reparentTo(self.yHandles)
elif handle == 'y-ring':
self.yRingGroup.reparentTo(self.yHandles)
elif handle == 'y-disc':
self.yDiscGroup.reparentTo(self.yHandles)
if handle == 'z-post':
self.zPostGroup.reparentTo(self.zHandles)
elif handle == 'z-ring':
self.zRingGroup.reparentTo(self.zHandles)
elif handle == 'z-disc':
self.zDiscGroup.reparentTo(self.zHandles)
def disableHandles(self, handles):
if type(handles) == types.ListType:
for handle in handles:
self.disableHandle(handle)
elif handles == 'x':
self.disableHandles(['x-post','x-ring','x-disc'])
elif handles == 'y':
self.disableHandles(['y-post','y-ring','y-disc'])
elif handles == 'z':
self.disableHandles(['z-post','z-ring','z-disc'])
elif handles == 'post':
self.disableHandles(['x-post','y-post','z-post'])
elif handles == 'ring':
self.disableHandles(['x-ring','y-ring','z-ring'])
elif handles == 'disc':
self.disableHandles(['x-disc','y-disc','z-disc'])
elif handles == 'all':
self.disableHandles(['x-post','x-ring','x-disc',
'y-post','y-ring','y-disc',
'z-post','z-ring','z-disc'])
def disableHandle(self, handle):
if handle == 'x-post':
self.xPostGroup.reparentTo(hidden)
elif handle == 'x-ring':
self.xRingGroup.reparentTo(hidden)
elif handle == 'x-disc':
self.xDiscGroup.reparentTo(hidden)
if handle == 'y-post':
self.yPostGroup.reparentTo(hidden)
elif handle == 'y-ring':
self.yRingGroup.reparentTo(hidden)
elif handle == 'y-disc':
self.yDiscGroup.reparentTo(hidden)
if handle == 'z-post':
self.zPostGroup.reparentTo(hidden)
elif handle == 'z-ring':
self.zRingGroup.reparentTo(hidden)
elif handle == 'z-disc':
self.zDiscGroup.reparentTo(hidden)
def showAllHandles(self):
self.xPost.show()
self.xRing.show()
self.xDisc.show()
self.yPost.show()
self.yRing.show()
self.yDisc.show()
self.zPost.show()
self.zRing.show()
self.zDisc.show()
def hideAllHandles(self):
self.xPost.hide()
self.xRing.hide()
self.xDisc.hide()
self.yPost.hide()
self.yRing.hide()
self.yDisc.hide()
self.zPost.hide()
self.zRing.hide()
self.zDisc.hide()
def showHandle(self, handle):
if handle == 'x-post':
self.xPost.show()
elif handle == 'x-ring':
self.xRing.show()
elif handle == 'x-disc':
self.xDisc.show()
elif handle == 'y-post':
self.yPost.show()
elif handle == 'y-ring':
self.yRing.show()
elif handle == 'y-disc':
self.yDisc.show()
elif handle == 'z-post':
self.zPost.show()
elif handle == 'z-ring':
self.zRing.show()
elif handle == 'z-disc':
self.zDisc.show()
def showGuides(self):
self.guideLines.show()
def hideGuides(self):
self.guideLines.hide()
def setScalingFactor(self, scaleFactor):
self.ohScalingFactor = scaleFactor
self.scalingNode.setScale(self.ohScalingFactor)
def getScalingFactor(self):
return self.scalingNode.getScale()
def transferObjectHandlesScale(self):
# see how much object handles have been scaled
ohs = self.getScale()
sns = self.scalingNode.getScale()
# Transfer this to the scaling node
self.scalingNode.setScale(
ohs[0] * sns[0],
ohs[1] * sns[1],
ohs[2] * sns[2])
self.setScale(1)
def multiplyScalingFactorBy(self, factor):
taskMgr.remove('resizeObjectHandles')
sf = self.ohScalingFactor = self.ohScalingFactor * factor
self.scalingNode.lerpScale(sf,sf,sf, 0.5,
blendType = 'easeInOut',
task = 'resizeObjectHandles')
def growToFit(self):
taskMgr.remove('resizeObjectHandles')
# Increase handles scale until they cover 80% of the min dimension
# Originally, here is "cover 30% of the min dimension", we changed.
pos = SEditor.widget.getPos(SEditor.camera)
minDim = min(SEditor.dr.nearWidth, SEditor.dr.nearHeight)
sf = 0.4 * minDim * (pos[1]/SEditor.dr.near)
self.ohScalingFactor = sf
self.scalingNode.lerpScale(sf,sf,sf, 0.5,
blendType = 'easeInOut',
task = 'resizeObjectHandles')
def createObjectHandleLines(self):
# X post
self.xPost = self.xPostGroup.attachNewNode('x-post-visible')
lines = LineNodePath(self.xPost)
lines.setColor(VBase4(1,0,0,1))
lines.setThickness(5)
lines.moveTo(0,0,0)
lines.drawTo(1.5,0,0)
lines.create()
lines = LineNodePath(self.xPost)
lines.setColor(VBase4(1,0,0,1))
lines.setThickness(1.5)
lines.moveTo(0,0,0)
lines.drawTo(-1.5,0,0)
lines.create()
# X ring
self.xRing = self.xRingGroup.attachNewNode('x-ring-visible')
lines = LineNodePath(self.xRing)
lines.setColor(VBase4(1,0,0,1))
lines.setThickness(3)
lines.moveTo(0,1,0)
for ang in range(15, 370, 15):
lines.drawTo(0,
math.cos(deg2Rad(ang)),
math.sin(deg2Rad(ang)))
lines.create()
# Y post
self.yPost = self.yPostGroup.attachNewNode('y-post-visible')
lines = LineNodePath(self.yPost)
lines.setColor(VBase4(0,1,0,1))
lines.setThickness(5)
lines.moveTo(0,0,0)
lines.drawTo(0,1.5,0)
lines.create()
lines = LineNodePath(self.yPost)
lines.setColor(VBase4(0,1,0,1))
lines.setThickness(1.5)
lines.moveTo(0,0,0)
lines.drawTo(0,-1.5,0)
lines.create()
# Y ring
self.yRing = self.yRingGroup.attachNewNode('y-ring-visible')
lines = LineNodePath(self.yRing)
lines.setColor(VBase4(0,1,0,1))
lines.setThickness(3)
lines.moveTo(1,0,0)
for ang in range(15, 370, 15):
lines.drawTo(math.cos(deg2Rad(ang)),
0,
math.sin(deg2Rad(ang)))
lines.create()
# Z post
self.zPost = self.zPostGroup.attachNewNode('z-post-visible')
lines = LineNodePath(self.zPost)
lines.setColor(VBase4(0,0,1,1))
lines.setThickness(5)
lines.moveTo(0,0,0)
lines.drawTo(0,0,1.5)
lines.create()
lines = LineNodePath(self.zPost)
lines.setColor(VBase4(0,0,1,1))
lines.setThickness(1.5)
lines.moveTo(0,0,0)
lines.drawTo(0,0,-1.5)
lines.create()
# Z ring
self.zRing = self.zRingGroup.attachNewNode('z-ring-visible')
lines = LineNodePath(self.zRing)
lines.setColor(VBase4(0,0,1,1))
lines.setThickness(3)
lines.moveTo(1,0,0)
for ang in range(15, 370, 15):
lines.drawTo(math.cos(deg2Rad(ang)),
math.sin(deg2Rad(ang)),
0)
lines.create()
def createGuideLines(self):
self.guideLines = self.attachNewNode('guideLines')
# X guide lines
lines = LineNodePath(self.guideLines)
lines.setColor(VBase4(1,0,0,1))
lines.setThickness(0.5)
lines.moveTo(-500,0,0)
lines.drawTo(500,0,0)
lines.create()
lines.setName('x-guide')
# Y guide lines
lines = LineNodePath(self.guideLines)
lines.setColor(VBase4(0,1,0,1))
lines.setThickness(0.5)
lines.moveTo(0,-500,0)
lines.drawTo(0,500,0)
lines.create()
lines.setName('y-guide')
# Z guide lines
lines = LineNodePath(self.guideLines)
lines.setColor(VBase4(0,0,1,1))
lines.setThickness(0.5)
lines.moveTo(0,0,-500)
lines.drawTo(0,0,500)
lines.create()
lines.setName('z-guide')
def getAxisIntersectPt(self, axis):
# Calc the xfrom from camera to widget
mCam2Widget = SEditor.camera.getMat(SEditor.widget)
lineDir = Vec3(mCam2Widget.xformVec(SEditor.dr.nearVec))
lineDir.normalize()
# And determine where the viewpoint is relative to widget
lineOrigin = VBase3(0)
decomposeMatrix(mCam2Widget, VBase3(0), VBase3(0), lineOrigin,
CSDefault)
# Now see where this hits the plane containing the 1D motion axis.
# Pick the intersection plane most normal to the intersection ray
# by comparing lineDir with plane normals. The plane with the
# largest dotProduct is most "normal"
if axis == 'x':
if (abs(lineDir.dot(Y_AXIS)) > abs(lineDir.dot(Z_AXIS))):
self.hitPt.assign(
planeIntersect(lineOrigin, lineDir, ORIGIN, Y_AXIS))
else:
self.hitPt.assign(
planeIntersect(lineOrigin, lineDir, ORIGIN, Z_AXIS))
# We really only care about the nearest point on the axis
self.hitPt.setY(0)
self.hitPt.setZ(0)
elif axis == 'y':
if (abs(lineDir.dot(X_AXIS)) > abs(lineDir.dot(Z_AXIS))):
self.hitPt.assign(
planeIntersect(lineOrigin, lineDir, ORIGIN, X_AXIS))
else:
self.hitPt.assign(
planeIntersect(lineOrigin, lineDir, ORIGIN, Z_AXIS))
# We really only care about the nearest point on the axis
self.hitPt.setX(0)
self.hitPt.setZ(0)
elif axis == 'z':
if (abs(lineDir.dot(X_AXIS)) > abs(lineDir.dot(Y_AXIS))):
self.hitPt.assign(
planeIntersect(lineOrigin, lineDir, ORIGIN, X_AXIS))
else:
self.hitPt.assign(
planeIntersect(lineOrigin, lineDir, ORIGIN, Y_AXIS))
# We really only care about the nearest point on the axis
self.hitPt.setX(0)
self.hitPt.setY(0)
return self.hitPt
def getWidgetIntersectPt(self, nodePath, plane):
# Find out the point of interection of the ray passing though the mouse
# with the plane containing the 2D xlation or 1D rotation widgets
# Calc the xfrom from camera to the nodePath
mCam2NodePath = SEditor.camera.getMat(nodePath)
# And determine where the viewpoint is relative to widget
lineOrigin = VBase3(0)
decomposeMatrix(mCam2NodePath, VBase3(0), VBase3(0), lineOrigin,
CSDefault)
# Next we find the vector from viewpoint to the widget through
# the mouse's position on near plane.
# This defines the intersection ray
lineDir = Vec3(mCam2NodePath.xformVec(SEditor.dr.nearVec))
lineDir.normalize()
# Find the hit point
if plane == 'x':
self.hitPt.assign(planeIntersect(
lineOrigin, lineDir, ORIGIN, X_AXIS))
elif plane == 'y':
self.hitPt.assign(planeIntersect(
lineOrigin, lineDir, ORIGIN, Y_AXIS))
elif plane == 'z':
self.hitPt.assign(planeIntersect(
lineOrigin, lineDir, ORIGIN, Z_AXIS))
return self.hitPt

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,267 @@
from PandaModules import *
import seParticles
import seForceGroup
import DirectNotifyGlobal
class ParticleEffect(NodePath):
notify = DirectNotifyGlobal.directNotify.newCategory('ParticleEffect')
pid = 1
def __init__(self, name=None, particles=None):
"""__init__()"""
if (name == None):
name = 'particle-effect-%d' % ParticleEffect.pid
ParticleEffect.pid += 1
NodePath.__init__(self, name)
# Record particle effect name
self.name = name
# Enabled flag
self.fEnabled = 0
# Dictionary of particles and forceGroups
self.particlesDict = {}
self.forceGroupDict = {}
# The effect's particle system
if (particles != None):
self.addParticles(particles)
self.renderParent = None
def start(self, parent=None, renderParent=None):
assert(self.notify.debug('start() - name: %s' % self.name))
self.renderParent = renderParent
self.enable()
if (parent != None):
self.reparentTo(parent)
def cleanup(self):
self.removeNode()
self.disable()
for f in self.forceGroupDict.values():
f.cleanup()
for p in self.particlesDict.values():
p.cleanup()
del self.renderParent
del self.particlesDict
del self.forceGroupDict
def reset(self):
self.removeAllForces()
self.removeAllParticles()
self.forceGroupDict = {}
self.particlesDict = {}
def enable(self):
"""enable()"""
if (self.renderParent != None):
for p in self.particlesDict.values():
p.setRenderParent(self.renderParent.node())
for f in self.forceGroupDict.values():
f.enable()
for p in self.particlesDict.values():
p.enable()
self.fEnabled = 1
def disable(self):
"""disable()"""
self.detachNode()
for p in self.particlesDict.values():
p.setRenderParent(p.node)
for f in self.forceGroupDict.values():
f.disable()
for p in self.particlesDict.values():
p.disable()
self.fEnabled = 0
def isEnabled(self):
"""
isEnabled()
Note: this may be misleading if enable(),disable() not used
"""
return self.fEnabled
def addForceGroup(self, forceGroup):
"""addForceGroup(forceGroup)"""
forceGroup.nodePath.reparentTo(self)
forceGroup.particleEffect = self
self.forceGroupDict[forceGroup.getName()] = forceGroup
# Associate the force group with all particles
for i in range(len(forceGroup)):
self.addForce(forceGroup[i])
def addForce(self, force):
"""addForce(force)"""
for p in self.particlesDict.values():
p.addForce(force)
def removeForceGroup(self, forceGroup):
"""removeForceGroup(forceGroup)"""
# Remove forces from all particles
for i in range(len(forceGroup)):
self.removeForce(forceGroup[i])
forceGroup.nodePath.removeNode()
forceGroup.particleEffect = None
del self.forceGroupDict[forceGroup.getName()]
def removeForce(self, force):
"""removeForce(force)"""
for p in self.particlesDict.values():
p.removeForce(force)
def removeAllForces(self):
for fg in self.forceGroupDict.values():
self.removeForceGroup(fg)
def addParticles(self, particles):
"""addParticles(particles)"""
particles.nodePath.reparentTo(self)
self.particlesDict[particles.getName()] = particles
# Associate all forces in all force groups with the particles
for fg in self.forceGroupDict.values():
for i in range(len(fg)):
particles.addForce(fg[i])
def removeParticles(self, particles):
"""removeParticles(particles)"""
if (particles == None):
self.notify.warning('removeParticles() - particles == None!')
return
particles.nodePath.detachNode()
del self.particlesDict[particles.getName()]
# Remove all forces from the particles
for fg in self.forceGroupDict.values():
for f in fg.asList():
particles.removeForce(f)
def removeAllParticles(self):
for p in self.particlesDict.values():
self.removeParticles(p)
def getParticlesList(self):
"""getParticles()"""
return self.particlesDict.values()
def getParticlesNamed(self, name):
"""getParticlesNamed(name)"""
return self.particlesDict.get(name, None)
def getParticlesDict(self):
"""getParticlesDict()"""
return self.particlesDict
def getForceGroupList(self):
"""getForceGroup()"""
return self.forceGroupDict.values()
def getForceGroupNamed(self, name):
"""getForceGroupNamed(name)"""
return self.forceGroupDict.get(name, None)
def getForceGroupDict(self):
"""getForceGroup()"""
return self.forceGroupDict
def saveConfig(self, filename):
"""saveFileData(filename)"""
f = open(filename.toOsSpecific(), 'wb')
# Add a blank line
f.write('\n')
# Make sure we start with a clean slate
f.write('self.reset()\n')
pos = self.getPos()
hpr = self.getHpr()
scale = self.getScale()
f.write('self.setPos(%0.3f, %0.3f, %0.3f)\n' %
(pos[0], pos[1], pos[2]))
f.write('self.setHpr(%0.3f, %0.3f, %0.3f)\n' %
(hpr[0], hpr[1], hpr[2]))
f.write('self.setScale(%0.3f, %0.3f, %0.3f)\n' %
(scale[0], scale[1], scale[2]))
# Save all the particles to file
num = 0
for p in self.particlesDict.values():
target = 'p%d' % num
num = num + 1
f.write(target + ' = Particles.Particles(\'%s\')\n' % p.getName())
p.printParams(f, target)
f.write('self.addParticles(%s)\n' % target)
# Save all the forces to file
num = 0
for fg in self.forceGroupDict.values():
target = 'f%d' % num
num = num + 1
f.write(target + ' = ForceGroup.ForceGroup(\'%s\')\n' % \
fg.getName())
fg.printParams(f, target)
f.write('self.addForceGroup(%s)\n' % target)
# Close the file
f.close()
def loadConfig(self, filename):
"""loadConfig(filename)"""
#try:
# if vfs:
print vfs.readFile(filename)
exec vfs.readFile(filename)
print "Particle Effect Reading using VFS"
# else:
# execfile(filename.toOsSpecific())
# print "Shouldnt be wrong"
#except:
# self.notify.error('loadConfig: failed to load particle file: '+ repr(filename))
def AppendConfig(self, f):
f.write('\n')
i1=" "
i2=i1+i1
# Make sure we start with a clean slate
f.write(i2+'self.effect.reset()\n')
pos = self.getPos()
hpr = self.getHpr()
scale = self.getScale()
f.write(i2+'self.effect.setPos(%0.3f, %0.3f, %0.3f)\n' %
(pos[0], pos[1], pos[2]))
f.write(i2+'self.effect.setHpr(%0.3f, %0.3f, %0.3f)\n' %
(hpr[0], hpr[1], hpr[2]))
f.write(i2+'self.effect.setScale(%0.3f, %0.3f, %0.3f)\n' %
(scale[0], scale[1], scale[2]))
# Save all the particles to file
num = 0
for p in self.particlesDict.values():
target = 'p%d' % num
num = num + 1
f.write(i2+"if(mode==0):\n")
f.write(i2+i1+target + ' = seParticles.Particles(\'%s\')\n' % p.getName())
f.write(i2+"else:\n")
f.write(i2+i1+target + ' = Particles.Particles(\'%s\')\n' % p.getName())
p.printParams(f, target)
f.write(i2+'self.effect.addParticles(%s)\n' % target)
# Save all the forces to file
num = 0
for fg in self.forceGroupDict.values():
target = 'f%d' % num
num = num + 1
f.write(i2+target + ' = ForceGroup.ForceGroup(\'%s\')\n' % \
fg.getName())
fg.printParams(f, target)
f.write(i2+'self.effect.addForceGroup(%s)\n' % target)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,449 @@
from PandaModules import *
from ParticleManagerGlobal import *
from PhysicsManagerGlobal import *
import ParticleSystem
import BaseParticleFactory
import PointParticleFactory
import ZSpinParticleFactory
#import OrientedParticleFactory
import BaseParticleRenderer
import PointParticleRenderer
import LineParticleRenderer
import GeomParticleRenderer
import SparkleParticleRenderer
import SpriteParticleRenderer
import BaseParticleEmitter
import BoxEmitter
import DiscEmitter
import LineEmitter
import PointEmitter
import RectangleEmitter
import RingEmitter
import SphereSurfaceEmitter
import SphereVolumeEmitter
import TangentRingEmitter
import string
import os
import DirectNotifyGlobal
import sys
class Particles(ParticleSystem.ParticleSystem):
notify = DirectNotifyGlobal.directNotify.newCategory('Particles')
id = 1
def __init__(self, name=None, poolSize=1024):
"""__init__(name, poolSize)"""
if (name == None):
self.name = 'particles-%d' % Particles.id
Particles.id += 1
else:
self.name = name
ParticleSystem.ParticleSystem.__init__(self, poolSize)
# self.setBirthRate(0.02)
# self.setLitterSize(10)
# self.setLitterSpread(0)
# Set up a physical node
self.node = PhysicalNode(self.name)
self.nodePath = NodePath(self.node)
self.setRenderParent(self.node)
self.node.addPhysical(self)
self.factory = None
self.factoryType = "undefined"
# self.setFactory("PointParticleFactory")
self.renderer = None
self.rendererType = "undefined"
# self.setRenderer("PointParticleRenderer")
self.emitter = None
self.emitterType = "undefined"
# self.setEmitter("SphereVolumeEmitter")
# Enable particles by default
self.fEnabled = 0
#self.enable()
def cleanup(self):
self.disable()
self.clearLinearForces()
self.clearAngularForces()
self.setRenderParent(self.node)
self.node.removePhysical(self)
self.nodePath.removeNode()
del self.node
del self.nodePath
del self.factory
del self.renderer
del self.emitter
def enable(self):
"""enable()"""
if (self.fEnabled == 0):
physicsMgr.attachPhysical(self)
particleMgr.attachParticlesystem(self)
self.fEnabled = 1
def disable(self):
"""disable()"""
if (self.fEnabled == 1):
physicsMgr.removePhysical(self)
particleMgr.removeParticlesystem(self)
self.fEnabled = 0
def isEnabled(self):
return self.fEnabled
def getNode(self):
return self.node
def setFactory(self, type):
"""setFactory(type)"""
if (self.factoryType == type):
return None
if (self.factory):
self.factory = None
self.factoryType = type
if (type == "PointParticleFactory"):
self.factory = PointParticleFactory.PointParticleFactory()
elif (type == "ZSpinParticleFactory"):
self.factory = ZSpinParticleFactory.ZSpinParticleFactory()
elif (type == "OrientedParticleFactory"):
self.factory = OrientedParticleFactory.OrientedParticleFactory()
else:
print "unknown factory type: %s" % type
return None
self.factory.setLifespanBase(0.5)
ParticleSystem.ParticleSystem.setFactory(self, self.factory)
def setRenderer(self, type):
"""setRenderer(type)"""
if (self.rendererType == type):
return None
if (self.renderer):
self.renderer = None
self.rendererType = type
if (type == "PointParticleRenderer"):
self.renderer = PointParticleRenderer.PointParticleRenderer()
self.renderer.setPointSize(1.0)
elif (type == "LineParticleRenderer"):
self.renderer = LineParticleRenderer.LineParticleRenderer()
elif (type == "GeomParticleRenderer"):
self.renderer = GeomParticleRenderer.GeomParticleRenderer()
npath = NodePath('default-geom')
# This was moved here because we do not want to download
# the direct tools with toontown.
import DirectSelection
bbox = DirectSelection.DirectBoundingBox(npath)
self.renderer.setGeomNode(bbox.lines.node())
elif (type == "SparkleParticleRenderer"):
self.renderer = SparkleParticleRenderer.SparkleParticleRenderer()
elif (type == "SpriteParticleRenderer"):
self.renderer = SpriteParticleRenderer.SpriteParticleRenderer()
if (self.renderer.getSourceType() ==
SpriteParticleRenderer.SpriteParticleRenderer.STTexture):
# Use current default texture
# See sourceTextureName SpriteParticleRenderer-extensions.py
self.renderer.setTextureFromFile()
else:
# Use current default model file and node
# See sourceFileName and sourceNodeName in SpriteParticleRenderer-extensions.py
self.renderer.setTextureFromNode()
else:
print "unknown renderer type: %s" % type
return None
ParticleSystem.ParticleSystem.setRenderer(self, self.renderer)
def setEmitter(self, type):
"""setEmitter(type)"""
if (self.emitterType == type):
return None
if (self.emitter):
self.emitter = None
self.emitterType = type
if (type == "BoxEmitter"):
self.emitter = BoxEmitter.BoxEmitter()
elif (type == "DiscEmitter"):
self.emitter = DiscEmitter.DiscEmitter()
elif (type == "LineEmitter"):
self.emitter = LineEmitter.LineEmitter()
elif (type == "PointEmitter"):
self.emitter = PointEmitter.PointEmitter()
elif (type == "RectangleEmitter"):
self.emitter = RectangleEmitter.RectangleEmitter()
elif (type == "RingEmitter"):
self.emitter = RingEmitter.RingEmitter()
elif (type == "SphereSurfaceEmitter"):
self.emitter = SphereSurfaceEmitter.SphereSurfaceEmitter()
elif (type == "SphereVolumeEmitter"):
self.emitter = SphereVolumeEmitter.SphereVolumeEmitter()
self.emitter.setRadius(1.0)
elif (type == "TangentRingEmitter"):
self.emitter = TangentRingEmitter.TangentRingEmitter()
else:
print "unknown emitter type: %s" % type
return None
ParticleSystem.ParticleSystem.setEmitter(self, self.emitter)
def addForce(self, force):
"""addForce(force)"""
if (force.isLinear()):
self.addLinearForce(force)
else:
self.addAngularForce(force)
def removeForce(self, force):
"""removeForce(force)"""
if (force == None):
self.notify.warning('removeForce() - force == None!')
return
if (force.isLinear()):
self.removeLinearForce(force)
else:
self.removeAngularForce(force)
def setRenderNodePath(self, nodePath):
self.setRenderParent(nodePath.node())
## Getters ##
def getName(self):
"""getName()"""
return self.name
def getFactory(self):
"""getFactory()"""
return self.factory
def getEmitter(self):
"""getEmitter()"""
return self.emitter
def getRenderer(self):
"""getRenderer()"""
return self.renderer
def printParams(self, file = sys.stdout, targ = 'self'):
"""printParams(file, targ)"""
i1=" "
i2=i1+i1
file.write(i2+'# Particles parameters\n')
file.write(i2+targ + '.setFactory(\"' + self.factoryType + '\")\n')
file.write(i2+targ + '.setRenderer(\"' + self.rendererType + '\")\n')
file.write(i2+targ + '.setEmitter(\"' + self.emitterType + '\")\n')
# System parameters
file.write(i2+targ + ('.setPoolSize(%d)\n' %
int(self.getPoolSize())))
file.write(i2+targ + ('.setBirthRate(%.4f)\n' %
self.getBirthRate()))
file.write(i2+targ + ('.setLitterSize(%d)\n' %
int(self.getLitterSize())))
file.write(i2+targ + ('.setLitterSpread(%d)\n' %
self.getLitterSpread()))
file.write(i2+targ + ('.setSystemLifespan(%.4f)\n' %
self.getSystemLifespan()))
file.write(i2+targ + ('.setLocalVelocityFlag(%d)\n' %
self.getLocalVelocityFlag()))
file.write(i2+targ + ('.setSystemGrowsOlderFlag(%d)\n' %
self.getSystemGrowsOlderFlag()))
file.write(i2+'# Factory parameters\n')
file.write(i2+targ + ('.factory.setLifespanBase(%.4f)\n' %
self.factory.getLifespanBase()))
file.write(i2+targ + '.factory.setLifespanSpread(%.4f)\n' % \
self.factory.getLifespanSpread())
file.write(i2+targ + '.factory.setMassBase(%.4f)\n' % \
self.factory.getMassBase())
file.write(i2+targ + '.factory.setMassSpread(%.4f)\n' % \
self.factory.getMassSpread())
file.write(i2+targ + '.factory.setTerminalVelocityBase(%.4f)\n' % \
self.factory.getTerminalVelocityBase())
file.write(i2+targ + '.factory.setTerminalVelocitySpread(%.4f)\n' % \
self.factory.getTerminalVelocitySpread())
if (self.factoryType == "PointParticleFactory"):
file.write(i2+'# Point factory parameters\n')
elif (self.factoryType == "ZSpinParticleFactory"):
file.write(i2+'# Z Spin factory parameters\n')
file.write(i2+targ + '.factory.setInitialAngle(%.4f)\n' % \
self.factory.getInitialAngle())
file.write(i2+targ + '.factory.setInitialAngleSpread(%.4f)\n' % \
self.factory.getInitialAngleSpread())
file.write(i2+targ + '.factory.enableAngularVelocity(%d)\n' % \
self.factory.getAngularVelocityEnabled())
if(self.factory.getAngularVelocityEnabled()):
file.write(i2+targ + '.factory.setAngularVelocity(%.4f)\n' % \
self.factory.getAngularVelocity())
file.write(i2+targ + '.factory.setAngularVelocitySpread(%.4f)\n' % \
self.factory.getAngularVelocitySpread())
else:
file.write(i2+targ + '.factory.setFinalAngle(%.4f)\n' % \
self.factory.getFinalAngle())
file.write(i2+targ + '.factory.setFinalAngleSpread(%.4f)\n' % \
self.factory.getFinalAngleSpread())
elif (self.factoryType == "OrientedParticleFactory"):
file.write(i2+'# Oriented factory parameters\n')
file.write(i2+targ + '.factory.setInitialOrientation(%.4f)\n' % \
self.factory.getInitialOrientation())
file.write(i2+targ + '.factory.setFinalOrientation(%.4f)\n' % \
self.factory.getFinalOrientation())
file.write(i2+'# Renderer parameters\n')
alphaMode = self.renderer.getAlphaMode()
aMode = "PRALPHANONE"
if (alphaMode == BaseParticleRenderer.BaseParticleRenderer.PRALPHANONE):
aMode = "PRALPHANONE"
elif (alphaMode ==
BaseParticleRenderer.BaseParticleRenderer.PRALPHAOUT):
aMode = "PRALPHAOUT"
elif (alphaMode ==
BaseParticleRenderer.BaseParticleRenderer.PRALPHAIN):
aMode = "PRALPHAIN"
elif (alphaMode ==
BaseParticleRenderer.BaseParticleRenderer.PRALPHAUSER):
aMode = "PRALPHAUSER"
file.write(i2+targ + '.renderer.setAlphaMode(BaseParticleRenderer.' + aMode + ')\n')
file.write(i2+targ + '.renderer.setUserAlpha(%.2f)\n' % \
self.renderer.getUserAlpha())
if (self.rendererType == "PointParticleRenderer"):
file.write(i2+'# Point parameters\n')
file.write(i2+targ + '.renderer.setPointSize(%.2f)\n' % \
self.renderer.getPointSize())
sColor = self.renderer.getStartColor()
file.write(i2+(targ + '.renderer.setStartColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3])))
sColor = self.renderer.getEndColor()
file.write(i2+(targ + '.renderer.setEndColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3])))
blendType = self.renderer.getBlendType()
bType = "PPONECOLOR"
if (blendType == PointParticleRenderer.PointParticleRenderer.PPONECOLOR):
bType = "PPONECOLOR"
elif (blendType == PointParticleRenderer.PointParticleRenderer.PPBLENDLIFE):
bType = "PPBLENDLIFE"
elif (blendType == PointParticleRenderer.PointParticleRenderer.PPBLENDVEL):
bType = "PPBLENDVEL"
file.write(i2+targ + '.renderer.setBlendType(PointParticleRenderer.' + bType + ')\n')
blendMethod = self.renderer.getBlendMethod()
bMethod = "PPNOBLEND"
if (blendMethod == BaseParticleRenderer.BaseParticleRenderer.PPNOBLEND):
bMethod = "PPNOBLEND"
elif (blendMethod == BaseParticleRenderer.BaseParticleRenderer.PPBLENDLINEAR):
bMethod = "PPBLENDLINEAR"
elif (blendMethod == BaseParticleRenderer.BaseParticleRenderer.PPBLENDCUBIC):
bMethod = "PPBLENDCUBIC"
file.write(i2+targ + '.renderer.setBlendMethod(BaseParticleRenderer.' + bMethod + ')\n')
elif (self.rendererType == "LineParticleRenderer"):
file.write(i2+'# Line parameters\n')
sColor = self.renderer.getHeadColor()
file.write(i2+(targ + '.renderer.setHeadColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3])))
sColor = self.renderer.getTailColor()
file.write(i2+(targ + '.renderer.setTailColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3])))
elif (self.rendererType == "GeomParticleRenderer"):
file.write(i2+'# Geom parameters\n')
node = self.renderer.getGeomNode()
file.write(i2+targ + '.renderer.setGeomNode(' + node.getName() + ')\n')
elif (self.rendererType == "SparkleParticleRenderer"):
file.write(i2+'# Sparkle parameters\n')
sColor = self.renderer.getCenterColor()
file.write(i2+(targ + '.renderer.setCenterColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3])))
sColor = self.renderer.getEdgeColor()
file.write(i2+(targ + '.renderer.setEdgeColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3])))
file.write(i2+targ + '.renderer.setBirthRadius(%.4f)\n' % self.renderer.getBirthRadius())
file.write(i2+targ + '.renderer.setDeathRadius(%.4f)\n' % self.renderer.getDeathRadius())
lifeScale = self.renderer.getLifeScale()
lScale = "SPNOSCALE"
if (lifeScale == SparkleParticleRenderer.SparkleParticleRenderer.SPSCALE):
lScale = "SPSCALE"
file.write(i2+targ + '.renderer.setLifeScale(SparkleParticleRenderer.' + lScale + ')\n')
elif (self.rendererType == "SpriteParticleRenderer"):
file.write(i2+'# Sprite parameters\n')
if (self.renderer.getSourceType() ==
SpriteParticleRenderer.SpriteParticleRenderer.STTexture):
tex = self.renderer.getTexture()
file.write(i2+targ + '.renderer.setTexture(loader.loadTexture(\'' + tex.getFilename().getFullpath() + '\'))\n')
else:
modelName = self.renderer.getSourceFileName()
nodeName = self.renderer.getSourceNodeName()
file.write(i2+targ + '.renderer.setTextureFromNode("%s", "%s")\n' % (modelName, nodeName))
sColor = self.renderer.getColor()
file.write(i2+(targ + '.renderer.setColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3])))
file.write(i2+targ + '.renderer.setXScaleFlag(%d)\n' % self.renderer.getXScaleFlag())
file.write(i2+targ + '.renderer.setYScaleFlag(%d)\n' % self.renderer.getYScaleFlag())
file.write(i2+targ + '.renderer.setAnimAngleFlag(%d)\n' % self.renderer.getAnimAngleFlag())
file.write(i2+targ + '.renderer.setInitialXScale(%.4f)\n' % self.renderer.getInitialXScale())
file.write(i2+targ + '.renderer.setFinalXScale(%.4f)\n' % self.renderer.getFinalXScale())
file.write(i2+targ + '.renderer.setInitialYScale(%.4f)\n' % self.renderer.getInitialYScale())
file.write(i2+targ + '.renderer.setFinalYScale(%.4f)\n' % self.renderer.getFinalYScale())
file.write(i2+targ + '.renderer.setNonanimatedTheta(%.4f)\n' % self.renderer.getNonanimatedTheta())
blendMethod = self.renderer.getAlphaBlendMethod()
bMethod = "PPNOBLEND"
if (blendMethod == BaseParticleRenderer.BaseParticleRenderer.PPNOBLEND):
bMethod = "PPNOBLEND"
elif (blendMethod == BaseParticleRenderer.BaseParticleRenderer.PPBLENDLINEAR):
bMethod = "PPBLENDLINEAR"
elif (blendMethod == BaseParticleRenderer.BaseParticleRenderer.PPBLENDCUBIC):
bMethod = "PPBLENDCUBIC"
file.write(i2+targ + '.renderer.setAlphaBlendMethod(BaseParticleRenderer.' + bMethod + ')\n')
file.write(i2+targ + '.renderer.setAlphaDisable(%d)\n' % self.renderer.getAlphaDisable())
file.write(i2+'# Emitter parameters\n')
emissionType = self.emitter.getEmissionType()
eType = "ETEXPLICIT"
if (emissionType == BaseParticleEmitter.BaseParticleEmitter.ETEXPLICIT):
eType = "ETEXPLICIT"
elif (emissionType == BaseParticleEmitter.BaseParticleEmitter.ETRADIATE):
eType = "ETRADIATE"
elif (emissionType == BaseParticleEmitter.BaseParticleEmitter.ETCUSTOM):
eType = "ETCUSTOM"
file.write(i2+targ + '.emitter.setEmissionType(BaseParticleEmitter.' + eType + ')\n')
file.write(i2+targ + '.emitter.setAmplitude(%.4f)\n' % self.emitter.getAmplitude())
file.write(i2+targ + '.emitter.setAmplitudeSpread(%.4f)\n' % self.emitter.getAmplitudeSpread())
oForce = self.emitter.getOffsetForce()
file.write(i2+(targ + '.emitter.setOffsetForce(Vec3(%.4f, %.4f, %.4f))\n' % (oForce[0], oForce[1], oForce[2])))
oForce = self.emitter.getExplicitLaunchVector()
file.write(i2+(targ + '.emitter.setExplicitLaunchVector(Vec3(%.4f, %.4f, %.4f))\n' % (oForce[0], oForce[1], oForce[2])))
orig = self.emitter.getRadiateOrigin()
file.write(i2+(targ + '.emitter.setRadiateOrigin(Point3(%.4f, %.4f, %.4f))\n' % (orig[0], orig[1], orig[2])))
if (self.emitterType == "BoxEmitter"):
file.write(i2+'# Box parameters\n')
bound = self.emitter.getMinBound()
file.write(i2+(targ + '.emitter.setMinBound(Point3(%.4f, %.4f, %.4f))\n' % (bound[0], bound[1], bound[2])))
bound = self.emitter.getMaxBound()
file.write(i2+(targ + '.emitter.setMaxBound(Point3(%.4f, %.4f, %.4f))\n' % (bound[0], bound[1], bound[2])))
elif (self.emitterType == "DiscEmitter"):
file.write(i2+'# Disc parameters\n')
file.write(i2+targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius())
if (eType == "ETCUSTOM"):
file.write(i2+targ + '.emitter.setOuterAngle(%.4f)\n' % self.emitter.getOuterAngle())
file.write(i2+targ + '.emitter.setInnerAngle(%.4f)\n' % self.emitter.getInnerAngle())
file.write(i2+targ + '.emitter.setOuterMagnitude(%.4f)\n' % self.emitter.getOuterMagnitude())
file.write(i2+targ + '.emitter.setInnerMagnitude(%.4f)\n' % self.emitter.getInnerMagnitude())
file.write(i2+targ + '.emitter.setCubicLerping(%d)\n' % self.emitter.getCubicLerping())
elif (self.emitterType == "LineEmitter"):
file.write(i2+'# Line parameters\n')
point = self.emitter.getEndpoint1()
file.write(i2+(targ + '.emitter.setEndpoint1(Point3(%.4f, %.4f, %.4f))\n' % (point[0], point[1], point[2])))
point = self.emitter.getEndpoint2()
file.write(i2+(targ + '.emitter.setEndpoint2(Point3(%.4f, %.4f, %.4f))\n' % (point[0], point[1], point[2])))
elif (self.emitterType == "PointEmitter"):
file.write(i2+'# Point parameters\n')
point = self.emitter.getLocation()
file.write(i2+(targ + '.emitter.setLocation(Point3(%.4f, %.4f, %.4f))\n' % (point[0], point[1], point[2])))
elif (self.emitterType == "RectangleEmitter"):
file.write(i2+'# Rectangle parameters\n')
point = self.emitter.getMinBound()
file.write(i2+(targ + '.emitter.setMinBound(Point2(%.4f, %.4f))\n' % (point[0], point[1])))
point = self.emitter.getMaxBound()
file.write(i2+(targ + '.emitter.setMaxBound(Point2(%.4f, %.4f))\n' % (point[0], point[1])))
elif (self.emitterType == "RingEmitter"):
file.write(i2+'# Ring parameters\n')
file.write(i2+targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius())
if (eType == "ETCUSTOM"):
file.write(i2+targ + '.emitter.setAngle(%.4f)\n' % self.emitter.getAngle())
elif (self.emitterType == "SphereSurfaceEmitter"):
file.write(i2+'# Sphere Surface parameters\n')
file.write(i2+targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius())
elif (self.emitterType == "SphereVolumeEmitter"):
file.write(i2+'# Sphere Volume parameters\n')
file.write(i2+targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius())
elif (self.emitterType == "TangentRingEmitter"):
file.write(i2+'# Tangent Ring parameters\n')
file.write(i2+targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius())

799
doc/SceneEditor/sePlacer.py Normal file
View File

@ -0,0 +1,799 @@
""" DIRECT Nine DoF Manipulation Panel """
# Import Tkinter, Pmw, and the dial code from this directory tree.
from PandaObject import *
from DirectGlobals import *
from TkGlobal import *
from AppShell import *
import Dial
import Floater
"""
TODO:
Task to monitor pose
"""
class Placer(AppShell):
# Override class variables here
appname = 'Placer Panel'
frameWidth = 625
frameHeight = 215
usecommandarea = 0
usestatusarea = 0
def __init__(self, parent = None, **kw):
INITOPT = Pmw.INITOPT
optiondefs = (
('title', self.appname, None),
('nodePath', SEditor.camera, None),
)
self.defineoptions(kw, optiondefs)
# Call superclass initialization function
AppShell.__init__(self)
self.initialiseoptions(Placer)
# Accept the message from sceneEditor to update the information about the target nodePath
self.accept('placerUpdate', self.updatePlacer)
def appInit(self):
# Initialize state
self.tempCS = SEditor.group.attachNewNode('placerTempCS')
self.orbitFromCS = SEditor.group.attachNewNode(
'placerOrbitFromCS')
self.orbitToCS = SEditor.group.attachNewNode('placerOrbitToCS')
self.refCS = self.tempCS
# Dictionary keeping track of all node paths manipulated so far
self.nodePathDict = {}
self.nodePathDict['camera'] = SEditor.camera
self.nodePathDict['widget'] = SEditor.widget
self.nodePathNames = ['camera', 'widget', 'selected']
self.refNodePathDict = {}
self.refNodePathDict['parent'] = self['nodePath'].getParent()
self.refNodePathDict['render'] = render
self.refNodePathDict['camera'] = SEditor.camera
self.refNodePathDict['widget'] = SEditor.widget
self.refNodePathNames = ['parent', 'self', 'render',
'camera', 'widget', 'selected']
# Initial state
self.initPos = Vec3(0)
self.initHpr = Vec3(0)
self.initScale = Vec3(1)
self.deltaHpr = Vec3(0)
# Offset for orbital mode
self.posOffset = Vec3(0)
# Set up event hooks
self.undoEvents = [('DIRECT_undo', self.undoHook),
('DIRECT_pushUndo', self.pushUndoHook),
('DIRECT_undoListEmpty', self.undoListEmptyHook),
('DIRECT_redo', self.redoHook),
('DIRECT_pushRedo', self.pushRedoHook),
('DIRECT_redoListEmpty', self.redoListEmptyHook)]
for event, method in self.undoEvents:
self.accept(event, method)
# Init movement mode
self.movementMode = 'Relative To:'
def createInterface(self):
# The interior of the toplevel panel
interior = self.interior()
interior['relief'] = FLAT
# Add placer commands to menubar
self.menuBar.addmenu('Placer', 'Placer Panel Operations')
self.menuBar.addmenuitem('Placer', 'command',
'Zero Node Path',
label = 'Zero All',
command = self.zeroAll)
self.menuBar.addmenuitem('Placer', 'command',
'Reset Node Path',
label = 'Reset All',
command = self.resetAll)
self.menuBar.addmenuitem('Placer', 'command',
'Print Node Path Info',
label = 'Print Info',
command = self.printNodePathInfo)
self.menuBar.addmenuitem(
'Placer', 'command',
'Toggle widget visability',
label = 'Toggle Widget Vis',
command = SEditor.toggleWidgetVis)
self.menuBar.addmenuitem(
'Placer', 'command',
'Toggle widget manipulation mode',
label = 'Toggle Widget Mode',
command = SEditor.manipulationControl.toggleObjectHandlesMode)
# Get a handle to the menu frame
menuFrame = self.menuFrame
self.nodePathMenu = Pmw.ComboBox(
menuFrame, labelpos = W, label_text = 'Node Path:',
entry_width = 20,
selectioncommand = self.selectNodePathNamed,
scrolledlist_items = self.nodePathNames)
self.nodePathMenu.selectitem('selected')
self.nodePathMenuEntry = (
self.nodePathMenu.component('entryfield_entry'))
self.nodePathMenuBG = (
self.nodePathMenuEntry.configure('background')[3])
self.nodePathMenu.pack(side = 'left', fill = 'x', expand = 1)
self.bind(self.nodePathMenu, 'Select node path to manipulate')
modeMenu = Pmw.OptionMenu(menuFrame,
items = ('Relative To:',
'Orbit:'),
initialitem = 'Relative To:',
command = self.setMovementMode,
menubutton_width = 8)
modeMenu.pack(side = 'left', expand = 0)
self.bind(modeMenu, 'Select manipulation mode')
self.refNodePathMenu = Pmw.ComboBox(
menuFrame, entry_width = 16,
selectioncommand = self.selectRefNodePathNamed,
scrolledlist_items = self.refNodePathNames)
self.refNodePathMenu.selectitem('parent')
self.refNodePathMenuEntry = (
self.refNodePathMenu.component('entryfield_entry'))
self.refNodePathMenu.pack(side = 'left', fill = 'x', expand = 1)
self.bind(self.refNodePathMenu, 'Select relative node path')
self.undoButton = Button(menuFrame, text = 'Undo',
command = SEditor.undo)
if SEditor.undoList:
self.undoButton['state'] = 'normal'
else:
self.undoButton['state'] = 'disabled'
self.undoButton.pack(side = 'left', expand = 0)
self.bind(self.undoButton, 'Undo last operation')
self.redoButton = Button(menuFrame, text = 'Redo',
command = SEditor.redo)
if SEditor.redoList:
self.redoButton['state'] = 'normal'
else:
self.redoButton['state'] = 'disabled'
self.redoButton.pack(side = 'left', expand = 0)
self.bind(self.redoButton, 'Redo last operation')
# Create and pack the Pos Controls
posGroup = Pmw.Group(interior,
tag_pyclass = Menubutton,
tag_text = 'Position',
tag_font=('MSSansSerif', 14),
tag_activebackground = '#909090',
ring_relief = RIDGE)
posMenubutton = posGroup.component('tag')
self.bind(posMenubutton, 'Position menu operations')
posMenu = Menu(posMenubutton, tearoff = 0)
posMenu.add_command(label = 'Set to zero', command = self.zeroPos)
posMenu.add_command(label = 'Reset initial',
command = self.resetPos)
posMenubutton['menu'] = posMenu
posGroup.pack(side='left', fill = 'both', expand = 1)
posInterior = posGroup.interior()
# Create the dials
self.posX = self.createcomponent('posX', (), None,
Floater.Floater, (posInterior,),
text = 'X', relief = FLAT,
value = 0.0,
label_foreground = 'Red')
self.posX['commandData'] = ['x']
self.posX['preCallback'] = self.xformStart
self.posX['postCallback'] = self.xformStop
self.posX['callbackData'] = ['x']
self.posX.pack(expand=1,fill='both')
self.posY = self.createcomponent('posY', (), None,
Floater.Floater, (posInterior,),
text = 'Y', relief = FLAT,
value = 0.0,
label_foreground = '#00A000')
self.posY['commandData'] = ['y']
self.posY['preCallback'] = self.xformStart
self.posY['postCallback'] = self.xformStop
self.posY['callbackData'] = ['y']
self.posY.pack(expand=1,fill='both')
self.posZ = self.createcomponent('posZ', (), None,
Floater.Floater, (posInterior,),
text = 'Z', relief = FLAT,
value = 0.0,
label_foreground = 'Blue')
self.posZ['commandData'] = ['z']
self.posZ['preCallback'] = self.xformStart
self.posZ['postCallback'] = self.xformStop
self.posZ['callbackData'] = ['z']
self.posZ.pack(expand=1,fill='both')
# Create and pack the Hpr Controls
hprGroup = Pmw.Group(interior,
tag_pyclass = Menubutton,
tag_text = 'Orientation',
tag_font=('MSSansSerif', 14),
tag_activebackground = '#909090',
ring_relief = RIDGE)
hprMenubutton = hprGroup.component('tag')
self.bind(hprMenubutton, 'Orientation menu operations')
hprMenu = Menu(hprMenubutton, tearoff = 0)
hprMenu.add_command(label = 'Set to zero', command = self.zeroHpr)
hprMenu.add_command(label = 'Reset initial', command = self.resetHpr)
hprMenubutton['menu'] = hprMenu
hprGroup.pack(side='left',fill = 'both', expand = 1)
hprInterior = hprGroup.interior()
# Create the dials
self.hprH = self.createcomponent('hprH', (), None,
Dial.AngleDial, (hprInterior,),
style = 'mini',
text = 'H', value = 0.0,
relief = FLAT,
label_foreground = 'blue')
self.hprH['commandData'] = ['h']
self.hprH['preCallback'] = self.xformStart
self.hprH['postCallback'] = self.xformStop
self.hprH['callbackData'] = ['h']
self.hprH.pack(expand=1,fill='both')
self.hprP = self.createcomponent('hprP', (), None,
Dial.AngleDial, (hprInterior,),
style = 'mini',
text = 'P', value = 0.0,
relief = FLAT,
label_foreground = 'red')
self.hprP['commandData'] = ['p']
self.hprP['preCallback'] = self.xformStart
self.hprP['postCallback'] = self.xformStop
self.hprP['callbackData'] = ['p']
self.hprP.pack(expand=1,fill='both')
self.hprR = self.createcomponent('hprR', (), None,
Dial.AngleDial, (hprInterior,),
style = 'mini',
text = 'R', value = 0.0,
relief = FLAT,
label_foreground = '#00A000')
self.hprR['commandData'] = ['r']
self.hprR['preCallback'] = self.xformStart
self.hprR['postCallback'] = self.xformStop
self.hprR['callbackData'] = ['r']
self.hprR.pack(expand=1,fill='both')
# Create and pack the Scale Controls
# The available scaling modes
self.scalingMode = StringVar()
self.scalingMode.set('Scale Uniform')
# The scaling widgets
scaleGroup = Pmw.Group(interior,
tag_text = 'Scale Uniform',
tag_pyclass = Menubutton,
tag_font=('MSSansSerif', 14),
tag_activebackground = '#909090',
ring_relief = RIDGE)
self.scaleMenubutton = scaleGroup.component('tag')
self.bind(self.scaleMenubutton, 'Scale menu operations')
self.scaleMenubutton['textvariable'] = self.scalingMode
# Scaling menu
scaleMenu = Menu(self.scaleMenubutton, tearoff = 0)
scaleMenu.add_command(label = 'Set to unity',
command = self.unitScale)
scaleMenu.add_command(label = 'Reset initial',
command = self.resetScale)
scaleMenu.add_radiobutton(label = 'Scale Free',
variable = self.scalingMode)
scaleMenu.add_radiobutton(label = 'Scale Uniform',
variable = self.scalingMode)
scaleMenu.add_radiobutton(label = 'Scale Proportional',
variable = self.scalingMode)
self.scaleMenubutton['menu'] = scaleMenu
# Pack group widgets
scaleGroup.pack(side='left',fill = 'both', expand = 1)
scaleInterior = scaleGroup.interior()
# Create the dials
self.scaleX = self.createcomponent('scaleX', (), None,
Floater.Floater, (scaleInterior,),
text = 'X Scale',
relief = FLAT,
min = 0.0001, value = 1.0,
resetValue = 1.0,
label_foreground = 'Red')
self.scaleX['commandData'] = ['sx']
self.scaleX['callbackData'] = ['sx']
self.scaleX['preCallback'] = self.xformStart
self.scaleX['postCallback'] = self.xformStop
self.scaleX.pack(expand=1,fill='both')
self.scaleY = self.createcomponent('scaleY', (), None,
Floater.Floater, (scaleInterior,),
text = 'Y Scale',
relief = FLAT,
min = 0.0001, value = 1.0,
resetValue = 1.0,
label_foreground = '#00A000')
self.scaleY['commandData'] = ['sy']
self.scaleY['callbackData'] = ['sy']
self.scaleY['preCallback'] = self.xformStart
self.scaleY['postCallback'] = self.xformStop
self.scaleY.pack(expand=1,fill='both')
self.scaleZ = self.createcomponent('scaleZ', (), None,
Floater.Floater, (scaleInterior,),
text = 'Z Scale',
relief = FLAT,
min = 0.0001, value = 1.0,
resetValue = 1.0,
label_foreground = 'Blue')
self.scaleZ['commandData'] = ['sz']
self.scaleZ['callbackData'] = ['sz']
self.scaleZ['preCallback'] = self.xformStart
self.scaleZ['postCallback'] = self.xformStop
self.scaleZ.pack(expand=1,fill='both')
# Make sure appropriate labels are showing
self.setMovementMode('Relative To:')
# Set up placer for inital node path
self.selectNodePathNamed('init')
self.selectRefNodePathNamed('parent')
# Update place to reflect initial state
self.updatePlacer()
# Now that you're done setting up, attach commands
self.posX['command'] = self.xform
self.posY['command'] = self.xform
self.posZ['command'] = self.xform
self.hprH['command'] = self.xform
self.hprP['command'] = self.xform
self.hprR['command'] = self.xform
self.scaleX['command'] = self.xform
self.scaleY['command'] = self.xform
self.scaleZ['command'] = self.xform
### WIDGET OPERATIONS ###
def setMovementMode(self, movementMode):
# Set prefix
namePrefix = ''
self.movementMode = movementMode
if (movementMode == 'Relative To:'):
namePrefix = 'Relative '
elif (movementMode == 'Orbit:'):
namePrefix = 'Orbit '
# Update pos widgets
self.posX['text'] = namePrefix + 'X'
self.posY['text'] = namePrefix + 'Y'
self.posZ['text'] = namePrefix + 'Z'
# Update hpr widgets
if (movementMode == 'Orbit:'):
namePrefix = 'Orbit delta '
self.hprH['text'] = namePrefix + 'H'
self.hprP['text'] = namePrefix + 'P'
self.hprR['text'] = namePrefix + 'R'
# Update temp cs and initialize widgets
self.updatePlacer()
def setScalingMode(self):
if self['nodePath']:
scale = self['nodePath'].getScale()
if ((scale[0] != scale[1]) or
(scale[0] != scale[2]) or
(scale[1] != scale[2])):
self.scalingMode.set('Scale Free')
def selectNodePathNamed(self, name):
nodePath = None
if name == 'init':
nodePath = self['nodePath']
# Add Combo box entry for the initial node path
self.addNodePath(nodePath)
elif name == 'selected':
nodePath = SEditor.selected.last
# Add Combo box entry for this selected object
self.addNodePath(nodePath)
else:
nodePath = self.nodePathDict.get(name, None)
if (nodePath == None):
# See if this evaluates into a node path
try:
nodePath = eval(name)
if isinstance(nodePath, NodePath):
self.addNodePath(nodePath)
else:
# Good eval but not a node path, give up
nodePath = None
except:
# Bogus eval
nodePath = None
# Clear bogus entry from listbox
listbox = self.nodePathMenu.component('scrolledlist')
listbox.setlist(self.nodePathNames)
else:
if name == 'widget':
# Record relationship between selected nodes and widget
SEditor.selected.getWrtAll()
# Update active node path
self.setActiveNodePath(nodePath)
def setActiveNodePath(self, nodePath):
self['nodePath'] = nodePath
if self['nodePath']:
self.nodePathMenuEntry.configure(
background = self.nodePathMenuBG)
# Check to see if node path and ref node path are the same
if ((self.refCS != None) and
(self.refCS.id() == self['nodePath'].id())):
# Yes they are, use temp CS as ref
# This calls updatePlacer
self.setReferenceNodePath(self.tempCS)
# update listbox accordingly
self.refNodePathMenu.selectitem('parent')
else:
# Record initial value and initialize the widgets
self.updatePlacer()
# Record initial position
self.updateResetValues(self['nodePath'])
# Set scaling mode based on node path's current scale
self.setScalingMode()
else:
# Flash entry
self.nodePathMenuEntry.configure(background = 'Pink')
def selectRefNodePathNamed(self, name):
nodePath = None
if name == 'self':
nodePath = self.tempCS
elif name == 'selected':
nodePath = SEditor.selected.last
# Add Combo box entry for this selected object
self.addRefNodePath(nodePath)
elif name == 'parent':
nodePath = self['nodePath'].getParent()
else:
nodePath = self.refNodePathDict.get(name, None)
if (nodePath == None):
# See if this evaluates into a node path
try:
nodePath = eval(name)
if isinstance(nodePath, NodePath):
self.addRefNodePath(nodePath)
else:
# Good eval but not a node path, give up
nodePath = None
except:
# Bogus eval
nodePath = None
# Clear bogus entry from listbox
listbox = self.refNodePathMenu.component('scrolledlist')
listbox.setlist(self.refNodePathNames)
# Check to see if node path and ref node path are the same
if (nodePath != None) and (nodePath.id() == self['nodePath'].id()):
# Yes they are, use temp CS and update listbox accordingly
nodePath = self.tempCS
self.refNodePathMenu.selectitem('parent')
# Update ref node path
self.setReferenceNodePath(nodePath)
def setReferenceNodePath(self, nodePath):
self.refCS = nodePath
if self.refCS:
self.refNodePathMenuEntry.configure(
background = self.nodePathMenuBG)
# Update placer to reflect new state
self.updatePlacer()
else:
# Flash entry
self.refNodePathMenuEntry.configure(background = 'Pink')
def addNodePath(self, nodePath):
self.addNodePathToDict(nodePath, self.nodePathNames,
self.nodePathMenu, self.nodePathDict)
def addRefNodePath(self, nodePath):
self.addNodePathToDict(nodePath, self.refNodePathNames,
self.refNodePathMenu, self.refNodePathDict)
def addNodePathToDict(self, nodePath, names, menu, dict):
if not nodePath:
return
# Get node path's name
name = nodePath.getName()
if name in ['parent', 'render', 'camera']:
dictName = name
else:
# Generate a unique name for the dict
dictName = name + '-' + `nodePath.id()`
if not dict.has_key(dictName):
# Update combo box to include new item
names.append(dictName)
listbox = menu.component('scrolledlist')
listbox.setlist(names)
# Add new item to dictionary
dict[dictName] = nodePath
menu.selectitem(dictName)
def updatePlacer(self):
pos = Vec3(0)
hpr = Vec3(0)
scale = Vec3(1)
np = self['nodePath']
if (np != None) and isinstance(np, NodePath):
# Update temp CS
self.updateAuxiliaryCoordinateSystems()
# Update widgets
if self.movementMode == 'Orbit:':
pos.assign(self.posOffset)
hpr.assign(ZERO_VEC)
scale.assign(np.getScale())
elif self.refCS:
pos.assign(np.getPos(self.refCS))
hpr.assign(np.getHpr(self.refCS))
scale.assign(np.getScale())
self.updatePosWidgets(pos)
self.updateHprWidgets(hpr)
self.updateScaleWidgets(scale)
def updateAuxiliaryCoordinateSystems(self):
# Temp CS
self.tempCS.setPosHpr(self['nodePath'], 0,0,0,0,0,0)
# Orbit CS
# At reference
self.orbitFromCS.setPos(self.refCS, 0,0,0)
# But aligned with target
self.orbitFromCS.setHpr(self['nodePath'], 0,0,0)
# Also update to CS
self.orbitToCS.setPosHpr(self.orbitFromCS, 0,0,0,0,0,0)
# Get offset from origin
self.posOffset.assign(self['nodePath'].getPos(self.orbitFromCS))
### NODE PATH TRANSFORMATION OPERATIONS ###
def xform(self, value, axis):
if axis in ['sx', 'sy', 'sz']:
self.xformScale(value,axis)
elif self.movementMode == 'Relative To:':
self.xformRelative(value, axis)
elif self.movementMode == 'Orbit:':
self.xformOrbit(value, axis)
if self.nodePathMenu.get() == 'widget':
if SEditor.manipulationControl.fSetCoa:
# Update coa based on current widget position
SEditor.selected.last.mCoa2Dnp.assign(
SEditor.widget.getMat(SEditor.selected.last))
else:
# Move the objects with the widget
SEditor.selected.moveWrtWidgetAll()
def xformStart(self, data):
# Record undo point
self.pushUndo()
# If moving widget kill follow task and update wrts
if self.nodePathMenu.get() == 'widget':
taskMgr.remove('followSelectedNodePath')
# Record relationship between selected nodes and widget
SEditor.selected.getWrtAll()
# Record initial state
self.deltaHpr = self['nodePath'].getHpr(self.refCS)
# Update placer to reflect new state
self.updatePlacer()
def xformStop(self, data):
# Throw event to signal manipulation done
# Send nodepath as a list
messenger.send('DIRECT_manipulateObjectCleanup', [[self['nodePath']]])
# Update placer to reflect new state
self.updatePlacer()
# If moving widget restart follow task
if self.nodePathMenu.get() == 'widget':
# Restart followSelectedNodePath task
SEditor.manipulationControl.spawnFollowSelectedNodePathTask()
def xformRelative(self, value, axis):
nodePath = self['nodePath']
if (nodePath != None) and (self.refCS != None):
if axis == 'x':
nodePath.setX(self.refCS, value)
elif axis == 'y':
nodePath.setY(self.refCS, value)
elif axis == 'z':
nodePath.setZ(self.refCS, value)
else:
if axis == 'h':
self.deltaHpr.setX(value)
elif axis == 'p':
self.deltaHpr.setY(value)
elif axis == 'r':
self.deltaHpr.setZ(value)
# Put node path at new hpr
nodePath.setHpr(self.refCS, self.deltaHpr)
def xformOrbit(self, value, axis):
nodePath = self['nodePath']
if ((nodePath != None) and (self.refCS != None) and
(self.orbitFromCS != None) and (self.orbitToCS != None)):
if axis == 'x':
self.posOffset.setX(value)
elif axis == 'y':
self.posOffset.setY(value)
elif axis == 'z':
self.posOffset.setZ(value)
elif axis == 'h':
self.orbitToCS.setH(self.orbitFromCS, value)
elif axis == 'p':
self.orbitToCS.setP(self.orbitFromCS, value)
elif axis == 'r':
self.orbitToCS.setR(self.orbitFromCS, value)
nodePath.setPosHpr(self.orbitToCS, self.posOffset, ZERO_VEC)
def xformScale(self, value, axis):
if self['nodePath']:
mode = self.scalingMode.get()
scale = self['nodePath'].getScale()
if mode == 'Scale Free':
if axis == 'sx':
scale.setX(value)
elif axis == 'sy':
scale.setY(value)
elif axis == 'sz':
scale.setZ(value)
elif mode == 'Scale Uniform':
scale.set(value,value,value)
elif mode == 'Scale Proportional':
if axis == 'sx':
sf = value/scale[0]
elif axis == 'sy':
sf = value/scale[1]
elif axis == 'sz':
sf = value/scale[2]
scale = scale * sf
self['nodePath'].setScale(scale)
def updatePosWidgets(self, pos):
self.posX.set(pos[0])
self.posY.set(pos[1])
self.posZ.set(pos[2])
def updateHprWidgets(self, hpr):
self.hprH.set(hpr[0])
self.hprP.set(hpr[1])
self.hprR.set(hpr[2])
def updateScaleWidgets(self, scale):
self.scaleX.set(scale[0])
self.scaleY.set(scale[1])
self.scaleZ.set(scale[2])
def zeroAll(self):
self.xformStart(None)
self.updatePosWidgets(ZERO_VEC)
self.updateHprWidgets(ZERO_VEC)
self.updateScaleWidgets(UNIT_VEC)
self.xformStop(None)
def zeroPos(self):
self.xformStart(None)
self.updatePosWidgets(ZERO_VEC)
self.xformStop(None)
def zeroHpr(self):
self.xformStart(None)
self.updateHprWidgets(ZERO_VEC)
self.xformStop(None)
def unitScale(self):
self.xformStart(None)
self.updateScaleWidgets(UNIT_VEC)
self.xformStop(None)
def updateResetValues(self, nodePath):
self.initPos.assign(nodePath.getPos())
self.posX['resetValue'] = self.initPos[0]
self.posY['resetValue'] = self.initPos[1]
self.posZ['resetValue'] = self.initPos[2]
self.initHpr.assign(nodePath.getHpr())
self.hprH['resetValue'] = self.initHpr[0]
self.hprP['resetValue'] = self.initHpr[1]
self.hprR['resetValue'] = self.initHpr[2]
self.initScale.assign(nodePath.getScale())
self.scaleX['resetValue'] = self.initScale[0]
self.scaleY['resetValue'] = self.initScale[1]
self.scaleZ['resetValue'] = self.initScale[2]
def resetAll(self):
if self['nodePath']:
self.xformStart(None)
self['nodePath'].setPosHprScale(
self.initPos, self.initHpr, self.initScale)
self.xformStop(None)
def resetPos(self):
if self['nodePath']:
self.xformStart(None)
self['nodePath'].setPos(self.initPos)
self.xformStop(None)
def resetHpr(self):
if self['nodePath']:
self.xformStart(None)
self['nodePath'].setHpr(self.initHpr)
self.xformStop(None)
def resetScale(self):
if self['nodePath']:
self.xformStart(None)
self['nodePath'].setScale(self.initScale)
self.xformStop(None)
def pushUndo(self, fResetRedo = 1):
SEditor.pushUndo([self['nodePath']])
def undoHook(self, nodePathList = []):
# Reflect new changes
self.updatePlacer()
def pushUndoHook(self):
# Make sure button is reactivated
self.undoButton.configure(state = 'normal')
def undoListEmptyHook(self):
# Make sure button is deactivated
self.undoButton.configure(state = 'disabled')
def pushRedo(self):
SEditor.pushRedo([self['nodePath']])
def redoHook(self, nodePathList = []):
# Reflect new changes
self.updatePlacer()
def pushRedoHook(self):
# Make sure button is reactivated
self.redoButton.configure(state = 'normal')
def redoListEmptyHook(self):
# Make sure button is deactivated
self.redoButton.configure(state = 'disabled')
def printNodePathInfo(self):
np = self['nodePath']
if np:
name = np.getName()
pos = np.getPos()
hpr = np.getHpr()
scale = np.getScale()
posString = '%.2f, %.2f, %.2f' % (pos[0], pos[1], pos[2])
hprString = '%.2f, %.2f, %.2f' % (hpr[0], hpr[1], hpr[2])
scaleString = '%.2f, %.2f, %.2f' % (scale[0], scale[1], scale[2])
print 'NodePath: %s' % name
print 'Pos: %s' % posString
print 'Hpr: %s' % hprString
print 'Scale: %s' % scaleString
print ('%s.setPosHprScale(%s, %s, %s)' %
(name, posString, hprString, scaleString))
def onDestroy(self, event):
# Remove hooks
for event, method in self.undoEvents:
self.ignore(event)
self.tempCS.removeNode()
self.orbitFromCS.removeNode()
self.orbitToCS.removeNode()
# send out a message to let sceneEditor know that placer panel has been closed.
# Also, stop accepting the updata message from sceneEditor
messenger.send('Placer_close')
self.ignore('placerUpdate')
def place(nodePath):
return Placer(nodePath = nodePath)
######################################################################
# Create demo in root window for testing.
if __name__ == '__main__':
root = Pmw.initialise()
widget = Placer()

View File

@ -0,0 +1,208 @@
#################################################################
# seSceneGraphExplorer.py
# Originally from SceneGraphExplorer.py
# Altered by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#
# we need a customized SceneGraphExplorer.
#
# Do forget to check the seTree.
#
#################################################################
from PandaObject import *
from TkGlobal import *
from seTree import *
# changing these strings requires changing sceneEditor.py SGE_ strs too!
# This list of items will be showed on the pop out window when user right click on
# any node on the graph. And, this is also the main reason we decide to copy from
# the original one but not inherited from it.
# Because except drawing part, we have changed a lot of things...
DEFAULT_MENU_ITEMS = [
'Update Explorer',
'Separator',
'Properties',
'Separator',
'Duplicate',
'Remove',
'Add Dummy',
'Add Collision Object',
'Metadata',
'Separator',
'Set as Reparent Target',
'Reparent to Target',
'Separator',
'Animation Panel',
'Blend Animation Panel',
'MoPath Panel',
'Align Tool',
'Separator']
class seSceneGraphExplorer(Pmw.MegaWidget, PandaObject):
"Graphical display of a scene graph"
def __init__(self, parent = None, nodePath = render, **kw):
# Define the megawidget options.
optiondefs = (
('menuItems', [], Pmw.INITOPT),
)
self.defineoptions(kw, optiondefs)
# Initialise superclass
Pmw.MegaWidget.__init__(self, parent)
# Initialize some class variables
self.nodePath = nodePath
# Create the components.
# Setup up container
interior = self.interior()
interior.configure(relief = GROOVE, borderwidth = 2)
# Create a label and an entry
self._scrolledCanvas = self.createcomponent(
'scrolledCanvas',
(), None,
Pmw.ScrolledCanvas, (interior,),
hull_width = 200, hull_height = 300,
usehullsize = 1)
self._canvas = self._scrolledCanvas.component('canvas')
self._canvas['scrollregion'] = ('0i', '0i', '2i', '4i')
self._scrolledCanvas.resizescrollregion()
self._scrolledCanvas.pack(padx = 3, pady = 3, expand=1, fill = BOTH)
self._canvas.bind('<ButtonPress-2>', self.mouse2Down)
self._canvas.bind('<B2-Motion>', self.mouse2Motion)
self._canvas.bind('<Configure>',
lambda e, sc = self._scrolledCanvas:
sc.resizescrollregion())
self.interior().bind('<Destroy>', self.onDestroy)
# Create the contents
self._treeItem = SceneGraphExplorerItem(self.nodePath)
self._node = TreeNode(self._canvas, None, self._treeItem,
DEFAULT_MENU_ITEMS + self['menuItems'])
self._node.expand()
self._parentFrame = Frame(interior)
self._label = self.createcomponent(
'parentLabel',
(), None,
Label, (interior,),
text = 'Active Reparent Target: ',
anchor = W, justify = LEFT)
self._label.pack(fill = X)
# Add update parent label
def updateLabel(nodePath = None, s = self):
s._label['text'] = 'Active Reparent Target: ' + nodePath.getName()
self.accept('DIRECT_activeParent', updateLabel)
# Add update hook
self.accept('SGE_Update Explorer',
lambda np, s = self: s.update())
# Check keywords and initialise options based on input values.
self.initialiseoptions(seSceneGraphExplorer)
def update(self):
""" Refresh scene graph explorer """
self._node.update()
def mouse2Down(self, event):
self._width = 1.0 * self._canvas.winfo_width()
self._height = 1.0 * self._canvas.winfo_height()
xview = self._canvas.xview()
yview = self._canvas.yview()
self._left = xview[0]
self._top = yview[0]
self._dxview = xview[1] - xview[0]
self._dyview = yview[1] - yview[0]
self._2lx = event.x
self._2ly = event.y
def mouse2Motion(self,event):
newx = self._left - ((event.x - self._2lx)/self._width) * self._dxview
self._canvas.xview_moveto(newx)
newy = self._top - ((event.y - self._2ly)/self._height) * self._dyview
self._canvas.yview_moveto(newy)
self._2lx = event.x
self._2ly = event.y
self._left = self._canvas.xview()[0]
self._top = self._canvas.yview()[0]
def onDestroy(self, event):
# Remove hooks
self.ignore('DIRECT_activeParent')
self.ignore('SGE_Update Explorer')
def deSelectTree(self):
self._node.deselecttree()
def selectNodePath(self,nodePath, callBack=True):
item = self._node.find(nodePath.id())
if item!= None:
item.select(callBack)
else:
print '----SGE: Error Selection'
class SceneGraphExplorerItem(TreeItem):
"""Example TreeItem subclass -- browse the file system."""
def __init__(self, nodePath):
self.nodePath = nodePath
def GetText(self):
type = self.nodePath.node().getType().getName()
name = self.nodePath.getName()
return type + " " + name
def GetTextForEdit(self):
name = self.nodePath.getName()
return name
def GetKey(self):
return self.nodePath.id()
def IsEditable(self):
# All nodes' names can be edited nowadays.
return 1
#return issubclass(self.nodePath.node().__class__, NamedNode)
def SetText(self, text):
try:
messenger.send('SGE_changeName', [self.nodePath, text])
except AttributeError:
pass
def GetIconName(self):
return "sphere2" # XXX wish there was a "file" icon
def IsExpandable(self):
return self.nodePath.getNumChildren() != 0
def GetSubList(self):
sublist = []
for nodePath in self.nodePath.getChildrenAsList():
item = SceneGraphExplorerItem(nodePath)
sublist.append(item)
return sublist
def OnSelect(self, callback):
messenger.send('SGE_Flash', [self.nodePath])
if not callback:
messenger.send('SGE_madeSelection', [self.nodePath, callback])
else:
messenger.send('SGE_madeSelection', [self.nodePath])
def MenuCommand(self, command):
messenger.send('SGE_' + command, [self.nodePath])
def explore(nodePath = render):
tl = Toplevel()
tl.title('Explore: ' + nodePath.getName())
sge = seSceneGraphExplorer(parent = tl, nodePath = nodePath)
sge.pack(expand = 1, fill = 'both')
return sge

View File

@ -0,0 +1,716 @@
#################################################################
# seSelection.py
# Originally from DirectSelection.py
# Altered by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#
# We didn't change anything essential.
# Just because we customized the seSession from DirectSession,
# So we need related files can follow the change.
# However, we don't want to change anything inside the original directool
# to let them can work with our scene editor.
# (If we do change original directools, it will force user has to install the latest version of OUR Panda)
#
#################################################################
from PandaObject import *
from DirectGlobals import *
from DirectUtil import *
from seGeometry import *
from quad import *
COA_ORIGIN = 0
COA_CENTER = 1
# MRM: To do: handle broken node paths in selected and deselected dicts
class DirectNodePath(NodePath):
# A node path augmented with info, bounding box, and utility methods
def __init__(self, nodePath):
# Initialize the superclass
NodePath.__init__(self)
self.assign(nodePath)
# Create a bounding box
self.bbox = DirectBoundingBox(self)
center = self.bbox.getCenter()
# Create matrix to hold the offset between the nodepath
# and its center of action (COA)
self.mCoa2Dnp = Mat4(Mat4.identMat())
if SEditor.coaMode == COA_CENTER:
self.mCoa2Dnp.setRow(3, Vec4(center[0], center[1], center[2], 1))
# Transform from nodePath to widget
self.tDnp2Widget = TransformState.makeIdentity()
def highlight(self):
self.bbox.show()
def dehighlight(self):
self.bbox.hide()
def getCenter(self):
return self.bbox.getCenter()
def getRadius(self):
return self.bbox.getRadius()
def getMin(self):
return self.bbox.getMin()
def getMax(self):
return self.bbox.getMax()
class SelectedNodePaths(PandaObject):
def __init__(self):
self.reset()
def reset(self):
self.selectedDict = {}
self.deselectedDict = {}
__builtins__["last"] = self.last = None
def select(self, nodePath, fMultiSelect = 0):
""" Select the specified node path. Multiselect as required """
# Do nothing if nothing selected
if not nodePath:
print 'Nothing selected!!'
return None
# Reset selected objects and highlight if multiSelect is false
if not fMultiSelect:
self.deselectAll()
# Get this pointer
id = nodePath.id()
# First see if its already in the selected dictionary
dnp = self.getSelectedDict(id)
# If so, we're done
if not dnp:
# See if it is in the deselected dictionary
dnp = self.getDeselectedDict(id)
if dnp:
# Remove it from the deselected dictionary
del(self.deselectedDict[id])
# Show its bounding box
dnp.highlight()
else:
# Didn't find it, create a new selectedNodePath instance
dnp = DirectNodePath(nodePath)
# Show its bounding box
dnp.highlight()
# Add it to the selected dictionary
self.selectedDict[dnp.id()] = dnp
# And update last
__builtins__["last"] = self.last = dnp
return dnp
def deselect(self, nodePath):
""" Deselect the specified node path """
# Get this pointer
id = nodePath.id()
# See if it is in the selected dictionary
dnp = self.getSelectedDict(id)
if dnp:
# It was selected:
# Hide its bounding box
dnp.dehighlight()
# Remove it from the selected dictionary
del(self.selectedDict[id])
# And keep track of it in the deselected dictionary
self.deselectedDict[id] = dnp
# Send a message
messenger.send('DIRECT_deselectedNodePath', [dnp])
return dnp
def getSelectedAsList(self):
"""
Return a list of all selected node paths. No verification of
connectivity is performed on the members of the list
"""
return self.selectedDict.values()[:]
def __getitem__(self,index):
return self.getSelectedAsList()[index]
def getSelectedDict(self, id):
"""
Search selectedDict for node path, try to repair broken node paths.
"""
dnp = self.selectedDict.get(id, None)
if dnp:
return dnp
else:
# Not in selected dictionary
return None
def getDeselectedAsList(self):
return self.deselectedDict.values()[:]
def getDeselectedDict(self, id):
"""
Search deselectedDict for node path, try to repair broken node paths.
"""
dnp = self.deselectedDict.get(id, None)
if dnp:
# Yes
return dnp
else:
# Not in deselected dictionary
return None
def forEachSelectedNodePathDo(self, func):
"""
Perform given func on selected node paths. No node path
connectivity verification performed
"""
selectedNodePaths = self.getSelectedAsList()
for nodePath in selectedNodePaths:
func(nodePath)
def forEachDeselectedNodePathDo(self, func):
"""
Perform given func on deselected node paths. No node path
connectivity verification performed
"""
deselectedNodePaths = self.getDeselectedAsList()
for nodePath in deselectedNodePaths:
func(nodePath)
def getWrtAll(self):
self.forEachSelectedNodePathDo(self.getWrt)
def getWrt(self, nodePath):
nodePath.tDnp2Widget = nodePath.getTransform(SEditor.widget)
def moveWrtWidgetAll(self):
self.forEachSelectedNodePathDo(self.moveWrtWidget)
def moveWrtWidget(self, nodePath):
nodePath.setTransform(SEditor.widget, nodePath.tDnp2Widget)
def deselectAll(self):
self.forEachSelectedNodePathDo(self.deselect)
def highlightAll(self):
self.forEachSelectedNodePathDo(DirectNodePath.highlight)
def dehighlightAll(self):
self.forEachSelectedNodePathDo(DirectNodePath.dehighlight)
def removeSelected(self):
selected = self.last
if selected:
selected.remove()
__builtins__["last"] = self.last = None
def removeAll(self):
# Remove all selected nodePaths from the Scene Graph
self.forEachSelectedNodePathDo(NodePath.remove)
def toggleVisSelected(self):
selected = self.last
# Toggle visibility of selected node paths
if selected:
selected.toggleVis()
def toggleVisAll(self):
# Toggle viz for all selected node paths
self.forEachSelectedNodePathDo(NodePath.toggleVis)
def isolateSelected(self):
selected = self.last
if selected:
selected.isolate()
def getDirectNodePath(self, nodePath):
# Get this pointer
id = nodePath.id()
# First check selected dict
dnp = self.getSelectedDict(id)
if dnp:
return dnp
# Otherwise return result of deselected search
return self.getDeselectedDict(id)
def getNumSelected(self):
return len(self.selectedDict.keys())
class DirectBoundingBox:
def __init__(self, nodePath):
# Record the node path
self.nodePath = nodePath
# Compute bounds, min, max, etc.
self.computeTightBounds()
# Generate the bounding box
self.lines = self.createBBoxLines()
def computeTightBounds(self):
# Compute bounding box using tighter calcTightBounds function
# Need to clear out existing transform on node path
tMat = Mat4()
tMat.assign(self.nodePath.getMat())
self.nodePath.clearMat()
# Get bounds
self.min = Point3(0)
self.max = Point3(0)
self.nodePath.calcTightBounds(self.min,self.max)
# Calc center and radius
self.center = Point3((self.min + self.max)/2.0)
self.radius = Vec3(self.max - self.min).length()
# Restore transform
self.nodePath.setMat(tMat)
del tMat
def computeBounds(self):
self.bounds = self.getBounds()
if self.bounds.isEmpty() or self.bounds.isInfinite():
self.center = Point3(0)
self.radius = 1.0
else:
self.center = self.bounds.getCenter()
self.radius = self.bounds.getRadius()
self.min = Point3(self.center - Point3(self.radius))
self.max = Point3(self.center + Point3(self.radius))
def createBBoxLines(self):
# Create a line segments object for the bbox
lines = LineNodePath(hidden)
lines.node().setName('bboxLines')
lines.setColor( VBase4( 1., 0., 0., 1. ) )
lines.setThickness( 0.5 )
minX = self.min[0]
minY = self.min[1]
minZ = self.min[2]
maxX = self.max[0]
maxY = self.max[1]
maxZ = self.max[2]
# Bottom face
lines.moveTo( minX, minY, minZ )
lines.drawTo( maxX, minY, minZ )
lines.drawTo( maxX, maxY, minZ )
lines.drawTo( minX, maxY, minZ )
lines.drawTo( minX, minY, minZ )
# Front Edge/Top face
lines.drawTo( minX, minY, maxZ )
lines.drawTo( maxX, minY, maxZ )
lines.drawTo( maxX, maxY, maxZ )
lines.drawTo( minX, maxY, maxZ )
lines.drawTo( minX, minY, maxZ )
# Three remaining edges
lines.moveTo( maxX, minY, minZ )
lines.drawTo( maxX, minY, maxZ )
lines.moveTo( maxX, maxY, minZ )
lines.drawTo( maxX, maxY, maxZ )
lines.moveTo( minX, maxY, minZ )
lines.drawTo( minX, maxY, maxZ )
# Create and return bbox lines
lines.create()
# Make sure bbox is never lit or drawn in wireframe
useDirectRenderStyle(lines)
return lines
def updateBBoxLines(self):
ls = self.lines.lineSegs
minX = self.min[0]
minY = self.min[1]
minZ = self.min[2]
maxX = self.max[0]
maxY = self.max[1]
maxZ = self.max[2]
# Bottom face
ls.setVertex( 0, minX, minY, minZ )
ls.setVertex( 1, maxX, minY, minZ )
ls.setVertex( 2, maxX, maxY, minZ )
ls.setVertex( 3, minX, maxY, minZ )
ls.setVertex( 4, minX, minY, minZ )
# Front Edge/Top face
ls.setVertex( 5, minX, minY, maxZ )
ls.setVertex( 6, maxX, minY, maxZ )
ls.setVertex( 7, maxX, maxY, maxZ )
ls.setVertex( 8, minX, maxY, maxZ )
ls.setVertex( 9, minX, minY, maxZ )
# Three remaining edges
ls.setVertex( 10, maxX, minY, minZ )
ls.setVertex( 11, maxX, minY, maxZ )
ls.setVertex( 12, maxX, maxY, minZ )
ls.setVertex( 13, maxX, maxY, maxZ )
ls.setVertex( 14, minX, maxY, minZ )
ls.setVertex( 15, minX, maxY, maxZ )
def getBounds(self):
# Get a node path's bounds
nodeBounds = BoundingSphere()
nodeBounds.extendBy(self.nodePath.node().getInternalBound())
for child in self.nodePath.getChildrenAsList():
nodeBounds.extendBy(child.getBounds())
return nodeBounds.makeCopy()
def show(self):
self.lines.reparentTo(self.nodePath)
def hide(self):
self.lines.reparentTo(hidden)
def getCenter(self):
return self.center
def getRadius(self):
return self.radius
def getMin(self):
return self.min
def getMax(self):
return self.max
def vecAsString(self, vec):
return '%.2f %.2f %.2f' % (vec[0], vec[1], vec[2])
def __repr__(self):
return (`self.__class__` +
'\nNodePath:\t%s\n' % self.nodePath.getName() +
'Min:\t\t%s\n' % self.vecAsString(self.min) +
'Max:\t\t%s\n' % self.vecAsString(self.max) +
'Center:\t\t%s\n' % self.vecAsString(self.center) +
'Radius:\t\t%.2f' % self.radius
)
class SelectionQueue(CollisionHandlerQueue):
def __init__(self, parentNP = render):
# Initialize the superclass
CollisionHandlerQueue.__init__(self)
# Current index and entry in collision queue
self.index = -1
self.entry = None
self.skipFlags = SKIP_NONE
# Create a collision node path attached to the given NP
self.collisionNodePath = NodePath(CollisionNode("collisionNP"))
self.setParentNP(parentNP)
# Don't pay the penalty of drawing this collision ray
self.collisionNodePath.hide()
self.collisionNode = self.collisionNodePath.node()
# Intersect with geometry to begin with
self.collideWithGeom()
# And a traverser to do the actual collision tests
self.ct = CollisionTraverser()
# Let the traverser know about the collision node and the queue
self.ct.addCollider(self.collisionNode, self)
# List of objects that can't be selected
self.unpickable = UNPICKABLE
# Derived class must add Collider to complete initialization
def setParentNP(self, parentNP):
# Update collisionNodePath's parent
self.collisionNodePath.reparentTo(parentNP)
def addCollider(self, collider):
# Inherited class must call this function to specify collider object
# Record collision object
self.collider = collider
# Add the collider to the collision Node
self.collisionNode.addSolid( self.collider )
def collideWithBitMask(self, bitMask):
# The into collide mask is the bit pattern colliders look at
# when deciding whether or not to test for a collision "into"
# this collision solid. Set to all Off so this collision solid
# will not be considered in any collision tests
self.collisionNode.setIntoCollideMask(BitMask32().allOff())
# The from collide mask is the bit pattern *this* collision solid
# compares against the into collide mask of candidate collision solids
# Turn this mask all off since we're not testing for collisions against
# collision solids
self.collisionNode.setFromCollideMask(bitMask)
# Don't test against actual geometry
self.collisionNode.setCollideGeom(0)
def collideWithGeom(self):
# The into collide mask is the bit pattern colliders look at
# when deciding whether or not to test for a collision "into"
# this collision solid. Set to all Off so this collision solid
# will not be considered in any collision tests
self.collisionNode.setIntoCollideMask(BitMask32().allOff())
# The from collide mask is the bit pattern *this* collision solid
# compares against the into collide mask of candidate collision solids
# Turn this mask all off since we're not testing for collisions against
# collision solids
self.collisionNode.setFromCollideMask(BitMask32().allOff())
# What we want to test against is actual geometry
self.collisionNode.setCollideGeom(1)
def collideWithWidget(self):
# This collision node should not be tested against by any other
# collision solids
self.collisionNode.setIntoCollideMask(BitMask32().allOff())
# This collision node will test for collisions with any collision
# solids with a bit mask set to 0x80000000
mask = BitMask32()
mask.setWord(0x80000000)
self.collisionNode.setFromCollideMask(mask)
# But in this case, don't test against actual geometry
self.collisionNode.setCollideGeom(0)
def addUnpickable(self, item):
if item not in self.unpickable:
self.unpickable.append(item)
def removeUnpickable(self, item):
if item in self.unpickable:
self.unpickable.remove(item)
def setCurrentIndex(self, index):
if (index < 0) or (index >= self.getNumEntries()):
self.index = -1
else:
self.index = index
def setCurrentEntry(self, entry):
self.entry = entry
def getCurrentEntry(self):
return self.entry
def isEntryBackfacing(self, entry):
# If dot product of collision point surface normal and
# ray from camera to collision point is positive, we are
# looking at the backface of the polygon
if not entry.hasFromSurfaceNormal():
# Well, no way to tell. Assume we're not backfacing.
return 0
v = Vec3(entry.getFromIntersectionPoint())
n = entry.getFromSurfaceNormal()
# Convert to camera space for backfacing test
if self.collisionNodePath.getParent() != base.cam:
# Problem: assumes base.cam is the camera in question
p2cam = self.collisionNodePath.getParent().getMat(base.cam)
v = Vec3(p2cam.xformPoint(v))
n = p2cam.xformVec(n)
# Normalize and check angle between to vectors
v.normalize()
return v.dot(n) >= 0
def findNextCollisionEntry(self, skipFlags = SKIP_NONE):
return self.findCollisionEntry(skipFlags, self.index + 1)
def findCollisionEntry(self, skipFlags = SKIP_NONE, startIndex = 0 ):
# Init self.index and self.entry
self.setCurrentIndex(-1)
self.setCurrentEntry(None)
# Pick out the closest object that isn't a widget
for i in range(startIndex,self.getNumEntries()):
entry = self.getEntry(i)
nodePath = entry.getIntoNodePath()
if (skipFlags & SKIP_HIDDEN) and nodePath.isHidden():
# Skip if hidden node
pass
elif (skipFlags & SKIP_BACKFACE) and self.isEntryBackfacing(entry):
# Skip, if backfacing poly
pass
elif ((skipFlags & SKIP_CAMERA) and
(camera in nodePath.getAncestry())):
# Skip if parented to a camera.
pass
# Can pick unpickable, use the first visible node
elif ((skipFlags & SKIP_UNPICKABLE) and
(nodePath.getName() in self.unpickable)):
# Skip if in unpickable list
pass
else:
self.setCurrentIndex(i)
self.setCurrentEntry(entry)
break
return self.getCurrentEntry()
class SelectionRay(SelectionQueue):
def __init__(self, parentNP = render):
# Initialize the superclass
SelectionQueue.__init__(self, parentNP)
self.addCollider(CollisionRay())
def pick(self, targetNodePath, xy = None):
# Determine ray direction based upon the mouse coordinates
if xy:
mx = xy[0]
my = xy[1]
elif direct:
mx = SEditor.dr.mouseX
my = SEditor.dr.mouseY
else:
if not base.mouseWatcherNode.hasMouse():
# No mouse in window.
self.clearEntries()
return
mx = base.mouseWatcherNode.getMouseX()
my = base.mouseWatcherNode.getMouseY()
#base.mouseWatcherNode.setDisplayRegion(base.win.getDisplayRegion(0))
#mx = base.mouseWatcherNode.getMouseX()+1
#my = base.mouseWatcherNode.getMouseY()+1
#print base.camNode.getName()
#print "Arrived X" + str(mx) + " Arrived Y " + str(my)
self.collider.setFromLens( base.camNode, mx, my )
self.ct.traverse( targetNodePath )
self.sortEntries()
def pickBitMask(self, bitMask = BitMask32.allOff(),
targetNodePath = render,
skipFlags = SKIP_ALL ):
self.collideWithBitMask(bitMask)
self.pick(targetNodePath)
# Determine collision entry
return self.findCollisionEntry(skipFlags)
def pickGeom(self, targetNodePath = render, skipFlags = SKIP_ALL,
xy = None):
self.collideWithGeom()
self.pick(targetNodePath, xy = xy)
# Determine collision entry
return self.findCollisionEntry(skipFlags)
def pickWidget(self, targetNodePath = render, skipFlags = SKIP_NONE ):
self.collideWithWidget()
self.pick(targetNodePath)
# Determine collision entry
return self.findCollisionEntry(skipFlags)
def pick3D(self, targetNodePath, origin, dir):
# Determine ray direction based upon the mouse coordinates
self.collider.setOrigin( origin )
self.collider.setDirection( dir )
self.ct.traverse( targetNodePath )
self.sortEntries()
def pickGeom3D(self, targetNodePath = render,
origin = Point3(0), dir = Vec3(0,0,-1),
skipFlags = SKIP_HIDDEN | SKIP_CAMERA ):
self.collideWithGeom()
self.pick3D(targetNodePath, origin, dir)
# Determine collision entry
return self.findCollisionEntry(skipFlags)
def pickBitMask3D(self, bitMask = BitMask32.allOff(),
targetNodePath = render,
origin = Point3(0), dir = Vec3(0,0,-1),
skipFlags = SKIP_ALL ):
self.collideWithBitMask(bitMask)
self.pick3D(targetNodePath, origin, dir)
# Determine collision entry
return self.findCollisionEntry(skipFlags)
class SelectionSegment(SelectionQueue):
# Like a selection ray but with two endpoints instead of an endpoint
# and a direction
def __init__(self, parentNP = render, numSegments = 1):
# Initialize the superclass
SelectionQueue.__init__(self, parentNP)
self.colliders = []
self.numColliders = 0
for i in range(numSegments):
self.addCollider(CollisionSegment())
def addCollider(self, collider):
# Record new collision object
self.colliders.append(collider)
# Add the collider to the collision Node
self.collisionNode.addSolid( collider )
self.numColliders += 1
def pickGeom(self, targetNodePath = render, endPointList = [],
skipFlags = SKIP_HIDDEN | SKIP_CAMERA ):
self.collideWithGeom()
for i in range(min(len(endPointList), self.numColliders)):
pointA, pointB = endPointList[i]
collider = self.colliders[i]
collider.setPointA( pointA )
collider.setPointB( pointB )
self.ct.traverse( targetNodePath )
# Determine collision entry
return self.findCollisionEntry(skipFlags)
def pickBitMask(self, bitMask = BitMask32.allOff(),
targetNodePath = render, endPointList = [],
skipFlags = SKIP_HIDDEN | SKIP_CAMERA ):
self.collideWithBitMask(bitMask)
for i in range(min(len(endPointList), self.numColliders)):
pointA, pointB = endPointList[i]
collider = self.colliders[i]
collider.setPointA( pointA )
collider.setPointB( pointB )
self.ct.traverse( targetNodePath )
# Determine collision entry
return self.findCollisionEntry(skipFlags)
class SelectionSphere(SelectionQueue):
# Wrapper around collision sphere
def __init__(self, parentNP = render, numSpheres = 1):
# Initialize the superclass
SelectionQueue.__init__(self, parentNP)
self.colliders = []
self.numColliders = 0
for i in range(numSpheres):
self.addCollider(CollisionSphere(Point3(0), 1))
def addCollider(self, collider):
# Record new collision object
self.colliders.append(collider)
# Add the collider to the collision Node
self.collisionNode.addSolid( collider )
self.numColliders += 1
def setCenter(self, i, center):
c = self.colliders[i]
c.setCenter(center)
def setRadius(self, i, radius):
c = self.colliders[i]
c.setRadius(radius)
def setCenterRadius(self, i, center, radius):
c = self.colliders[i]
c.setCenter(center)
c.setRadius(radius)
def isEntryBackfacing(self, entry):
# If dot product of collision point surface normal and
# ray from sphere origin to collision point is positive,
# center is on the backside of the polygon
v = Vec3(entry.getFromIntersectionPoint() -
entry.getFrom().getCenter())
n = entry.getFromSurfaceNormal()
# If points almost on top of each other, reject face
# (treat as backfacing)
if v.length() < 0.05:
return 1
# Normalize and check angle between to vectors
v.normalize()
return v.dot(n) >= 0
def pick(self, targetNodePath, skipFlags):
self.ct.traverse( targetNodePath )
self.sortEntries()
return self.findCollisionEntry(skipFlags)
def pickGeom(self, targetNodePath = render,
skipFlags = SKIP_HIDDEN | SKIP_CAMERA ):
self.collideWithGeom()
return self.pick(targetNodePath, skipFlags)
def pickBitMask(self, bitMask = BitMask32.allOff(),
targetNodePath = render,
skipFlags = SKIP_HIDDEN | SKIP_CAMERA ):
self.collideWithBitMask(bitMask)
return self.pick(targetNodePath, skipFlags)

421
doc/SceneEditor/seTree.py Normal file
View File

@ -0,0 +1,421 @@
#################################################################
# seTree.py
# Originally from Tree.py
# Altered by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#
# This class actually decides the behavior of the sceneGraphExplorer
# You might feel it realy looks like the original one, but we actually did a lots of change in it.
# such as, when selection happend in other place, such as picking directly inside the scene. or,
# when user removed something by hot key.
# The rename process has also been changed. It won't be rename in here anymore.
# Instead, here we will send out a message to sceneEditor to reaname the target.
#
#################################################################
import os
import sys
import string
from TkGlobal import *
from PandaObject import *
# Initialize icon directory
f = Filename('icons')
f.resolveFilename(getModelPath())
ICONDIR = f.toOsSpecific()
if not os.path.isdir(ICONDIR):
raise RuntimeError, "can't find DIRECT icon directory (%s)" % `ICONDIR`
class TreeNode:
def __init__(self, canvas, parent, item, menuList = []):
self.canvas = canvas
self.parent = parent
self.item = item
self.state = 'collapsed'
self.selected = 0
self.children = {}
self.kidKeys = []
self.x = self.y = None
self.iconimages = {} # cache of PhotoImage instances for icons
self.menuList = menuList
self.menuVar = IntVar()
self.menuVar.set(0)
self._popupMenu = None
self.image_id = None
if self.menuList:
if self.menuList[-1] == 'Separator':
self.menuList = self.menuList[:-1]
self._popupMenu = Menu(self.canvas, tearoff = 0)
for i in range(len(self.menuList)):
item = self.menuList[i]
if item == 'Separator':
self._popupMenu.add_separator()
else:
self._popupMenu.add_radiobutton(
label = item,
variable = self.menuVar,
value = i,
indicatoron = 0,
command = self.popupMenuCommand)
def destroy(self):
for key in self.kidKeys:
c = self.children[key]
del self.children[key]
c.destroy()
self.parent = None
def geticonimage(self, name):
try:
return self.iconimages[name]
except KeyError:
pass
file, ext = os.path.splitext(name)
ext = ext or ".gif"
fullname = os.path.join(ICONDIR, file + ext)
image = PhotoImage(master=self.canvas, file=fullname)
self.iconimages[name] = image
return image
def select(self, event=None):
if self.selected:
return
self.deselectall()
self.selected = 1
if self.parent != None:
if self.parent.state == 'expanded':
self.canvas.delete(self.image_id)
self.drawicon()
self.drawtext()
self.item.OnSelect(event)
def deselect(self, event=None):
if not self.selected:
return
self.selected = 0
if self.parent != None:
if self.parent.state == 'expanded':
self.canvas.delete(self.image_id)
self.drawicon()
self.drawtext()
def deselectall(self):
if self.parent:
self.parent.deselectall()
else:
self.deselecttree()
def deselecttree(self):
if self.selected:
self.deselect()
for key in self.kidKeys:
child = self.children[key]
child.deselecttree()
def flip(self, event=None):
if self.state == 'expanded':
self.collapse()
else:
self.expand()
self.item.OnDoubleClick()
return "break"
def popupMenu(self, event=None):
if self._popupMenu:
self._popupMenu.post(event.widget.winfo_pointerx(),
event.widget.winfo_pointery())
return "break"
def popupMenuCommand(self):
command = self.menuList[self.menuVar.get()]
self.item.MenuCommand(command)
if self.parent and (command != 'Update Explorer'):
# Update parent to try to keep explorer up to date
self.parent.update()
def expand(self, event=None):
if not self.item.IsExpandable():
return
if self.state != 'expanded':
self.state = 'expanded'
self.update()
self.view()
def collapse(self, event=None):
if self.state != 'collapsed':
self.state = 'collapsed'
self.update()
def view(self):
top = self.y - 2
bottom = self.lastvisiblechild().y + 17
height = bottom - top
visible_top = self.canvas.canvasy(0)
visible_height = self.canvas.winfo_height()
visible_bottom = self.canvas.canvasy(visible_height)
if visible_top <= top and bottom <= visible_bottom:
return
x0, y0, x1, y1 = self.canvas._getints(self.canvas['scrollregion'])
if top >= visible_top and height <= visible_height:
fraction = top + height - visible_height
else:
fraction = top
fraction = float(fraction) / y1
self.canvas.yview_moveto(fraction)
def reveal(self):
# Make sure all parent nodes are marked as expanded
parent = self.parent
while parent:
if parent.state == 'collapsed':
parent.state = 'expanded'
parent = parent.parent
else:
break
# Redraw tree accordingly
self.update()
# Bring this item into view
self.view()
def lastvisiblechild(self):
if self.kidKeys and self.state == 'expanded':
return self.children[self.kidKeys[-1]].lastvisiblechild()
else:
return self
def update(self):
if self.parent:
self.parent.update()
else:
oldcursor = self.canvas['cursor']
self.canvas['cursor'] = "watch"
self.canvas.update()
self.canvas.delete(ALL) # XXX could be more subtle
self.draw(7, 2)
x0, y0, x1, y1 = self.canvas.bbox(ALL)
self.canvas.configure(scrollregion=(0, 0, x1, y1))
self.canvas['cursor'] = oldcursor
def draw(self, x, y):
# XXX This hard-codes too many geometry constants!
self.x, self.y = x, y
self.drawicon()
self.drawtext()
if self.state != 'expanded':
return y+17
# draw children
sublist = self.item._GetSubList()
if not sublist:
# IsExpandable() was mistaken; that's allowed
return y+17
self.kidKeys = []
for item in sublist:
key = item.GetKey()
if self.children.has_key(key):
child = self.children[key]
else:
child = TreeNode(self.canvas, self, item, self.menuList)
self.children[key] = child
self.kidKeys.append(key)
# Remove unused children
for key in self.children.keys():
if key not in self.kidKeys:
del(self.children[key])
cx = x+20
cy = y+17
cylast = 0
for key in self.kidKeys:
child = self.children[key]
cylast = cy
self.canvas.create_line(x+9, cy+7, cx, cy+7, fill="gray50")
cy = child.draw(cx, cy)
if child.item.IsExpandable():
if child.state == 'expanded':
iconname = "minusnode"
callback = child.collapse
else:
iconname = "plusnode"
callback = child.expand
image = self.geticonimage(iconname)
id = self.canvas.create_image(x+9, cylast+7, image=image)
# XXX This leaks bindings until canvas is deleted:
self.canvas.tag_bind(id, "<1>", callback)
self.canvas.tag_bind(id, "<Double-1>", lambda x: None)
id = self.canvas.create_line(x+9, y+10, x+9, cylast+7,
##stipple="gray50", # XXX Seems broken in Tk 8.0.x
fill="gray50")
self.canvas.tag_lower(id) # XXX .lower(id) before Python 1.5.2
return cy
def drawicon(self):
if self.selected:
imagename = (self.item.GetSelectedIconName() or
self.item.GetIconName() or
"openfolder")
else:
imagename = self.item.GetIconName() or "folder"
image = self.geticonimage(imagename)
id = self.canvas.create_image(self.x, self.y, anchor="nw", image=image)
self.image_id = id
self.canvas.tag_bind(id, "<1>", self.select)
self.canvas.tag_bind(id, "<Double-1>", self.flip)
self.canvas.tag_bind(id, "<3>", self.popupMenu)
def drawtext(self, text=None):
textx = self.x+20-1
texty = self.y-1
labeltext = self.item.GetLabelText()
if labeltext:
id = self.canvas.create_text(textx, texty, anchor="nw",
text=labeltext)
self.canvas.tag_bind(id, "<1>", self.select)
self.canvas.tag_bind(id, "<Double-1>", self.flip)
x0, y0, x1, y1 = self.canvas.bbox(id)
textx = max(x1, 200) + 10
if text==None:
text = self.item.GetText() or "<no text>"
try:
self.entry
except AttributeError:
pass
else:
self.edit_finish()
try:
label = self.label
except AttributeError:
# padding carefully selected (on Windows) to match Entry widget:
self.label = Label(self.canvas, text=text, bd=0, padx=2, pady=2)
if self.selected:
self.label.configure(fg="white", bg="darkblue")
else:
fg = self.item.GetTextFg()
self.label.configure(fg=fg, bg="white")
id = self.canvas.create_window(textx, texty,
anchor="nw", window=self.label)
self.label.bind("<1>", self.select_or_edit)
self.label.bind("<Double-1>", self.flip)
self.label.bind("<3>", self.popupMenu)
# Update text if necessary
if text != self.label['text']:
self.label['text'] = text
self.text_id = id
def select_or_edit(self, event=None):
if self.selected and self.item.IsEditable():
text = self.item.GetTextForEdit()
self.label['text'] = text
self.drawtext(text)
self.edit(event)
else:
self.select(event)
def edit(self, event=None):
self.entry = Entry(self.label, bd=0, highlightthickness=1, width=0)
self.entry.insert(0, self.label['text'])
self.entry.selection_range(0, END)
self.entry.pack(ipadx=5)
self.entry.focus_set()
self.entry.bind("<Return>", self.edit_finish)
self.entry.bind("<Escape>", self.edit_cancel)
def edit_finish(self, event=None):
try:
entry = self.entry
del self.entry
except AttributeError:
return
text = entry.get()
entry.destroy()
if text and text != self.item.GetText():
self.item.SetText(text)
text = self.item.GetText()
self.label['text'] = text
self.drawtext()
self.canvas.focus_set()
def edit_cancel(self, event=None):
self.drawtext()
self.canvas.focus_set()
def find(self, searchKey):
# Search for a node who's key matches the given key
# Is it this node
if searchKey == self.item.GetKey():
return self
# Nope, check the children
sublist = self.item._GetSubList()
for item in sublist:
key = item.GetKey()
# Use existing child or create new TreeNode if none exists
if self.children.has_key(key):
child = self.children[key]
else:
child = TreeNode(self.canvas, self, item, self.menuList)
# Update local list of children and keys
self.children[key] = child
self.kidKeys.append(key)
# See if node is child (or one of child's descendants)
retVal = child.find(searchKey)
if retVal:
return retVal
# Not here
return None
class TreeItem:
"""Abstract class representing tree items.
Methods should typically be overridden, otherwise a default action
is used.
"""
def __init__(self):
"""Constructor. Do whatever you need to do."""
def GetText(self):
"""Return text string to display."""
def GetTextFg(self):
return "black"
def GetLabelText(self):
"""Return label text string to display in front of text (if any)."""
def IsExpandable(self):
"""Return whether there are subitems."""
return 1
def _GetSubList(self):
"""Do not override! Called by TreeNode."""
if not self.IsExpandable():
return []
sublist = self.GetSubList()
return sublist
def IsEditable(self):
"""Return whether the item's text may be edited."""
def SetText(self, text):
"""Change the item's text (if it is editable)."""
def GetIconName(self):
"""Return name of icon to be displayed normally."""
def GetSelectedIconName(self):
"""Return name of icon to be displayed when selected."""
def GetSubList(self):
"""Return list of items forming sublist."""
def OnDoubleClick(self):
"""Called on a double-click on the item."""
def OnSelect(self):
"""Called when item selected."""
def GetTextForEdit(self):
"""Called before editting the item."""

View File

@ -0,0 +1,9 @@
#ifndef MAINHELIX_H
#define MAINHELIX_H
// This file is a stub header file.
class DLLAccess {};
class IHXClientEngine {};
class IHXPlayer {};
#endif

View File

@ -0,0 +1,6 @@
#ifndef DLLPATH_H
#define DLLPATH_H
// This file is a stub header file.
#endif

View File

@ -0,0 +1,6 @@
#ifndef HXCOM_H
#define HXCOM_H
// This file is a stub header file.
#endif

View File

@ -0,0 +1,6 @@
#ifndef HXCOMM_H
#define HXCOMM_H
// This file is a stub header file.
#endif

View File

@ -0,0 +1,6 @@
#ifndef HXCORE_H
#define HXCORE_H
// This file is a stub header file.
#endif

View File

@ -0,0 +1,6 @@
#ifndef HXENGIN_H
#define HXENGIN_H
// This file is a stub header file.
#endif

View File

@ -0,0 +1,6 @@
#ifndef HXERROR_H
#define HXERROR_H
// This file is a stub header file.
#endif

View File

@ -0,0 +1,6 @@
#ifndef HXFILES_H
#define HXFILES_H
// This file is a stub header file.
#endif

View File

@ -0,0 +1,6 @@
#ifndef HXTBUF_H
#define HXTBUF_H
// This file is a stub header file.
#endif

View File

@ -0,0 +1,6 @@
#ifndef HXTBUFF_H
#define HXTBUFF_H
// This file is a stub header file.
#endif

View File

@ -0,0 +1,6 @@
#ifndef HXWIN_H
#define HXWIN_H
// This file is a stub header file.
#endif

View File

@ -0,0 +1,801 @@
// Filename: HelixClient.cxx
// Created by: jjtaylor (10Feb04)
//
////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Panda Header Files
////////////////////////////////////////////////////////////////////
#include "helixclient.h"
// Initialize Static Data Members.
TypeHandle HelixClient::_type_handle;
// Static Members used for the DoEvents Method. These might
// be removed in the future since Panda calls the Win32 API
// Message calls internally.
const int HelixClient::_time_delta = 2000;
const int HelixClient::_sleep_time = 10;
const int HelixClient::_guid_length = 64;
////////////////////////////////////////////////////////////////////
// Method: HelixClient::HelixClient()
// Access: PUBLISHED
// Purpose: This is the default constructor for creating the
// the wrapper object that encapsulates the Helix Engine.
// The constructor calls the init() which loads the main
// Helix DLL, clntcore.dll.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
HelixClient::HelixClient()
: _engine(0),
_dll_access(0) {
const char * envName = "PLAYER";
char* envPath = getenv( envName );
_dll_home = string(string(envPath) + "\\ExtLib\\HelixLib\\.");
init();
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::~HelixClient()
// Access: PUBLISHED
// Purpose: This is the destructor for the HelixClient proxy class.
// The destructor simply invokes the shutdown(), which
// closes any open players on the engine, successfully
// frees the DLLAccess and engine objects.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
HelixClient::~HelixClient() {
shutdown();
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::do_event()
// Access: PUBLISHED
// Purpose: This method is was used primarily in the Win32
// test application to give the Helix Engine the necessary
// time slices to keep it running properly. In addition,
// it has been modified to manually set each texture in
// the _textures map to dirty. This means that the image
// will be loaded once again into memory, essentially
// updating the texture each frame with the new video
// image applied to it.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::do_event() {
// Legacy Win32 API code from the test application. This can
// probably be removed since Panda already calls these methods
// for retreiving and dispatching Win32 messages.
MSG msg;
GetMessage(&msg, NULL, 0, 0);
DispatchMessage(&msg);
// Simply iterate through the _textures map and set the texture
// dirty so that it will be updated in memory.
TEXTURES::iterator iter;
for(iter = _textures.begin(); iter != _textures.end(); iter++) {
iter->second->mark_dirty(Texture::DF_image);
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::do_events()
// Access: PUBLISHED
// Purpose: This method was used primarily in the Win32
// test application to give the Helix Engine the necessary
// time slices to keep it running properly. It is still
// used in the HelixClient::begin() to get the engine
// started for playback, but it most likely can be safely
// removed in the future.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::do_events() {
MSG msg;
DWORD start_time, end_time, i;
BOOL sleep = TRUE;
static const int check_interval = 10;
start_time = GetTickCount();
end_time = start_time + _time_delta;
i = 0;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
DispatchMessage(&msg);
if((i % check_interval) == 0) {
if(GetTickCount() > end_time) {
break;
}
++i;
}
sleep = FALSE;
}
if(sleep) {
Sleep(_sleep_time);
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::create_player(...)
// Access: PUBLISHED
// Purpose: This wrapper method encapsulates the creation of a
// player object for the Helix Engine.
////////////////////////////////////////////////////////////////////
// Params: const string &name - Desired name of the Player
// Texture* tex - Panda Texture that is to be udpated with
// the video that this player will run.
// bool sink_on - Determines with the HxAdviseSink Object
// should print out the presentation stats
// in the command prompt.
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::create_player(const string &name, Texture* tex, bool sink_on) {
// Check to make certain that the engine interface has been
// instantiated, otherwise, players cannot be created!
if (_engine != 0) {
// For now, check if there is an actual Panda texture present. If not,
// then this player should not be created.
// NOTE: This portion of the interface must be redesigned as the current
// design forces the user to specify a valid texture. A more suitable
// approach would be to automatically generate a panda texture and allow
// the user to retreive that texture and set it for any piece of geometry
// within the world.
if( tex == 0 ) {
STDOUT("ERROR: HelixClient::CreatePlayer, INVALID Texture Object!\n");
STDOUT("ERROR: NO PLAYER CREATED!!\n");
return;
}
// Initialize necessary Helix pointers.
IHXPlayer* tmp_player = 0;
HxClientContext* context = 0;
IHXErrorSinkControl* controller = 0;
IHXErrorSink* error_sink = 0;
// Tell the texture object to keep the actual image buffer in memory. If
// the image buffer is deallocated, which is the default in panda, Helix
// and Panda because the engine will try to Blit to an invalid buffer.
tex->set_keep_ram_image(true);
// Try and create a valid helix player on the engine
if (HXR_OK != _engine->CreatePlayer(tmp_player)) {
STDOUT("ERROR: HelixClient::CreatePlayer, Failed Player Creation!\n");
}
else {
// Since a player has been successfully instantiated, a context
// for that player must be created.
context = new HxClientContext(_players.size());
if(context != 0) {
context->AddRef();
// Specify a default GUID. Not really necessary, but here for
// convenience if needed later on.
char guid[_guid_length + 1];
IHXPreferences * pref = 0;
guid[0] = '\0';
// Query the Preferences Interface for the player.
tmp_player->QueryInterface(IID_IHXPreferences, (void**)&pref);
// Send the Texture buffer down into the Context. It will then
// ship the buffer to the site supplier, where the actual site
// and surface are generated.
context->init(tmp_player, pref, guid, sink_on, tex);
tmp_player->SetClientContext(context);
HX_RELEASE(pref);
// Query the Error Sink Controller
tmp_player->QueryInterface(IID_IHXErrorSinkControl, (void**)&controller);
if(controller != 0) {
context->QueryInterface(IID_IHXErrorSink, (void**)&error_sink);
if(error_sink != 0) {
controller->AddErrorSink(error_sink, HXLOG_EMERG, HXLOG_INFO);
}
HX_RELEASE(error_sink);
error_sink = 0;
}
HX_RELEASE(controller);
controller = 0;
context = 0;
}
// Create a new map object for the player and its respective texture.
pair<string, IHXPlayer*> player(name, tmp_player);
pair<string, PT(Texture)> texture(name, tex);
// Now that the pair has been created, set the tmp_player
// address to 0 to protect against dangling references.
tmp_player = 0;
// Now, actually insert the pairs into their respective maps.
_players.insert(player);
_textures.insert(texture);
}
}
else {
STDOUT("ERROR: In HelixClient::CreatePlayer, pEngine = NULL");
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::close_player(...)
// Access: PUBLISHED
// Purpose: This wrapper method encapsulates the closing of a
// player object for the Helix Engine. This method
// determines if a player with the designated name exists
// by searching the _players map. If it does, it properly
// closes the player, deletes it from memory, and removes
// the pair instance from the map as well as its texture
// counter part.
////////////////////////////////////////////////////////////////////
// Params: const string &name - Desired name of the Player to close.
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::close_player(const string &name) {
if (_engine != 0) {
IUnknown* context = 0;
// Determine if the player is in the map. If so, go about
// removing that player from the engine.
PLAYERS::iterator iter = _players.find(name);
if (iter != _players.end()) {
iter->second->Stop();
iter->second->GetClientContext(context);
context->Release();
context = 0;
_engine->ClosePlayer(iter->second);
iter->second->Release();
iter->second = 0;
// Remove the player its associated texture from their
// respective maps.
_players.erase(name);
_textures.erase(name);
}
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::close_all_players()
// Access: PUBLISHED
// Purpose: This wrapper method encapsulates the closing of every
// player object for the Helix Engine. This method simply
// iterates through the _players map, and invokes the
// the close_player routine to actually close the player.
////////////////////////////////////////////////////////////////////
// Params: none
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::close_all_players() {
if (_engine != 0) {
if (!_players.empty()) {
IUnknown* context = 0;
PLAYERS::iterator iter;
// Iterate through the _players map to close each player
// currently associated with the engine.
unsigned int total_players = _players.size();
for (unsigned int cntr = 0; cntr <= total_players; cntr++) {
close_player(_players.begin()->first);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::get_player_count()
// Access: PUBLISHED
// Purpose: This wrapper method simply returns the current number
// of players that are associated with the Helix Engine.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: Int - the number of players currently associated with
// the Helix Engine.
////////////////////////////////////////////////////////////////////
int HelixClient::get_player_count() {
if (_engine != 0) {
return _engine->GetPlayerCount();
}
else {
return 0;
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::init()
// Access: Private
// Purpose: This member function provides all of the dirty work
// for instantiating a Helix Engine object. First it
// searches for the main Helix DLL, clntcore.dll, and then
// it instantiates the actual engine itself.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: bool - True if the engine is successfully initialized.
////////////////////////////////////////////////////////////////////
bool HelixClient::init() {
// Local Variable Defination and Initialization
FPRMCREATEENGINE create_engine = 0;
FPRMSETDLLACCESSPATH set_dll_access_path = 0;
// Instantiate a DLLAccess object which will be used to properly
// load the clntcore.dll at runtime.
_dll_access = new DLLAccess();
// Attempt to load the clntcore.dll. If this fails, an error message will
// be generated and printed to the console.
STDOUT("HelixClient is looking for the client core at %s\n", _dll_home.c_str());
if(DLLAccess::DLL_OK != _dll_access->open(string(_dll_home+"\\clntcore.dll").c_str())) {
const char * error_string = 0;
error_string = _dll_access->getErrorString();
STDERR("HelixClient: %s\n\n", error_string);
// Print out an explanation of what is wrong.
STDERR("You must tell the player where to find the client core and\n");
STDERR("all of its supporting DLLs and codecs.\n");
// Deallocate the memory from the heap to avoid a memory leak.
delete _dll_access;
_dll_access = 0;
return false;
}
// Now that the client core has been loaded, retrieve the function pointer
// to the engine and the DLL access path.
create_engine = (FPRMCREATEENGINE) _dll_access->getSymbol("CreateEngine");
set_dll_access_path = (FPRMSETDLLACCESSPATH) _dll_access->getSymbol("SetDLLAccessPath");
// If either function pointer was not retreived, print an error message to
// the console, deallocate the DLLAccess object from memory, and abort the
// initialization of the engine.
if((create_engine == 0) || (set_dll_access_path == 0)) {
STDOUT("---{ERROR: HelixClient::Init, set_dll_access_path}---");
delete _dll_access;
_dll_access = 0;
return false;
}
// Now that the clntcore.dll has been succesfully loaded. Specify where it
// can find all of the accompanying DLLs that are necessary for Helix to
// function.
char paths[256];
char* path_next_position = paths;
memset(paths, 0, 256);
UINT32 bytes_left = 256;
char next_path[256];
memset(next_path, 0, 256);
// Apply the Common DLL Path to the paths string. For simplicity,
// this is the same path as the clntcore.dll path.
SafeSprintf(next_path, 256, "DT_Common=%s", _dll_home.c_str());
STDERR("Common DLL path %s\n", next_path );
UINT32 bytes_to_copy = strlen(next_path) + 1;
if (bytes_to_copy <= bytes_left)
{
memcpy(path_next_position, next_path, bytes_to_copy);
path_next_position += bytes_to_copy;
bytes_left -= bytes_to_copy;
}
// Apply the Plug-in DLL Path to the paths string. For simplicity,
// this is the same path as the clntcore.dll path.
SafeSprintf(next_path, 256, "DT_Plugins=%s", _dll_home.c_str());
STDERR("Plugin path %s\n", next_path );
bytes_to_copy = strlen(next_path) + 1;
if (bytes_to_copy <= bytes_left)
{
memcpy(path_next_position, next_path, bytes_to_copy);
path_next_position += bytes_to_copy;
bytes_left -= bytes_to_copy;
}
// Apply the Codecs DLL Path to the paths string. For simplicity,
// this is the same path as the clntcore.dll path.
SafeSprintf(next_path, 256, "DT_Codecs=%s", _dll_home.c_str());
bytes_to_copy = strlen(next_path) + 1;
if (bytes_to_copy <= bytes_left)
{
memcpy(path_next_position, next_path, bytes_to_copy);
path_next_position += bytes_to_copy;
bytes_left -= bytes_to_copy;
*path_next_position='\0';
}
STDOUT((char*)paths);
set_dll_access_path((char*)paths);
// The dll_access_path has been set, so the engine can now be initialized. If
// this fails, then deallocate the DLLAccess object from memory and abort the
// initialization of the engine.
if (HXR_OK != create_engine((IHXClientEngine**) &_engine)) {
STDOUT("---{ERROR: HelixClient::Init, Creating Engine Problem}---");
delete _dll_access;
_dll_access = 0;
return false;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::shutdown()
// Access: PUBLISHED
// Purpose: This member function closes all open players before it
// proceeds to close the engine itself.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::shutdown() {
if (_engine != 0) {
// Close All Open Players that are associated with the
// given Helix Engine.
close_all_players();
// Retrieve the Function Pointer for closing the Helix engine.
FPRMCLOSEENGINE close_engine = (FPRMCLOSEENGINE) _dll_access->getSymbol("CloseEngine");
// If the function pointer was successfully retrieved, close
// the helix engine.
if (close_engine != 0) {
STDOUT("Closing Helix Engine...\n");
close_engine(_engine);
_engine = 0;
}
// Close the link with the clntCore.dll and freeing the DLLAccess
// object from memory to prevent a memory leak on the heap.
STDOUT("Closing the link to clntCore.dll...\n");
_dll_access->close();
delete _dll_access;
_dll_access = 0;
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::begin(...)
// Access: PUBLISHED
// Purpose: This wrapper function encapsulates the Helix Player
// Begin method. It first searches for the name of the
// specified player within the _players map. If that
// is found, it calls the IHXPlayer::Begin method.
////////////////////////////////////////////////////////////////////
// Params: const string &name - Name of the Player to begin playback.
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::begin(const string &name) {
if (_engine != 0) {
// Search for the specified player in the map. If the player
// is found, begin playback of the media file.
PLAYERS::iterator iter = _players.find(name);
if (iter != _players.end()) {
iter->second->Begin();
}
// This is legacy code from the test application, however, it
// was necessary for helix to function since do_events was called
// to give helix the necessary time-slice of the CPU. I think this
// most likely can be removed since Panda calls the necessary
// Win32 API Message calls.
//UINT curr_time = 0;
//UINT32 start_time = GetTickCount();
//UINT32 end_time = start_time + _time_delta;
//while(1) {
// do_events();
//curr_time = GetTickCount();
//if(curr_time >= end_time)
// break;
//}
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::begin_all()
// Access: PUBLISHED
// Purpose: This wrapper function simply calls the IHXPlayer::Begin
// routine for each player currently associated with the
// the engine.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::begin_all() {
if (_engine != 0) {
// Iterate through the _players map and call the Begin
// routine to start playback of the media.
PLAYERS::iterator iter;
for(iter = _players.begin(); iter != _players.end(); iter++) {
iter->second->Begin();
}
// This is legacy code from the test application, however, it
// was necessary for helix to function since do_events was called
// to give helix the necessary time-slice of the CPU. I think this
// most likely can be removed since Panda calls the necessary
// Win32 API Message calls.
// UINT curr_time = 0;
// UINT32 start_time = GetTickCount();
// UINT32 end_time = start_time + _time_delta;
// while(1) {
// do_events();
// curr_time = GetTickCount();
// if (curr_time >= end_time)
// break;
// }
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::pause(...)
// Access: PUBLISHED
// Purpose: This wrapper function encapsulates the Helix Player
// Pause method. It first searches for the name of the
// specified player within the _players map. If that
// is found, it calls the IHXPlayer::Pause method.
////////////////////////////////////////////////////////////////////
// Params: const string &name - Name of the Player to pause playback.
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::pause(const string &name) {
// Search for the specified player in the map. If the player
// is found, pause the playback of the media file.
if (_engine != 0) {
PLAYERS::iterator iter = _players.find(name);
if (iter != _players.end()) {
iter->second->Pause();
}
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::pause_all()
// Access: PUBLISHED
// Purpose: This wrapper function simply calls the IHXPlayer::Pause
// routine for each player currently associated with the
// the engine.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::pause_all() {
if (_engine != 0) {
// Iterate through the _players map and call the Pause
// routine to start playback of the media.
PLAYERS::iterator iter;
for(iter = _players.begin(); iter != _players.end(); iter++) {
iter->second->Pause();
}
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::seek(...)
// Access: PUBLISHED
// Purpose: This wrapper function encapsulates the Helix Player
// Pause method. It first searches for the name of the
// specified player within the _players map. If that
// is found, it calls the IHXPlayer::Pause method.
////////////////////////////////////////////////////////////////////
// Params: const string &name - Name of the Player to seek to a
// current time in the playback.
// long &time - the time to seek to in the playback.
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::seek_time(const string &name, long time) {
if (_engine != 0) {
// Search for the specified player in the map. If the player
// is found, seek to the current time in the playback of the
// media file.
PLAYERS::iterator iter = _players.find(name);
if (iter != _players.end()) {
iter->second->Seek(time);
}
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::stop(...)
// Access: PUBLISHED
// Purpose: This wrapper function encapsulates the Helix Player
// Stop method. It first searches for the name of the
// specified player within the _players map. If that
// is found, it calls the IHXPlayer::Stop method which
// stops the playback of the media.
////////////////////////////////////////////////////////////////////
// Params: const string &name - Name of the Player to stop playback.
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::stop(const string &name) {
if (_engine != 0) {
// Search for the specified player in the map. If the player
// is found, stop the playback of the media file.
PLAYERS::iterator iter = _players.find(name);
if (iter != _players.end()) {
iter->second->Stop();
}
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::stop_all()
// Access: PUBLISHED
// Purpose: This wrapper function simply calls the IHXPlayer::Stop
// routine for each player currently associated with the
// the engine.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::stop_all() {
if (_engine != 0) {
// Iterate through the _players map and call the Pause
// routine to stop playback of the media.
PLAYERS::iterator iter;
for(iter = _players.begin(); iter != _players.end(); iter++) {
iter->second->Stop();
}
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::open_url(...)
// Access: PUBLISHED
// Purpose: This wrapper function encapsulates the Helix Player
// OpenURL method. It first searches for the name of the
// specified player within the _players map. If that
// is found, it calls the IHXPlayer::OpenURL method which
// actually opens the specified media format. URLs can
// come in two forms:
//
// Remote File: rtsp://www.realone.com/somevideo.ram
// Local File: file://f:\\smildemohurl.ram
////////////////////////////////////////////////////////////////////
// Params: const string &name - Name of the Player to open the URL.
// string url - Name of the URL to be opened for playback.
// Return: None
////////////////////////////////////////////////////////////////////
void HelixClient::open_url(const string &name, string url) {
if (_engine != 0) {
// Determine if a URL has been specified within the string.
// If it hasn't, assume that the request has been made for
// a local file, so insert, file://, at the beginning of the
// string.
if (url.find("://")==string::npos) {
url.insert(0,"file://");
}
// Check wheter the player specified exists
// within the map. If it does, call the IHXPlayer::OpenURL(...)
PLAYERS::iterator iter = _players.find(name);
if (iter != _players.end()) {
iter->second->OpenURL(url.c_str());
}
}
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::is_live(...)
// Access: PUBLISHED
// Purpose: This wrapper function encapsulates the Helix Player
// IsLive method. It first searches for the name of the
// specified player within the _players map. If that
// is found, it calls the IHXPlayer::IsLive method. This
// indicates whether the player contains a live source
// or not.
////////////////////////////////////////////////////////////////////
// Params: const string &name - Name of the Player to check.
// Return: None
////////////////////////////////////////////////////////////////////
bool HelixClient::is_live(const string &name) {
if (_engine != 0) {
// Search for the specified player in the map. If the player
// is found, check to see if it contains a live media source.
PLAYERS::iterator iter = _players.find(name);
if (iter != _players.end()) {
return (iter->second->IsLive()) ? true : false;
}
}
return false;
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::is_done(...)
// Access: PUBLISHED
// Purpose: This wrapper function encapsulates the Helix Player
// IsDone method. It first searches for the name of the
// specified player within the _players map. If that
// is found, it calls the IHXPlayer::IsDone method. This
// indicates whether the player is finished playing the
// the current presentation.
////////////////////////////////////////////////////////////////////
// Params: const string &name - Name of the Player to check.
// Return: bool - true if the player has finished playback,
// otherwise it is false.
////////////////////////////////////////////////////////////////////
bool HelixClient::is_done(const string &name) {
if (_engine != 0) {
// Search for the specified player in the map. If the player
// is found, check to see if it has finished playing the
// the current presentation.
PLAYERS::iterator iter = _players.find(name);
if (iter != _players.end()) {
return iter->second->IsDone();
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::are_players_done()
// Access: PUBLISHED
// Purpose: This wrapper function simply calls the IHXPlayer::IsDone
// routine for each player currently associated with the
// the engine. If all of the players have finished with
// their respective presentations, it returns true.
// Otherwise it would return false.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: bool - true if all players finished playback, otherwise
// it is false.
////////////////////////////////////////////////////////////////////
bool HelixClient::are_players_done() {
if (_engine != 0) {
bool done = true;
PLAYERS::iterator iter;
for(iter = _players.begin(); iter != _players.end(); iter++) {
if(!iter->second->IsDone()) {
done = false;
}
}
return done;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Method: HelixClient::get_source_count()
// Access: PUBLISHED
// Purpose: This wrapper function simply calls the
// IHXPlayer::GetSourceCount routine. This returns the
// number of stream source instances currently used by
// the player. In case of audio, it would be 1. In case
// of a movie file, it would be 2.
////////////////////////////////////////////////////////////////////
// Params: const string &name - Name of the Player to check.
// Return: Int - value of source count or -1 if there is no player
// or engine.
////////////////////////////////////////////////////////////////////
int HelixClient::get_source_count(const string &name) {
if (_engine != 0) {
// Search for the specified player in the map. If the player
// is found, check to see if it has finished playing the
// the current presentation.
PLAYERS::iterator iter = _players.find(name);
if (iter != _players.end()) {
return iter->second->GetSourceCount();
}
}
return -1;
}

View File

@ -0,0 +1,123 @@
// Filename: HelixClient.h
// Created by: jjtaylor (10Feb04)
//
////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef HELIXCLIENT_H
#define HELIXCLIENT_H
////////////////////////////////////////////////////////////////////
// Panda Header Files
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#include "typedObject.h"
#include "texture.h"
#include "pmap.h"
////////////////////////////////////////////////////////////////////
// Helix Main Header Files
////////////////////////////////////////////////////////////////////
#include <mainHelix.h>
////////////////////////////////////////////////////////////////////
// Normal Header Files
////////////////////////////////////////////////////////////////////
#include <string>
#include <iostream>
////////////////////////////////////////////////////////////////////
// Class: HelixClient
// Purpose: This proxy class provides the top-level interface for
// loading the Helix Client Engine, creating players on
// the Helix engine, and initializing the media playback.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA HelixClient {
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
register_type(_type_handle, "HelixClient");
}
private:
static TypeHandle _type_handle;
PUBLISHED:
HelixClient();
~HelixClient();
////////////////////////////////////////////////////////////////////
// IHXClientEngine Interface Methods
// Purpose: These are wrapper methods that invoke the actual Helix
// Engine Interface method calls. For instance, the method
// create_player invotes the Helix Engine method
// engine->CreatePlayer().
////////////////////////////////////////////////////////////////////
void create_player(const string &name, Texture* tex = 0, bool sink_on = false);
void close_player(const string &name);
void close_all_players();
int get_player_count();
////////////////////////////////////////////////////////////////////
// IHXPlayer Interface Methods Prototypes
// Purpose: These are wrapper methods that invoke the actual Helix
// Player Interface method calls. For instance, the method
// begin invotes the Helix Engine method player->Begin().
////////////////////////////////////////////////////////////////////
void begin(const string &name);
void pause(const string &name);
void seek_time(const string &name, long time);
void stop(const string &name);
void begin_all();
void pause_all();
void stop_all();
void open_url(const string &name, string url);
int get_source_count(const string &name);
bool is_done(const string &name);
bool is_live(const string &name);
bool are_players_done();
////////////////////////////////////////////////////////////////////
// Utility Method Prototypes
// Purpose: These methods provide basic utility functions which are
// necessary for the Helix engine to play and close.
////////////////////////////////////////////////////////////////////
void do_event();
void do_events();
void shutdown();
private:
// Private Member Functions
bool init();
// Private Member variables
DLLAccess* _dll_access;
string _dll_home;
static const int _time_delta;
static const int _sleep_time;
static const int _guid_length;
// Where the Engine will actually reside.
IHXClientEngine* _engine;
typedef pmap<string, IHXPlayer*> PLAYERS;
typedef pmap<string, PT(Texture)> TEXTURES;
PLAYERS _players;
TEXTURES _textures;
};
#endif

421
panda/src/helix/HelixDefs.h Normal file
View File

@ -0,0 +1,421 @@
#ifndef HELIX_CONFIG_MS_PSDK
#define HELIX_CONFIG_MS_PSDK 1
#endif
#ifndef HELIX_FEATURE_3GPP
#define HELIX_FEATURE_3GPP 1
#endif
#ifndef HELIX_FEATURE_ADVANCEDGROUPMGR
#define HELIX_FEATURE_ADVANCEDGROUPMGR 1
#endif
#ifndef HELIX_FEATURE_ALT_URL
#define HELIX_FEATURE_ALT_URL 1
#endif
#ifndef HELIX_FEATURE_ASM
#define HELIX_FEATURE_ASM 1
#endif
#ifndef HELIX_FEATURE_AUDIO
#define HELIX_FEATURE_AUDIO 1
#endif
#ifndef HELIX_FEATURE_AUDIOHOOK
#define HELIX_FEATURE_AUDIOHOOK 1
#endif
#ifndef HELIX_FEATURE_AUDIO_CODEC_28_8
#define HELIX_FEATURE_AUDIO_CODEC_28_8 1
#endif
#ifndef HELIX_FEATURE_AUDIO_CODEC_AMRNB
#define HELIX_FEATURE_AUDIO_CODEC_AMRNB 1
#endif
#ifndef HELIX_FEATURE_AUDIO_CODEC_AMRWB
#define HELIX_FEATURE_AUDIO_CODEC_AMRWB 1
#endif
#ifndef HELIX_FEATURE_AUDIO_CODEC_GECKO
#define HELIX_FEATURE_AUDIO_CODEC_GECKO 1
#endif
#ifndef HELIX_FEATURE_AUDIO_CODEC_INTERLEAVE_ALL
#define HELIX_FEATURE_AUDIO_CODEC_INTERLEAVE_ALL 1
#endif
#ifndef HELIX_FEATURE_AUDIO_CODEC_O5_6
#define HELIX_FEATURE_AUDIO_CODEC_O5_6 1
#endif
#ifndef HELIX_FEATURE_AUDIO_CODEC_RAAC
#define HELIX_FEATURE_AUDIO_CODEC_RAAC 1
#endif
#ifndef HELIX_FEATURE_AUDIO_CODEC_SIPRO
#define HELIX_FEATURE_AUDIO_CODEC_SIPRO 1
#endif
#ifndef HELIX_FEATURE_AUDIO_CODEC_TOKYO
#define HELIX_FEATURE_AUDIO_CODEC_TOKYO 1
#endif
#ifndef HELIX_FEATURE_AUDIO_INACCURATESAMPLING
#define HELIX_FEATURE_AUDIO_INACCURATESAMPLING 1
#endif
#ifndef HELIX_FEATURE_AUDIO_INCOMPLETESAMPLE
#define HELIX_FEATURE_AUDIO_INCOMPLETESAMPLE 1
#endif
#ifndef HELIX_FEATURE_AUDIO_MPA_LAYER1
#define HELIX_FEATURE_AUDIO_MPA_LAYER1 1
#endif
#ifndef HELIX_FEATURE_AUDIO_MPA_LAYER2
#define HELIX_FEATURE_AUDIO_MPA_LAYER2 1
#endif
#ifndef HELIX_FEATURE_AUDIO_MPA_LAYER3
#define HELIX_FEATURE_AUDIO_MPA_LAYER3 1
#endif
#ifndef HELIX_FEATURE_AUDIO_MPEG4
#define HELIX_FEATURE_AUDIO_MPEG4 1
#endif
#ifndef HELIX_FEATURE_AUDIO_MULTIPLAYER_PAUSE
#define HELIX_FEATURE_AUDIO_MULTIPLAYER_PAUSE 1
#endif
#ifndef HELIX_FEATURE_AUDIO_POSTMIXHOOK
#define HELIX_FEATURE_AUDIO_POSTMIXHOOK 1
#endif
#ifndef HELIX_FEATURE_AUDIO_PREMIXHOOK
#define HELIX_FEATURE_AUDIO_PREMIXHOOK 1
#endif
#ifndef HELIX_FEATURE_AUDIO_RALF
#define HELIX_FEATURE_AUDIO_RALF 1
#endif
#ifndef HELIX_FEATURE_AUDIO_REAL
#define HELIX_FEATURE_AUDIO_REAL 1
#endif
#ifndef HELIX_FEATURE_AUTHENTICATION
#define HELIX_FEATURE_AUTHENTICATION 1
#endif
#ifndef HELIX_FEATURE_AUTOUPGRADE
#define HELIX_FEATURE_AUTOUPGRADE 1
#endif
#ifndef HELIX_FEATURE_BASICGROUPMGR
#define HELIX_FEATURE_BASICGROUPMGR 1
#endif
#ifndef HELIX_FEATURE_CHUNKRES
#define HELIX_FEATURE_CHUNKRES 1
#endif
#ifndef HELIX_FEATURE_COOKIES
#define HELIX_FEATURE_COOKIES 1
#endif
#ifndef HELIX_FEATURE_CORECOMM
#define HELIX_FEATURE_CORECOMM 1
#endif
#ifndef HELIX_FEATURE_CROSSFADE
#define HELIX_FEATURE_CROSSFADE 1
#endif
#ifndef HELIX_FEATURE_DBG_LOG
#define HELIX_FEATURE_DBG_LOG 1
#endif
#ifndef HELIX_FEATURE_DIRECT_SOUND
#define HELIX_FEATURE_DIRECT_SOUND 1
#endif
#ifndef HELIX_FEATURE_DRM
#define HELIX_FEATURE_DRM 1
#endif
#ifndef HELIX_FEATURE_DTDR_AUDIO_DECODER
#define HELIX_FEATURE_DTDR_AUDIO_DECODER 1
#endif
#ifndef HELIX_FEATURE_DTDR_AVSYNC_ADJUSTER
#define HELIX_FEATURE_DTDR_AVSYNC_ADJUSTER 1
#endif
#ifndef HELIX_FEATURE_DTDR_DECRYPTER
#define HELIX_FEATURE_DTDR_DECRYPTER 1
#endif
#ifndef HELIX_FEATURE_DTDR_ENCODER
#define HELIX_FEATURE_DTDR_ENCODER 1
#endif
#ifndef HELIX_FEATURE_EVENTMANAGER
#define HELIX_FEATURE_EVENTMANAGER 1
#endif
#ifndef HELIX_FEATURE_FIFOCACHE
#define HELIX_FEATURE_FIFOCACHE 1
#endif
#ifndef HELIX_FEATURE_FILESYSTEMMGR
#define HELIX_FEATURE_FILESYSTEMMGR 1
#endif
#ifndef HELIX_FEATURE_FRAGMENTBUFFER
#define HELIX_FEATURE_FRAGMENTBUFFER 1
#endif
#ifndef HELIX_FEATURE_FULLGUID
#define HELIX_FEATURE_FULLGUID 1
#endif
#ifndef HELIX_FEATURE_GAINTOOL
#define HELIX_FEATURE_GAINTOOL 1
#endif
#ifndef HELIX_FEATURE_GIF_BROKENIMAGE
#define HELIX_FEATURE_GIF_BROKENIMAGE 1
#endif
#ifndef HELIX_FEATURE_GROUPMGR
#define HELIX_FEATURE_GROUPMGR 1
#endif
#ifndef HELIX_FEATURE_HTTPCLOAK
#define HELIX_FEATURE_HTTPCLOAK 1
#endif
#ifndef HELIX_FEATURE_HTTP_GZIP
#define HELIX_FEATURE_HTTP_GZIP 1
#endif
#ifndef HELIX_FEATURE_HYPER_NAVIGATE
#define HELIX_FEATURE_HYPER_NAVIGATE 1
#endif
#ifndef HELIX_FEATURE_IGNORE_SIGPIPE
#define HELIX_FEATURE_IGNORE_SIGPIPE 1
#endif
#ifndef HELIX_FEATURE_ISMA
#define HELIX_FEATURE_ISMA 1
#endif
#ifndef HELIX_FEATURE_LIMITER
#define HELIX_FEATURE_LIMITER 1
#endif
#ifndef HELIX_FEATURE_MASTERTAC
#define HELIX_FEATURE_MASTERTAC 1
#endif
#ifndef HELIX_FEATURE_MEDIAMARKER
#define HELIX_FEATURE_MEDIAMARKER 1
#endif
#ifndef HELIX_FEATURE_MEMMAP_IO
#define HELIX_FEATURE_MEMMAP_IO 1
#endif
#ifndef HELIX_FEATURE_META
#define HELIX_FEATURE_META 1
#endif
#ifndef HELIX_FEATURE_MIXER
#define HELIX_FEATURE_MIXER 1
#endif
#ifndef HELIX_FEATURE_MP3FF_LENIENT
#define HELIX_FEATURE_MP3FF_LENIENT 1
#endif
#ifndef HELIX_FEATURE_MP3FF_ONDEMANDMETAINFO
#define HELIX_FEATURE_MP3FF_ONDEMANDMETAINFO 1
#endif
#ifndef HELIX_FEATURE_MP3FF_SHOUTCAST
#define HELIX_FEATURE_MP3FF_SHOUTCAST 1
#endif
#ifndef HELIX_FEATURE_NESTEDMETA
#define HELIX_FEATURE_NESTEDMETA 1
#endif
#ifndef HELIX_FEATURE_NETCHECK
#define HELIX_FEATURE_NETCHECK 1
#endif
#ifndef HELIX_FEATURE_NETINTERFACES
#define HELIX_FEATURE_NETINTERFACES 1
#endif
#ifndef HELIX_FEATURE_NEXTGROUPMGR
#define HELIX_FEATURE_NEXTGROUPMGR 1
#endif
#ifndef HELIX_FEATURE_OPTIMIZED_SCHEDULER
#define HELIX_FEATURE_OPTIMIZED_SCHEDULER 1
#endif
#ifndef HELIX_FEATURE_OVERLAYMGR
#define HELIX_FEATURE_OVERLAYMGR 1
#endif
#ifndef HELIX_FEATURE_PAC
#define HELIX_FEATURE_PAC 1
#endif
#ifndef HELIX_FEATURE_PACKETHOOKMGR
#define HELIX_FEATURE_PACKETHOOKMGR 1
#endif
#ifndef HELIX_FEATURE_PLAYBACK_LOCAL
#define HELIX_FEATURE_PLAYBACK_LOCAL 1
#endif
#ifndef HELIX_FEATURE_PLAYBACK_NET
#define HELIX_FEATURE_PLAYBACK_NET 1
#endif
#ifndef HELIX_FEATURE_PLAYERNAVIGATOR
#define HELIX_FEATURE_PLAYERNAVIGATOR 1
#endif
#ifndef HELIX_FEATURE_PLUGINHANDLER2
#define HELIX_FEATURE_PLUGINHANDLER2 1
#endif
#ifndef HELIX_FEATURE_PNA
#define HELIX_FEATURE_PNA 1
#endif
#ifndef HELIX_FEATURE_PREFERENCES
#define HELIX_FEATURE_PREFERENCES 1
#endif
#ifndef HELIX_FEATURE_PREFETCH
#define HELIX_FEATURE_PREFETCH 1
#endif
#ifndef HELIX_FEATURE_PROXYMGR
#define HELIX_FEATURE_PROXYMGR 1
#endif
#ifndef HELIX_FEATURE_RAREND_ADV_PACKET_FEEDER
#define HELIX_FEATURE_RAREND_ADV_PACKET_FEEDER 1
#endif
#ifndef HELIX_FEATURE_RAREND_BANDWIDTH_LISTER
#define HELIX_FEATURE_RAREND_BANDWIDTH_LISTER 1
#endif
#ifndef HELIX_FEATURE_RAREND_PREREDSTONE_SUPPORT
#define HELIX_FEATURE_RAREND_PREREDSTONE_SUPPORT 1
#endif
#ifndef HELIX_FEATURE_RAREND_SURESTREAM
#define HELIX_FEATURE_RAREND_SURESTREAM 1
#endif
#ifndef HELIX_FEATURE_RDT
#define HELIX_FEATURE_RDT 1
#endif
#ifndef HELIX_FEATURE_RECORDCONTROL
#define HELIX_FEATURE_RECORDCONTROL 1
#endif
#ifndef HELIX_FEATURE_REGISTRY
#define HELIX_FEATURE_REGISTRY 1
#endif
#ifndef HELIX_FEATURE_RESAMPLER
#define HELIX_FEATURE_RESAMPLER 1
#endif
#ifndef HELIX_FEATURE_RESOURCEMGR
#define HELIX_FEATURE_RESOURCEMGR 1
#endif
#ifndef HELIX_FEATURE_REVERTER
#define HELIX_FEATURE_REVERTER 1
#endif
#ifndef HELIX_FEATURE_RMFF_BANDWIDTH_NEGOTIATOR
#define HELIX_FEATURE_RMFF_BANDWIDTH_NEGOTIATOR 1
#endif
#ifndef HELIX_FEATURE_RMFF_DYNAMICASM
#define HELIX_FEATURE_RMFF_DYNAMICASM 1
#endif
#ifndef HELIX_FEATURE_RMFF_LEGACYAUDIO
#define HELIX_FEATURE_RMFF_LEGACYAUDIO 1
#endif
#ifndef HELIX_FEATURE_RMFF_LICENSING
#define HELIX_FEATURE_RMFF_LICENSING 1
#endif
#ifndef HELIX_FEATURE_RMFF_LIVEINFO
#define HELIX_FEATURE_RMFF_LIVEINFO 1
#endif
#ifndef HELIX_FEATURE_RMFF_MULTIRATE
#define HELIX_FEATURE_RMFF_MULTIRATE 1
#endif
#ifndef HELIX_FEATURE_RMFF_ONDEMANDMETAINFO
#define HELIX_FEATURE_RMFF_ONDEMANDMETAINFO 1
#endif
#ifndef HELIX_FEATURE_RMFF_TIMEOFFSET_FIXUP
#define HELIX_FEATURE_RMFF_TIMEOFFSET_FIXUP 1
#endif
#ifndef HELIX_FEATURE_RMFF_TIMEOFFSET_HANDLER
#define HELIX_FEATURE_RMFF_TIMEOFFSET_HANDLER 1
#endif
#ifndef HELIX_FEATURE_RMFF_VIEWSOURCE
#define HELIX_FEATURE_RMFF_VIEWSOURCE 1
#endif
#ifndef HELIX_FEATURE_RTP
#define HELIX_FEATURE_RTP 1
#endif
#ifndef HELIX_FEATURE_SECURECONN
#define HELIX_FEATURE_SECURECONN 1
#endif
#ifndef HELIX_FEATURE_SETSRCPROPS
#define HELIX_FEATURE_SETSRCPROPS 1
#endif
#ifndef HELIX_FEATURE_SINKCONTROL
#define HELIX_FEATURE_SINKCONTROL 1
#endif
#ifndef HELIX_FEATURE_SMARTERNETWORK
#define HELIX_FEATURE_SMARTERNETWORK 1
#endif
#ifndef HELIX_FEATURE_SMIL1
#define HELIX_FEATURE_SMIL1 1
#endif
#ifndef HELIX_FEATURE_SMIL2
#define HELIX_FEATURE_SMIL2 1
#endif
#ifndef HELIX_FEATURE_SMIL2_ANIMATION
#define HELIX_FEATURE_SMIL2_ANIMATION 1
#endif
#ifndef HELIX_FEATURE_SMIL2_BRUSH
#define HELIX_FEATURE_SMIL2_BRUSH 1
#endif
#ifndef HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT
#define HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT 1
#endif
#ifndef HELIX_FEATURE_SMIL2_TRANSITIONS
#define HELIX_FEATURE_SMIL2_TRANSITIONS 1
#endif
#ifndef HELIX_FEATURE_SMIL2_VALIDATION
#define HELIX_FEATURE_SMIL2_VALIDATION 1
#endif
#ifndef HELIX_FEATURE_SMIL_REPEAT
#define HELIX_FEATURE_SMIL_REPEAT 1
#endif
#ifndef HELIX_FEATURE_SMIL_SOUNDLEVEL
#define HELIX_FEATURE_SMIL_SOUNDLEVEL 1
#endif
#ifndef HELIX_FEATURE_STATS
#define HELIX_FEATURE_STATS 1
#endif
#ifndef HELIX_FEATURE_SYSTEMREQUIRED
#define HELIX_FEATURE_SYSTEMREQUIRED 1
#endif
#ifndef HELIX_FEATURE_THREADSAFE_MEMMAP_IO
#define HELIX_FEATURE_THREADSAFE_MEMMAP_IO 1
#endif
#ifndef HELIX_FEATURE_TIMEDTEXT
#define HELIX_FEATURE_TIMEDTEXT 1
#endif
#ifndef HELIX_FEATURE_TRANSPORT_MULTICAST
#define HELIX_FEATURE_TRANSPORT_MULTICAST 1
#endif
#ifndef HELIX_FEATURE_TURBOPLAY
#define HELIX_FEATURE_TURBOPLAY 1
#endif
#ifndef HELIX_FEATURE_VIDEO
#define HELIX_FEATURE_VIDEO 1
#endif
#ifndef HELIX_FEATURE_VIDEO_CODEC_RV20
#define HELIX_FEATURE_VIDEO_CODEC_RV20 1
#endif
#ifndef HELIX_FEATURE_VIDEO_CODEC_RV30
#define HELIX_FEATURE_VIDEO_CODEC_RV30 1
#endif
#ifndef HELIX_FEATURE_VIDEO_CODEC_RV40
#define HELIX_FEATURE_VIDEO_CODEC_RV40 1
#endif
#ifndef HELIX_FEATURE_VIDEO_H263
#define HELIX_FEATURE_VIDEO_H263 1
#endif
#ifndef HELIX_FEATURE_VIDEO_MPEG4
#define HELIX_FEATURE_VIDEO_MPEG4 1
#endif
#ifndef HELIX_FEATURE_VIDEO_REAL
#define HELIX_FEATURE_VIDEO_REAL 1
#endif
#ifndef HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO
#define HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO 1
#endif
#ifndef HELIX_FEATURE_VIDREND_SYNCSMOOTHING
#define HELIX_FEATURE_VIDREND_SYNCSMOOTHING 1
#endif
#ifndef HELIX_FEATURE_VIEWPORT
#define HELIX_FEATURE_VIEWPORT 1
#endif
#ifndef HELIX_FEATURE_VIEWSOURCE
#define HELIX_FEATURE_VIEWSOURCE 1
#endif
#ifndef HELIX_FEATURE_VOLUME
#define HELIX_FEATURE_VOLUME 1
#endif
#ifndef HELIX_FEATURE_XMLPARSER
#define HELIX_FEATURE_XMLPARSER 1
#endif
#ifndef HELIX_FEATURE_PANDA3D
#define HELIX_FEATURE_PANDA3D 1
#endif
#ifndef STRICT
#define STRICT 1
#endif
#ifndef THREADS_SUPPORTED
#define THREADS_SUPPORTED 1
#endif
#ifndef WIN32
#define WIN32 1
#endif
#ifndef _LITTLE_ENDIAN
#define _LITTLE_ENDIAN 1
#endif
#ifndef _M_IX86
#define _M_IX86 1
#endif
#ifndef _WIN32
#define _WIN32 1
#endif
#ifndef _WINDOWS
#define _WINDOWS 1
#endif

View File

@ -0,0 +1,653 @@
// Filename: HxAdviseSink.cpp
// Created by: jjtaylor (27Jan04)
//
////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Panda Header Files
////////////////////////////////////////////////////////////////////
#include "HxAdviseSink.h"
////////////////////////////////////////////////////////////////////
// Normal Header Files
////////////////////////////////////////////////////////////////////
#include <stdio.h>
////////////////////////////////////////////////////////////////////
// Method: HxAdviseSink::Constructor
// Access: Public
// Purpose: Initializes member variables and sets up object
// related interfaces.
////////////////////////////////////////////////////////////////////
// Input: pUnknown - Pointer to an IUnknown Interface
// client_index - Client Instance Identifier
// Output: None
////////////////////////////////////////////////////////////////////
HxAdviseSink::HxAdviseSink(IUnknown* unknown, LONG32 client_index, bool sink_on)
: _ref_count (0),
_client_index (client_index),
_unknown (0),
_registry (0),
_scheduler (0),
_current_bandwidth(0),
_average_bandwidth(0),
_on_stop(0),
_sink_on(sink_on)
{
if (unknown != 0) {
_unknown = unknown;
_unknown->AddRef();
if (HXR_OK != _unknown->QueryInterface(IID_IHXRegistry, (void**)&_registry)) {
_registry = 0;
}
if (HXR_OK != _unknown->QueryInterface(IID_IHXScheduler, (void**)&_scheduler)) {
_scheduler = 0;
}
IHXPlayer* player;
if(HXR_OK == _unknown->QueryInterface(IID_IHXPlayer, (void**)&player)) {
player->AddAdviseSink(this);
player->Release();
}
}
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::~HxClientAdviseSink
// Access: Private
// Purpose: Class destructor which releases corresponding
// interfaces which are related to this class.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
HxAdviseSink::~HxAdviseSink() {
// Release components and set the member variables to the
// NULL-state.
if (_scheduler != 0) {
_scheduler->Release();
_scheduler = 0;
}
if (_registry != 0) {
_registry->Release();
_registry = 0;
}
if (_unknown != 0) {
_unknown->Release();
_unknown = 0;
}
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::QueryInterface
// Access: Public
// Purpose: Queries this class to determine whether it supports
// supports a specific interface. If the call succeeds
// then the methods of that interface are made
// available for use.
////////////////////////////////////////////////////////////////////
// Params: id - Indicates the reference identifier of the
// the interface being queried.
// interface_obj - Points to an interface pointer that is
// filled in if the query succeeds.
// Return: HX_RESULT - Varies based on wheter the interface is
// supported or not.
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAdviseSink::QueryInterface(REFIID id, void** interface_obj) {
// Determine if the IUnknown and ClientAdviseSink interfaces
// are supported.
if (IsEqualIID(id, IID_IUnknown)) {
// Increase the reference count, set the Interface Object,
// and return that the interface is supported within this
// object.
AddRef();
*interface_obj = (IUnknown*)(IHXClientAdviseSink*)this;
}
else if (IsEqualIID(id, IID_IHXClientAdviseSink)) {
// Same as above.
AddRef();
*interface_obj = (IHXClientAdviseSink*)this;
}
else {
// This Interface is not supported by this object. Set the
// Interface Object to the NULL-state and return.
*interface_obj = 0;
return HXR_NOINTERFACE;
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::AddRef
// Access: Public
// Purpose: Increases the classes reference count by one.
// Whenever an object is created, it's reference count
// begins at 1. If an application calls IUnknown::AddRef,
// queries an interface belonging to a specific object,
// or uses a creation function like HXCreateInstance,
// the reference count is incremented by 1.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: Returns the new reference count.
////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG32) HxAdviseSink::AddRef() {
return InterlockedIncrement(&_ref_count);
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::Release
// Access: Public
// Purpose: Decreases the object's reference count by one.
// Every call to IUnknown::AddRef,
// IUnknown::QueryInterface, or a creation function
// such as HXCreateInstance must have a corresponding
// call to IUnknown::Release. When the reference count
// reaches 0 (zero), the object is destroyed.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: Returns the new reference count.
////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG32) HxAdviseSink::Release() {
// As long as the reference count is greater than 0, then this
// object is still in "scope."
if (InterlockedDecrement(&_ref_count) > 0 ) {
return _ref_count;
}
// Otherwise, this object is no longer necessary and should be
// removed from memory.
delete this;
return 0;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::OnPosLength
// Access: Public
// Purpose: Advises the client that the position or length of
// the current playback context has changed
////////////////////////////////////////////////////////////////////
// Params: ulPosition - The new position of the playback.
// ulLength - The new length of the playback.
// Return: HXR_OK - Helix Specific result saying things are "Okay".
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAdviseSink::OnPosLength(ULONG32 ulPosition, ULONG32 ulLength) {
// Initialize Variables
if(_sink_on) {
STDOUT("OnPosLength(%ld, %ld)\n", ulPosition, ulLength);
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::OnPresentationOpened
// Access: Public
// Purpose: Advises the client that a presentation has been
// opened.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: HXR_OK - Helix Specific result saying things are "Okay".
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAdviseSink::OnPresentationOpened() {
// For now, check if advise sinking is enabled. If so, print that
// a presenatation has been opened.
if(_sink_on) {
STDOUT("OnPresentationOpened()\n");
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::OnPresentationClosed()
// Access: Public
// Purpose: Advises the cleint that a presentation has been
// closed.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: HXR_OK - Helix Specific result saying things are "Okay".
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAdviseSink::OnPresentationClosed() {
// For now, check if advise sinking is enabled. If so, print that
// a presenatation has been closed.
if(_sink_on) {
STDOUT("OnPresentationClosed()\n");
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Method: HxAdviseSink::get_statistics
// Access: Private
// Purpose: Retrieves the statistic for the particular key that
// is in the Helix Registry Interface.
////////////////////////////////////////////////////////////////////
// Params: char* registry_key - the key whose value we wish to
// retrieve from the registry.
// Return: None
////////////////////////////////////////////////////////////////////
void HxAdviseSink::get_statistics(char* registry_key) {
if(_sink_on) {
char RegistryValue[MAX_DISPLAY_NAME] = {0};
INT32 lValue = 0;
INT32 i = 0;
INT32 lStatistics = 8;
UINT32 *plValue;
// Collect all of the necessary statistics from the registry
// and print them to the screen.
for (i = 0; i < lStatistics; i++) {
plValue = NULL;
switch (i) {
case 0:
SafeSprintf(RegistryValue, MAX_DISPLAY_NAME, "%s.Normal", registry_key);
break;
case 1:
SafeSprintf(RegistryValue, MAX_DISPLAY_NAME, "%s.Recovered", registry_key);
break;
case 2:
SafeSprintf(RegistryValue, MAX_DISPLAY_NAME, "%s.Received", registry_key);
break;
case 3:
SafeSprintf(RegistryValue, MAX_DISPLAY_NAME, "%s.Lost", registry_key);
break;
case 4:
SafeSprintf(RegistryValue, MAX_DISPLAY_NAME, "%s.Late", registry_key);
break;
case 5:
SafeSprintf(RegistryValue, MAX_DISPLAY_NAME, "%s.ClipBandwidth", registry_key);
break;
case 6:
SafeSprintf(RegistryValue, MAX_DISPLAY_NAME, "%s._average_bandwidth", registry_key);
plValue = &_average_bandwidth;
break;
case 7:
SafeSprintf(RegistryValue, MAX_DISPLAY_NAME, "%s._current_bandwidth", registry_key);
plValue = &_current_bandwidth;
break;
default:
break;
}
_registry->GetIntByName(RegistryValue, lValue);
if (plValue) {
if (_on_stop || lValue == 0) {
lValue = *plValue;
}
else {
*plValue = lValue;
}
}
STDOUT("%s = %ld\n", RegistryValue, lValue);
}
}
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::get_all_statistics
// Access: Private
// Purpose: Displays the content of the entire registry. Not
// truly necessary for Panda, however, it is useful
// for debugging purposes of streaming files.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
void HxAdviseSink::get_all_statistics() {
if(_sink_on) {
UINT32 PlayerIndex = 0;
UINT32 SourceIndex = 0;
UINT32 StreamIndex = 0;
char* RegistryPrefix = "Statistics";
char RegistryName[MAX_DISPLAY_NAME] = {0};
// Display the content of whole statistic registry
if (_registry) {
// Start from the first player.
SafeSprintf(RegistryName, MAX_DISPLAY_NAME, "%s.Player%ld", RegistryPrefix, _client_index);
if (PT_COMPOSITE == _registry->GetTypeByName(RegistryName)) {
// Display player statistic
get_statistics(RegistryName);
SafeSprintf(RegistryName, MAX_DISPLAY_NAME, "%s.Source%ld", RegistryName, SourceIndex);
while (PT_COMPOSITE == _registry->GetTypeByName(RegistryName)) {
// Display source statistic
get_statistics(RegistryName);
SafeSprintf(RegistryName, MAX_DISPLAY_NAME, "%s.Stream%ld", RegistryName, StreamIndex);
while (PT_COMPOSITE == _registry->GetTypeByName(RegistryName)) {
// Display stream statistic
get_statistics(RegistryName);
StreamIndex++;
SafeSprintf(RegistryName, MAX_DISPLAY_NAME, "%s.Player%ld.Source%ld.Stream%ld",
RegistryPrefix, PlayerIndex, SourceIndex, StreamIndex);
}
SourceIndex++;
SafeSprintf(RegistryName, MAX_DISPLAY_NAME, "%s.Player%ld.Source%ld",
RegistryPrefix, PlayerIndex, SourceIndex);
}
PlayerIndex++;
SafeSprintf(RegistryName, MAX_DISPLAY_NAME, "%s.Player%ld",
RegistryPrefix, PlayerIndex);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::OnStatisticsChanged
// Access: Public
// Purpose: Advises the client that the presentation statistics
// have changed and prints those statistics out.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: HXR_OK - Helix Specific result saying things are "Okay".
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAdviseSink::OnStatisticsChanged() {
if(_sink_on) {
char Buff[1024];
HX_RESULT res = HXR_OK;
UINT16 Player = 0;
STDOUT("OnStatisticsChanged():\n");
SafeSprintf(Buff, 1024, "Statistics.Player%u", Player);
while( HXR_OK == res ) {
res = dump_reg_tree( Buff );
Player++;
SafeSprintf(Buff, 1024, "Statistics.Player%u", Player );
}
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::DumpRegTree
// Access: Private
// Purpose: Prints the contents of the Registry tree for this
// particular object.
////////////////////////////////////////////////////////////////////
// Params: pszTreeName - The name of the Registry tree that should
// be printed.
// Return: HX_RESULT - result varies.
////////////////////////////////////////////////////////////////////
HX_RESULT HxAdviseSink::dump_reg_tree(const char* tree_name) {
//Initialize Local Variables related to the Registry Tree
const char* pszName = NULL;
ULONG32 ulRegID = 0;
HX_RESULT res = HXR_OK;
INT32 nVal = 0;
IHXBuffer* pBuff = NULL;
IHXValues* pValues = NULL;
// Check if the name exists in the registry. If its not
// return a failure.
res = _registry->GetPropListByName(tree_name, pValues);
if (HXR_OK!=res || !pValues) {
return HXR_FAIL;
}
// Make sure this is a PT_COMPOSITE type registry entry. If
// its not, return a failure.
if (PT_COMPOSITE != _registry->GetTypeByName(tree_name)) {
return HXR_FAIL;
}
// Print out the value of each member of this tree.
res = pValues->GetFirstPropertyULONG32( pszName, ulRegID );
while( HXR_OK == res ) {
// There is at least one entry in the Registry. Now
// check the type.
HXPropType pt = _registry->GetTypeById(ulRegID);
switch(pt) {
case PT_COMPOSITE:
dump_reg_tree(pszName);
break;
case PT_INTEGER:
nVal = 0;
_registry->GetIntById( ulRegID, nVal );
STDOUT("%s : %d\n", pszName, nVal );
break;
case PT_INTREF :
nVal = 0;
_registry->GetIntById( ulRegID, nVal );
STDOUT("%s : %d\n", pszName, nVal );
break;
case PT_STRING :
pBuff = NULL;
_registry->GetStrById( ulRegID, pBuff );
STDOUT("%s : \"", pszName );
if( pBuff ) {
STDOUT("%s", (const char *)(pBuff->GetBuffer()) );
}
STDOUT("\"\n" );
HX_RELEASE(pBuff);
break;
case PT_BUFFER :
STDOUT("%s : BUFFER TYPE NOT SHOWN\n", pszName, nVal );
break;
case PT_UNKNOWN:
STDOUT("%s Unkown registry type entry\n", pszName );
break;
default:
STDOUT("%s Unkown registry type entry\n", pszName );
break;
}
res = pValues->GetNextPropertyULONG32(pszName, ulRegID);
}
HX_RELEASE( pValues );
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::OnPreSeek
// Access: Public
// Purpose: Informs the client that a seek is about to occur.
// The client is informed of the last time in the
// stream's time line before the seek, as well as the
// first new time in the stream's time line after the
// seek is completed.
////////////////////////////////////////////////////////////////////
// Params: ulOldTime - The end of the stream's time line before the
// current seek.
// ulNewTime - The beginning of the stream's time line after
// the current seek.
// Return: HXR_OK - Helix Specific result saying things are "Okay".
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAdviseSink::OnPreSeek(ULONG32 ulOldTime, ULONG32 ulNewTime) {
// For now, check if advise sinking is enabled. If so, print that
// a seek is about to happen.
if(_sink_on) {
STDOUT("OnPreSeek(%ld, %ld)\n", ulOldTime, ulNewTime);
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::OnPostSeek
// Access: Public
// Purpose: Informs the client that a seek has just occured.
// The client is informed of the last time in the
// stream's time line before the seek, as well as the
// first new time in the stream's time line after the
// seek is completed.
////////////////////////////////////////////////////////////////////
// Params: ulOldTime - The end of the stream's time line before the
// current seek.
// ulNewTime - The beginning of the stream's time line after
// the current seek.
// Return: HXR_OK - Helix Specific result saying things are "Okay".
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAdviseSink::OnPostSeek(ULONG32 ulOldTime, ULONG32 ulNewTime) {
// For now, check if advise sinking is enabled. If so, print that
// a seek just happened.
if(_sink_on) {
STDOUT("OnPostSeek(%ld, %ld)\n", ulOldTime, ulNewTime);
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::OnStop
// Access: Public
// Purpose: Informs the client that a stop has just occured
// in a presentation, and calculates the total time
// that a file has been playing.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: HXR_OK - Helix Specific result saying things are "Okay".
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAdviseSink::OnStop() {
if(_sink_on) {
HXTimeval curr_time;
STDOUT("OnStop()\n");
STDOUT("Player %ld stopped.\n", _client_index);
_on_stop = TRUE;
get_all_statistics();
// Retrieve the current time and subtract the beginning time to figure out
// how long the file has played.
curr_time = _scheduler->GetCurrentSchedulerTime();
_stop_time = curr_time.tv_sec;
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::OnPause
// Access: Public
// Purpose: Informs the client that a pause has just occured.
////////////////////////////////////////////////////////////////////
// Params: time - time in the stream's time line that the pause
// occured.
// Return: HXR_OK - Helix Specific result saying things are "Okay".
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAdviseSink::OnPause(ULONG32 time) {
// For now, check if advise sinking is enabled. If so, print that
// the a pause in the presentation has occured for debugging
// purposes.
if(_sink_on) {
STDOUT("OnPause(%ld)\n", time);
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::OnBegin
// Access: Public
// Purpose: Informs the client that a presenentation has begun.
////////////////////////////////////////////////////////////////////
// Params: time - The time that the presentation has begun.
// Return: HXR_OK - Helix Specific result saying things are "Okay".
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAdviseSink::OnBegin(ULONG32 time) {
if(_sink_on) {
// Local Variable Declarations
HXTimeval curr_time;
STDOUT("OnBegin(%ld)\n", time);
STDOUT("Player %ld beginning playback...\n", _client_index);
// Record the current time that this begins so that the number
// of seconds the media file has been playing can be calculated.
curr_time = _scheduler->GetCurrentSchedulerTime();
_start_time = curr_time.tv_sec;
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::OnBuffering
// Access: Public
// Purpose: Informs the client that buffering of data is occuring.
// The render is informed of the reason for the buffering
// (start-up of stream, seek has occured, network congestion,
// etc.), as well as percentage complete of the buffering process.
////////////////////////////////////////////////////////////////////
// Params: flags - The reason for buffering. Can be any of the following:
// BUFFERING_START_UP, BUFFERING_SEEK,
// BUFFERING_CONGESTION, BUFFERING_LIVE_PAUSE
// percent_complete - The percentage fo the buffering that
// has been completed.
// Return: HXR_OK - Helix Specific result saying things are "Okay".
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAdviseSink::OnBuffering(ULONG32 flags, UINT16 percent_complete) {
// For now, check if advise sinking is enabled. If so, print that
// the a presentation is now buffering.
if(_sink_on) {
STDOUT("OnBuffering(%ld, %d)\n", flags, percent_complete);
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientAdviseSink::OnContacting
// Access: Public
// Purpose: Informs the client that the engine is contacting
// a host.
////////////////////////////////////////////////////////////////////
// Params: host_name - Host name that the engine is contacting.
// Return: HXR_OK - Helix Specific result saying things are "Okay".
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAdviseSink::OnContacting(const char* host_name) {
// For now, check if advise sinking is enabled. If so, print that
// the client is contacting a host for streaming.
if(_sink_on) {
STDOUT("OnContacting(\"%s\")\n", host_name);
}
return HXR_OK;
}

View File

@ -0,0 +1,97 @@
// Filename: HxAdviseSink.h
// Created by: jjtaylor (10Feb04)
//
////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef HXADVISESINK_H
#define HXADVISESINK_H
////////////////////////////////////////////////////////////////////
// Panda Header Files
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
////////////////////////////////////////////////////////////////////
// Helix Main Header Files
////////////////////////////////////////////////////////////////////
#include "mainHelix.h"
////////////////////////////////////////////////////////////////////
// Prototype/Struct/Class Forward Delcarations
////////////////////////////////////////////////////////////////////
struct IHXClientAdviseSink;
struct IUnknown;
struct IHXRegistry;
struct IHXScheduler;
////////////////////////////////////////////////////////////////////
// Class: HxAdviseSink
// Purpose: This is a derived class from the IHXClientAdviseSink
// base interface. This class is meant to receive
// notifications from the client engine about changes in
// or about a presentation's playback status.
////////////////////////////////////////////////////////////////////
class HxAdviseSink : public IHXClientAdviseSink {
public:
HxAdviseSink(IUnknown* unknown, LONG32 client_index, bool sink_on);
////////////////////////////////////////////////////////////////////
// IHUnkown Interface Methods Prototypes
// Purpose: Implements the basic COM interface methods for reference
// coutning and querying of related interfaces.
////////////////////////////////////////////////////////////////////
STDMETHOD(QueryInterface) (THIS_ REFIID id, void** interface_obj);
STDMETHOD_(ULONG32,AddRef) (THIS);
STDMETHOD_(ULONG32,Release) (THIS);
////////////////////////////////////////////////////////////////////
// IHXClientAdviseSink Interface Methods Prototypes
// Purpose: Implements the necessary interface methods that may
// be called during a presentations status.
////////////////////////////////////////////////////////////////////
STDMETHOD(OnPosLength) (THIS_ UINT32 position, UINT32 length);
STDMETHOD(OnPresentationOpened) (THIS);
STDMETHOD(OnPresentationClosed) (THIS);
STDMETHOD(OnStatisticsChanged) (THIS);
STDMETHOD(OnPreSeek) (THIS_ ULONG32 old_time, ULONG32 new_time);
STDMETHOD(OnPostSeek) (THIS_ ULONG32 old_time, ULONG32 new_time);
STDMETHOD(OnStop) (THIS);
STDMETHOD(OnPause) (THIS_ ULONG32 Time);
STDMETHOD(OnBegin) (THIS_ ULONG32 Time);
STDMETHOD(OnBuffering) (THIS_ ULONG32 flags, UINT16 percent_complete);
STDMETHOD(OnContacting) (THIS_ const char* host_name);
private:
// Private Member Functions
~HxAdviseSink();
HX_RESULT dump_reg_tree(const char* tree_name );
void get_statistics (char* registry_key);
void get_all_statistics (void);
// Private Member variables
LONG32 _ref_count;
LONG32 _client_index;
UINT32 _start_time;
UINT32 _stop_time;
UINT32 _current_bandwidth;
UINT32 _average_bandwidth;
BOOL _on_stop;
bool _sink_on;
IUnknown* _unknown;
IHXRegistry* _registry;
IHXScheduler* _scheduler;
};
#endif

View File

@ -0,0 +1,210 @@
// Filename: HxAuthenticationManager.cxx
// Created by: jjtaylor (10Feb04)
//
////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Panda Header Files
////////////////////////////////////////////////////////////////////
#include "HxAuthenticationManager.h"
#include "print.h"
////////////////////////////////////////////////////////////////////
// Normal Header Files
////////////////////////////////////////////////////////////////////
#include <ctype.h>
#include <stdio.h>
////////////////////////////////////////////////////////////////////
// Member: HxAuthenticationManager::HxAuthenticationManager
// Access: Public
// Purpose: A default constructor which initializes the member
// variables for the class.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
HxAuthenticationManager::HxAuthenticationManager()
: _ref_count(0),
_sent_password(FALSE) {
}
////////////////////////////////////////////////////////////////////
// Member: HxAuthenticationManager::Destructor
// Access: Public
// Purpose: The default destructor which removes existing
// COM interfaces that have not been freed from
// memory.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
HxAuthenticationManager::~HxAuthenticationManager() {
}
////////////////////////////////////////////////////////////////////
// Member: HxAuthenticationManager::QueryInterface
// Access: Public
// Purpose: Queries this class to determine whether it supports
// supports a specific interface. If the call succeeds
// then the methods of that interface are made
// available for use.
////////////////////////////////////////////////////////////////////
// Params: id - Indicates the reference identifier of the
// the interface being queried.
// ppInterfaceObj - Points to an interface pointer that is
// filled in if the query succeeds.
// Return: HX_RESULT - Varies based on wheter the interface is
// supported or not.
////////////////////////////////////////////////////////////////////
HX_RESULT HxAuthenticationManager::QueryInterface(THIS_ REFIID id, void** ppInterfaceObj) {
// Determine if the IUnknown and AuthenticationManager interfaces
// are supported.
if (IsEqualIID(id, IID_IUnknown)) {
// Increase the reference count, set the Interface Object,
// and return that the interface is supported within this
// object.
AddRef();
*ppInterfaceObj = (IUnknown*)(IHXAuthenticationManager *)this;
}
else if (IsEqualIID(id, IID_IHXAuthenticationManager)) {
// Same as above.
AddRef();
*ppInterfaceObj = (IHXAuthenticationManager *)this;
}
else {
// This Interface is not supported by this object. Set the
// Interface Object to the NULL-state and return.
*ppInterfaceObj = 0;
return HXR_NOINTERFACE;
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Member: HxAuthenticationManager::AddRef
// Access: Public
// Purpose: Increases the object's reference count by one.
// Every call to IUnknown::AddRef,
// IUnknown::QueryInterface, or a creation function
// such as HXCreateInstance must have a corresponding
// call to IUnknown::Release. When the reference count
// reaches 0 (zero), the object is destroyed.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: ULONG32 - The new reference count.
////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG32) HxAuthenticationManager::AddRef(THIS) {
return InterlockedIncrement(&_ref_count);
}
////////////////////////////////////////////////////////////////////
// Member: HxAuthenticationManager::Release
// Access: Public
// Purpose: Decreases the object's reference count by one.
// Every call to IUnknown::AddRef,
// IUnknown::QueryInterface, or a creation function
// such as HXCreateInstance must have a corresponding
// call to IUnknown::Release. When the reference count
// reaches 0 (zero), the object is destroyed.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: ULONG32 - The new reference count.
////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG32) HxAuthenticationManager::Release(THIS) {
// As long as the reference count is greater than 0, then this
// object is still in "scope."
if (InterlockedDecrement(&_ref_count) > 0 ) {
return _ref_count;
}
// Otherwise, this object is no longer necessary and should be
// removed from memory.
delete this;
return 0;
}
////////////////////////////////////////////////////////////////////
// Member: HxAuthenticationManager:HandleAuthenticationRequest
// Access: Public
// Purpose: Retrieves the username and password which is
// needed to access a specific file or URL.
////////////////////////////////////////////////////////////////////
// Params: pResponse - Pointer to a response interface that
// manages the response of the authentication
// of the username and password.
// Return: HX_RESULT - Based on the authentication process.
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxAuthenticationManager::HandleAuthenticationRequest(IHXAuthenticationManagerResponse* pResponse)
{
char username[1024] = ""; /* Flawfinder: ignore */
char password[1024] = ""; /* Flawfinder: ignore */
HX_RESULT res = HXR_FAIL;
if( !_sent_password )
{
res = HXR_OK;
STDOUT("\nSending Username and Password...\n");
SafeStrCpy(username, "", 1024);
SafeStrCpy(password, "", 1024);
//strip trailing whitespace
char* c;
for(c = username + strlen(username) - 1;
c > username && isspace(*c);
c--)
;
*(c+1) = 0;
for(c = password + strlen(password) - 1;
c > password && isspace(*c);
c--)
;
*(c+1) = 0;
_sent_password = TRUE;
}
if (FAILED(res))
STDOUT("\nInvalid Username and/or Password.\n");
pResponse->AuthenticationRequestDone(res, username, password);
return res;
}

View File

@ -0,0 +1,67 @@
// Filename: hxAuthenticationManager.cxx
// Created by: jjtaylor (28Jan04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#if !defined (_HXAUTHENTICATIONMANAGER_H_)
#define _HXAUTHENTICATIONMANAGER_H_
////////////////////////////////////////////////////////////////////
// Panda Header Files
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
////////////////////////////////////////////////////////////////////
// Helix Main Header Files
////////////////////////////////////////////////////////////////////
#include "mainHelix.h"
////////////////////////////////////////////////////////////////////
// Class: HxAuthenticationManager
// Purpose: This is a derived class from the IHXAuthenticationManager
// base interface. This class is meant to gain a user name
// and password for a restricted file. Typically, this
// occurs from a popup box in windows, but it would need
// to be specified in code to use with Panda.
////////////////////////////////////////////////////////////////////
class HxAuthenticationManager : public IHXAuthenticationManager {
public:
// Public Class Method Declarations
HxAuthenticationManager();
////////////////////////////////////////////////////////////////////
// IHXClientAdviseSink Interface Methods Prototypes
// Purpose: Implements the necessary interface methods that is
// called when a username and password is required.
////////////////////////////////////////////////////////////////////
STDMETHOD (HandleAuthenticationRequest) (IHXAuthenticationManagerResponse* response);
////////////////////////////////////////////////////////////////////
// IHUnkown Interface Methods Prototypes
// Purpose: Implements the basic COM interface methods for reference
// coutning and querying of related interfaces.
////////////////////////////////////////////////////////////////////
STDMETHOD (QueryInterface) (THIS_ REFIID id, void** ppInterfaceObj);
STDMETHOD_ (UINT32, AddRef) (THIS);
STDMETHOD_ (UINT32, Release) (THIS);
private:
// Private Class Method Declarations
~HxAuthenticationManager();
// Private Class Variable Declarations
INT32 _ref_count;
BOOL _sent_password;
};
#endif

View File

@ -0,0 +1,327 @@
// Filename: HxClientContext.h
// Created by: jjtaylor (01Feb04)
//
////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Helix Main Header Files
////////////////////////////////////////////////////////////////////
#include "mainHelix.h"
////////////////////////////////////////////////////////////////////
// Member: HxClientContext::Constructor
// Access: Public
// Purpose: The constructor simply initializes all of the
// member variables.
////////////////////////////////////////////////////////////////////
// Params: LONG32 client_index - the player/client count
// Return: None
////////////////////////////////////////////////////////////////////
HxClientContext::HxClientContext(LONG32 client_index)
: _ref_count(0),
_client_index(client_index),
_client_sink(0),
_error_sink(0),
_auth_mgr(0),
_site_supplier(0),
_default_prefs(0) {
}
////////////////////////////////////////////////////////////////////
// Member: HxClientContext::Destructor
// Access: Public
// Purpose: The destructor simply calls the close member
// function.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
HxClientContext::~HxClientContext(){
close();
}
////////////////////////////////////////////////////////////////////
// Member: HxClientContext::init
// Access: Public
// Purpose: This member performs all of the dirty work for
// initializing the the client context for a player
// as well as instantiating all of the necessary
// Helix interface objects that must be declared so
// the engine can properly communicate with the player
////////////////////////////////////////////////////////////////////
// Params: IUnknown* unknown - a Helix Interface Object
// IHXPreferences* prefs -
// char* guid - a GUID, if applicable.
// bool sink_on - True if the AdviseSink should broadcast
// presentation statistics.
// Texture* tex - a Panda Texture Object which will be
// updated with the video each frame.
// Return: None
////////////////////////////////////////////////////////////////////
void HxClientContext::init(IUnknown* unknown, IHXPreferences* prefs, char* guid, bool sink_on, Texture* tex) {
char * cipher = 0;
_client_sink = new HxAdviseSink(unknown, _client_index, sink_on);
_error_sink = new HxErrorSink(unknown);
_auth_mgr = new HxAuthenticationManager();
#if defined(HELIX_FEATURE_VIDEO)
// From this point, we need to create a site supplier object since we are dealing with video.
// In addtion, we must send the Panda Texture buffer down to the site supplier, where it will
// inevitably be sent to the video surface object so that it can be updated.
//cout << "Buffer: " << buffer << endl;
_site_supplier = new HxSiteSupplier(unknown, tex);
#endif
if (_client_sink != 0) {
_client_sink->AddRef();
}
if (_error_sink != 0) {
_error_sink->AddRef();
}
if (_auth_mgr != 0) {
_auth_mgr->AddRef();
}
if (_site_supplier != 0) {
_site_supplier->AddRef();
}
if (prefs != 0) {
_default_prefs = prefs;
_default_prefs->AddRef();
}
if (guid && *guid) {
// Encode GUID
cipher = Cipher(guid);
SafeStrCpy(_guid, cipher, 256);
}
else {
_guid[0] = '\0';
}
}
////////////////////////////////////////////////////////////////////
// Member: HxClientContext::close
// Access: Public
// Purpose: This method simply releases each of the helix
// interface objects that are associated with the
// player. For instance, the site supplier and the
// error sink.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
void HxClientContext::close() {
HX_RELEASE(_client_sink);
HX_RELEASE(_error_sink);
HX_RELEASE(_auth_mgr);
HX_RELEASE(_site_supplier);
HX_RELEASE(_default_prefs);
}
////////////////////////////////////////////////////////////////////
// Method: HxClientContext::QueryInterface
// Access: Public
// Purpose: Queries this class to determine whether it supports
// supports a specific interface. If the call succeeds
// then the methods of that interface are made
// available for use.
////////////////////////////////////////////////////////////////////
// Params: id - Indicates the reference identifier of the
// the interface being queried.
// interface_obj - Points to an interface pointer that is
// filled in if the query succeeds.
// Return: HX_RESULT - Varies based on wheter the interface is
// supported or not.
////////////////////////////////////////////////////////////////////
HX_RESULT HxClientContext::QueryInterface(THIS_ REFIID id, void** interface_obj) {
HX_RESULT result = HXR_NOINTERFACE;
// Determine if the IUnknown and ClientAdviseSink interfaces
// are supported.
if (IsEqualIID(id, IID_IUnknown)) {
// Increase the reference count, set the Interface Object,
// and return that the interface is supported within this
// object.
AddRef();
*interface_obj = (IUnknown*)(IHXClientAdviseSink*)this;
result = HXR_OK;
}
else if (IsEqualIID(id, IID_IHXPreferences)) {
// Same as above.
AddRef();
*interface_obj = (IHXPreferences*)this;
result = HXR_OK;
}
else if ((_client_sink != 0) &&
(_client_sink->QueryInterface(id, interface_obj) == HXR_OK)) {
result = HXR_OK;
}
else if ((_error_sink != 0) &&
(_error_sink->QueryInterface(id, interface_obj) == HXR_OK)) {
result = HXR_OK;
}
else if ((_auth_mgr != 0) &&
(_auth_mgr->QueryInterface(id, interface_obj) == HXR_OK)) {
result = HXR_OK;
}
else if ((_site_supplier != 0) &&
(_site_supplier->QueryInterface(id, interface_obj) == HXR_OK)) {
result = HXR_OK;
}
else {
// This Interface is not supported by this object. Set the
// Interface Object to the NULL-state and return.
*interface_obj = 0;
}
return result;
}
////////////////////////////////////////////////////////////////////
// Method: HxClientContex::AddRef
// Access: Public
// Purpose: Increases the classes reference count by one.
// Whenever an object is created, it's reference count
// begins at 1. If an application calls IUnknown::AddRef,
// queries an interface belonging to a specific object,
// or uses a creation function like HXCreateInstance,
// the reference count is incremented by 1.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: Returns the new reference count.
////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG32) HxClientContext::AddRef(THIS) {
return InterlockedIncrement(&_ref_count);
}
////////////////////////////////////////////////////////////////////
// Method: HxClientContext::Release
// Access: Public
// Purpose: Decreases the object's reference count by one.
// Every call to IUnknown::AddRef,
// IUnknown::QueryInterface, or a creation function
// such as HXCreateInstance must have a corresponding
// call to IUnknown::Release. When the reference count
// reaches 0 (zero), the object is destroyed.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: Returns the new reference count.
////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG32) HxClientContext::Release(THIS) {
// As long as the reference count is greater than 0, then this
// object is still in "scope."
if (InterlockedDecrement(&_ref_count) > 0 ) {
return _ref_count;
}
// Otherwise, this object is no longer necessary and should be
// removed from memory.
delete this;
return 0;
}
////////////////////////////////////////////////////////////////////
// Member: HxClientContext::ReadPref
// Access: Public
// Purpose: This method reads a preference from the client
// registry.
////////////////////////////////////////////////////////////////////
// Params: const char* pref_key - preference key to add to the
// registry.
// IHXBuffer* buffer - a buffer that manages the value of
// the preference.
// Return: IHXBuffer* buffer - returns a buffer that manages
// the value of the preference.
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxClientContext::ReadPref(const char* pref_key, IHXBuffer*& buffer) {
HX_RESULT result = HXR_OK;
char * cipher = 0;
if ((stricmp(pref_key, CLIENT_GUID_REGNAME) == 0) &&
(*_guid != 0 )) {
// Create a buffer
buffer = new CHXBuffer();
buffer->AddRef();
buffer->Set((UCHAR*)_guid, strlen(_guid) + 1);
}
else if (_default_prefs != 0) {
result = _default_prefs->ReadPref(pref_key, buffer);
}
else {
result = HXR_NOTIMPL;
}
return result;
}
////////////////////////////////////////////////////////////////////
// Member: HxClientContext::WritePref
// Access: Public
// Purpose: This method writes a preference to the helix
// client registry.
////////////////////////////////////////////////////////////////////
// Params: const char* pref_key - preference key to add to the
// registry.
// IHXBuffer* buffer - a buffer that manages the value of
// the preference.
// Return: IHXBuffer* buffer - returns a buffer that manages
// the value of the preference.
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxClientContext::WritePref(const char* pref_key, IHXBuffer *buffer) {
if (_default_prefs != 0) {
return _default_prefs->WritePref(pref_key, buffer);
}
else {
return HXR_OK;
}
}

View File

@ -0,0 +1,88 @@
// Filename: HxClientContext.h
// Created by: jjtaylor (01Feb04)
//
////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef HXCLIENTCONTEXT_H
#define HXCLIENTCONTEXT_H
////////////////////////////////////////////////////////////////////
// Panda Header Files
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#include "texture.h"
////////////////////////////////////////////////////////////////////
// Helix Main Header Files
////////////////////////////////////////////////////////////////////
#include "mainHelix.h"
////////////////////////////////////////////////////////////////////
// Prototype/Struct/Class Forward Delcarations
////////////////////////////////////////////////////////////////////
struct IUnknown;
struct IHXPreferences;
class HxAdviseSink;
class HxErrorSink;
class HxAuthenticationManager;
////////////////////////////////////////////////////////////////////
// Class: HxClientContext
// Purpose: This is a derived class from the IHXPreferences
// base interface. This class is meant to set the
// default preferences for a player. It contains the
// necessary interface objects such as the Advise Sink,
// Error Sink, and Site Supplier.
////////////////////////////////////////////////////////////////////
class HxClientContext : public IHXPreferences {
public:
HxClientContext(LONG32 client_index);
~HxClientContext();
void init(IUnknown* unknown, IHXPreferences* prefs, char* guid, bool sink_on, Texture* tex);
void close();
////////////////////////////////////////////////////////////////////
// IHUnkown Interface Methods Prototypes
// Purpose: Implements the basic COM interface methods for reference
// coutning and querying of related interfaces.
////////////////////////////////////////////////////////////////////
STDMETHOD (QueryInterface) (THIS_ REFIID id, void** interface_obj);
STDMETHOD_ (ULONG32, AddRef) (THIS);
STDMETHOD_ (ULONG32, Release) (THIS);
////////////////////////////////////////////////////////////////////
// IHXPreference Interface Methods Prototypes
// Purpose: Implements the necessary interface methods that are
// called to read or write from the Helix client registry.
////////////////////////////////////////////////////////////////////
STDMETHOD(ReadPref) (THIS_ const char* pref_key, IHXBuffer*& buffer);
STDMETHOD(WritePref) (THIS_ const char* pref_key, IHXBuffer* buffer);
private:
// Private Class Variable Declarations
LONG32 _ref_count;
LONG32 _client_index;
char _guid[256];
HxAdviseSink* _client_sink;
HxErrorSink* _error_sink;
HxAuthenticationManager* _auth_mgr;
HxSiteSupplier * _site_supplier;
IHXPreferences * _default_prefs;
};
#endif

View File

@ -0,0 +1,229 @@
// Filename: hxErrorSink.cpp
// Created by: jjtaylor (27Jan04)
//
////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Panda Header Files
////////////////////////////////////////////////////////////////////
#include "HxErrorSink.h"
#include "print.h"
////////////////////////////////////////////////////////////////////
// Normal Header Files
////////////////////////////////////////////////////////////////////
#include <stdio.h>
////////////////////////////////////////////////////////////////////
// Member: HxErrorSink::Constructor
// Access: Public
// Purpose: The default constructor of the class which
// initializes the member variables.
////////////////////////////////////////////////////////////////////
// Params: IUnknown * - Pointer to an IUnknown COM Interface
// Return: None
////////////////////////////////////////////////////////////////////
HxErrorSink::HxErrorSink(IUnknown* unknown)
: ref_count(0),
_player(0)
{
IHXClientEngine* pEngine = 0;
unknown->QueryInterface(IID_IHXClientEngine, (void**)&pEngine );
if( pEngine != 0 )
{
IUnknown* pTemp = 0;
pEngine->GetPlayer(0, pTemp);
_player = (IHXPlayer*)pTemp;
}
HX_RELEASE(pEngine);
HX_ASSERT(_player);
}
/////////////////////////////////////////////////////////////////////
// Member: HxErrorSink::Destructor
// Access: Private
// Purpose: The default destructor of the class that releases
// the interface member variables from memory.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
HxErrorSink::~HxErrorSink() {
HX_RELEASE(_player);
}
////////////////////////////////////////////////////////////////////
// Member: HxErrorSink::QueryInterface
// Access:
// Purpose: Queries this class to determine whether it supports
// supports a specific interface. If the call succeeds
// then the methods of that interface are made
// available for use.
/////////////////////////////////////////////////////////////////////
// Params: _id - Indicates the reference identifier of the
// the interface being queried.
// _interface_obj - Points to an interface pointer that is
// filled in if the query succeeds.
// Return: HX_RESULT - Varies based on wheter the interface is
// supported or not.
////////////////////////////////////////////////////////////////////
HX_RESULT HxErrorSink::QueryInterface(REFIID _id, void** _interface_obj) {
// Determine if the IUnknown and ErrorSink interfaces
// are supported.
if (IsEqualIID(_id, IID_IUnknown)) {
// Increase the reference count, set the Interface Object,
// and return that the interface is supported within this
// object.
AddRef();
*_interface_obj = (IUnknown*)(IHXErrorSink*)this;
}
else if (IsEqualIID(_id, IID_IHXErrorSink)) {
// Same as above.
AddRef();
*_interface_obj = (IHXErrorSink*)this;
}
else {
// This Interface is not supported by this object. Set the
// Interface Object to the NULL-state and return.
*_interface_obj = 0;
return HXR_NOINTERFACE;
}
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Member: HxErrorSink::AddRef
// Access: Public
// Purpose: Increases the object's reference count by one.
// Whenever an object is created, it's reference count
// begins at 1.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: ULONG32 - The new reference count.
////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG32) HxErrorSink::AddRef() {
return InterlockedIncrement(&ref_count);
}
////////////////////////////////////////////////////////////////////
// Member: HxErrorSink::Release
// Access: Public
// Purpose: Decreases the object's reference count by one.
// Every call to IUnknown::AddRef,
// IUnknown::QueryInterface, or a creation function
// such as HXCreateInstance must have a corresponding
// call to IUnknown::Release. When the reference count
// reaches 0 (zero), the object is destroyed.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: ULONG32 - The new reference count.
////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG32) HxErrorSink::Release() {
// As long as the reference count is greater than 0, then this
// object is still in "scope."
if (InterlockedDecrement(&ref_count) > 0 ) {
return ref_count;
}
// Otherwise, this object is no longer necessary and should be
// removed from memory.
delete this;
return 0;
}
////////////////////////////////////////////////////////////////////
// Member: HxErrorSink::ErrorOccurred
// Access: Public
// Description: Reports an error, event, or status message
////////////////////////////////////////////////////////////////////
// Params: severity - Severity or level of the error message.
// hx_code - Specific Error Code
// user_code - User-Specific Error Code
// user_string - Pointer to a user-specific string.
// more_info_url - Pointer to a specific more information
// URL string.
// Return: None
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxErrorSink::ErrorOccurred(const UINT8 severity, const UINT32 hx_code,
const UINT32 user_code, const char* user_string,
const char* more_info_url) {
// Initialize Local Variables to the Method.
char HXDefine[256];
// Store the error code that was generated.
convert_to_string(hx_code, HXDefine, 256);
STDOUT("Report(%d, %ld, \"%s\", %ld, \"%s\", \"%s\")\n", severity,
hx_code, (user_string && *user_string) ? user_string : "(NULL)",
user_code, (more_info_url && *more_info_url) ? more_info_url : "(NULL)",
HXDefine);
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Member: HxErrorSink::ConvertErrorToText
// Access: Protected
// Purpose: Converts the Helix error code to text for the
// client to display.
////////////////////////////////////////////////////////////////////
// Params: hx_code - the error code to be translated to text.
// buffer - Text buffer that holds the code.
// buffer_length - The length of the text buffer.
// Return: None
////////////////////////////////////////////////////////////////////
void HxErrorSink::convert_to_string(const ULONG32 hx_code, char* buffer, UINT32 buffer_length) {
// Initialize Local Variables to this method.
//IHXErrorMessages * pErrMsg = 0;
// If the buffer is not empty, then there is nothing to do.
if( !buffer ) {
return;
}
buffer[0] = '\0';
if (strlen(buffer) == 0) {
SafeSprintf(buffer, buffer_length, "Can't convert the error code %p", hx_code);
}
}

View File

@ -0,0 +1,77 @@
// Filename: hxErrorSink.h
// Created by: jjtaylor (29Jan04)
//
////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#if !defined (_HXERRORSINK_H_)
#define _HXERRORSINK_H_
////////////////////////////////////////////////////////////////////
// Panda Header Files
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
////////////////////////////////////////////////////////////////////
// Helix Main Header Files
////////////////////////////////////////////////////////////////////
#include "mainHelix.h"
////////////////////////////////////////////////////////////////////
// Prototype/Struct/Class Forward Delcarations
////////////////////////////////////////////////////////////////////
struct IUnknown;
struct IHXErrorMessages;
struct IHXPlayer;
////////////////////////////////////////////////////////////////////
// Class: HxErrorSink
// Purpose: This is a derived class from the IHXErrorSink
// base interface. This class is meant to receive
// error messages from the client engine.
////////////////////////////////////////////////////////////////////
class HxErrorSink : public IHXErrorSink {
public:
HxErrorSink(IUnknown* unknown);
~HxErrorSink();
////////////////////////////////////////////////////////////////////
// IHXErrorSink Interface Methods Prototypes
// Purpose: Implements the necessary interface methods that may
// be called when an error message is generated.
////////////////////////////////////////////////////////////////////
STDMETHOD (ErrorOccurred) (THIS_ const UINT8 severity, const UINT32 hx_code,
const UINT32 user_code, const char* user_string,
const char* more_info_url);
////////////////////////////////////////////////////////////////////
// IHUnkown Interface Methods Prototypes
// Purpose: Implements the basic COM interface methods for reference
// coutning and querying of related interfaces.
////////////////////////////////////////////////////////////////////
STDMETHOD (QueryInterface) (THIS_ REFIID _id, void** _interface_obj);
STDMETHOD_ (ULONG32, AddRef) (THIS);
STDMETHOD_ (ULONG32, Release) (THIS);
protected:
// Protected Class Method Declarations
void convert_to_string(const ULONG32 hx_code, char * buffer, UINT32 buffer_length);
// Protected Class Variable Declarations
INT32 ref_count;
IHXPlayer* _player;
};
#endif

View File

@ -0,0 +1,322 @@
// Filename: hxSiteSupplier.cxx
// Created by: jjtaylor (29Jan04)
//
////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Helix Main Header Files
////////////////////////////////////////////////////////////////////
#include "mainHelix.h"
////////////////////////////////////////////////////////////////////
// Normal Header Files
////////////////////////////////////////////////////////////////////
#include <iostream>
////////////////////////////////////////////////////////////////////
// Member: HxSiteSupplier::Constructor
// Access: Public
// Purpose: The default constructor of the class which
// initializes the member variables, and queries
// the appropriate Helix Interfaces.
////////////////////////////////////////////////////////////////////
// Params: IUnknown * - Pointer to an IUnknown COM Interface
// Texture * tex- Pointer to the Panda texture object.
// Return: None
////////////////////////////////////////////////////////////////////
HxSiteSupplier::HxSiteSupplier(IUnknown* unknown, Texture* tex)
: _ref_count(0),
_site_manager(0),
_ccf(0),
_unknown(unknown),
_dest_buffer(0),
_texture(tex) {
if(_unknown) {
_unknown->QueryInterface(IID_IHXSiteManager, (void**)&_site_manager);
_unknown->QueryInterface(IID_IHXCommonClassFactory, (void**)&_ccf);
_unknown->AddRef();
}
}
/////////////////////////////////////////////////////////////////////
// Member: HxSiteSupplier:Destructor
// Access: Private
// Purpose: The default destructor of the class that releases
// the interface member variables from memory.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
HxSiteSupplier::~HxSiteSupplier() {
HX_RELEASE(_site_manager);
HX_RELEASE(_ccf);
HX_RELEASE(_unknown);
}
////////////////////////////////////////////////////////////////////
// Member: HxSiteSupplier::QueryInterface
// Access:
// Purpose: Queries this class to determine whether it supports
// supports a specific interface. If the call succeeds
// then the methods of that interface are made
// available for use.
/////////////////////////////////////////////////////////////////////
// Params: _id - Indicates the reference identifier of the
// the interface being queried.
// _interface_obj - Points to an interface pointer that is
// filled in if the query succeeds.
// Return: HX_RESULT - Varies based on wheter the interface is
// supported or not.
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxSiteSupplier::QueryInterface(REFIID _id, void** _interface_obj) {
if (IsEqualIID(_id, IID_IUnknown)) {
AddRef();
*_interface_obj = (IUnknown*)(IHXSiteSupplier*)this;
return HXR_OK;
}
else if (IsEqualIID(_id, IID_IHXSiteSupplier)) {
AddRef();
*_interface_obj = (IHXSiteSupplier*)this;
return HXR_OK;
}
*_interface_obj = NULL;
return HXR_NOINTERFACE;
}
////////////////////////////////////////////////////////////////////
// Member: HxSiteSupplier::AddRef
// Access: Public
// Purpose: Increases the object's reference count by one.
// Whenever an object is created, it's reference count
// begins at 1.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: ULONG32 - The new reference count.
////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG32) HxSiteSupplier::AddRef() {
return InterlockedIncrement(&_ref_count);
}
////////////////////////////////////////////////////////////////////
// Member: HxSite::Release
// Access: Public
// Purpose: Decreases the object's reference count by one.
// Every call to IUnknown::AddRef,
// IUnknown::QueryInterface, or a creation function
// such as HXCreateInstance must have a corresponding
// call to IUnknown::Release. When the reference count
// reaches 0 (zero), the object is destroyed.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: ULONG32 - The new reference count.
////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG32)HxSiteSupplier::Release() {
if (InterlockedDecrement(&_ref_count) > 0) {
return _ref_count;
}
delete this;
return 0;
}
////////////////////////////////////////////////////////////////////
// Member: HxSiteSupplier::SitesNeeded
// Access: Public
// Purpose: Informs the site supplier that a site with a
// particular set of characteristics is needed. If the
// supplier can fulfill the requestion, it should call
// the site manager and add a new site to it.
////////////////////////////////////////////////////////////////////
// Params: UINT32 request_id - ID used to map between corresponding
// "sites needed" and "sites not needed"
// calls.
// IHXValues * pProps - The properties of the requested site
// Return: None
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxSiteSupplier::SitesNeeded(UINT32 request_id, IHXValues* pProps) {
// Determine if there are valid properties. If not then a site
// can not properly be created.
if (!pProps) {
return HXR_INVALID_PARAMETER;
}
// Local Variable Declaration and Intialization
HRESULT hres = HXR_OK;
IHXValues* site_props = NULL;
IHXSiteWindowed* pSiteWindowed = NULL;
IHXBuffer* pValue = NULL;
UINT32 style = 0;
IHXSite* pSite = NULL;
// Just let the Helix client core create a windowed site for us.
hres = _ccf->CreateInstance(CLSID_IHXSiteWindowed,(void**)&pSiteWindowed);
if (HXR_OK != hres) {
goto exit;
}
hres = pSiteWindowed->QueryInterface(IID_IHXSite,(void**)&pSite);
if (HXR_OK != hres) {
goto exit;
}
hres = pSiteWindowed->QueryInterface(IID_IHXValues,(void**)&site_props);
if (HXR_OK != hres) {
goto exit;
}
// Figures out what type of site must be created.
hres = pProps->GetPropertyCString("playto",pValue);
if (HXR_OK == hres) {
site_props->SetPropertyCString("channel",pValue);
HX_RELEASE(pValue);
}
else {
hres = pProps->GetPropertyCString("name",pValue);
if (HXR_OK == hres) {
site_props->SetPropertyCString("LayoutGroup",pValue);
HX_RELEASE(pValue);
}
}
#ifdef _WINDOWS
style = WS_OVERLAPPED | WS_VISIBLE | WS_CLIPCHILDREN;
#endif
// Determine if there is a valid Panda buffer available
// so that it may be sent down into the sites video
// surface object.
if( _texture->has_ram_image() ) {
pSiteWindowed->SetDstBuffer(_texture->_pbuffer->_image,
_texture->_pbuffer->get_xsize(),
_texture->_pbuffer->get_ysize());
}
else {
cout << "--- {{ HxSiteSupplier.cxx, RELOADED RAM IMAGE!!! }}---" << endl;
PixelBuffer* fake = _texture->get_ram_image();
if( fake ) {
pSiteWindowed->SetDstBuffer(fake->_image,
_texture->_pbuffer->get_xsize(),
_texture->_pbuffer->get_ysize());
}
else {
cout << "--- {{ HxSiteSupplier.cxx, NO RAM IMAGE PRESENT!!! }} ---" << endl;
}
}
// Create the window. Not necessary later on.
hres = pSiteWindowed->Create(NULL, style);
//hres = pSiteWindowed->AttachWindow(NULL);
if (HXR_OK != hres) {
goto exit;
}
// Add the site to the site manager.
hres = _site_manager->AddSite(pSite);
if (HXR_OK != hres) {
goto exit;
}
_created_sites.SetAt((void*)request_id,pSite);
//pair<UINT32, IHXSite*> site(request_id, pSite);
//_created_sites.insert(site);
pSite->AddRef();
exit:
HX_RELEASE(site_props);
HX_RELEASE(pSiteWindowed);
HX_RELEASE(pSite);
return hres;
}
////////////////////////////////////////////////////////////////////
// Member: HxSiteSupplier::SitesNotNeeded
// Access: Public
// Purpose: Informs the site supplier that all sites from a
// previous site request are no longer needed.
////////////////////////////////////////////////////////////////////
// Params: UINT32 request_id - ID used to map between corresponding
// "sites needed" and "sites not needed"
// calls.
// Return: None
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxSiteSupplier::SitesNotNeeded(UINT32 request_id) {
// Local Variable Declaration and Initialization
IHXSite* pSite = NULL;
IHXSiteWindowed* pSiteWindowed = NULL;
void* pVoid = NULL;
// search for the site id in the map
if (!_created_sites.Lookup((void*)request_id,pVoid)) {
return HXR_INVALID_PARAMETER;
}
//SITES::iterator iter = _created_sites.find(request_id);
//if(iter == _created_sites.end()) {
// return HXR_INVALID_PARAMETER;
//}
pSite = (IHXSite*)pVoid;
// Remove the site from the site manager.
_site_manager->RemoveSite(pSite);
// Need to actually do the work on destroying the window
// and all that jazz.
pSite->QueryInterface(IID_IHXSiteWindowed,(void**)&pSiteWindowed);
pSiteWindowed->Destroy();
// ref count = 2
pSiteWindowed->Release();
// ref count = 1; deleted from this object's view!
pSite->Release();
// Remove the site from the map.
_created_sites.RemoveKey((void*)request_id);
//_created_sites.erase(request_id);
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Member: HxSiteSupplier::BeginChangeLayout
// Access: Public
// Purpose: Informs the site supplier that a layout change
// has begun and that it can expect to receive calls
// to the SitesNeeded and SitesNotNeeded method.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxSiteSupplier::BeginChangeLayout() {
return HXR_OK;
}
////////////////////////////////////////////////////////////////////
// Member: HxSiteSupplier::DoneChangeLayout
// Access: Public
// Purpose: Informs the site supplier that the layout changes
// are completed.
////////////////////////////////////////////////////////////////////
// Params: None
// Return: None
////////////////////////////////////////////////////////////////////
STDMETHODIMP HxSiteSupplier::DoneChangeLayout() {
return HXR_OK;
}

View File

@ -0,0 +1,67 @@
// Filename: HxSiteSupplier.h
// Created by: jjtaylor (29Jan04)
//
////////////////////////////////////////////////////////////////////
//
//
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef HXSITESUPPLIER_H
#define HXSITESUPPLIER_H
////////////////////////////////////////////////////////////////////
// Panda Header Files
////////////////////////////////////////////////////////////////////
#include "pandabase.h"
#include "pmap.h"
#include "texture.h"
#include "fivemmap.h"
////////////////////////////////////////////////////////////////////
// Class: HxSiteSupplier
// Purpose: This is a derived class from the IHXSiteSupplier
// base interface. This class is meant to create or
// remove Helix Sites.
////////////////////////////////////////////////////////////////////
class HxSiteSupplier : public IHXSiteSupplier {
public:
HxSiteSupplier(IUnknown* unknown, Texture* tex);
~HxSiteSupplier();
////////////////////////////////////////////////////////////////////
// IHUnkown Interface Methods Prototypes
// Purpose: Implements the basic COM interface methods for reference
// coutning and querying of related interfaces.
////////////////////////////////////////////////////////////////////
STDMETHOD(QueryInterface) (THIS_ REFIID id, void** interface_obj);
STDMETHOD_(ULONG32,AddRef) (THIS);
STDMETHOD_(ULONG32,Release) (THIS);
////////////////////////////////////////////////////////////////////
// IHXClientAdviseSink Interface Methods Prototypes
// Purpose: Implements the necessary interface methods that may
// be called when a site must be created or closed.
////////////////////////////////////////////////////////////////////
STDMETHOD(SitesNeeded) (THIS_ UINT32 request_id, IHXValues* site_props);
STDMETHOD(SitesNotNeeded) (THIS_ UINT32 request_id);
STDMETHOD(BeginChangeLayout) (THIS);
STDMETHOD(DoneChangeLayout) (THIS);
private:
LONG32 _ref_count;
IHXSiteManager* _site_manager;
IHXCommonClassFactory* _ccf;
IUnknown* _unknown;
FiveMinuteMap _created_sites;
UCHAR* _dest_buffer;
Texture* _texture;
};
#endif

View File

@ -0,0 +1,74 @@
#if !defined (_MAINHELIX_H_)
#define _MAINHELIX_H_
// This file basically just contains all of the header
// files that I will need to invoke the client core
// and start an engine.
#include "pandabase.h"
#include "helixDefs.h"
#include <hxtypes.h>
#include <stdlib.h>
#include <hlxclib/time.h>
#include <hxwintyp.h>
#include <hxcom.h>
#include <ihxpckts.h>
#include <hxcomm.h>
#include <hxmon.h>
#include <hxfiles.h>
#include <hxengin.h>
#include <hxcore.h>
#include <hxclsnk.h>
#include <hxerror.h>
#include <hxauth.h>
#include <hxwin.h>
#include <hxprefs.h>
#include <hxtbuf.h>
#include <hxbuffer.h>
#include <hxmangle.h>
//#include "fivemmap.h"
#include <dllacces.h>
#include <dllpath.h>
#include <hxstrutl.h>
#include <HxAdviseSink.h>
#include <HxErrorSink.h>
#include <HxSiteSupplier.h>
#include <HxAuthenticationManager.h>
#include <HxClientContext.h>
#include "print.h"
typedef HX_RESULT (HXEXPORT_PTR FPRMSETDLLACCESSPATH) (const char*);
#endif
/*
#include "hxtypes.h>
#include <stdlib.h>
#include <common/runtime/pub/hlxclib/time.h>
#include <common/include/hxwintyp.h>
#include <common/include/hxcom.h>
#include <common/include/ihxpckts.h>
#include <common/include/hxcomm.h>
#include <common/include/hxmon.h>
#include <common/include/hxfiles.h>
#include <common/include/hxengin.h>
#include <common/include/hxcore.h>
#include <client/include/hxclsnk.h>
#include <common/include/hxerror.h>
#include <common/include/hxauth.h>
#include <common/include/hxwin.h>
#include <common/include/hxprefs.h>
#include <common/include/hxtbuf.h>
#include <common/container/pub/hxbuffer.h>
#include <common/util/pub/hxmangle.h>
//#include "fivemmap.h"
#include <common/system/pub/dllacces.h>
#include <common/system/pub/dllpath.h>
#include <common/util/pub/hxstrutl.h> */

View File

@ -0,0 +1,28 @@
#define BUILD_DIRECTORY $[HAVE_HELIX]
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
dtoolutil:c dtoolbase:c dtool:m
#begin lib_target
#define TARGET helix
#define LOCAL_LIBS \
dgraph
#define WIN_SYS_LIBS $[WIN_SYS_LIBS] user32.lib advapi32.lib winmm.lib
#define USE_PACKAGES helix
#define SOURCES \
config_helix.cxx config_helix.h fivemmap.cxx fivemmap.h \
HelixClient.cxx HelixClient.h HxAdviseSink.cxx HxAdviseSink.h \
HxAuthenticationManager.cxx HxAuthenticationManager.h \
HxClientContext.cxx HxClientContext.h HxErrorSink.cxx HxErrorSink.h \
HxSiteSupplier.cxx HxSiteSupplier.h iids.cxx MainHelix.h print.cxx print.h
#define INSTALL_HEADERS \
config_helix.h \
HelixClient.h
#define IGATESCAN \
HelixClient.cxx
#end lib_target

View File

@ -0,0 +1,36 @@
// Filename: config_helix.h
// Created by: jjtaylor (27Feb04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "config_helix.h"
#include "helixClient.h"
#include <dconfig.h>
DLLAccessPath statClnt;
DLLAccessPath* GetDLLAccessPath()
{
return &statClnt;
}
Configure(config_helix);
NotifyCategoryDef(helix, "");
ConfigureFn(config_helix) {
HelixClient::init_type();
}

View File

@ -0,0 +1,28 @@
// Filename: config_helix.h
// Created by: jjtaylor (27Feb04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef CONFIG_HELIX_H
#define CONFIG_HELIX_H
#include "pandabase.h"
#include "notifyCategoryProxy.h"
NotifyCategoryDecl(helix, EXPCL_PANDA, EXPTP_PANDA);
#endif

View File

@ -0,0 +1,175 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#include <string.h>
//#include "hxtypes.h"
#include "fivemmap.h"
void* FiveMinuteMap::GetFirstValue()
{
m_nCursor = 0;
if (m_nMapSize)
{
return ValueArray[m_nCursor];
}
else
{
return NULL;
}
}
void* FiveMinuteMap::GetNextValue()
{
m_nCursor++;
if (m_nCursor < m_nMapSize)
{
return ValueArray[m_nCursor];
}
else
{
return NULL;
}
}
BOOL FiveMinuteMap::Lookup(void* Key, void*& Value) const
{
BOOL bFound = FALSE;
int nIndex = 0;
// If Key is alrady in the list, replace value
for (; nIndex < m_nMapSize; nIndex++)
{
if (KeyArray[nIndex] == Key)
{
Value = ValueArray[nIndex];
bFound = TRUE;
goto exit;
}
}
exit:
return bFound;
}
void FiveMinuteMap::RemoveKey(void* Key)
{
BOOL bFound = FALSE;
int nIndex = 0;
// If Key is alrady in the list, replace value
for (; nIndex < m_nMapSize; nIndex++)
{
if (KeyArray[nIndex] == Key)
{
if (nIndex < (m_nMapSize-1))
{
memmove(&(KeyArray[nIndex]),&(KeyArray[nIndex+1]),sizeof(void*)*(m_nMapSize-(nIndex+1)));
memmove(&(ValueArray[nIndex]),&(ValueArray[nIndex+1]),sizeof(void*)*(m_nMapSize-(nIndex+1)));
}
m_nMapSize--;
goto exit;
}
}
exit:
(NULL); // We're done!
}
void FiveMinuteMap::RemoveValue(void* Value)
{
BOOL bFound = FALSE;
int nIndex = 0;
// If Value is alrady in the list, replace value
for (; nIndex < m_nMapSize; nIndex++)
{
if (ValueArray[nIndex] == Value)
{
if (nIndex < (m_nMapSize-1))
{
memmove(&(KeyArray[nIndex]),&(KeyArray[nIndex+1]),sizeof(void*)*(m_nMapSize-(nIndex+1)));
memmove(&(ValueArray[nIndex]),&(ValueArray[nIndex+1]),sizeof(void*)*(m_nMapSize-(nIndex+1)));
}
m_nMapSize--;
goto exit;
}
}
exit:
(NULL); // We're done!
}
void FiveMinuteMap::SetAt(void* Key, void* Value)
{
int nIndex = 0;
// If Key is alrady in the list, replace value
for (; nIndex < m_nMapSize; nIndex++)
{
if (KeyArray[nIndex] == Key)
{
ValueArray[nIndex] = Value;
goto exit;
}
}
// If we have room, add it to the end!
if (m_nAllocSize == m_nMapSize)
{
m_nAllocSize += AllocationSize;
void** pNewKeys = new void*[m_nAllocSize];
void** pNewValues = new void*[m_nAllocSize];
memcpy(pNewKeys,KeyArray,sizeof(void*)*m_nMapSize); /* Flawfinder: ignore */
memcpy(pNewValues,ValueArray,sizeof(void*)*m_nMapSize); /* Flawfinder: ignore */
delete [] KeyArray;
delete [] ValueArray;
KeyArray = pNewKeys;
ValueArray = pNewValues;
}
KeyArray[m_nMapSize] = Key;
ValueArray[m_nMapSize] = Value;
m_nMapSize++;
exit:
(NULL); // We're done!
}

View File

@ -0,0 +1,83 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#ifndef _FIVEMMAP_H_
#define _FIVEMMAP_H_
#include "pandabase.h"
#include "helixDefs.h"
#include <hxtypes.h>
#ifndef _HXTYPES_H_
#error FiveMinuteMap assumes pntypes.h.
#endif
class FiveMinuteMap {
const int AllocationSize;
void** KeyArray;
void** ValueArray;
int m_nMapSize;
int m_nAllocSize;
int m_nCursor;
public:
FiveMinuteMap()
: KeyArray(NULL)
, ValueArray(NULL)
, m_nMapSize(0)
, m_nAllocSize(0)
, m_nCursor(0)
, AllocationSize(10)
{};
~FiveMinuteMap()
{
delete [] KeyArray;
delete [] ValueArray;
};
int GetCount() {return m_nMapSize;}
void* GetFirstValue();
void* GetNextValue();
BOOL Lookup(void* Key, void*& Value) const;
void RemoveKey(void* Key);
void RemoveValue(void* Value);
void SetAt(void* Key, void* Value);
};
#endif /* _FIVEMMAP_H_ */

52
panda/src/helix/iids.cxx Normal file
View File

@ -0,0 +1,52 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
// define all guids here once...
#define INITGUID
#define NCIHACK
#include "pandabase.h"
#include "helixDefs.h"
#include "hxtypes.h"
#include "hxcom.h"
#include "hxiids.h"
#include "hxpiids.h"
#if defined _WINDOWS
#if defined (HELIX_FEATURE_DIRECT_SOUND)
#include "dsound.h"
#endif /* HELIX_FEATURE_DIRECT_SOUND */
#if defined (HELIX_FEATURE_VIDEO) && !defined(_WINCE)
#include "ddraw.h"
#endif /* HELIX_FEATURE_VIDEO */
#endif

62
panda/src/helix/main.cpp Normal file
View File

@ -0,0 +1,62 @@
#include "dllpath.h"
#include "HelixClient.h"
// typedef for SetDLLAccessPath
#if defined _DEBUG || defined DEBUG
#include "debug.h"
#endif
#if defined(HELIX_CONFIG_NOSTATICS)
# include "globals/hxglobals.h"
#endif
DLLAccessPath statClnt;
DLLAccessPath* GetDLLAccessPath()
{
return &statClnt;
}
int main( int argc, char *argv[] )
{
setvbuf(stdout, NULL, _IONBF, 0);
HelixClient* myClient = new HelixClient();
STDOUT("%s", argv[1]);
myClient->create_player("myPlayer", true);
//myClient->open_url("myPlayer", argv[1]);
myClient->open_url("myPlayer", "rage.mp3");
bool done = true;
myClient->begin("myPlayer");
while (done != myClient->is_done("myPlayer")) {
//Do Nothing for now
MSG msg;
GetMessage(&msg, NULL, 0, 0);
DispatchMessage(&msg);
}
delete myClient;
myClient = 0;
return 0;
}

80
panda/src/helix/print.cxx Normal file
View File

@ -0,0 +1,80 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#include <stdarg.h>
#include <stdio.h>
#include "print.h"
#ifdef WIN32_PLATFORM_PSPC
#include "hlxosstr.h"
#include <winbase.h>
#endif
int print2stdout(const char* pFmt, ...)
{
va_list args;
va_start(args, pFmt);
#ifdef WIN32_PLATFORM_PSPC
char Message[512];
int ret = vsprintf(Message, pFmt, args);
OutputDebugString(OS_STRING(Message));
#else
int ret = vfprintf(stdout, pFmt, args);
#endif
va_end(args);
return ret;
}
int print2stderr(const char* pFmt, ...)
{
va_list args;
va_start(args, pFmt);
#ifdef WIN32_PLATFORM_PSPC
char Message[512];
int ret = vsprintf(Message, pFmt, args);
OutputDebugString(OS_STRING(Message));
#else
int ret = vfprintf(stderr, pFmt, args);
#endif
va_end(args);
return ret;
}

62
panda/src/helix/print.h Normal file
View File

@ -0,0 +1,62 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#ifndef PRINT_H
#define PRINT_H
#include "pandabase.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _SYMBIAN
#include "platform/symbian/symbian_print.h"
#define STDOUT symbianPrint
#define STDERR symbianPrint
#else
int print2stdout(const char* pFmt, ...);
int print2stderr(const char* pFmt, ...);
#define STDOUT print2stdout
#define STDERR print2stderr
#endif
#ifdef __cplusplus
};
#endif
#endif /* PRINT_H */