#################################################################
# propertyWindow.py
# Written by Yi-Hong Lin, yihhongl@andrew.cmu.edu, 2004
#################################################################
from direct.tkwidgets.AppShell import *
from direct.showbase.TkGlobal import *

from seColorEntry import *

from direct.tkwidgets import Floater
from direct.tkwidgets import Dial
from direct.tkwidgets import Slider
from direct.tkwidgets import VectorWidgets
from pandac.PandaModules import *
from Tkinter import *
import Pmw

class propertyWindow(AppShell,Pmw.MegaWidget):
    #################################################################
    # propertyWindow(AppShell,Pmw.MegaWidget)
    # This class will create a widow to show the object property and
    # let user can change shoe of them.
    #################################################################
    appversion      = '1.0'
    appname         = 'Property Window'
    frameWidth      = 400
    frameHeight     = 400
    padx            = 0
    pady            = 0
    usecommandarea  = 0
    usestatusarea   = 0
    widgetsDict = {}

    
    def __init__(self, target, type, info, parent = None, nodePath = render, **kw):
        self.nodePath = target
        self.name = target.getName()
        self.type = type
        self.info = info
        

        # Initialise superclass
        Pmw.MegaWidget.__init__(self, parent)
        
        # 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.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)
        name_label = Label(mainFrame, text= self.name,font=('MSSansSerif', 15),
                           relief = RIDGE, borderwidth=5)
        name_label.pack()
        outFrame = Frame(mainFrame, relief = RIDGE, borderwidth=3)
        self.contentWidge = self.createcomponent(
            'scrolledFrame',
            (), None,
            Pmw.ScrolledFrame, (outFrame,),
            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)
        outFrame.pack(fill = 'both', expand = 1)

        # Creating different interface depands on object's type
        if self.type == 'camera':
            self.cameraInterface(self.contentFrame)
            self.accept('forPorpertyWindow'+self.name, self.trackDataFromSceneCamera)
        elif self.type == 'Model':
            self.modelInterface(self.contentFrame)
            self.accept('forPorpertyWindow'+self.name, self.trackDataFromSceneModel)
        elif self.type == 'Actor':
            self.modelInterface(self.contentFrame)
            self.actorInterface(self.contentFrame)
            self.accept('forPorpertyWindow'+self.name, self.trackDataFromSceneActor)
            pass
        elif self.type == 'Light':
            self.lightInterface(self.contentFrame)
            self.accept('forPorpertyWindow'+self.name, self.trackDataFromSceneLight)
            pass
        elif self.type == 'dummy':
            self.dummyInterface(self.contentFrame)
            self.accept('forPorpertyWindow'+self.name, self.trackDataFromSceneDummy)
            pass
        elif self.type == 'collisionNode':
            self.collisionInterface(self.contentFrame)
            self.accept('forPorpertyWindow'+self.name, self.trackDataFromSceneCollision)
            pass
        elif self.type == 'Special':
            # If user try to open the property window for node "SEditor"
            # It will show the grid property.
            self.gridInterface(self.contentFrame)
            self.accept('forPorpertyWindow'+self.name, None)
            pass

        self.curveFrame = None
        #### If nodePath has been binded with any curves
        if self.info.has_key('curveList'):
            self.createCurveFrame(self.contentFrame)
       
        ## Set all stuff done
        mainFrame.pack(fill = 'both', expand = 1)

    
    def createMenuBar(self):
        # we don't need menu bar here.
        self.menuBar.destroy()
        
    def onDestroy(self, event):
        self.ignore('forPorpertyWindow'+self.name)
        messenger.send('PW_close', [self.name])
        '''
        If you have open any thing, please rewrite here!
        '''
        pass

    def createEntryField(self, parent,text, value,
                         command, initialState, labelWidth = 12,
                         side = 'left', fill = X, expand = 0,
                         validate = None,
                         defaultButton = False, buttonText = 'Default',defaultFunction = None ):
        #################################################################
        # createEntryField(self, parent,text, value,
        #                  command, initialState, labelWidth = 12,
        #                  side = 'left', fill = X, expand = 0,
        #                  validate = None,
        #                  defaultButton = False, buttonText = 'Default',defaultFunction = None ):
        # This function will create a Entry on the frame "parent"
        # Also, if user has enabled the "defaultButton," it will create a button right after the entry.
        #################################################################
        frame = Frame(parent)
        widget = Pmw.EntryField(frame, labelpos='w', label_text = text,
                                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.widgetsDict[text] = widget
        if defaultButton and (defaultFunction!=None):
            # create a button if they need.
            widget = Button(frame, text=buttonText, font=('MSSansSerif', 10), command = defaultFunction)
            widget.pack(side=LEFT, padx=3)
            self.widgetsDict[text+'-'+'DefaultButton']=widget
            
        frame.pack(side = side, fill = fill, expand = expand,pady=3)


    def createPosEntry(self, contentFrame):
        #################################################################
        # createPosEntry(self, contentFrame)
        # This function will create three entries for setting position for the objects.
        # the entry type is Floater.
        # And, it will set the call back function to setNodePathPosHprScale()
        #################################################################
        posInterior = Frame(contentFrame)
        self.posX = self.createcomponent('posX', (), None,
                                         Floater.Floater, (posInterior,),
                                         text = 'X', relief = FLAT,
                                         value = self.nodePath.getX(),
                                         label_foreground = 'Red',
                                         entry_width = 9)
        self.posX['commandData'] = ['x']
        self.posX['command'] = self.setNodePathPosHprScale
        self.posX.pack(side=LEFT,expand=0,fill=X, padx=1)
        
        self.posY = self.createcomponent('posY', (), None,
                                         Floater.Floater, (posInterior,),
                                         text = 'Y', relief = FLAT,
                                         value = self.nodePath.getY(),
                                         label_foreground = '#00A000',
                                         entry_width = 9)
        self.posY['commandData'] = ['y']
        self.posY['command'] = self.setNodePathPosHprScale
        self.posY.pack(side=LEFT, expand=0,fill=X, padx=1)
        
        self.posZ = self.createcomponent('posZ', (), None,
                                         Floater.Floater, (posInterior,),
                                         text = 'Z', relief = FLAT,
                                         value = self.nodePath.getZ(),
                                         label_foreground = 'Blue',
                                         entry_width = 9)
        self.posZ['commandData'] = ['z']
        self.posZ['command'] = self.setNodePathPosHprScale
        self.posZ.pack(side=LEFT, expand=0,fill=X, padx=1)
        posInterior.pack(side=TOP, expand=0,fill=X, padx=3, pady=3)

    def createHprEntry(self, contentFrame):
        #################################################################
        # createHprEntry(self, contentFrame)
        # This function will create three entries for setting orientation for the objects.
        # the entry type is Floater.
        # And, it will set the call back function to setNodePathPosHprScale()
        #################################################################
        hprInterior = Frame(contentFrame)
        self.hprH = self.createcomponent('hprH', (), None,
                                         Dial.AngleDial, (hprInterior,),
                                         style = 'mini',
                                         text = 'H', value = self.nodePath.getH(),
                                         relief = FLAT,
                                         label_foreground = 'blue',
                                         entry_width = 9)
        self.hprH['commandData'] = ['h']
        self.hprH['command'] = self.setNodePathPosHprScale
        self.hprH.pack(side = LEFT, expand=0,fill=X)
        
        self.hprP = self.createcomponent('hprP', (), None,
                                         Dial.AngleDial, (hprInterior,),
                                         style = 'mini',
                                         text = 'P', value = self.nodePath.getP(),
                                         relief = FLAT,
                                         label_foreground = 'red',
                                         entry_width = 9)
        self.hprP['commandData'] = ['p']
        self.hprP['command'] = self.setNodePathPosHprScale
        self.hprP.pack(side = LEFT, expand=0,fill=X)
        
        self.hprR = self.createcomponent('hprR', (), None,
                                         Dial.AngleDial, (hprInterior,),
                                         style = 'mini',
                                         text = 'R', value = self.nodePath.getR(),
                                         relief = FLAT,
                                         label_foreground = '#00A000',
                                         entry_width = 9)
        self.hprR['commandData'] = ['r']
        self.hprR['command'] = self.setNodePathPosHprScale
        self.hprR.pack(side = LEFT, expand=0,fill=X)

        hprInterior.pack(side=TOP, expand=0,fill=X, padx=3, pady=3)


    def createScaleEntry(self, contentFrame):
        #################################################################
        # createScaleEntry(self, contentFrame)
        # This function will create three entries for setting scale for the objects.
        # the entry type is Floater.
        # And, it will set the call back function to setNodePathPosHprScale()
        #################################################################
        scaleInterior = Frame(contentFrame)
        
        self.scale = self.createcomponent('scale', (), None,
                                           Floater.Floater, (scaleInterior,),
                                           text = 'Scale',
                                           relief = FLAT,
                                           min = 0.0001, value = self.nodePath.getScale().getX(),
                                           resetValue = 1.0,
                                           label_foreground = 'Blue')
        self.scale['commandData'] = ['s']
        self.scale['command'] = self.setNodePathPosHprScale
        self.scale.pack(side=LEFT,expand=0,fill=X)

        scaleInterior.pack(side=TOP,expand=0,fill=X, padx=3, pady=3)

    def createColorEntry(self, contentFrame):
        #################################################################
        # createColorEntry(self, contentFrame)
        # This function will create three entries for setting color for the objects.
        # the entry type is Floater.
        # And, it will set the call back function to setNodeColorVec()
        #################################################################
        color = self.nodePath.getColor()
        print color
        self.nodeColor = VectorWidgets.ColorEntry(
            contentFrame, text = 'Node Color', value=[color.getX()*255,
                                                      color.getY()*255,
                                                      color.getZ()*255,
                                                      color.getW()*255])
        self.nodeColor['command'] = self.setNodeColorVec
        self.nodeColor['resetValue'] = [255,255,255,255]
        self.nodeColor.place(anchor=NW,y=235)
        self.bind(self.nodeColor, 'Set nodePath color')        
        self.nodeColor.pack(side=TOP,expand=0,fill=X, padx=3, pady=3)
        return
    
    def setNodeColorVec(self, color):
        #################################################################
        # setNodeColorVec(self, color)
        # This function will set the color of the object
        #################################################################
        self.nodePath.setColor(color[0]/255.0,
                               color[1]/255.0,
                               color[2]/255.0,
                               color[3]/255.0)
        return

    
    def setNodePathPosHprScale(self, data, axis):
        #################################################################
        # setNodePathPosHprScale(self, data, axis)
        # This function will set the postion, orientation or scale of the object
        # use the "axis" parameter to decide which property should be set.
        #################################################################
        if axis == 'x':
            self.nodePath.setX(data)
        elif axis == 'y':
            self.nodePath.setY(data)
        elif axis == 'z':
            self.nodePath.setZ(data)
        elif axis == 'h':
            self.nodePath.setH(data)
        elif axis == 'p':
            self.nodePath.setP(data)
        elif axis == 'r':
            self.nodePath.setR(data)
        elif axis == 's':
            self.nodePath.setScale(data)


    #### Curve property
    def createCurveFrame(self, contentFrame):
        #################################################################
        # createCurveFrame(self, contentFrame)
        # Draw the curve property frame
        # This function will draw the property frame and content of curves
        # pass the target frame as a variable
        #################################################################
        if self.curveFrame==None:
            self.curveFrame = Frame(contentFrame)
            group = Pmw.Group(self.curveFrame,
                              tag_text='Motion Path List for this Node',
                              tag_font=('MSSansSerif', 10))
            innerFrame = group.interior()
            n = 0
            for curve in self.info['curveList']:
                n += 1
                self.createEntryField(innerFrame,'Curve %d:' %n,
                                      value = curve.getCurve(0).getName(),
                                      command = None,
                                      initialState='disabled',
                                      side = 'top',
                                      defaultButton = True,
                                      buttonText = 'delete',
                                      defaultFunction = lambda a = n, b = self : b.deleteCurve(a))
            group.pack(side = TOP, fill = X, expand = 0,pady=3, padx=3)
            self.curveFrame.pack(side = TOP, fill = X, expand = 0,pady=3, padx=3)
            
        return
    
    def deleteCurve(self, number = 0):
        #################################################################
        # deleteCurve(self, number = 0)
        # Call back function, will be called when user click on the "delete" button beside the curve name.
        # This function will send the message to sceneEditor to remove the target curve
        # and will set a callback function waitting the result.
        #################################################################
        widget = self.widgetsDict['Curve %d:' %number]
        curveName = widget.getvalue()
        self.accept('curveRemovedFromNode',self.redrawCurveProperty)
        messenger.send('PW_removeCurveFromNode',[self.nodePath, curveName])
        return

    def redrawCurveProperty(self, nodePath, curveList):
        #################################################################
        # redrawCurveProperty(self, nodePath, curveList)
        # Callback function, will be called once get the result from dataHolder.
        # It will check the target nodePath first, then check the curve list is empty or not.
        # If yes, then delete whole curve frame. If not, then renew the data and redraw the curve frame again.
        #################################################################
        self.name = self.nodePath.getName()
        if self.name != nodePath.getName():
            messenger.send('curveRemovedFromNode',[nodePath, curveList])
            return
        else:
            self.ignore('curveRemovedFromNode')
            
        if curveList!= None:
            del self.info['curveList']
            self.info['curveList'] = curveList
            self.curveFrame.destroy()
            del self.curveFrame
            self.curveFrame = None
            self.createCurveFrame(self.contentFrame)
        else:
            del self.info['curveList']
            self.curveFrame.destroy()
            del self.curveFrame
            self.curveFrame = None
        return

    ####
    ####  Anything about Camera will be here!
    ####
    def cameraInterface(self, contentFrame):
        #################################################################
        # cameraInterface(self, interior, mainFrame)
        # Create the interface for camera node.
        #################################################################
        
        ## Type entry : unchageable
        widget = self.createEntryField(contentFrame,'Type:',
                                       value = self.type,
                                       command = None,
                                       initialState='disabled',
                                       side = 'top')

        ## lens Type entry
        widget = self.createEntryField(contentFrame, 'Lens Type:',
                                       value = self.info['lensType'],
                                       command = None,
                                       initialState='disabled',
                                       side = 'top')

        ## Pos
        group = Pmw.Group(contentFrame,tag_text='Position',
                          tag_font=('MSSansSerif', 10))
        self.createPosEntry(group.interior())
        group.pack(side=TOP,fill = X, expand = 0, pady=3)

        ## Orientation
        group = Pmw.Group(contentFrame,tag_text='Orientation',
                          tag_font=('MSSansSerif', 10))
        self.createHprEntry(group.interior())
        group.pack(side=TOP,fill = X, expand = 0, pady=3)
        
        ## near entry
        group = Pmw.Group(contentFrame,tag_text='Lens Property',
                          tag_font=('MSSansSerif', 10))
        lensFrame = group.interior()
        widget = self.createEntryField(lensFrame, 'Near:',value = self.info['near'],
                                       command = self.setCameraNear,
                                       initialState='normal',
                                       validate = Pmw.realvalidator,
                                       side = 'top',
                                       defaultButton = True,
                                       defaultFunction = self.defaultCameraNear)

        ## far entry
        widget = self.createEntryField(lensFrame, 'Far:',
                                       value = self.info['far'],
                                       command = self.setCameraFar,
                                       initialState='normal',
                                       side = 'top',
                                       validate = Pmw.realvalidator,
                                       defaultButton = True,
                                       defaultFunction = self.defaultCameraFar)

        ## Hfov entry
        widget = self.createEntryField(lensFrame, 'H.F.O.V.:',
                                           value = self.info['hFov'],
                                           command = self.setCameraFov,
                                           validate = Pmw.realvalidator,
                                           initialState='normal',
                                           side = 'top',
                                           defaultButton = True,
                                           defaultFunction = self.defaultCameraHfov)

        ## Vfov entry
        widget = self.createEntryField(lensFrame, 'V.F.O.V.:',
                                       value = self.info['vFov'],
                                       command = self.setCameraFov,
                                       validate = Pmw.realvalidator,
                                       initialState='normal',
                                       side = 'top',
                                       defaultButton = True,
                                       defaultFunction = self.defaultCameraVfov)

        ## Film Size entry
        frame = Frame(lensFrame)
        widget = Label(frame, text = "Film Size:", font=('MSSansSerif', 10),width=12)
        widget.pack(side=LEFT)
        frame.pack(side = TOP, fill = X, expand = 0, pady=3)
            
        frame = Frame(lensFrame)
        widget = Pmw.EntryField(frame, labelpos='w', label_text = '                        ',
                                value = self.info['FilmSize'].getX(),
                                entry_font=('MSSansSerif', 10),
                                label_font=('MSSansSerif', 10),
                                modifiedcommand=self.setCameraFilmSize, validate = Pmw.realvalidator,
                                entry_width = 8)
        self.widgetsDict['FilmSizeX']=widget
        widget.pack(side=LEFT, padx=3)
        widget = Pmw.EntryField(frame, labelpos='w', label_text = ': ', value = self.info['FilmSize'].getY() ,
                                label_font=('MSSansSerif', 10),
                                entry_font=('MSSansSerif', 10),
                                modifiedcommand=self.setCameraFilmSize, validate = Pmw.realvalidator,
                                entry_width = 8)
        self.widgetsDict['FilmSizeY']=widget
        widget.pack(side=LEFT, padx=3)
        widget = Button(frame, text='Default', font=('MSSansSerif', 10), command = self.defaultCameraFilmSize)
        widget.pack(side=LEFT, padx=3)
        self.widgetsDict['FilmSize'+'-'+'DefaultButton']=widget            
        frame.pack(side = TOP, fill = X, expand = 0,pady=0)

        ## Focal Length entry
        widget = self.createEntryField(lensFrame, 'Focal Length:',
                                       value = self.info['focalLength'],
                                       command = self.setCameraFocalLength,
                                       validate = Pmw.realvalidator,
                                       initialState='normal',
                                       side = 'top',
                                       defaultButton = True,
                                       defaultFunction = self.defaultCameraFocalLength)
        group.pack(side = TOP, fill = X, expand = 0,pady=2)

        
    def defaultCameraFar(self):
        #################################################################
        # defaultCameraFar(self)
        # set the camera "Far" value back to default.
        #################################################################
        widget = self.widgetsDict['Far:']
        widget.setvalue(base.cam.node().getLens().getDefaultFar())
        return

    def setCameraFar(self):
        #################################################################
        # setCameraFar(self)
        # set the camera "Far" value to what now user has typed in the entry
        #################################################################
        if self.widgetsDict['Far:'].getvalue() != '':
            value = float(self.widgetsDict['Far:'].getvalue())
        else:
            value = 0
        camera.getChild(0).node().getLens().setFar(value)
        return

    def defaultCameraNear(self):
        #################################################################
        # defaultCameraNear(self)
        # set the camera "Near" value back to default.
        #################################################################
        widget = self.widgetsDict['Near:']
        widget.setvalue(base.cam.node().getLens().getDefaultNear())
        return

    def setCameraNear(self):
        #################################################################
        # setCameraNear(self)
        # set the camera "Near" value to what now user has typed in the entry
        #################################################################
        if self.widgetsDict['Near:'].getvalue() != '':
            value = float(self.widgetsDict['Near:'].getvalue())
        else:
            value = 0
        camera.getChild(0).node().getLens().setNear(value)
        return

    def defaultCameraHfov(self):
        #################################################################
        # defaultCameraHfov(self)
        # set the camera "Hfov" value back to default.
        #################################################################
        widget = self.widgetsDict['H.F.O.V.:']
        widget.setvalue(45.0)
        return

    def setCameraFov(self):
        #################################################################
        # setCameraFov(self)
        # set the camera "Fov" value to what now user has typed in the entry
        #################################################################
        if self.widgetsDict['H.F.O.V.:'].getvalue() != '':
            value1 = float(self.widgetsDict['H.F.O.V.:'].getvalue())
        else:
            value1 = 0
        if self.widgetsDict['V.F.O.V.:'].getvalue() != '':
            value2 = float(self.widgetsDict['V.F.O.V.:'].getvalue())
        else:
            value2 = 0
        camera.getChild(0).node().getLens().setFov(VBase2(value1,value2))
        return

    def defaultCameraVfov(self):
        #################################################################
        # defaultCameraVfov(self)
        # set the camera "Vfov" value back to default.
        #################################################################
        widget = self.widgetsDict['V.F.O.V.:']
        widget.setvalue(34.51587677)
        return

    def defaultCameraFocalLength(self):
        #################################################################
        # defaultCameraFocalLength(self)
        # set the camera "Focal Length" value back to default.
        #################################################################
        widget = self.widgetsDict['Focal Length:']
        widget.setvalue(1.20710682869)
        return

    def setCameraFocalLength(self):
        #################################################################
        # setCameraFocalLength(self)
        # set the camera "Focal Length" value to what now user has typed in the entry
        #################################################################
        if self.widgetsDict['Focal Length:'].getvalue() != '':
            value = float(self.widgetsDict['Focal Length:'].getvalue())
        else:
            value = 0
        camera.getChild(0).node().getLens().setFocalLength(value)
        camera.getChild(0).node().getLens().setFilmSize(VBase2(float(self.widgetsDict['FilmSizeX'].getvalue()),float(self.widgetsDict['FilmSizeY'].getvalue())))
        return

    def defaultCameraFilmSize(self):
        #################################################################
        # defaultCameraFilmSize(self)
        # set the camera "Film Size" value back to default.
        #################################################################
        widget = self.widgetsDict['FilmSizeX']
        widget.setvalue(1)
        widget = self.widgetsDict['FilmSizeY']
        widget.setvalue(0.75)
        return

    def setCameraFilmSize(self):
        #################################################################
        # setCameraFilmSize(self)
        # set the camera "Film Size" value to what now user has typed in the entry
        #################################################################
        if self.widgetsDict['FilmSizeX'].getvalue() != '':
            value1 = float(self.widgetsDict['FilmSizeX'].getvalue())
        else:
            value1 = 0
        if self.widgetsDict['FilmSizeY'].getvalue() != '':
            value2 = float(self.widgetsDict['FilmSizeY'].getvalue())
        else:
            value2 = 0
        camera.getChild(0).node().getLens().setFilmSize(VBase2(value1,value2))
        return

    ####
    ####  Anything about Model & Actor will be here!
    ####
    def modelInterface(self, contentFrame):
        #################################################################
        # modelInterface(self, contentFrame)
        # Create the basic interface for ModelRoot Type Node
        #################################################################
        widget = self.createEntryField(contentFrame,'Type:',
                                       value = self.type,
                                       command = None,
                                       initialState='disabled',
                                       side = 'top')
        widget = self.createEntryField(contentFrame,'Model File:',
                                       value = self.info['filePath'].getFullpath(),
                                       command = None,
                                       initialState='disabled',
                                       side = 'top',
                                       defaultButton = False,
                                       buttonText = 'Change',
                                       defaultFunction = None)
        group = Pmw.Group(contentFrame,tag_text='Position',
                          tag_font=('MSSansSerif', 10))
        self.createPosEntry(group.interior())
        group.pack(side=TOP,fill = X, expand = 0, pady=3)
        
        group = Pmw.Group(contentFrame,tag_text='Orientation',
                          tag_font=('MSSansSerif', 10))
        self.createHprEntry(group.interior())
        group.pack(side=TOP,fill = X, expand = 0, pady=3)

        self.createScaleEntry(contentFrame)

        group = Pmw.Group(contentFrame,tag_text='Color',
                          tag_font=('MSSansSerif', 10))
        frame = group.interior()
        self.createColorEntry(frame)
        self.varAlpha = IntVar()
        self.varAlpha.set(self.nodePath.hasTransparency())
        checkButton = Checkbutton(frame, text='Enable Alpha',
                                  variable=self.varAlpha, command=self.toggleAlpha)
        checkButton.pack(side=RIGHT,pady=3)
        group.pack(side=TOP,fill = X, expand = 0, pady=3)
        return

    def toggleAlpha(self):
        #################################################################
        # toggleAlpha(self)
        # This funtion will toggle the objects alpha value
        # And, it will also reset the "Bin" to
        # "fixed" if user enable the alpha for this object.
        #################################################################
        if self.nodePath.hasTransparency():
            self.nodePath.clearTransparency()
            self.nodePath.setBin("default", 0)
        else:
            self.nodePath.setTransparency(True)
            self.nodePath.setBin("fixed", 1)
        return
    
    def actorInterface(self, contentFrame):
        #################################################################
        # actorInterface(self, contentFrame)
        # Create the basic interface for Actor Type Node
        #################################################################
        self.animFrame = None
        animeDict = self.info['animDict']
        if len(animeDict)==0:
            return

        self.animFrame = Frame(contentFrame)
        group = Pmw.Group(self.animFrame,tag_text='Animations',
                                   tag_font=('MSSansSerif', 10))
        innerFrame = group.interior()
        for name in animeDict:
            self.createEntryField(innerFrame, name,
                                  value = animeDict[name],
                                  command = None,
                                  initialState='disabled',
                                  side = 'top',
                                  defaultButton = True,
                                  buttonText = 'Remove',
                                  defaultFunction = lambda a = name, b = self : b.deleteAnimation(a))
        group.pack(side=TOP,fill = X, expand = 0, pady=3)
        self.animFrame.pack(side=TOP,fill = X, expand = 0, pady=3)
        return


    def deleteAnimation(self, anim):
        #################################################################
        # deleteAnimation(self, anim)
        # This function will delete the animation named "anim" in this actor
        # But, not directly removed be this function.
        # This function will send out a message to notice dataHolder to remove this animation
        #################################################################
        print anim
        widget = self.widgetsDict[anim]
        self.accept('animRemovedFromNode',self.redrawAnimProperty)
        messenger.send('PW_removeAnimFromNode',[self.name, anim])
        return

    def redrawAnimProperty(self, nodePath, animDict):
        #################################################################
        # redrawCurveProperty(self, nodePath, curveList)
        # Callback function, will be called once get the result from dataHolder.
        # It will check the target nodePath first, then check the curve list is empty or not.
        # If yes, then delete whole curve frame. If not, then renew the data and redraw the curve frame again.
        #################################################################
        self.name = self.nodePath.getName()
        if self.name != nodePath.getName():
            messenger.send('animRemovedFromNode',[nodePath, animDict])
            return
        else:
            self.ignore('animRemovedFromNode')
            
        if len(animDict)!= 0:
            del self.info['animDict']
            self.info['animDict'] = animDict
            self.animFrame.destroy()
            del self.animFrame
            self.animFrame = None
            self.actorInterface(self.contentFrame)
        else:
            del self.info['animDict']
            self.animFrame.destroy()
            del self.animFrame
            self.animFrame = None
        return

    ####
    ####  Anything about Light will be here!
    ####
    def lightInterface(self, contentFrame):
        #################################################################
        # lightInterface(self, contentFrame)
        # Create the basic interface for light Type Node
        #################################################################
        widget = self.createEntryField(contentFrame,'Type:',
                                       value = self.nodePath.node().getType().getName(),
                                       command = None,
                                       initialState='disabled',
                                       side = 'top')

        self.lightNode = self.info['lightNode']

        lightingGroup = Pmw.Group(contentFrame,tag_pyclass=None)
        frame = lightingGroup.interior()
        self.lightColor = seColorEntry(
            frame, text = 'Light Color', label_font=('MSSansSerif', 10),
            value=[self.lightNode.lightcolor.getX()*255, self.lightNode.lightcolor.getY()*255,self.lightNode.lightcolor.getZ()*255,0])
        self.lightColor['command'] = self.setLightingColorVec
        self.lightColor['resetValue'] = [0.3*255,0.3*255,0.3*255,0]
        self.lightColor.pack(side=TOP, fill=X,expand=1, padx = 2, pady =2)
        self.bind(self.lightColor, 'Set light color')
        
        self.varActive = IntVar()
        self.varActive.set(self.lightNode.active)
        checkButton = Checkbutton(frame, text='Enable This Light',
                                  variable=self.varActive, command=self.toggleLight)
        checkButton.pack(side=RIGHT,pady=3)
        lightingGroup.pack(side=TOP, fill = X, expand =1)
        
        # Directional light controls
        if self.lightNode.type == 'directional':
            lightingGroup = Pmw.Group(contentFrame,tag_pyclass=None)
            directionalPage = lightingGroup.interior()
            self.dSpecularColor = seColorEntry(
                directionalPage, text = 'Specular Color',  label_font=('MSSansSerif', 10),value = [self.lightNode.specularColor.getX()*255,self.lightNode.specularColor.getY()*255,self.lightNode.specularColor.getZ()*255,0])
            self.dSpecularColor['command'] = self.setSpecularColor
            self.dSpecularColor.pack(fill = X, expand = 1)
            self.bind(self.dSpecularColor,
                      'Set directional light specular color')
            self.dPosition = VectorWidgets.Vector3Entry(
                directionalPage, text = 'Position',  label_font=('MSSansSerif', 10),value = [self.lightNode.getPosition().getX(),self.lightNode.getPosition().getY(),self.lightNode.getPosition().getZ()])
            self.dPosition['command'] = self.setPosition
            self.dPosition['resetValue'] = [0,0,0,0]
            self.dPosition.pack(fill = X, expand = 1)
            self.bind(self.dPosition, 'Set directional light position')
            self.dOrientation = VectorWidgets.Vector3Entry(
                directionalPage, text = 'Orientation', label_font=('MSSansSerif', 10),
                value = [self.lightNode.getOrientation().getX(),self.lightNode.getOrientation().getY(),self.lightNode.getOrientation().getZ(),0])
            self.dOrientation['command'] = self.setOrientation
            self.dOrientation['resetValue'] = [0,0,0,0]
            self.dOrientation.pack(fill = X, expand = 1)
            self.bind(self.dOrientation, 'Set directional light orientation')
            
            lightingGroup.pack(side=TOP, fill = X, expand =1)

        
        elif self.lightNode.type == 'point':
            # Point light controls
            lightingGroup = Pmw.Group(contentFrame,tag_pyclass=None)
            pointPage = lightingGroup.interior()
            self.pSpecularColor = seColorEntry(
                pointPage, text = 'Specular Color', label_font=('MSSansSerif', 10),
                value = [self.lightNode.specularColor.getX(),self.lightNode.specularColor.getY(),self.lightNode.specularColor.getZ(),0])
            self.pSpecularColor['command'] = self.setSpecularColor
            self.pSpecularColor.pack(fill = X, expand = 1)
            self.bind(self.pSpecularColor,
                      'Set point light specular color')
    
            self.pPosition = VectorWidgets.Vector3Entry(
                pointPage, text = 'Position',  label_font=('MSSansSerif', 10),
                value = [self.lightNode.getPosition().getX(),self.lightNode.getPosition().getY(),self.lightNode.getPosition().getZ(),0])
            self.pPosition['command'] = self.setPosition
            self.pPosition['resetValue'] = [0,0,0,0]
            self.pPosition.pack(fill = X, expand = 1)
            self.bind(self.pPosition, 'Set point light position')

            self.pConstantAttenuation = Slider.Slider(
                pointPage,
                text = 'Constant Attenuation', label_font=('MSSansSerif', 10),
                max = 1.0,
                value = self.lightNode.constant)
            self.pConstantAttenuation['command'] = self.setConstantAttenuation
            self.pConstantAttenuation.pack(fill = X, expand = 1)
            self.bind(self.pConstantAttenuation,
                      'Set point light constant attenuation')
           
            self.pLinearAttenuation = Slider.Slider(
                pointPage,
                text = 'Linear Attenuation', label_font=('MSSansSerif', 10),
                max = 1.0,
                value = self.lightNode.linear)
            self.pLinearAttenuation['command'] = self.setLinearAttenuation
            self.pLinearAttenuation.pack(fill = X, expand = 1)
            self.bind(self.pLinearAttenuation,
                      'Set point light linear attenuation')
           
            self.pQuadraticAttenuation = Slider.Slider(
                pointPage,
                text = 'Quadratic Attenuation', label_font=('MSSansSerif', 10),
                max = 1.0,
                value = self.lightNode.quadratic)
            self.pQuadraticAttenuation['command'] = self.setQuadraticAttenuation
            self.pQuadraticAttenuation.pack(fill = X, expand = 1)
            self.bind(self.pQuadraticAttenuation,
                      'Set point light quadratic attenuation')

            lightingGroup.pack(side=TOP, fill = X, expand =1)

           
        elif self.lightNode.type == 'spot':     
            # Spot light controls
            lightingGroup = Pmw.Group(contentFrame,tag_pyclass=None)
            spotPage = lightingGroup.interior()
            self.sSpecularColor = seColorEntry(
                spotPage, text = 'Specular Color', label_font=('MSSansSerif', 10),
                value = [self.lightNode.specularColor.getX()*255,self.lightNode.specularColor.getY()*255,self.lightNode.specularColor.getZ()*255,0])
            self.sSpecularColor['command'] = self.setSpecularColor
            self.sSpecularColor.pack(fill = X, expand = 1)
            self.bind(self.sSpecularColor,
                      'Set spot light specular color')

            self.sConstantAttenuation = Slider.Slider(
                spotPage,
                text = 'Constant Attenuation', label_font=('MSSansSerif', 10),
                max = 1.0,
                value = self.lightNode.constant)
            self.sConstantAttenuation['command'] = self.setConstantAttenuation
            self.sConstantAttenuation.pack(fill = X, expand = 1)
            self.bind(self.sConstantAttenuation,
                      'Set spot light constant attenuation')
           
            self.sLinearAttenuation = Slider.Slider(
                spotPage,
                text = 'Linear Attenuation', label_font=('MSSansSerif', 10),
                max = 1.0,
                value = self.lightNode.linear)
            self.sLinearAttenuation['command'] = self.setLinearAttenuation
            self.sLinearAttenuation.pack(fill = X, expand = 1)
            self.bind(self.sLinearAttenuation,
                      'Set spot light linear attenuation')
           
            self.sQuadraticAttenuation = Slider.Slider(
                spotPage,
                text = 'Quadratic Attenuation', label_font=('MSSansSerif', 10),
                max = 1.0,
                value = self.lightNode.quadratic)
            self.sQuadraticAttenuation['command'] = self.setQuadraticAttenuation
            self.sQuadraticAttenuation.pack(fill = X, expand = 1)
            self.bind(self.sQuadraticAttenuation,
                      'Set spot light quadratic attenuation')
           
            self.sExponent = Slider.Slider(
                spotPage,
                text = 'Exponent', label_font=('MSSansSerif', 10),
                max = 1.0,
                value = self.lightNode.exponent)
            self.sExponent['command'] = self.setExponent
            self.sExponent.pack(fill = X, expand = 1)
            self.bind(self.sExponent,
                      'Set spot light exponent')
            lightingGroup.pack(side=TOP, fill = X, expand =1)
            
        return

    def setLightingColorVec(self,color):
        if self.lightNode==None:
            return
        self.lightNode.setColor(VBase4((color[0]/255),(color[1]/255),(color[2]/255),1))
        return

    def setSpecularColor(self,color):
        if self.lightNode==None:
            return
        self.lightNode.setSpecColor(VBase4((color[0]/255),(color[1]/255),(color[2]/255),1))
        return

    def setPosition(self,position):
        if self.lightNode==None:
            return
        self.lightNode.setPosition(Point3(position[0],position[1],position[2]))
        return

    def setOrientation(self, orient):
        if self.lightNode==None:
            return
        self.lightNode.setOrientation(Vec3(orient[0],orient[1],orient[2]))
        return
    
    def setConstantAttenuation(self, value):
        self.lightNode.setConstantAttenuation(value)
        return
    
    def setLinearAttenuation(self, value):
        self.lightNode.setLinearAttenuation(value)
        return
    
    def setQuadraticAttenuation(self, value):
        self.lightNode.setQuadraticAttenuation(value)
        return
    
    def setExponent(self, value):
        self.lightNode.setExponent(value)
        return

    def toggleLight(self):
        messenger.send('PW_toggleLight',[self.lightNode])
        return


    ####
    ####  Anything about Dummy will be here!
    ####
    def dummyInterface(self, contentFrame):
        #################################################################
        # dummyInterface(self, contentFrame)
        # Create the basic interface for dummy Type Node
        #################################################################
        '''dummyInterface(self, contentFrame)
        Create the basic interface for dummy Node
        '''
        widget = self.createEntryField(contentFrame,'Type:',
                                       value = 'Dummy Nodepath',
                                       command = None,
                                       initialState='disabled',
                                       side = 'top')
        
        group = Pmw.Group(contentFrame,tag_text='Position',
                          tag_font=('MSSansSerif', 10))
        self.createPosEntry(group.interior())
        group.pack(side=TOP,fill = X, expand = 0, pady=3)
        
        group = Pmw.Group(contentFrame,tag_text='Orientation',
                          tag_font=('MSSansSerif', 10))
        self.createHprEntry(group.interior())
        group.pack(side=TOP,fill = X, expand = 0, pady=3)

        self.createScaleEntry(contentFrame)

        group = Pmw.Group(contentFrame,tag_text='Color',
                          tag_font=('MSSansSerif', 10))
        frame = group.interior()
        self.createColorEntry(frame)
        self.varAlpha = IntVar()
        self.varAlpha.set(self.nodePath.hasTransparency())
        checkButton = Checkbutton(frame, text='Enable Alpha',
                                  variable=self.varAlpha, command=self.toggleAlpha)
        checkButton.pack(side=RIGHT,pady=3)
        group.pack(side=TOP,fill = X, expand = 0, pady=3)
        return


    #########
    #######  This will be called when user try to open property window for SEditor Node
    #########
    def gridInterface(self, contentFrame):
        #################################################################
        # gridInterface(self, contentFrame)
        # Create the basic interface for grid (Which is stolen from directGrid)
        #################################################################
        group = Pmw.Group(contentFrame,tag_text='Grid Property',
                          tag_font=('MSSansSerif', 10))
        group.pack(side=TOP,fill = X, expand = 0, padx = 3, pady=3)

        gridPage = group.interior()
        
        self.xyzSnap = BooleanVar()
        self.xyzSnapButton = Checkbutton(
            gridPage,
            text = 'XYZ Snap',
            anchor = 'w', justify = LEFT,
            variable = self.xyzSnap,
            command = self.toggleXyzSnap)
        self.xyzSnapButton.pack(fill = X, expand = 0, pady=3)

        self.hprSnap = BooleanVar()
        self.hprSnapButton = Checkbutton(
            gridPage,
            text = 'HPR Snap',
            anchor = 'w', justify = LEFT,
            variable = self.hprSnap,
            command = self.toggleHprSnap)
        self.hprSnapButton.pack(fill = X, expand = 0, pady=3)

        self.xyzSnap.set(SEditor.grid.getXyzSnap())
        self.hprSnap.set(SEditor.grid.getHprSnap())

        self.gridSpacing = Floater.Floater(
            gridPage,
            text = 'Grid Spacing',
            min = 0.1,
            value = SEditor.grid.getGridSpacing())
        self.gridSpacing['command'] = SEditor.grid.setGridSpacing
        self.gridSpacing.pack(fill = X, expand = 0, pady=3)
        
        self.gridSize = Floater.Floater(
            gridPage,
            text = 'Grid Size',
            min = 1.0,
            value = SEditor.grid.getGridSize())
        self.gridSize['command'] = SEditor.grid.setGridSize
        self.gridSize.pack(fill = X, expand = 0, pady=3)

        self.gridSnapAngle = Dial.AngleDial(
            gridPage,
            text = 'Snap Angle',
            style = 'mini',
            value = SEditor.grid.getSnapAngle())
        self.gridSnapAngle['command'] = SEditor.grid.setSnapAngle
        self.gridSnapAngle.pack(fill = X, expand = 0, pady=3)
        
        return

    def toggleXyzSnap(self):
        SEditor.grid.setXyzSnap(self.xyzSnap.get())
        return

    def toggleHprSnap(self):
        SEditor.grid.setHprSnap(self.hprSnap.get())
        return



    ###### Collision Section!!!!
    def collisionInterface(self, contentFrame):
        #################################################################
        # collisionInterface(self, contentFrame)
        # Create the basic interface for CollisionNode Type Node
        #################################################################
        collisionNode = self.info['collisionNode']
        self.collisionObj = collisionNode.node().getSolid(0)
        widget = self.createEntryField(contentFrame,'Node Type:',
                                       value = self.type,
                                       command = None,
                                       initialState='disabled',
                                       side = 'top')
        cType = self.collisionObj.getType().getName()
        widget = self.createEntryField(contentFrame,'Object Type:',
                                       value = cType,
                                       command = None,
                                       initialState='disabled',
                                       side = 'top')
        group = Pmw.Group(contentFrame,tag_text='Position',
                          tag_font=('MSSansSerif', 10))
        self.createPosEntry(group.interior())
        group.pack(side=TOP,fill = X, expand = 0, pady=3)
        
        group = Pmw.Group(contentFrame,tag_text='Orientation',
                          tag_font=('MSSansSerif', 10))
        self.createHprEntry(group.interior())
        group.pack(side=TOP,fill = X, expand = 0, pady=3)

        self.createScaleEntry(contentFrame)
        
        collisionGroup = Pmw.Group(contentFrame,tag_text='Collision Object Properties',
                          tag_font=('MSSansSerif', 10))
        cObjFrame = collisionGroup.interior()

        ### Generate different Interface for each different kinds of Collision Objects
        ### Yeah, yeah. I know this part of code looks so ugly...
        if cType == 'CollisionSphere':
            centerPos = self.collisionObj.getCenter()
            radius = self.collisionObj.getRadius()
            group = Pmw.Group(cObjFrame,tag_text='Origin',
                              tag_font=('MSSansSerif', 10))


            posInterior = Frame(group.interior())
            self.cPosX = self.createcomponent('originX', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'X', relief = FLAT,
                                             value = centerPos.getX(),
                                             label_foreground = 'Red',
                                             entry_width = 9)
            self.cPosX['commandData'] = ['sphere-o']
            self.cPosX['command'] = self.setCollisionPosHprScale
            self.cPosX.pack(side=LEFT,expand=0,fill=X, padx=1)
        
            self.cPosY = self.createcomponent('originY', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'Y', relief = FLAT,
                                             value = centerPos.getY(),
                                             label_foreground = '#00A000',
                                             entry_width = 9)
            self.cPosY['commandData'] = ['sphere-o']
            self.cPosY['command'] = self.setCollisionPosHprScale
            self.cPosY.pack(side=LEFT, expand=0,fill=X, padx=1)
        
            self.cPosZ = self.createcomponent('originZ', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'Z', relief = FLAT,
                                             value = centerPos.getZ(),
                                             label_foreground = 'Blue',
                                             entry_width = 9)
            self.cPosZ['commandData'] = ['sphere-o']
            self.cPosZ['command'] = self.setCollisionPosHprScale
            self.cPosZ.pack(side=LEFT, expand=0,fill=X, padx=1)
            posInterior.pack(side=TOP, expand=0,fill=X, padx=3, pady=3)

            group.pack(side=TOP,fill = X, expand = 0, pady=3)

            scaleInterior = Frame(cObjFrame)
        
            self.scaleS = self.createcomponent('radius', (), None,
                                               Floater.Floater, (scaleInterior,),
                                               text = 'Radius',
                                               relief = FLAT,
                                               min = 0.0001, value = radius,
                                               resetValue = 1.0,
                                               label_foreground = 'Blue')
            self.scaleS['commandData'] = ['sphere-radius']
            self.scaleS['command'] = self.setCollisionPosHprScale
            self.scaleS.pack(side=LEFT,expand=0,fill=X)

            scaleInterior.pack(side=TOP,expand=0,fill=X, padx=3, pady=3)
            pass
        
        elif cType == 'CollisionPolygon':
            frame = Frame(cObjFrame)
            label = Label(frame, text= "Sorry!",font=('MSSansSerif', 10),
                          borderwidth=5)
            label.pack(side=LEFT)
            frame.pack(side=TOP, fill=X, expand=True)
            frame = Frame(cObjFrame)
            label = Label(frame, text= "There is no way to change",font=('MSSansSerif', 10),
                          borderwidth=5)
            label.pack(side=LEFT)
            frame.pack(side=TOP, fill=X, expand=True)
            frame = Frame(cObjFrame)
            label = Label(frame, text= "the basic properties of Collision Polygon!",font=('MSSansSerif', 10),
                          borderwidth=5)
            label.pack(side=LEFT)
            frame.pack(side=TOP, fill=X, expand=True)
            frame = Frame(cObjFrame)
            label = Label(frame, text= "If you really need to change, recreate one...",font=('MSSansSerif', 10),
                          borderwidth=5)
            label.pack(side=LEFT)
            frame.pack(side=TOP, fill=X, expand=True)        
            pass
        
        elif cType == 'CollisionSegment':
            pointA = self.collisionObj.getPointA()
            pointB = self.collisionObj.getPointB()
            group = Pmw.Group(cObjFrame,tag_text='Point A',
                              tag_font=('MSSansSerif', 10))
            posInterior = Frame(group.interior())
            self.cPosX = self.createcomponent('pointA-X', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'X', relief = FLAT,
                                             value = pointA.getX(),
                                             label_foreground = 'Red',
                                             entry_width = 9)
            self.cPosX['commandData'] = ['segment-A']
            self.cPosX['command'] = self.setCollisionPosHprScale
            self.cPosX.pack(side=LEFT,expand=0,fill=X, padx=1)
        
            self.cPosY = self.createcomponent('pointA-Y', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'Y', relief = FLAT,
                                             value = pointA.getY(),
                                             label_foreground = '#00A000',
                                             entry_width = 9)
            self.cPosY['commandData'] = ['segment-A']
            self.cPosY['command'] = self.setCollisionPosHprScale
            self.cPosY.pack(side=LEFT, expand=0,fill=X, padx=1)
        
            self.cPosZ = self.createcomponent('pointA-Z', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'Z', relief = FLAT,
                                             value = pointA.getZ(),
                                             label_foreground = 'Blue',
                                             entry_width = 9)
            self.cPosZ['commandData'] = ['segment-A']
            self.cPosZ['command'] = self.setCollisionPosHprScale
            self.cPosZ.pack(side=LEFT, expand=0,fill=X, padx=1)
            posInterior.pack(side=TOP, expand=0,fill=X, padx=3, pady=3)
            group.pack(side=TOP,fill = X, expand = 0, pady=3)
            group = Pmw.Group(cObjFrame,tag_text='Point B',
                              tag_font=('MSSansSerif', 10))
            posInterior = Frame(group.interior())
            self.cPosXB = self.createcomponent('pointB-X', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'X', relief = FLAT,
                                             value = pointB.getX(),
                                             label_foreground = 'Red',
                                             entry_width = 9)
            self.cPosXB['commandData'] = ['segment-B']
            self.cPosXB['command'] = self.setCollisionPosHprScale
            self.cPosXB.pack(side=LEFT,expand=0,fill=X, padx=1)
        
            self.cPosYB = self.createcomponent('pointB-Y', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'Y', relief = FLAT,
                                             value = pointB.getY(),
                                             label_foreground = '#00A000',
                                             entry_width = 9)
            self.cPosYB['commandData'] = ['segment-B']
            self.cPosYB['command'] = self.setCollisionPosHprScale
            self.cPosYB.pack(side=LEFT, expand=0,fill=X, padx=1)
        
            self.cPosZB = self.createcomponent('pointB-Z', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'Z', relief = FLAT,
                                             value = pointB.getZ(),
                                             label_foreground = 'Blue',
                                             entry_width = 9)
            self.cPosZB['commandData'] = ['segment-B']
            self.cPosZB['command'] = self.setCollisionPosHprScale
            self.cPosZB.pack(side=LEFT, expand=0,fill=X, padx=1)
            posInterior.pack(side=TOP, expand=0,fill=X, padx=3, pady=3)
            group.pack(side=TOP,fill = X, expand = 0, pady=3)
            pass
        elif cType == 'CollisionRay':
            origin = self.collisionObj.getOrigin()
            direction = self.collisionObj.getDirection()
            group = Pmw.Group(cObjFrame,tag_text='Origin Point',
                              tag_font=('MSSansSerif', 10))
            posInterior = Frame(group.interior())
            self.cPosX = self.createcomponent('origin-X', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'X', relief = FLAT,
                                             value = origin.getX(),
                                             label_foreground = 'Red',
                                             entry_width = 9)
            self.cPosX['commandData'] = ['ray-A']
            self.cPosX['command'] = self.setCollisionPosHprScale
            self.cPosX.pack(side=LEFT,expand=0,fill=X, padx=1)
        
            self.cPosY = self.createcomponent('origin-Y', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'Y', relief = FLAT,
                                             value = origin.getY(),
                                             label_foreground = '#00A000',
                                             entry_width = 9)
            self.cPosY['commandData'] = ['ray-A']
            self.cPosY['command'] = self.setCollisionPosHprScale
            self.cPosY.pack(side=LEFT, expand=0,fill=X, padx=1)
        
            self.cPosZ = self.createcomponent('origin-Z', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'Z', relief = FLAT,
                                             value = origin.getZ(),
                                             label_foreground = 'Blue',
                                             entry_width = 9)
            self.cPosZ['commandData'] = ['ray-A']
            self.cPosZ['command'] = self.setCollisionPosHprScale
            self.cPosZ.pack(side=LEFT, expand=0,fill=X, padx=1)
            posInterior.pack(side=TOP, expand=0,fill=X, padx=3, pady=3)
            group.pack(side=TOP,fill = X, expand = 0, pady=3)
            group = Pmw.Group(cObjFrame,tag_text='Direction',
                              tag_font=('MSSansSerif', 10))
            posInterior = Frame(group.interior())
            self.cPosXB = self.createcomponent('direction-X', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'X', relief = FLAT,
                                             value = direction.getX(),
                                             label_foreground = 'Red',
                                             entry_width = 9)
            self.cPosXB['commandData'] = ['ray-B']
            self.cPosXB['command'] = self.setCollisionPosHprScale
            self.cPosXB.pack(side=LEFT,expand=0,fill=X, padx=1)
        
            self.cPosYB = self.createcomponent('direction-Y', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'Y', relief = FLAT,
                                             value = direction.getY(),
                                             label_foreground = '#00A000',
                                             entry_width = 9)
            self.cPosYB['commandData'] = ['ray-B']
            self.cPosYB['command'] = self.setCollisionPosHprScale
            self.cPosYB.pack(side=LEFT, expand=0,fill=X, padx=1)
        
            self.cPosZB = self.createcomponent('direction-Z', (), None,
                                             Floater.Floater, (posInterior,),
                                             text = 'Z', relief = FLAT,
                                             value = direction.getZ(),
                                             label_foreground = 'Blue',
                                             entry_width = 9)
            self.cPosZB['commandData'] = ['ray-B']
            self.cPosZB['command'] = self.setCollisionPosHprScale
            self.cPosZB.pack(side=LEFT, expand=0,fill=X, padx=1)
            posInterior.pack(side=TOP, expand=0,fill=X, padx=3, pady=3)
            group.pack(side=TOP,fill = X, expand = 0, pady=3)
            pass
            
        collisionGroup.pack(side=TOP,fill = X, expand = 0, pady=3)

        return

    def setCollisionPosHprScale(self, data, dataType):
        #################################################################
        # setCollisionPosHprScale(self, data, dataType)
        # Well, the reason that we didn't use the same one with other nodePath
        # is that each tyoe of collsion objects has its unique properties and way to set value.
        # So, they have to be separated from other nodePath
        #################################################################
        if dataType == 'sphere-o':
            origin = Point3(float(self.cPosX._entry.get()),
                            float(self.cPosY._entry.get()),
                            float(self.cPosZ._entry.get()))
            self.collisionObj.setCenter(origin)
        elif dataType == 'sphere-radius':
            self.collisionObj.setRadius(data)
        elif dataType == 'segment-A':
            pointA = Point3(float(self.cPosX._entry.get()),
                            float(self.cPosY._entry.get()),
                            float(self.cPosZ._entry.get()))
            self.collisionObj.setPointA(pointA)
        elif dataType == 'segment-B':
            pointB = Point3(float(self.cPosXB._entry.get()),
                            float(self.cPosYB._entry.get()),
                            float(self.cPosZB._entry.get()))
            self.collisionObj.setPointB(pointB)
        elif dataType == 'ray-A':
            pointA = Point3(float(self.cPosX._entry.get()),
                            float(self.cPosY._entry.get()),
                            float(self.cPosZ._entry.get()))
            self.collisionObj.setOrigin(pointA)
        elif dataType == 'ray-B':
            pointB = Vec3(float(self.cPosXB._entry.get()),
                          float(self.cPosYB._entry.get()),
                          float(self.cPosZB._entry.get()))
            self.collisionObj.setDirection(pointB)
        return

    #################################################################
    #################################################################
    # Functions below are all call back function
    # They will be called when user has manipulated its node on the screen
    # The message itself is sent by a task called monitorSelectedNode in the sceneEditor.
    #################################################################
    #################################################################
    def trackDataFromSceneCamera(self, pos=Point3(0,0,0), hpr=Vec3(0,0,0), scale=Point3(0,0,0)):
        self.posX.set(pos.getX())
        self.posY.set(pos.getY())
        self.posZ.set(pos.getZ())
        self.hprH.set(hpr.getX())
        self.hprP.set(hpr.getY())
        self.hprR.set(hpr.getZ())
        return

    def trackDataFromSceneModel(self, pos=Point3(0,0,0), hpr=Vec3(0,0,0), scale=Point3(0,0,0)):
        self.posX.set(pos.getX())
        self.posY.set(pos.getY())
        self.posZ.set(pos.getZ())
        self.hprH.set(hpr.getX())
        self.hprP.set(hpr.getY())
        self.hprR.set(hpr.getZ())
        self.scale.set(scale.getX())
        return

    def trackDataFromSceneActor(self, pos=Point3(0,0,0), hpr=Vec3(0,0,0), scale=Point3(0,0,0)):
        self.posX.set(pos.getX())
        self.posY.set(pos.getY())
        self.posZ.set(pos.getZ())
        self.hprH.set(hpr.getX())
        self.hprP.set(hpr.getY())
        self.hprR.set(hpr.getZ())
        self.scale.set(scale.getX())
        return
    
    def trackDataFromSceneLight(self, pos=Point3(0,0,0), hpr=Vec3(0,0,0), scale=Point3(0,0,0)):
        if self.lightNode.type == 'directional':
            self.dPosition.set([pos.getX(),pos.getY(),pos.getZ()])
            self.dOrientation.set([hpr.getX(),hpr.getY(),hpr.getZ()])
            pass
        
        elif self.lightNode.type == 'point':
            self.pPosition.set([pos.getX(),pos.getY(),pos.getZ()])
            pass       
        return
    
    def trackDataFromSceneDummy(self, pos=Point3(0,0,0), hpr=Vec3(0,0,0), scale=Point3(0,0,0)):
        self.posX.set(pos.getX())
        self.posY.set(pos.getY())
        self.posZ.set(pos.getZ())
        self.hprH.set(hpr.getX())
        self.hprP.set(hpr.getY())
        self.hprR.set(hpr.getZ())
        self.scale.set(scale.getX())
        return
    
    def trackDataFromSceneCollision(self, pos=Point3(0,0,0), hpr=Vec3(0,0,0), scale=Point3(0,0,0)):
        self.posX.set(pos.getX())
        self.posY.set(pos.getY())
        self.posZ.set(pos.getZ())
        self.hprH.set(hpr.getX())
        self.hprP.set(hpr.getY())
        self.hprR.set(hpr.getZ())
        self.scale.set(scale.getX())
        return
        
