######################################################################################
#  File:        GameSketchingWorld.py 
#
#  Purpose:  This module will contain the graphics code for the graphic presentation of game sketchers.   It interfaces with Panda3d
#
#
#
#              The graphics for game sketching will be contained in a class called GameSketchingWorld
#
#
######################################################################################
#
#  Copyright (c)  2008 (gamesketching)
#
# Michael Augustin
# Mark Barrett
# John Buchanan
# Gina Chuang
# Albith Delgado
# Tony Ortega
# Joshua Seaver
#
#
#
#
#   This file is part of GameSketching:
#
#   GameSketching is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#    This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
# test
######################################################################################

######################################################################################
#  System and Python includes
######################################################################################

import sys,os
from math import *
__version__ = "@version $Id$"


######################################################################################
# Panda3d imports
######################################################################################

import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.gui.DirectGui import *
from direct.interval.IntervalGlobal import *
from direct.gui.DirectGui import *
from direct.actor import Actor
from direct.task import Task
from ui.SketchItUpGlowFilter import SketchItUpGlowFilter


from direct.showbase.DirectObject import DirectObject




######################################################################################
# GameSketching imports
######################################################################################

from PrintStuff import PrintStuff
from GameSketchingGlobals import GameSketchingGlobals, actorDataHolder

gameSketchingGlobals = GameSketchingGlobals()

# Figure out what directory this program is in.
MYDIR=os.path.abspath(sys.path[0])
MYDIR=Filename.fromOsSpecific(MYDIR).getFullpath()

printer = PrintStuff([0,1,31])  #31 is the local flag for verbose output

class GameSketchingActor ():


    """
    This is a container class for the actors in the world.
    Only information that cannot be stored in the Panda3D object
    should be stored here.
    """
    def __init__(self,name,actorNumber = -1, fileName = "", animations= {}, textures= {}):
        """
        Initialize an actor container for the world.
        """

        self.name = name            #name of the actor
        self.node = None            #Panda3d node
        self.number = actorNumber
        self.fileName = fileName    #fileName where the actor resides
        self.animations = animations
        self.textures = textures
        self.textureLoaded = None
        self.moveAnimationFrame = 0
        self.pickerObject = None      #this is where the picker node is going to go, save the pointer for easy access.
        self.collisionNode = None



        self.forwardSpeed =   gameSketchingGlobals.worldDefaultForwardSpeed
        self.sidewaysSpeed =  gameSketchingGlobals.worldDefaultSidewaysSpeed
        self.riseSpeed =      gameSketchingGlobals.worldDefaultRiseSpeed

        self.lookUpSpeed =    gameSketchingGlobals.worldDefaultLookUpSpeed
        self.lookLeftSpeed =  gameSketchingGlobals.worldDefaultLookLeftSpeed
        self.tiltLeftSpeed =  gameSketchingGlobals.worldDefaultTiltLeftSpeed

        self.sideView = 0 # to check if the current view is the side view. It is 1 if YES, 0 if NO.

    #end __init__
#end GameSketchingActor


class GameSketchingBullet ():


    """
    Instances of bullets in the world
    """
    def __init__(self,name,actorNumber = -1, fileName = ""):
        """
        Initialize an actor container for the world.
        """

        self.name = name            #name of the actor
        self.node = None            #Panda3d node
        self.number = actorNumber
        self.fileName = fileName    #fileName where the actor resides


        self.forwardSpeed =   gameSketchingGlobals.worldDefaultForwardSpeed
        self.sidewaysSpeed =  gameSketchingGlobals.worldDefaultSidewaysSpeed
        self.riseSpeed =      gameSketchingGlobals.worldDefaultRiseSpeed

        self.lookUpSpeed =    gameSketchingGlobals.worldDefaultLookUpSpeed
        self.lookLeftSpeed =  gameSketchingGlobals.worldDefaultLookLeftSpeed
        self.tiltLeftSpeed =  gameSketchingGlobals.worldDefaultTiltLeftSpeed

        self.sideView = 0 # to check if the current view is the side view. It is 1 if YES, 0 if NO.

    #end __init__
#end GameSketchingBullet





class GameSketchingWorld(DirectObject):
    """

    GameSketchingWorld:  This is the class that is used to interface with Panda3d.


    Access through the following functions

    __init__(self,render)  : render is the panda3d object we will render into

    setActorNumber(self,number) : Set the internal number used for the next actor name
                                  this is used for server client name synchronization

    getActorNumber(self,number) : Get the internal number used for the next actor name
                                  this is used for server client name synchronization

    __generateUniqueName(self)  : Use the internal number to generate a unique name for the
                                  next actor

    loadActor(self,fileName,name=None,position = None, orientation = None)
                                : load the actor and set the data as needed.
                                  If no name, position, and orientation are not provided
                                  then place at origin and generate unique name internally

    removeActor(self, actorName):  Remove the actor from the database

    positionActor(self, actorName, x,y,z): Position the actor

    orientActor(self, actorName, h, p, r): orient the actor

    moveActor(self, actorName, x,y,z): move the actor

    getActorData(self,actorName):  get the actor data

    getActors(self):               get a dictionary with all of the actors and their information
    """



    ####################################################################
    # __init__
    ####################################################################
    def __init__(self,render):
        """
        __init__(self, render): Initialize GameSketchingWorldho

        render:  The Panda3D node the world hangs off

        """
        ##########################
        #initialization of variables used in the world.
        ##########################
        
        # A class that handles Glow effect for highlighting purposes.
        self.glowFilter = SketchItUpGlowFilter()
        self.oldStatus = False
            
        # Define a variable to know if the ctrl key is pressed 
        self.ctrlPressed = False
        self.altPressed = False
        
        #Variable for notifying the client that the camera has to be attached
        self.callForCameraAttach = False
        self.isCameraAttached = False
        self.clientCanAttach = True
        
        #Variable for selecting all objects
        self.callForSelectAll = False
        self.callForDeselectAll = False
        
        # Definition of mouse variables for moving the camera around when alt is pressed
        self.mouse2Pressed = False
        
        self.isAClient = False
        
        #Create a variable for wall creating system in the world
        self.isWallCreateActive = False
        self.isWallCreateServerActive = False
        #Create a naming for the wall objects
        self.wallFirstName = "wall"
        self.wallSecondName = 1
        
        #variable for first wall and second wall
        self.wallFirstBrick = VBase3 (0, 0, 0)
        self.wallSecondBrick = VBase3 (0, 0, 0)
        
        #variable for the drag of the invisible walls for wall building
        self.invisibleWalls = False
        
        #create a variable for validating in what actor is the camera attached
        self.actorForCameraAttach = 'empty'
        
        self.bulletPlace = None
        
        #We define a variable for storing the position of the mouse when a click is done
        self.mouseInicialPosition = [0, 0] 
                                                        #Panda 3d head node
        self.headNodeOfWorld = render

        self.actorsHeadNode = self.headNodeOfWorld.attachNewNode('actors')
        self.levelHeadNode = self.headNodeOfWorld.attachNewNode('level')

                                                        #dictionary of actors
        self.actorsInPlay = {}
        self.groupsDefined = {}
        self.shadowsInPlay = {}
        self.bulletsInPlay = {}


        self.floorPosition = [0, 0]
        self.camera = camera


        ##########################
        #White directional light to set as default light
        ##########################
        self.dlight=DirectionalLight("myDLight")
        self.dlight.setColor(Vec4(0.7,0.7,0.7,1))
        self.dlightNodePath = render.attachNewNode(
        self.dlight.upcastToPandaNode())
        self.dlightNodePath.setHpr(0,-45,0)
        self.dlightNodePath.setPos(0,50,0)
        render.setLight(self.dlightNodePath)
        
        ##########################
        #Add an ambient light to the world
        ##########################
        self.alight = AmbientLight('alight')
        self.alight.setColor(Vec4(0.3, 0.3, 0.3, 1))
        self.alightNodePath = render.attachNewNode(self.alight.upcastToPandaNode())
        render.setLight(self.alightNodePath)


                                                        #Define the location of the actorfiles.
                                                        #they are stored in ../assets
        from pandac.PandaModules import loadPrcFile
        loadPrcFile(MYDIR + "/src/GameSketchingConfigExtension.prc")


        self.actorNumber = 0                           #Number used to generate unique actor names

        ##########################
        #graphics subsystem initialization
        ##########################

        base.setBackgroundColor(gameSketchingGlobals.worldDefaultBackground)
        base.disableMouse()


        ######################################################
        # This world uses the default camera  or camera as it is aliased
        # In order to get object picking we have to use this other camera.
        #
        ######################################################
        self.camera = base.makeCamera(base.win)

        self.camera.node().copyLens(base.cam.node().getLens())
        self.camera.node().setActive(0)
        self.camera.reparentTo(self.headNodeOfWorld)

        ######################################################
        #Move Camera Definition
        #Create an empty node for getting value movements for the camera
        ######################################################
        self.frontCamera=NodePath("frontCamera")
        self.frontCamera.setPos(0,3,0)
        self.frontCamera.reparentTo(base.camera)

        self.backCamera=NodePath("backCamera")
        self.backCamera.setPos(0,-3,0)
        self.backCamera.reparentTo(base.camera)
        #end moveCamera Definition
        
        
        ######################################################
        #Define empty node for putting buttons on the mousepointer
        ######################################################
        self.cameraButtons=NodePath("cameraButtons")
        self.cameraButtons.reparentTo(aspect2d)
        self.cameraButtons.setPos(10,10,10)
        #end 


        #predefine the buttons to be used
        self.inicialCameraButton = DirectButton(text = '', scale=0.05, pos=(0,0,0.065),command=self.baseCamera, image="assets/textures/rightclickmenu/sketch_01.png",image_scale=(3, 1.0, 0.9),extraArgs=['VR'],relief=None)
        self.topCameraButton = DirectButton(text = '', scale=0.05, pos=(0,0,0.0),command=self.topCamera, image="assets/textures/rightclickmenu/sketch_02.png",image_scale=(3, 1.0, 0.6),extraArgs=['VR'],relief=None)
        self.sideCameraButton = DirectButton(text = '', scale=0.05, pos=(0,0,-0.06),command=self.sideCamera, image="assets/textures/rightclickmenu/sketch_03.png",image_scale=(3, 1.0, 0.6),extraArgs=['VR'],relief=None)
        self.showAllButton = DirectButton(text = '', scale=0.05, pos=(0,0,-0.13),command=self.showWholeScene, image="assets/textures/rightclickmenu/sketch_04.png",image_scale=(3, 1.0, 0.9),extraArgs=['VR'],relief=None)
        self.zoomInButton = DirectButton(text = '', scale=0.05, pos=(0,0,-0.21),command=self.baseCamera, image="assets/textures/rightclickmenu/sketch_05.png",image_scale=(3, 1.0, 0.7),extraArgs=['VR'],relief=None)
        self.zoomOutButton = DirectButton(text = '', scale=0.05, pos=(0,0,-0.29),command=self.baseCamera, image="assets/textures/rightclickmenu/sketch_06.png",image_scale=(3, 1.0, 0.9),extraArgs=['VR'],relief=None)
        self.selectAllButton = DirectButton(text = '', scale=0.05, pos=(0,0,-0.37),command=self.selectAll, image="assets/textures/rightclickmenu/sketch_07.png",image_scale=(3, 1.0, 0.7),extraArgs=['VR'],relief=None)
        self.deselectAllButton = DirectButton(text = '', scale=0.05, pos=(0,0,-0.45),command=self.deselectAll, image="assets/textures/rightclickmenu/sketch_08.png",image_scale=(3, 1.0, 0.9),extraArgs=['VR'],relief=None)
        self.attachButton = DirectButton(text = '', scale=0.05, pos=(0,0,-0.52),command=self.attachNewCameraVariable, image="assets/textures/rightclickmenu/sketch_09.png",image_scale=(3, 1.0, 0.7),extraArgs=['VR'],relief=None)
        self.groupButton = DirectButton(text = '', scale=0.05, pos=(0,0,-0.59),command=self.baseCamera, image="assets/textures/rightclickmenu/sketch_10.png",image_scale=(3, 1.0, 0.7),extraArgs=['VR'],relief=None)
        self.ungroupButton = DirectButton(text = '', scale=0.05, pos=(0,0,-0.67),command=self.activateWallCreate, image="assets/textures/rightclickmenu/sketch_11.png",image_scale=(3, 1.0, 0.9),extraArgs=['VR'],relief=None)
        
        self.inicialCameraButton.setTransparency(1)
        self.topCameraButton.setTransparency(1)
        self.sideCameraButton.setTransparency(1)
        self.showAllButton.setTransparency(1)
        self.zoomInButton.setTransparency(1)
        self.zoomOutButton.setTransparency(1)
        self.selectAllButton.setTransparency(1)
        self.deselectAllButton.setTransparency(1)
        self.attachButton.setTransparency(1)
        self.groupButton.setTransparency(1)
        self.ungroupButton.setTransparency(1)
        
        self.topCameraButton.reparentTo(self.cameraButtons)
        self.sideCameraButton.reparentTo(self.cameraButtons)
        self.inicialCameraButton.reparentTo(self.cameraButtons)
        self.showAllButton.reparentTo(self.cameraButtons)
        self.zoomInButton.reparentTo(self.cameraButtons)
        self.zoomOutButton.reparentTo(self.cameraButtons)
        self.selectAllButton.reparentTo(self.cameraButtons)
        self.deselectAllButton.reparentTo(self.cameraButtons)
        self.attachButton.reparentTo(self.cameraButtons)
        self.groupButton.reparentTo(self.cameraButtons)
        self.ungroupButton.reparentTo(self.cameraButtons)
        
        camera.setPos ( gameSketchingGlobals.worldDefaultCameraPos)
        camera.setHpr ( gameSketchingGlobals.worldDefaultCameraHpr)

        self.cameraForwardSpeed = gameSketchingGlobals.worldDefaultCameraForwardSpeed
        self.cameraLeftSpeed    = gameSketchingGlobals.worldDefaultCameraLeftSpeed
        self.cameraUpSpeed      = gameSketchingGlobals.worldDefaultCameraUpSpeed

        self.cameraLookUpSpeed      = gameSketchingGlobals.worldDefaultCameraLookUpSpeed
        self.cameraLookLeftSpeed    = gameSketchingGlobals.worldDefaultCameraLookLeftSpeed
        self.cameraTiltLeftSpeed    = gameSketchingGlobals.worldDefaultCameraTiltLeftSpeed

        ################################
        # Prepare camera ray
        ################################

        self.lens = self.camera
        self.pickerRay = CollisionRay()
        self.picker = CollisionTraverser()
        self.queue = CollisionHandlerQueue()
        self.pickerNode = CollisionNode('mouseRay')
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        self.pickerNP.show()
        self.pickerNode.setFromCollideMask(BitMask32.bit(0))

        self.pickerNode.addSolid(self.pickerRay)        
        self.picker.addCollider(self.pickerNP, self.queue)
        self.picker.showCollisions (self.lens)

        #########################################
        #  Load the level stuff
        #########################################

        self.floorNode = loader.loadModelCopy(gameSketchingGlobals.defaultWorldFloorPlaneFile)
        self.floorNode.reparentTo(self.levelHeadNode)
        self.floorCollision = CollisionPlane(Plane(Vec3(0,0,1), Point3(0,0,0)))
        self.floorCollisionNode = CollisionNode('floor')
        self.floorCollisionNode.addSolid(self.floorCollision)
        self.floorNode.attachNewNode(self.floorCollisionNode)
        self.floorCollisionNode.setIntoCollideMask(BitMask32.bit(0))

        ################################################################
        # Define the commands for the control which will be used for grouping
        ################################################################
        self.accept("control", self.ctrlClick)
        self.accept("control-up", self.ctrlClickUp)
        self.accept("alt", self.altClick)
        self.accept("alt-up", self.altClickUp)
        #add he handlers for the mouse clicks for camera movement
        self.accept("mouse2", self.mouse2CameraClick)
        self.accept("mouse2-up", self.mouse2CameraClickUp)
        #we double the mouse1 click for attaching camera on the server
        self.accept("mouse1", self.mouse1ClickServer)
        #add funcionality for scrolling the wheel for zoom in or out
        self.accept("wheel_up", self.mouse2ZooomIn)
        self.accept("wheel_down", self.mouse2ZooomOut)
        
        #Create a task for updating the camera according to the mouse movement
        taskMgr.add(self.mouseCameraTracking, 'mouseCameraTracking')
    #end __init__
    
    ###################################################################
    # select All 
    ###################################################################
    def selectAll(self, args):
        """
        select all the objects for a client  
        
        """
        self.callForSelectAll = True
    #end selectall
    
    ###################################################################
    # deselect All 
    ###################################################################
    def deselectAll(self, args):
        """
        select all the objects for a client  
        
        """
        self.callForDeselectAll = True
    #end deselectAll

    ###################################################################
    # activateWallCreate 
    ###################################################################
    def activateWallCreate(self, args):
        """
        Activate wall creating variable for allowing player for creating a wall in the world  
        
        """
        self.deselectAll(args)
        self.isWallCreateActive = True
    #end activateWallCreate
    
    ###################################################################
    # shootingInteraction
    ###################################################################
    def shootingInteraction(self, myActors):
        """
        Start shooting for all characters in the screen  
        
        """
        if self.bulletPlace ==  None:
            #Define the model that will be loaded as the bullet
            fileName = 'test.egg'
            
            #Create the original bullet before instancing
            self.bulletPlace = render.attachNewNode("Bullet-Place")
            self.bulletPlace.setPos(0,0,0)
            
            #Load the bullets for all actors in play for the client recieved
            for oneActor in self.actorsInPlay:
                if oneActor in myActors:
                    actor = self.actorsInPlay[oneActor]
                    bulletInstance = loader.loadModelCopy(fileName)
                    bulletInstance.reparentTo(self.bulletPlace)
                    bulletInstance.setPos (actor.node.getPos(self.bulletPlace))
                    bulletInstance.setHpr(actor.node.getHpr()) 
                    self.bulletsInPlay[actor] = bulletInstance
                    #self.actorsInPlay [oneActor].node()
            taskMgr.add(self.shootAllCharacters, 'shootAllCharacters')
                #end if
    #end shootingInteraction
    
    
    ###################################################################
    # shootAllCharacters
    ###################################################################
    def shootAllCharacters(self, task):
        """
        Simulates the shooting object in screen  
        
        """
        if task.frame >  10:
            #After ten frames the bullet is destroyed
            self.bulletPlace.removeNode()
            self.bulletPlace = None
            return Task.done
        
        #Move each of the bullets that are currently in play
        for shootBullet in self.bulletsInPlay:
            bullet = self.bulletsInPlay[shootBullet]
            
            angle = bullet.getH(render)
            angle = abs(angle%360) - 90
            angle = (angle * 3.1416 ) / 180 
            
            bullet.setX(bullet.getX(render) + (3 *  cos(angle)))
            bullet.setY(bullet.getY(render) + (3 *  sin(angle)))
            
            angleZ = bullet.getP(render)
            angleZ = abs(angleZ%360)  + 90 
            angleZ = (angleZ * 3.1416 ) / 180
            
            bullet.setZ((bullet.getZ(render) + (3 *  cos(angleZ))))

            
        return task.cont
    #end shootAllCharacters
    
    
    ###################################################################
    # setInvisibleWalls
    ###################################################################
    def setInvisibleWalls(self, val):
        """
        Set the variable for the invisible walls creation  
        
        """
        self.invisibleWalls = val
    #end setInvisibleWalls
    
    ###################################################################
    # getInvisibleWalls
    ###################################################################
    def getInvisibleWalls(self):
        """
        get the variable for the invisibleWalls  
        
        """
        return self.invisibleWalls
    #end getInvisibleWalls
    
    ###################################################################
    # setWallFirstBrick
    ###################################################################
    def setWallFirstBrick(self, val):
        """
        Set the variable for wall second name which will be on which wall are we currently  
        
        """
        self.wallFirstBrick = val
    #end setWallFirstBrick
    
    ###################################################################
    # getWallFirstBrick
    ###################################################################
    def getWallFirstBrick(self):
        """
        get the variable for the wall second name which will be on which wall are we currently  
        
        """
        return self.wallFirstBrick
    #end getWallFirstBrick
    
    ###################################################################
    # setWallSecondBrick
    ###################################################################
    def setWallSecondBrick(self, val):
        """
        Set the variable for wall second name which will be on which wall are we currently  
        
        """
        self.wallSecondBrick = val1
    #end setWallSecondBrick
    
    ###################################################################
    # getWallSecondBrick
    ###################################################################
    def getWallSecondBrick(self):
        """
        get the variable for the wall second name which will be on which wall are we currently  
        
        """
        return self.wallSecondBrick
    #end getWallFirstBrick
    
    
    ###################################################################
    # setIsWallCreateActive
    ###################################################################
    def setIsWallCreateActive(self, newVal):
        """
        Set the variable for wall building  
        
        """
        self.isWallCreateActive = newVal
    #end setIsWallCreateActive
    
    ###################################################################
    # getIsWallCreateActive
    ###################################################################
    def getIsWallCreateActive(self):
        """
        Get the variable for wall building  
        
        """
        return self.isWallCreateActive
    #end getIsWallCreateActive
    
    ###################################################################
    # setIsWallCreateServerActive
    ###################################################################
    def setIsWallCreateServerActive(self, newVal):
        """
        Set the variable for wall building  
        
        """
        self.isWallCreateServerActive = newVal
    #end setIsWallCreateServerActive
    
    ###################################################################
    # getIsWallCreateServerActive
    ###################################################################
    def getIsWallCreateServerActive(self):
        """
        Get the variable for wall building  
        
        """
        return self.isWallCreateServerActive
    #end getIsWallCreateServerActive
    
    
    
    
    ###################################################################
    # baseCamera 
    ###################################################################
    def baseCamera(self, args):
        """
        put the camera on the original position  
        
        """
        self.isCameraAttached = False
        base.camera.reparentTo(render)
        camera.setPos ( gameSketchingGlobals.worldDefaultCameraPos)
        camera.setHpr ( gameSketchingGlobals.worldDefaultCameraHpr)
        self.sideView = 0
    #end baseCamera

    ###################################################################
    # topCamera 
    ###################################################################
    def topCamera(self, args):
        """
        put the camera on the original position  
        
        """
        self.isCameraAttached = False
        base.camera.reparentTo(render)
        camera.setPos (0,0,300)
        camera.setHpr (0,-90,0)
        self.sideView = 0
    #end baseCamera

    ###################################################################
    # baseCamera 
    ###################################################################
    def sideCamera(self, args):
        """
        put the camera on the original position  
        
        """
        self.isCameraAttached = False
        base.camera.reparentTo(render)
        camera.setPos (300,0,10)
        camera.setHpr (90,0,0)
        self.sideView = 1
    #end baseCamera

    ###################################################################
    # showWholeScene
    ###################################################################
    def showWholeScene (self, args):
        """
        Change camera position to show the whole scene
        """
        positionOfCameraBeforeShowAll = camera.getPos ()
        positionOfCameraAfterShowAll = camera.getPos () # This will be changed later
        self.isCameraAttached = False
        base.camera.reparentTo(render)
        
        self.leftMostPoint = VBase3 (0, 0, 0)
        self.rightMostPoint = VBase3 (0, 0, 0)
        self.topMostPoint = VBase3 (0, 0, 0)
        self.bottomMostPoint = VBase3 (0, 0, 0)
        
        boolCounter = 0
        highestZ = 0

        actorDict = self.getActors()
        
        for actorObj in actorDict:
            if (actorObj in self.actorsInPlay):
                tmpPosX = self.actorsInPlay [actorObj].node.getX ()
                tmpPosY = self.actorsInPlay [actorObj].node.getY ()
                tmpPosZ = self.actorsInPlay [actorObj].node.getZ ()
                
                tmpHeight = self.getHeight (actorObj)

                # get points
                if boolCounter == 0:
                    boolCounter = 1
                    self.leftMostActor = self.actorsInPlay [actorObj].node
                    self.bottomMostActor = self.actorsInPlay [actorObj].node
                    self.topMostActor = self.actorsInPlay [actorObj].node
                    self.rightMostActor = self.actorsInPlay [actorObj].node

                    self.leftMostPoint = self.actorsInPlay [actorObj].node.getPos ()
                    self.bottomMostPoint = self.actorsInPlay [actorObj].node.getPos ()
                    self.topMostPoint = self.actorsInPlay [actorObj].node.getPos ()
                    self.rightMostPoint = self.actorsInPlay [actorObj].node.getPos ()
            
                    if highestZ < tmpHeight:
                        highestZ = tmpHeight
                    
                if tmpPosX <= self.leftMostPoint.getX ():
                    self.leftMostPoint = self.actorsInPlay [actorObj].node.getPos ()
                    self.leftMostActor = self.actorsInPlay [actorObj].node
                if tmpPosY <= self.bottomMostPoint.getY ():
                    self.bottomMostPoint = self.actorsInPlay [actorObj].node.getPos ()
                    self.bottomMostActor = self.actorsInPlay [actorObj].node
                if tmpPosY >= self.topMostPoint.getY ():
                    self.topMostPoint = self.actorsInPlay [actorObj].node.getPos ()
                    self.topMostActor = self.actorsInPlay [actorObj].node
                if tmpPosX >= self.rightMostPoint.getX ():
                    self.rightMostPoint = self.actorsInPlay [actorObj].node.getPos ()
                    self.rightMostActor = self.actorsInPlay [actorObj].node
            else:
                print "Actor " + actorObj + " not in database"
        
        boolCounter = 0
        if len (actorDict) > 0:
            midPoint = VBase3 (((self.leftMostPoint.getX () + self.rightMostPoint.getX ())/2), ((self.topMostPoint.getY () + self.bottomMostPoint.getY ())/2), 0)
            midPoint.setZ (0)
            tempPoint = Point3(0, 0, 0)
            camera.setPos (midPoint)
           
            while not ((base.camNode.isInView (base.cam.getRelativePoint(self.leftMostActor, tempPoint)) == 1) and (base.camNode.isInView (base.cam.getRelativePoint(self.bottomMostActor, tempPoint)) == 1) and (base.camNode.isInView (base.cam.getRelativePoint(self.topMostActor, tempPoint)) == 1) and (base.camNode.isInView (base.cam.getRelativePoint(self.rightMostActor, tempPoint)) == 1)):
                self.mouse2ZooomOut ()

            # move up more as the shown images will be at the very edges of the screen
            for i in range (0, 15):
                self.mouse2ZooomOut ()
            if (self.sideView == 1):
                camera.setZ (10);
            positionOfCameraAfterShowAll = camera.getPos ()
        
        # set camera position ot previous position
        camera.setPos (positionOfCameraBeforeShowAll)
        cameraLerp = LerpPosInterval(camera, 1.2, positionOfCameraAfterShowAll,
                    blendType = 'easeInOut',
                    bakeInStart = 1, fluid = 0, name = 'cameraLerp')
        cameraLerp.start ()

    #end showWholeScene

    ####################################################################
    # createButtonForCameraAttach
    # Method for creating a new button for camera attachment
    ####################################################################
    def createButtonForCameraAttach (self):
        self.isAClient = True
        self.callForCameraAttach = False
        self.clientCanAttach = True
        v = [0]
        self.baseCamera(v)
    # end createButtonForCameraAttach

    ####################################################################
    # attachNewCameraVariable
    # This method if for modifying the variable to attach the new camera
    ####################################################################
    def attachNewCameraVariable (self, act):
        #if self.clientCanAttach:
        self.callForCameraAttach = True
    # end attachNewCameraVariable

    ####################################################################
    # attachNewCamera
    ####################################################################
    def attachNewCamera (self, act):
        self.isCameraAttached = True
        self.callForCameraAttach = False
        base.camera.setPos(0,0,8)
        base.camera.setHpr(180,0,0)
        actorO = self.actorsInPlay[act].node
        base.camera.reparentTo(actorO)
    # end attachNewCamera

    ####################################################################
    # getDistance
    ####################################################################
    def getDistance (self, point1, point2):
       xDist = abs (point1.getX ()) - abs (point2.getX ())
       yDist = abs (point1.getY ()) - abs (point2.getY ())
       zDist = abs (point1.getZ ()) - abs (point2.getZ ())
       return sqrt (xDist*xDist + yDist*yDist + zDist*zDist)
    # end getWidth

    ####################################################################
    # getWidth
    ####################################################################
    def getWidth (self, actor):
       temp1, temp2 = self.actorsInPlay [actor].node.getTightBounds ()
       actorWidth = abs (temp2.getX ()) - abs (temp1.getX ())
       return actorWidth
    # end getWidth

    ####################################################################
    # getLength
    ####################################################################
    def getLength (self, actor):
       temp1, temp2 = self.actorsInPlay [actor].node.getTightBounds ()
       actorLength = abs (temp2.getY ()) - abs (temp1.getY ())
       return actorLength
    # end getLength

    ####################################################################
    # getHeight
    ####################################################################
    def getHeight (self, actor):
       temp1, temp2 = self.actorsInPlay [actor].node.getTightBounds ()
       actorHeight = abs (temp2.getZ ()) - abs (temp1.getZ ())
       return actorHeight
    # end getHeight
    
    ####################################################################
    # resetWorld
    ####################################################################
    def resetWorld(self):
        """
        resetWorld(self): clear the world out
        """
        self.actorsHeadNode.detachNode()
        del self.actorsHeadNode
        self.actorsHeadNode = self.headNodeOfWorld.attachNewNode('level')


        self.actorNumber = 0
        self.actorsInPlay = {}
        self.shadowsInPlay = {}
        self.groupsDefined = {}
        self.bulletsInPlay = {}
    #end resetWorld



    def loadShadow(self,actorToBeShadowed):
        global actorDataHolder
        actorNumber = 77
        fileName = 'EGG_shadow'
        
        shadowName = actorToBeShadowed + '_shadow'
        
        actorOrg = self.actorsInPlay[actorToBeShadowed]
        
        shadow = GameSketchingActor(shadowName, actorNumber, fileName)
        shadow.node = loader.loadModelCopy(fileName)
        
        shadow.node.reparentTo(self.actorsHeadNode)
        
        if (actorOrg.node.getZ() >= 0):
            shadow.node.setPos(actorOrg.node.getX(),actorOrg.node.getY(),0)
        else:
            shadow.node.setPos(0,0,-7)
        shadow.node.setScale(actorOrg.node.getScale())
        
                     
        self.shadowsInPlay[shadowName] = shadow
    
        
    def moveShadow(self,actorToBeShadowed):
        if (actorToBeShadowed in self.groupsDefined):
            for actor in self.groupsDefined[actorToBeShadowed]:
                shadow = self.shadowsInPlay[actor.name+'_shadow']
                group = self.actorsInPlay[actorToBeShadowed]   
                test = actor.node.getX()
                terst2 = actor.node.getX(self.actorsHeadNode)
                if (actor.node.getZ(self.actorsHeadNode) >= 0):
                    shadow.node.setPos(actor.node.getX(self.actorsHeadNode),actor.node.getY(self.actorsHeadNode),0)
                else:
                    shadow.node.setPos(0,0,-7)
        else:
            actor = self.actorsInPlay[actorToBeShadowed]
            shadow = self.shadowsInPlay[actorToBeShadowed+'_shadow']
            if (actor.node.getZ() >= 0):
                shadow.node.setPos(actor.node.getX(),actor.node.getY(),0)
            else:
                shadow.node.setPos(0,0,-7)
        
    def scaleShadow(self,actorname,scaleFactor):
        if (actorname in self.groupsDefined):
            for actor in self.groupsDefined[actorname]:
                shadow = self.shadowsInPlay[actor.name+'_shadow']      
                shadow.node.setScale(shadow.node.getScale() + gameSketchingGlobals.worldDefaultWorldRate * scaleFactor)
                shadow.node.setPos(actor.node.getX(self.actorsHeadNode),actor.node.getY(self.actorsHeadNode),0)
        else:
            shadowName = actorname+'_shadow'
            if (shadowName in self.shadowsInPlay):
                actorNode = self.shadowsInPlay[shadowName].node
                actorNode.setScale(actorNode.getScale() + gameSketchingGlobals.worldDefaultWorldRate * scaleFactor)
        
    def removeShadow(self,actorToBeShadowed):
        shadowName = actorToBeShadowed+'_shadow'
        if (shadowName in self.shadowsInPlay):
            if actorToBeShadowed in self.groupsDefined:             #remove the children if a group
                pass

            self.shadowsInPlay[shadowName].node.detachNode() #remove from scene graph
            del self.shadowsInPlay[shadowName].node
            del self.shadowsInPlay[shadowName]

    ####################################################################
    # loadActor
    ####################################################################

    def loadActor(self, actorNumber,  name = None, position = None, rotation = None,  scale = None, texture = None, trans = None):
        """
        loadActor(self, fileName, name=None, position = None, orientation = None):
               Load an actor according to the fileName handed in
 
        actorData:  [filename [animations]]


        If the following three parameters are omitted then an internal name is generated

        name:          The name to be assigned to the actor
        position:      The position of the actor
        orientation:   The orientation of the actor
        """
        global actorDataHolder
        actorData = actorDataHolder.datum[actorNumber]
        fileName = actorData[0]
        animations = actorData[1]
        textures = actorData[2]
        ################################
        #   Generate a name if needed
        ################################
        if name == None:
            name = self.__generateUniqueName()
        #end if

        #####################################
        #  This is a serious error.  do not allow this to happen
        #####################################
        if (name in self.actorsInPlay):
            printer.error(True, 'the name ', name, 'Is already an actor')

            raise SystemExit
        #end if

        ################################
        # Initialize the actor data
        ################################
        actor = GameSketchingActor(name, actorNumber, fileName,animations, textures)

        ################################
        #  load the file
        ################################Actor
        if len(animations) == 0:
            actor.node = loader.loadModelCopy(fileName)
        else:
            actor.node = Actor.Actor(fileName,animations)
        #end if
        if trans == None:
            trans = 1.0
            actor.node.setTransparency(0)
            
        else:
            trans = float(trans)
            actor.node.setTransparency(1)
            actor.node.setAlphaScale(trans)
        
        if self.isWallCreateActive:
            actor.node.setTransparency(1)
            trans = 0.5
            actor.node.setAlphaScale(trans)
            
        
        #actor.node.setAlphaScale(trans)

        # Set a flag for being highlighted.
        actor.node.setTag('glowStatus','False')

        ##############################
        # set the texture to the first one in the list
        ##############################
        if len( textures) > 0:
            self.textures = textures
            t = loader.loadTexture(actor.textures[0])
            actor.textureLoaded = 0
            actor.node.setTexture(t, 1)

        #endif

        ##############################
        # The hugamaflip which sits above the actor
        ##############################
        picknode = actor.node.attachNewNode('noname')
        pickball = loader.loadModelCopy(gameSketchingGlobals.indicatorBallFileName)
        pickball.reparentTo(actor.node)
        actor.pickerObject = pickball
        pickball.setPos(0,0,10)
        actor.pickerObject.setTextureOff(1)

        ################################
        # Collision Node path stuff
        ################################
        tmpCollisionNode = pickball.attachNewNode(CollisionNode(name))
        tmpCollisionNode.node().addSolid(CollisionSphere(0,0,0,1))

        #tmpCollisionNode.show()
        tmpCollisionNode.node().setFromCollideMask(BitMask32.allOff())
        tmpCollisionNode.node().setIntoCollideMask(BitMask32.bit(0))

        actor.collisionNode = tmpCollisionNode

        ################################
        # Use any of the parameter data passed in
        ################################
        if not rotation == None:
            actor.node.setHpr(rotation)
        #endif

        if not scale == None:
            actor.node.setScale(scale)
        #endif

        if not position == None:
            actor.node.setPos(position)
        #endif

        if not texture == None:
            actor.node.setTexture(loader.loadTexture(actor.textures[texture]))
            actor.textureLoaded = texture
        #end if

        ################################
        # Parent to the world so its rendered
        ################################
        actor.node.reparentTo(self.actorsHeadNode)

        ################################
        # Register the actor node in the active actors list
        ################################
        self.actorsInPlay[name] = actor
        
        self.loadShadow(name)
        
        #end if
        return name
    #end loadActor


    ####################################################################
    # markFloorPosition
    ####################################################################
    def markFloorPosition(self,pos):
        """
        pickActor: Return the name of the actor picked (if any)

        pos:  the x coordinates of the mouse click
        """
        x = pos[0]
        y = pos[1]

        ############################################
        # Set up the collision ray to find the closest object
        # Note that we only deal with the world stuff here.
        ############################################
        self.pickerRay.setFromLens(self.camera.node(), x, y)
        self.picker.traverse(self.floorNode)

        if (self.queue.getNumEntries() > 0):        # pick the first object
            self.queue.sortEntries()
            obj = self.queue.getEntry(0).getIntoNodePath()
            self.floorPosition = self.queue.getEntry(0).getSurfacePoint(obj)

        #end if
        return None
    #end markFloorPosition

    def getFloorPosition(self):
        """ return the positon on the floor that the mouse was last seen at """
        return self.floorPosition
    #end getFloorPosition


    ####################################################################
    # pickActor
    ####################################################################
    def pickActor(self,pos):
        """
        pickActor: Return the name of the actor picked (if any)

        pos:  the x coordinates of the mouse click
        """
        x = pos[0]
        y = pos[1]

        ############################################
        # Set up the collision ray to find the closest object
        #
        # Note:  The world hangs off two head nodes.  actorsHeadNode and worldHeadNode
        #             Because of this we know that if we hit a collision object here it has to belong
        #               to a legal actor.
        ############################################yes
        self.pickerRay.setFromLens(self.camera.node(), x, y)
        self.picker.traverse(self.actorsHeadNode)

        if (self.queue.getNumEntries() > 0):
            self.queue.sortEntries()
            obj = self.queue.getEntry(0).getIntoNodePath()
            return obj.getName()
        #end if
        return None
    #end pickActor


    ####################################################################
    # groupActors
    ####################################################################
    def groupActors(self, groupName,actors, rotation = None  ):
        """
        groupActors(self,groupName, actors): Group the actors in panda3d

        groupName:  the name to be assigned to the node

        actors:  a list of names of the actors to be grouped
        """


        #####################################
        # define the base node for the group
        #####################################

        self.groupsDefined[groupName] = []
        position = Point3(0,0,0)
        newGroup = GameSketchingActor(groupName,'GROUP',{})
        newGroup.node = self.actorsHeadNode.attachNewNode(groupName)


        ###################################
        # Load the indicator ball
        ###################################
        pickball = loader.loadModelCopy(gameSketchingGlobals.indicatorBallFileName)
        pickball.reparentTo(newGroup.node)
        pickball.setPos(0,0,12)
        newGroup.pickerObject = pickball

        ###################################
        # Load the arrow for direction of the group
        ############
        arrow = loader.loadModelCopy(gameSketchingGlobals.groupArrowFileName)
        arrow.setPos(0,0,-2)
        arrow.reparentTo(pickball)


        ######################################
        # Set up the collision sphere above the group for selection
        ######################################
        tmpCollisionNode = pickball.attachNewNode(CollisionNode(groupName))
        tmpCollisionNode.node().addSolid(CollisionSphere(0,0,0,1))


        #tmpCollisionNode.show()
        tmpCollisionNode.node().setFromCollideMask(BitMask32.allOff())
        tmpCollisionNode.node().setIntoCollideMask(BitMask32.bit(0))

        newGroup.collisionNode = tmpCollisionNode
        ##################################
        # Find the center of gravity for the group
        # Turn off the collision volumes for the group members
        # Remove from the actor list since its going to be in a group
        ##################################
        for slave in actors:
            self.groupsDefined[groupName].append(self.actorsInPlay[slave])
            self.actorsInPlay[slave].collisionNode.node().setIntoCollideMask(BitMask32.allOff())
            self.actorsInPlay[slave].pickerObject.detachNode()
            position += self.actorsInPlay[slave].node.getPos()
            self.actorsInPlay.pop(slave)

        position /= len(actors)
        newGroup.node.setPos(position)
        
        ######################################
        # Now make sure the orientation of the objects is correct with
        # respect to the rotated group
        ######################################
        if rotation != None:
            newGroup.node.setHpr(rotation)
        #endif

        ##################################
        # Now have the actors be part of this group,
        ##################################
        for tmpActor in self.groupsDefined[groupName]:
            tmpActor.node.wrtReparentTo(newGroup.node)
            tmpActor.pickerObject.setColor(VBase4(.5,.5,.5,.5))
        #end for
       

        self.actorsInPlay[groupName] = newGroup


    #end groupActors


    ####################################################################
    # ungroupActors
    ####################################################################
    def ungroupActors(self, groupName):
        """
        groupActors(self,groupName, actors): Group the actors in panda3d

        groupName:  the name to be assigned to the node


        """
        if not (groupName in self.groupsDefined):
            printer.error("you tried to remove a group which is not defined "+groupName)
            raise SystemExit
        #end if
        for tmpActor in self.groupsDefined[groupName]:
            self.actorsInPlay[tmpActor.name] = tmpActor
            tmpActor.collisionNode.node().setIntoCollideMask(BitMask32.bit(0))
            transform = tmpActor.node.getNetTransform()
            tmpActor.pickerObject.reparentTo(tmpActor.node)

            tmpActor.node.reparentTo(self.actorsHeadNode)
            tmpActor.node.setTransform(transform)
        #end for

        self.actorsInPlay[groupName].node.detachNode()
        self.groupsDefined.pop(groupName)
        self.actorsInPlay.pop(groupName)


    #end ungroupActors



    ####################################################################
    # setActorNumber
    ####################################################################
    def setActorNumber(self, number):
        """
        setActorNumber(self,number): Set the internal number for the next actor

        number:  The value to set the internal number to
        """
        self.actorNumber = number
    #end setActorNumber


    ##################################################################
    # nextTexture
    ##################################################################
    def nextTexture(self, actorName,  number = None):
        """
        nextTexture(self,number): Set the internal texture number for the next number or the one passed in

        number:  The value to set the internal number to
        """
        if actorName in self.actorsInPlay:
            if len (self.actorsInPlay[actorName].textures) > 0:
                #################
                # no parameter just pass to next
                #################
                actor = self.actorsInPlay[actorName]
                if number == None:
                    nextTexture = (actor.textureLoaded +1)% len(actor.textures)
                elif (number >=0 ) and (number < len(actor.textures)):
                    nextTexture = number
                else:
                    printer.error('The texture ', +str(number)+' is badly defined')
                    raise SystemExit
                # end if
                texture = loader.loadTexture(actor.textures[nextTexture])
                actor.textureLoaded = nextTexture
                actor.node.setTexture(texture,1)

            # end if

        else:
            printer.error('The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        # end if
    # end nextTexture



    ####################################################################
    # getCtrlPressed
    ####################################################################
    def getCtrlPressed(self):
        """
        getCtrlPressed.  get the status fo ctrlpressed variable
        """
        return self.ctrlPressed
    #end ctrlPressed




    ####################################################################
    # getActorName
    ####################################################################
    def getActorNumber(self):
        """
        getActorNumber(self): Returns the next actor number
        """
        return self.actorNumber
    #end getActorNumber
    
    ####################################################################
    # getCallForCameraAttach
    ####################################################################
    def getCallForCameraAttach(self):
        """
        return the value of the calling for camera attachment
        """
        #self.callForCameraAttach = True 
        return self.callForCameraAttach
    #end getActorNumber
    
    ####################################################################
    # getCallForSelectAll
    ####################################################################
    def getCallForSelectAll(self):
        """
        return the value of the select all global variable
        """
        #self.callForCameraAttach = True 
        return self.callForSelectAll
    #end getCallForSelectAll
    
    ####################################################################
    # getCallForDeselectAll
    ####################################################################
    def getCallForDeselectAll(self):
        """
        return the value of the select all global variable
        """
        #self.callForCameraAttach = True 
        return self.callForDeselectAll
    #end getCallForDeselectAll
    
    ####################################################################
    # getCallForCameraAttach
    ####################################################################
    def getIsCameraAttached(self):
        """
        return the value of the flag for camera attachment
        """
        #self.callForCameraAttach = True 
        return self.isCameraAttached
    #end getIsCameraAttached
    
    ####################################################################
    # setCallForCameraAttach
    ####################################################################
    def setIsCameraAttached(self, val):
        """
        Changes the value of the camera attach status
        """ 
        self.isCameraAttached = val
    #end setIsCameraAttached
    
    ####################################################################
    # setCallForSelectAll
    ####################################################################
    def setCallForSelectAll(self, val):
        """
        Changes the value of the select all variable
        """ 
        self.callForSelectAll = val
    #end setCallForSelectAll
    
    ####################################################################
    # setCallFordeSelectAll
    ####################################################################
    def setCallForDeselectAll(self, val):
        """
        Changes the value of the de-select all variable
        """ 
        self.callForDeselectAll = val
    #end setCallFordeSelectAll
    

    ####################################################################
    # generateUniqueName
    ####################################################################
    def __generateUniqueName(self):
        """
        __generateUniqueName(self): Generate a name using the next actor number

        Internal routine
        """
        name = "a"+str(self.actorNumber)
        self.actorNumber += 1
        return name
    #end __generateUniqueName
    
    ####################################################################
    # get next name to be generated from the __generateUniqueName 
    # function. to be used in undo redo rutines.
    ####################################################################
    def getNextNameToBeGenerated(self):
        name = "a"+str(self.actorNumber)
        return name




    ####################################################################
    # removeActor
    ####################################################################
    def removeActor(self, actorName):
        """
        removeActor(self, actorName):Remove the actor from the actor database.

        actorName:  The name of the actor to be removed

        """

        if (actorName in self.actorsInPlay):
            if actorName in self.groupsDefined:             #remove the children if a group
                for slave in self.groupsDefined[actorName]:
                    slave.node.detachNode()
                    self.removeShadow(slave.name)
                    del slave.node
                #end for
                self.groupsDefined.pop(actorName)

            self.actorsInPlay[actorName].node.detachNode() #remove from scene graph
            del self.actorsInPlay[actorName].node
            del self.actorsInPlay[actorName]
            self.removeShadow(actorName)
        else:
            printer.error('The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif (actorName in self.actorsInPlay)

    #end removeActor


    def MoveRotateScaleActor(self,actorName,pos,hpr,scale):
        if (actorName in self.actorsInPlay):
            self.actorsInPlay[actorName].node.setPos(pos)
            self.actorsInPlay[actorName].node.setHpr(hpr)
            self.actorsInPlay[actorName].node.setScale(scale)
            self.moveShadow(actorName)
            
            

    ####################################################################
    # positionActor
    ####################################################################
    def positionActor(self, actorName, pos_x, y = None, z = None):
        """
        positionActor(self, actorName, pos_x,y,z):
                        Set the position of the actor to pos which is a Point3 data type
                        or three values.

        pos_x:  If this is a type Point3 then it contains the whole data
        y:
        z:
        If the actor is not in the database then raise a system exit
        """

        if (actorName in self.actorsInPlay):
            if z == None and isinstance(x,Point3):
                self.actorsInPlay[actorName].node.setPos(pos_x)
            else:
                self.actorsInPlay[actorName].node.setPos(x,y,z)
            #end if
        else:
            printer.error('The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif (actorName in self.actorsInPlay)
    #end positionActor

    ####################################################################
    # setControllerColorOnActor
    ####################################################################
    def setControllerStatusOnActor(self, actorName, status):
        """
        setControllerColorOnActor(self,actorName, color):

        set the status of the controller thingy above the actors.

        status: [red,green, blue, alpha] for the colour
        """
        if (actorName in self.actorsInPlay):
           self.actorsInPlay[actorName].pickerObject.setColor(status)
        else:
            printer.error('The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif
    #end setControllerColorOnActor

    ####################################################################
    # orientActor
    ####################################################################
    def orientActor(self, actorName, h,p,r):
        """
        Set the orientation of the actor setHPR()

        h: heading
        p: pitch
        r: rotation

        If the actor is not in the database raise a SystemExit
        """

        if (actorName in self.actorsInPlay):
            self.actorsInPlay[actorName].node.setHpr(h,p,r)
        else:
            printer.errror( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif (actorName in self.actorsInPlay)
    #end orientActor


    ####################################################################
    # scaleActor
    ####################################################################
    def scaleActor(self, actorName, scaleFactor):
        """
        increase or decrease the scale of the actor

        scale:  the scale of the actor

        If the actor is not in the database raise a SystemExit
        """

        if (actorName in self.actorsInPlay):
            actorNode = self.actorsInPlay[actorName].node
            actorNode.setScale(actorNode.getScale() + gameSketchingGlobals.worldDefaultWorldRate * scaleFactor)
            self.scaleShadow(actorName, scaleFactor)
        else:
            printer.errror( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif (actorName in self.actorsInPlay)
    #end scaleActor



    ####################################################################
    # __moveActor
    ####################################################################
    def __moveActor(self, actorName, x_dir, y = None, z = None):
        """
        internal Move the actor in her own coordinate frame.

        used by forwardActor, sidewaysActor, riseActor

        x_dir:  Either the x coordinate of the vector or the Point3 type
        y:  either the y coordinate or None
        z:  either the z coordinate or None


        If the actor is not in the database raise a SystemExit
        """

        if (y == None) and (z == None) and isinstance(x_dir, Point3):
            myX = x_dir[0]
            myY = x_dir[1]
            myZ = x_dir[2]
        else:
            myX = x_dir
            myY = y
            myZ = z
        #endif

        if (actorName in self.actorsInPlay):
            actor = self.actorsInPlay[actorName]

            backward = actor.node.getNetTransform().getMat().getRow3(1)
            backward.normalize()

            left = actor.node.getNetTransform().getMat().getRow3(0)
            left.normalize()

            up = left.cross(backward)

            actor.node.setPos(actor.node.getPos() + left*myX - backward*myY + up*myZ)
            self.moveShadow(actorName)
        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif (actorName in self.actorsInPlay)
    #enddef moveActor

    ####################################################################
    # forwardActor
    ####################################################################
    def forwardActor(self, actorName, speed= 1.0):
        """
        Move the actor it her own coordinate frame.

        speed: (default = 1.0)  multiplier on the forwardSpeed vector


        If the actor is not in the database raise a SystemExit
        """
        if (actorName in self.actorsInPlay):
            direction = self.actorsInPlay[actorName].forwardSpeed * speed
            self.__playMoveAnimationActor(actorName)
            self.__moveActor(actorName, direction)
        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            fred = sam
            raise SystemExit
        #endif
    #end forwardActor

    ####################################################################
    # forwardActor
    ####################################################################
    def relativeMoveActor(self, actorName, delta):
        """
        Move the actor using the x and y coordinate of delta.

        speed: (default = 1.0)  multiplier on the forwardSpeed vector


        If the actor is not in the database raise a SystemExit
        """

        if (actorName in self.actorsInPlay):
            actor = self.actorsInPlay[actorName]
            actor.node.setPos(actor.node.getPos() + delta)
            self.moveShadow(actorName)
        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            fred = sam
            raise SystemExit
        #endif
    #end forwardActor


    ####################################################################
    # __playMoveAnimationActor
    ####################################################################
    def __playMoveAnimationActor(self, actorName):
        """
        __playMoveAnimationActor(self,actorName, animation)
        .

        internal routine to play the move animation on the actor when moving the actor


        If the actor is not in the database raise a SystemExit
        """


        if (actorName in self.actorsInPlay):
            if ('move' in self.actorsInPlay[actorName].animations):
                startFrame = self.actorsInPlay[actorName].moveAnimationFrame

                if (startFrame + gameSketchingGlobals.moveAnimationSpeed) > self.actorsInPlay[actorName].node.getNumFrames('move') :
                    endFrame = self.actorsInPlay[actorName].node.getNumFrames('move')
                    nextFrame = 0
                else:
                    endFrame = startFrame+gameSketchingGlobals.moveAnimationSpeed
                    nextFrame = endFrame

                #end if


                self.actorsInPlay[actorName].node.play('move', fromFrame = startFrame, toFrame = endFrame)
                self.actorsInPlay[actorName].moveAnimationFrame = nextFrame
            #end if
        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif
    #end __playMoveAnimationActor

    ####################################################################
    # animateActor
    ####################################################################
    def animateActor(self, actorName, data):
        """
        animateActor(self,actorName, animation)
        .

        animation: the name of the animation to play


        If the actor is not in the database raise a SystemExit
        """
        animation = data[0]
        playmode = data[1]


        if (actorName in self.actorsInPlay):

            if (animation in self.actorsInPlay[actorName].animations):
                if playmode == 'loop':
                    self.actorsInPlay[actorName].node.loop(animation)
                else:
                    self.actorsInPlay[actorName].node.play(animation)
                #end if
            #end if
        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif
    #end animateActor

    ####################################################################
    # stopActor
    ####################################################################
    def stopActor(self, actorName, HACKholder):
        """
        stopActor(self,actorName, animation)
        .

        HACKholder, need to fix the constructor to allow for no parameters


        If the actor is not in the database raise a SystemExit
        """
        if (actorName in self.actorsInPlay):
            self.actorsInPlay[actorName].node.stop()
        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif
    #end stopActor

    ####################################################################
    # sidewaysActor
    ####################################################################
    def sidewaysActor(self, actorName, speed= 1.0):
        """
        sideways the actor it her own coordinate frame.

        speed: (default = 1.0)  multiplier on the sidewaysSpeed vector


        If the actor is not in the database raise a SystemExit
        """

        if (actorName in self.actorsInPlay):
            direction = self.actorsInPlay[actorName].sidewaysSpeed * speed
            self.__moveActor(actorName, direction)
        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif
    #end sidewaysActor

    ####################################################################
    # riseActor
    ####################################################################
    def riseActor(self, actorName, speed= 1.0):
        """
        rise the actor it her own coordinate frame.

        speed: (default = 1.0)  multiplier on the riseSpeed vector


        If the actor is not in the database raise a SystemExit
        """

        if (actorName in self.actorsInPlay):
            direction = self.actorsInPlay[actorName].riseSpeed * speed
            self.__moveActor(actorName, direction)
        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif
    #end forwardActor


    ####################################################################
    # lookUpActor
    ####################################################################
    def lookUpActor(self,actorName, speed = 1.0):
        """
        Get the information for the actor.
        return a tuple which can be used by setActorData
        """

        if (actorName in self.actorsInPlay):
            actor = self.actorsInPlay[actorName]
            hpr = actor.node.getHpr()
            hpr += VBase3(0, actor.lookUpSpeed*speed, 0)

            actor.node.setHpr(hpr)
            self.moveShadow(actorName)
        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif
    #end lookUpActor

    ####################################################################
    # lookleftActor
    ####################################################################
    def lookLeftActor(self,actorName, speed = 1.0):
        """
        Get the information for the actor.
        return a tuple which can be used by setActorData
        """
        if (actorName in self.actorsInPlay):
            actor = self.actorsInPlay[actorName]
            hpr = actor.node.getHpr()
            hpr += VBase3(actor.lookLeftSpeed*speed, 0, 0)

            actor.node.setHpr(hpr)
            self.moveShadow(actorName)
        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif
    #end lookLeftActor
    
    ####################################################################
    # placeWall
    ####################################################################
    def placeWall(self,actorN, posX, posY, hpr):
        """
        Validate if the actor exist
        """

        if (actorName in self.actorsInPlay):
            actor = self.actorsInPlay[actorName]
            hprNew = int(hprNew)*1.0
            hpr = actor.node.getH()
            actor.node.setH(hprNew)
            #self.moveShadow(actorName)
        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif
    #end placeWall

    ####################################################################
    # tiltLeftActor
    ####################################################################
    def tiltLeftActor(self,actorName, speed = 1.0):
        """
        Tilt the Actor (modify the roll)
        """
        if (actorName in self.actorsInPlay):
            actor = self.actorsInPlay[actorName]
            hpr = actor.node.getHpr()
            hpr += VBase3(0, 0, actor.tiltLeftSpeed*speed)

            actor.node.setHpr(hpr)
            self.moveShadow(actorName)
        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif

    #end tiltLeftActor

    ####################################################################
    #clearActorRotation
    ####################################################################
    def clearActorRotation(self,actorName, HACKholder= 1.0):
        """
        Tilt the Actor (modify the roll)
        """
        if (actorName in self.actorsInPlay):
            actor = self.actorsInPlay[actorName]
            hpr = actor.node.setHpr(0,0,0)
            self.moveShadow(actorName)

        else:
            printer.error( 'The name ', actorName, 'Was not in the actor database')
            raise SystemExit
        #endif

    #end clearActorRotation


    ####################################################################
    # __moveCamera
    ####################################################################
    def __moveCamera(self, x_dir, y = None, z = None):
        """
        internal Move the camera in its own coordinate frame.

        used by forwardCamera, leftCamera, upCamera

        x_dir:  Either the x coordinate of the vector or the Point3 type
        y:  either the y coordinate or None
        z:  either the z coordinate or None

        """

        if (y == None) and (z == None) and isinstance(x_dir, Point3):
            myX = x_dir[0]
            myY = x_dir[1]
            myZ = x_dir[2]
        else:
            myX = x_dir
            myY = y
            myZ = z
        #endif


        backward = camera.getNetTransform().getMat().getRow3(1)
        backward.normalize()

        left = camera.getNetTransform().getMat().getRow3(0)
        left.normalize()

        up = left.cross(backward)

        camera.setPos(camera.getPos() + left*myX - backward*myY + up*myZ)


    #end __moveCamera


    ####################################################################
    # upCamera
    ####################################################################
    def upCamera(self, speed = 1.0):
        """
        Move the camera up in its own frame
        """

        self.__moveCamera(self.cameraUpSpeed*speed)
    #end upCamera

    ####################################################################
    # Camera
    ####################################################################
    def forwardCamera(self, speed = 1.0):
        """
        Move the camera up in its own frame
        """

        self.__moveCamera(self.cameraForwardSpeed*speed)
    #end forwardCamera

    ####################################################################
    # upCamera
    ####################################################################
    def leftCamera(self, speed = 1.0):
        """
        Move the camera up in its own frame
        """

        self.__moveCamera(self.cameraLeftSpeed*speed)
    #end leftCamera

    ####################################################################
    # lookUpCamera
    ####################################################################
    def lookUpCamera(self, speed = 1.0):
        """
        Make the camera look up without moving it.
        """

        hpr = camera.getHpr()
        hpr += VBase3(0, self.cameraLookUpSpeed*speed, 0)
        camera.setHpr(hpr)


        #endif
    #end lookUpCamera

    ####################################################################
    # Rotating the camera with button 1 of the mouse
    ####################################################################
    def mouse1Camera(self, val):
        """
        Make the camera move its HPR then the mouse 1 button is clicked.
        """

        hpr = camera.getHpr()
        hpr += val #VBase3(0, val, 0)
        camera.setHpr(hpr)


        #endif
    #end mouse1Camera

    ####################################################################
    # Rotating the camera with button 2 of the mouse
    ####################################################################
    def mouse2Camera(self, val):
        """
        Make the camera move to the position of her forward or back node
        """
        base.camera.setPos(val)
    #end mouse2Camera

    ####################################################################
    # lookLeftCamera
    ####################################################################
    def lookLeftCamera(self, speed = 1.0):
        """
        Make the camera look left without moving it.
        """

        hpr = camera.getHpr()
        hpr += VBase3( self.cameraLookLeftSpeed*speed, 0, 0)

        camera.setHpr(hpr)


        #endif
    #end lookLeftCamera

    ####################################################################
    # tiltLeftCamera
    ####################################################################
    def tiltLeftCamera(self, speed = 1.0):
        """
        Make the camera tilt left without moving it.
        """

        hpr = camera.getHpr()
        #hpr += VBase3(  0, 0, self.cameraTiltLeftSpeed*speed)

        camera.setHpr(hpr)


        #endif
    #end tiltLeftCamera

    ###################################################################
    # setCamera
    ###################################################################
    def setCamera(self,position, rotation):
        """ setCamera(self,position, rotation): set the value for the camera """
        camera.setPos(position)
        camera.setHpr(rotation)
    #end setCamera

    ###################################################################
    #getFrontCamera
    #Gets the data from the empty node that defines the Front movement for the camera
    ###################################################################
    def getFrontCamera(self):
        return self.frontCamera
    #end getFrontCamera

    ###################################################################
    #getMoveCamera
    #Gets the data from the empty node that defines the back movement for the camera
    ###################################################################
    def getBackCamera(self):
        return self.backCamera
    #end getBackCamera


    ####################################################################
    # getActorData
    ####################################################################
    def getActorData(self,actor):
        """
        Get the information for the actor.
        return a tuple which can be used by setActorData
        """

        data = []
        transform = actor.node.getNetTransform()
        data += [transform.getPos()]
        data += [transform.getHpr()]
        data += [transform.getScale()]
        data += [actor.textureLoaded]

        return data
    #end def

    ####################################################################
    # getActors
    ####################################################################
    def getActors(self):
        """
        Return a dictionary of the actors with the associated file names
        """
        actorsReturn = {}
        for name in self.actorsInPlay:
            if name in self.groupsDefined:
                ##########################
                # Get the actors in the group
                ##########################
                for slave in self.groupsDefined[name]:
                    actor = slave
                    actorData = self.getActorData(slave)
                    actorsReturn[slave.name] = [actor.number, actor.fileName,actor.animations, actor.textures, actorData]
                #end for
            else:
                ###########################
                # Just a single actor
                ###########################
                actor = self.actorsInPlay[name]
                actorData = self.getActorData(actor)
                actorsReturn [name] = [actor.number, actor.fileName,actor.animations, actor.textures,actorData]
            #end if
        return (actorsReturn)
        #endfor actor in self.actors
    #end getActors
    ###################################################################
    # getGroupRotation
    ###################################################################
    def getGroupRotation(self,group):
        """
        getGroupRotation(self,group):

        group:  return the Hpr of the group
        """
        if not (group in self.groupsDefined):
            printer.error("a group rotation was requested from a group that does not exist ", group)
            raise SystemExit
        #end if
        return self.actorsInPlay[group].node.getHpr()
    #end getGroupRotation

    ###################################################################
    # highlightActor
    ###################################################################
    def toggleHighlightActor(self,objectId):
        """
        Toggle an actor highlight on/off
        
        @param obnjectId: the id of the actor/group that we want to highlight
        """
        # Check if Shaders are supported
        if self.glowFilter.areShadersSupported():
            # Check if the object is a group or an individual actor  
            if (objectId in self.groupsDefined):
                # Proceed to toggle glow effect for each actor. 
                for actor in self.groupsDefined[objectId]:
                    self.glowFilter.toggleGlow(actor.node)
            # An individual actor
            else:
                # Proceed to toggle glow effect for the actor.
                self.glowFilter.toggleGlow(self.actorsInPlay[objectId].node)
    #end highlightActor

    ###################################################################
    # unhighlightActor
    ###################################################################
    def unhighlightHighlightedActors(self):
        """
        Unhighlight all actors.
        """
        highlightedActors = self.headNodeOfWorld.findAllMatches("**/=glowStatus=True")
        for i in range(0,highlightedActors.getNumPaths()):
            self.glowFilter.toggleGlow(highlightedActors[i])
    # End unhighlightActor


    ###################################################################
    # control click 
    ###################################################################
    def ctrlClick(self):
        """
        Move the variable ctrlPressed from on or of depending if the key is pressed  
        
        """
        if self.ctrlPressed == False:
            self.ctrlPressed = True
    #end ctrlclick
    
    ###################################################################
    # control un click 
    ###################################################################
    def ctrlClickUp(self):
        """
        Move the variable ctrlPressed from on or of depending if the key is pressed  
        
        """
        if self.ctrlPressed == True:
            self.ctrlPressed = False
    #end ctrlclick


    ###################################################################
    # ALT click 
    ###################################################################
    def altClick(self):
        """
        Move the variable altPressed from on or of depending if the key is pressed  
        
        """
        if base.mouseWatcherNode.hasMouse():
            x=base.mouseWatcherNode.getMouseX()
            y=base.mouseWatcherNode.getMouseY()
        else:
            x = 10
            y = 10    
        self.cameraButtons.setPos(x,0,y)
        if self.altPressed == False:
            self.altPressed = True
    #end altclick
    
    ###################################################################
    # ALTun click 
    ###################################################################
    def altClickUp(self):
        """
        Move the variable altPressed from on or of depending if the key is pressed  
        
        """
        self.cameraButtons.setPos(10,10,0)
        if self.altPressed == True:
            self.altPressed = False
    #end altclick


    ###################################################################
    # Mouse 1 click 
    ###################################################################
    def mouse1ClickServer(self):
        """
        Click on the server to attach a camera  
        """
        if self.isAClient == False:
            #if base.mouseWatcherNode.hasMouse():
            x=base.mouseWatcherNode.getMouseX()
            y=base.mouseWatcherNode.getMouseY()
            pos = [0,0]
            pos[0] = x
            pos[1] = y
            actor = self.pickActor(pos)
            if not actor == None: 
                if self.callForCameraAttach:
                    self.callForCameraAttach = False
                    self.attachNewCamera(actor)
                    self.actorForCameraAttach = actor
    #end mouse1ClickServer

    ###################################################################
    # Mouse s click 
    ###################################################################
    def mouse2CameraClick(self):
        """
        Move variables of mouse1 click to on to move the camera as needed  
        
        """
        if base.mouseWatcherNode.hasMouse():
            x=base.mouseWatcherNode.getMouseX()
            y=base.mouseWatcherNode.getMouseY()
        else:
            x = 0
            y = 0    
        self.mouseInicialPosition = [x,y]
        if self.mouse2Pressed == False:
            self.mouse2Pressed = True
    #end mouse1CameraClick
    
    ###################################################################
    # Mouse 1 click 
    ###################################################################
    def mouse2CameraClickUp(self):
        """
        Release the variables for the mouse 1  
        
        """
        self.mouseInicialPosition = (0,0)
        if self.mouse2Pressed == True:
            self.mouse2Pressed = False
    #end mouse1CameraClickUp

    ###################################################################
    # mouse2ZooomIn 
    ###################################################################
    def mouse2ZooomIn(self):
        """
        Zoom into the world when the mouse wheel is moved  
        
        """
        if self.isCameraAttached == False:
            newPosition = self.getFrontCamera().getPos(render)
            self.mouse2Camera(newPosition)
    #end mouse2ZooomIn
    
    ###################################################################
    # mouse2ZooomOut 
    ###################################################################
    def mouse2ZooomOut(self):
        """
        Zoom out the world when the mouse wheel is moved
        
        """
        if self.isCameraAttached == False:
            newPosition = self.getBackCamera().getPos(render)
            self.mouse2Camera(newPosition)
    #end mouse1CameraClickUp

    ###################################################################
    # getActorForCameraAttach
    ###################################################################
    def getActorForCameraAttach(self):
        """
        Return value of the actur currently with the camera  
        
        """
        return self.actorForCameraAttach
    #end getActorForCameraAttach

    ###################################################################
    # setActorForCameraAttach
    ###################################################################
    def setActorForCameraAttach(self, v):
        """
        Set the value where the camera is attached  
        
        """
        self.actorForCameraAttach = v
    #end getActorForCameraAttach

    ###################################################################
    # get Alt Pressed 
    ###################################################################
    def getAltPressed(self):
        """
        Return the Alt Pressed variable  
        
        """
        return self.altPressed
    #end getAltPressed
    
    ###################################################################
    # setCameraButtons 
    ###################################################################
    def setCameraButtons(self, x, y):
        """
        Change the value of the position of the buttons for the camera  
        
        """
        self.cameraButtons.setPos(x,y, 0)
    #end setCameraButtons


    def mouseCameraTracking(self, task):
        if self.mouse2Pressed:
            deltaX = Vec3(0,0,0)
            deltaY = Vec3(0,0,0)
            
            x=base.mouseWatcherNode.getMouseX()
            y=base.mouseWatcherNode.getMouseY()
            #self.mouseInicialPosition = [x,y]
            #Modify the HPR of the main camera
            if x < self.mouseInicialPosition[0] - 0.2:
                deltaX += Vec3(0.5,0,0)
            elif x > self.mouseInicialPosition[0] + 0.2:
                deltaX += Vec3(-0.5,0,0)

            if y < self.mouseInicialPosition[1] - 0.2:
                deltaY += Vec3(0,-0.5,0)
            elif y > self.mouseInicialPosition[1] + 0.2:
                deltaY += Vec3(0,0.5,0)
                
            delta = deltaX + deltaY    
            self.mouse1Camera(delta)
        return Task.cont
    #end handleWxEvents
#############################################################################
#end GameSketchingWorld
#############################################################################
