class Logger: """ Prints messages to the consol and/or file and or gui element """ def __init__(self, gui=None, out_file=None): self.notify = DirectNotify().newCategory('a4p') self.gui = gui self.out_file = None if out_file: self.out_file = open(path + out_file, 'a') self.out_file.write('---<Opening file on: ' + str(datetime.now()) + ' >---\n') self.debug('Logger is now logging') self.debug('Logger gui is ' + str(gui)) self.debug('Logger out_file is ' + str(out_file)) def error(self, msg): if self.gui: self.gui.showMsg('Error: ' + msg) if self.out_file: self.out_file.write('Error:' + msg + '\n') self.notify.warning('Error: ' + msg) def warning(self, msg): self.notify.warning(msg) if self.gui: self.gui.showMsg('Warning: ' + msg) if self.out_file: self.out_file.write('Warning: ' + msg + '\n') def info(self, msg): self.notify.info(msg) if self.gui: self.gui.showMsg(msg) if self.out_file: self.out_file.write(msg) def debug(self, msg): self.notify.debug(msg) if self.gui: self.gui.showMsg('Debug: ' + msg) if self.out_file: self.out_file.write('Debug: ' + msg + '\n') def exception(self, msg): if self.gui: self.gui.showMsg('Exception: ' + msg) if self.out_file: self.out_file.write('Exception: ' + msg + '\n') self.notify.error(msg) def closeLogFile(self): if self.out_file: self.out_file.write('---<Closing file on: ' + str(datetime.now()) + ' >---\n') self.out_file.close() self.out_file = None
class Logging(object): def __init__(self): #create a new notify category self._notify = DirectNotify().newCategory("CamMovement") self._notify.info("Put some informational text here.") self._notify.debug("Put some informational text here.") self._notify.warning("Put some informational text here.") self._notify.error( "Put some informational text here.") #raise an exeption
class Logger: """ Prints messages to the consol and/or file and or gui element """ def __init__(self, gui=None, out_file=None): self.notify = DirectNotify().newCategory('a4p') self.gui=gui self.out_file=None if out_file: self.out_file=open(path+out_file,'a') self.out_file.write('---<Opening file on: '+str(datetime.now())+' >---\n') self.debug('Logger is now logging') self.debug('Logger gui is '+str(gui)) self.debug('Logger out_file is '+str(out_file)) def error(self, msg): if self.gui: self.gui.showMsg('Error: '+msg) if self.out_file: self.out_file.write('Error:'+msg+'\n') self.notify.warning('Error: '+msg) def warning(self, msg): self.notify.warning(msg) if self.gui: self.gui.showMsg('Warning: '+msg) if self.out_file: self.out_file.write('Warning: '+msg+'\n') def info(self, msg): self.notify.info(msg) if self.gui: self.gui.showMsg(msg) if self.out_file: self.out_file.write(msg) def debug(self, msg): self.notify.debug(msg) if self.gui: self.gui.showMsg('Debug: '+msg) if self.out_file: self.out_file.write('Debug: '+msg+'\n') def exception(self, msg): if self.gui: self.gui.showMsg('Exception: '+msg) if self.out_file: self.out_file.write('Exception: '+msg+'\n') self.notify.error(msg) def closeLogFile(self): if self.out_file: self.out_file.write('---<Closing file on: '+str(datetime.now())+' >---\n') self.out_file.close() self.out_file=None
def land(self): if (self.__z == 0): notify = DirectNotify().newCategory("") notify.warning("The drone has already landed") exit() self.__commandCheck() seq = self.droneActor.posInterval(self.__z / 5, Point3(self.__x, self.__y, 0)) self.__z = 0 self.__overallSequence.append(seq)
def takeoff(self): if (self.__z != 0): notify = DirectNotify().newCategory("") notify.warning("The drone has already taken off") exit() self.__commandCheck() seq = self.droneActor.posInterval( 2, Point3(self.__x, self.__y, self.__z + 10)) self.__z = self.__z + 10 self.__overallSequence.append(seq)
def disconnect(self): if (self.__connection != None): __tello = None __commanding = False __connection = None notify = DirectNotify().newCategory("") notify.warning("Disonnected!") else: notify = DirectNotify().newCategory("") notify.warning("You are not connected to a drone yet") exit()
class Logger: def __init__(self): self.notify = DirectNotify().newCategory("core") def error(self, msg): self.notify.warning(msg) def warning(self, msg): self.notify.warning(msg) def info(self, msg): self.notify.info(msg) def debug(self, msg): self.notify.debug(msg) def exception(self, msg): self.notify.error(msg)
def cw(self, amount): self.__commandCheck() if (amount > 3600 or amount < 1): #print("Error Line ",self.__get_linenumber,": Please enter amount between 1 and 3600 ") notify = DirectNotify().newCategory("MyCategory") notify.warning( "Error: For 'cw' please enter amount between 1 and 3600 ") exit() seq = self.droneActor.hprInterval(amount / 45, Vec3(amount, 0, 0)) self.__heading = self.__heading + amount while (self.__heading > 360): self.__heading = self.__heading - 360 self.__overallSequence.append(seq)
def up(self, distance): self.__commandCheck() if (distance > 500 or distance < 20): #print("Error Line ",self.__get_linenumber,": Please enter amount between 1 and 3600 ") notify = DirectNotify().newCategory("") notify.warning( "Error: For 'up' please enter amount between 20 and 500 ") exit() distance = distance / 10 newz = self.__z + distance seq = self.droneActor.posInterval(distance / 5, Point3(self.__x, self.__y, newz)) self.__z = newz self.__overallSequence.append(seq)
def forward(self, distance): self.__commandCheck() if (distance > 500 or distance < 20): #print("Error Line ",self.__get_linenumber,": Please enter amount between 1 and 3600 ") notify = DirectNotify().newCategory("") notify.warning( "Error: For 'forwards' please enter amount between 20 and 500 " ) exit() distance = distance / 10 newx = (distance * math.cos(self.__heading)) + self.__x newy = (distance * math.sin(self.__heading)) + self.__y seq = self.droneActor.posInterval(distance / 5, Point3(newx, newy, self.__z)) self.__x = newx self.__y = newy self.__overallSequence.append(seq)
class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) # Load the environment model. self.scene = self.loader.loadModel("models/environment") # Reparent the model to render. self.scene.reparentTo(self.render) # Apply scale and position transforms on the model. self.scene.setScale(0.25, 0.25, 0.25) self.scene.setPos(-8, 42, 0) self.accept('a', self.printRepeat) self.py3notify = DirectNotify().newCategory("Python3_main") def printRepeat(self): #print("got 'a'") self.py3notify.warning("got 'a'")
def connect(self): if (self.__connection == None): notify = DirectNotify().newCategory("") notify.warning("(Connection placeholder)") self.__connection = "placeholder" notify = DirectNotify().newCategory("") notify.warning("Connected!") #Note: Connecting to the drone will be considered successful for tests else: notify = DirectNotify().newCategory("") notify.warning("Oops, something went wrong connecting the socket") exit()
class Player(object): ''' ''' def __init__(self, number, ode_world, ode_space, device=None, camera=None): ''' ''' self._notify = DirectNotify().newCategory("Player") self._notify.info("New Player-Object created: %s" % (self)) self._ode_world = ode_world self._ode_space = ode_space self._number = number self._camera = camera self._vehicle = vehicle.Vehicle(self._ode_world, self._ode_space) # the properties of the vehicle self._device = device # The input device # self._osd_health = OnscreenText(text = "100", pos = ((self._number*0.2)-1,0.9)) self._position = 0 self._pre_position = 0 self._rank = 0 self._lap = 1 self._time = 0 # --------------------------------------------------------- def activateGameCam(self): self._camera.followVehicle(self._vehicle.boost_direction, self._vehicle) self._camera.camera.reparentTo(render) self._vehicle.model.reparentTo(render) # --------------------------------------------------------- def setPosition(self, position): ''' ''' self._position = position def getPosition(self): ''' ''' return self._position position = property(fget=getPosition, fset=setPosition) # --------------------------------------------------------- def setTime(self, time): ''' ''' self._time = time def getTime(self): ''' ''' return self._time time = property(fget=getTime, fset=setTime) # --------------------------------------------------------- def setNumber(self, number): ''' ''' self._number = number def getNumber(self): ''' ''' return self._number number = property(fget=getNumber, fset=setNumber) # --------------------------------------------------------- def setPrePosition(self, pre_position): ''' ''' self._pre_position = pre_position def getPrePosition(self): ''' ''' return self._pre_position pre_position = property(fget=getPrePosition, fset=setPrePosition) # --------------------------------------------------------- def setLap(self, lap): ''' ''' self._lap = lap def getLap(self): ''' ''' return self._lap lap = property(fget=getLap, fset=setLap) # --------------------------------------------------------- def setRank(self, rank): ''' ''' self._rank = rank def getRank(self): ''' ''' return self._rank rank = property(fget=getRank, fset=setRank) # --------------------------------------------------------- def setCamera(self, camera): ''' ''' self._camera = camera def getCamera(self): ''' ''' return self._camera camera = property(fget=getCamera, fset=setCamera) # --------------------------------------------------------- def updateOSD(self): ''' update the osd-information ''' # self._osd_health.setText(str(round(self._vehicle.energy))) def recalculateOSD(self): ''' recalculate positions of the osd ''' pass # --------------------------------------------------------- def setVehicle(self, vehicle): ''' ''' loading = self.camera.camera.getParent().find("LoadingNode") # loading.detachNode() if loading: loading.removeNode() else: self._notify.warning("Could not remove the loading node") vehicle.hide() vehicle.reparentTo(self.camera.camera.getParent()) self._vehicle.setVehicle(vehicle) vehicle.show() def getVehicle(self): ''' ''' return self._vehicle vehicle = property(fget=getVehicle, fset=setVehicle) # --------------------------------------------------------- def setDevice(self, device): ''' ''' self._device = device def getDevice(self): ''' ''' return self._device device = property(fget=getDevice, fset=setDevice) # --------------------------------------------------------- def doStep(self): ''' Needs to get executed every Ode-Step ''' self._vehicle.doStep() # --------------------------------------------------------- def updatePlayer(self): ''' Needs to get executed every Ode-Step ''' self._vehicle.model.setPosQuat(render, self._vehicle.physics_model.getPosition(), Quat(self._vehicle.physics_model.getQuaternion())) # set new position self._camera.updateCam() # --------------------------------------------------------- def __del__(self): ''' destroys all objects of the player-object ''' # Del one Camera self._camera.camera.removeNode() # node() self._notify.info("Player-Object deleted: %s" % (self))
class PlaneCamera(FSM, DirectObject): """Give this class a plane as argument and it will create some nodes around it which you can parent the camera to (if there are no such nodes yet). Keep in mind, that it only uses base.camera the whole time - no other cams are involved. Usage: plane_camera = PlaneCamera(aeroplane) plane_camera.setView("ThirdPerson") plane_camera.setView("Next") """ def __init__(self, parent): """Arguments: parent -- Aeroplane which the camera should follow """ # Used for debugging. Verbosity is set in config file. # Usually this is called self.notify, but in this case it would # override FSM's own. self.notifier = DirectNotify().newCategory("azure-camera") self.parent = parent # Replaced by a NodePath with all available cameras as children and # plane node as parent. self.cameras = None #if parent.__class__.__name__ is not "Aeroplane": if not isinstance(self.parent, Aeroplane): raise ParamError, "Parent must be an Aeroplane instance, " + \ "but is %s" % type(self.parent) FSM.__init__(self, "PlaneCamera: %s" % self.parent.name) DirectObject.__init__(self) try: self.camera = base.camera except: raise BaseMissing self.cameras = self.parent.node.find("cameras") if self.cameras.isEmpty(): self.createCamNodes() self.updateCamArray() self.sideview_direction = 0 # Set up the default camera self.setView("ThirdPerson") def createCamNodes(self): """Creates a few empty nodes around a plane which the camera might be parented to. It looks if there are cameras inside the model file and uses those if possible. Where everything named "camera CamType" is considered a camera. At least ThirdPerson, FirstPerson and Cockpit should be defined inside the egg file, otherwise some guessed defaults are taken. """ # Look for cameras inside the model (loaded egg file) self.cameras = NodePath("cameras") found_cams = self.parent.node.findAllMatches("**/camera ?*") found_cams.removeDuplicatePaths() found_cams.reparentTo(self.cameras) if not found_cams.isEmpty(): self.notifier.info("Cameras found under model:\n%s" % found_cams) else: self.notifier.info("No cameras found under model.") # FirstPerson camera is a must-have. Set up a guessed one if none # defined yet. if self.cameras.find("camera FirstPerson").isEmpty(): assert self.notifier.debug("No first person camera found in %s. " "Guessing best position." % self.parent.name) first_person = NodePath("camera FirstPerson") # TODO: Guess best position based on bounding box. first_person.setY(5) first_person.reparentTo(cameras) # ThirdPerson camera is a must-have. Set up a guessed one if none # defined yet. if self.cameras.find("camera ThirdPerson").isEmpty(): assert self.notifier.debug("No third person camera found in %s. " "Guessing best position." % self.parent.name) third_person = NodePath("camera ThirdPerson") # TODO: Guess best position based on bounding box. third_person.setPos(0, -30, 5) #third_person.setP(-80) third_person.reparentTo(cameras) # Cockpit needs to be accurate. Don't try to guess it. if self.cameras.find("camera Cockpit").isEmpty(): assert self.notifier.debug("No cockpit camera found in " "%s. Cockpit camera disabled." % self.parent.name) self.sideview_cam = NodePath("camera Sideview") self.sideview_cam.reparentTo(render) # Store the cams at parent node.. # You can edit the camera nodes from outside as well. # If you attach new camera nodes, though, you'll have to call this # function again. self.cameras.reparentTo(self.parent.node) def updateCamArray(self, cameramodes=None): """Set the cameras which next and previous will switch to. Expects a list or tuple. Defaults to all available cameras.""" a = [] if not cameramodes: for c in self.cameras.getChildren(): if c.getName().startswith("camera "): a.append(c.getName().strip("camera ")) self.setStateArray(a) else: self.setStateArray(cameramodes) def getView(self): """Returns the current view mode.""" return self.getCurrentOrNextState() def setView(self, mode, *args): """Convenience function.""" return self.request(mode, args) def defaultEnter(self, *args): """Executed by the FSM every time an undefined state is entered. Note: this function is called AFTER the responsible filter.""" assert self.notifier.debug("Changing state from %s to %s with args: %s." % (self.oldState, self.newState, args)) request = self.newState target_cam = self.cameras.find("camera " + request) if not target_cam.isEmpty(): try: self.camera.reparentTo(target_cam) self.camera.setPosHpr(0, 0, 0, 0, 0, 0) except: self.notifier.warning( "Ok, now this really shouldn't happen! Filter said the " "camera is there and enter can't find it...") def defaultFilter(self, request, args): """Executed by the FSM every time an undefined state is requested.""" assert self.notifier.debug("Requested %s with args: %s" % (request, args)) self.camera.setPosHpr(0, 0, 0, 0, 0, 0) # Always available. if request == "Off": # implemented in FSM.py return (request,) + args if request == "Next": # implemented in FSM.py return self.requestNext(args) if request == "Prev": # implemented in FSM.py return self.requestPrev(args) if request == "Detached": return (request,) + args if request == "Sideview": return (request,) + args # Depending on airplane. if not self.cameras.find("camera " + request).isEmpty(): # TODO(Nemesis13, 26.10.09): add some nice camera transition return (request,) + args assert self.notifier.info("Sorry, no %s camera found." % request) return None def enterOff(self, *args): """Clean up everything by reparenting the camera to the airplane.""" self.camera.reparentTo(self.parent.node) self.camera.setPosHpr(0, 0, 0, 0, 0, 0) def enterSideview(self, *args): self.sideview_direction += 90 self.camera.reparentTo(self.sideview_cam) self.camera.setY(-30) self.sideview_cam.setH(self.sideview_direction) self.addTask(self.updateSideview, "sideview camera", taskChain="world") def exitSideview(self, *args): self.removeTask("sideview camera") def updateSideview(self, task): self.sideview_cam.setPos(self.parent.node.getPos()) return Task.cont def enterDetached(self, *args): """Lets the camera view the plane from far away.""" self.camera.reparentTo(render) self.camera.setPosHpr(0, 0, 10, 0, 0, 0) self.addTask(self.updateDetachedCam, "detached camera", taskChain="world") def exitDetached(self, *args): self.removeTask("detached camera") def updateDetachedCam(self, task): """Updates camera position and rotation for Detached camera.""" try: self.camera.lookAt(self.parent.node) except: self.notifier.warning("Error on detached cam task. Exit.") return Task.done return Task.cont def enterThirdPerson(self, *args): """Lets the camera view the plane from far away.""" self._hist = [] self.camera.reparentTo(self.cameras.find("camera ThirdPerson")) self.addTask(self.updateThirdPersonCam, "third person camera", taskChain="world") #print "entering third person" def exitThirdPerson(self, *args): self.removeTask("third person camera") del self._hist #print "third person exited" def updateThirdPersonCam(self, task): """Updates camera position and rotation for ThirdPerson camera.""" #speed = self.parent.speed() #plane = self.parent.node #self._hist.insert(0, [task.time, camera.getPos(plane)]) #while len(self._hist) > 50: # self._hist.pop() # #for snapshot in self._hist: # if snapshot[0] > task.time: # break #time_delta = snapshot[0] - task.time #self.camera.setPos(plane, snapshot[1]) #print snapshot #self.camera.setPos(render, snapshot[1]) #self.camera.lookAt(plane, (0, 20+1*speed, 0)) #self.camera.setY(5+0.1*speed) #self.camera.setZ(5-0.1*speed) return Task.cont def destroy(self): self.removeAllTasks() self.demand("Off")
file.write('\n') file.close() else: toonlaff = raw_input( "Enter a positive number of laff for your toon: ") else: rewrite = raw_input( "Would you like to create new toon data? (Yes or No) ") if os.path.isfile('DataFolder/Data.txt'): print "Data file exists" create() else: file = open('DataFolder/Data.txt', "w") file.close() create() print "Data file created" from direct.directnotify.DirectNotify import DirectNotify notify = DirectNotify().newCategory("MyCategory") notify.warning("Put some informational text here.") from LocalAvatar import * from AvatarGui import * from TTC import * run()
'world', "username": "******", "version": 'alpha-dev 20.05 build A' } } settingsfile = open(directory + normpath("assets/settings.dat"), 'xb') pickle.dump(settings, settingsfile) fileManagerOutputLog.debug( "Successfully created a new preferences file.") settingsfile.close() if settings['config']['fullscreen'] == '#t' or settings['config'][ 'fullscreen'] == '#f': catchAllOutputLog.warning('User setting \'fullscreen\' was invalid :~(') settings['config']['fullscreen'] = 1 try: plop = settings['config']['version'] except KeyError: settings['config']['version'] = 'alpha-dev 20.05 build A' class txtfile: def __init__(self, path, version, newcontent=None): # file for download self.path = path self.version = version self.winpath = normpath(self.path) self.newcontent = newcontent fileManagerOutputLog.debug("Looking for file %s..." % path)
from panda3d.core import ConfigVariableString from direct.directnotify.DirectNotify import DirectNotify language = ConfigVariableString('language', 'English') language = language.getValue() notify = DirectNotify().newCategory("OTPLocalizer") def getLanguage(): return language _languageModule = 'otp.otpbase.OTPLocalizer' + language try: exec 'from ' + _languageModule + ' import *' print ":OTPLocalizer: Running in language: %s" % language except: notify.warning("Error, Language %s not found!" % language) notify.warning("Setting language to default (English)") from otp.otpbase.OTPLocalizerEnglish import *
def push(self, val): if self.heapSize == len(self): super(MaxHeap, self).append(float('-inf')) self.heapSize += 1 else: self[self.heapSize] = float('-inf') self.heapSize += 1 self._increaseKey(self.heapSize - 1, val) def __str__(self): return super(MaxHeap, self).__str__() if __name__ == '__main__': l = list(reversed([10, 9, 8, 7, 6, 5, 4, 3, 2, 1])) heap = MaxHeap(l) notify.warning("l {0}".format(l)) notify.warning("heap {0}".format(heap)) heap.heapSort() notify.warning("sorted {0}".format(heap)) notify.warning("size {0}".format(heap.heapSize)) heap.buildHeap() notify.warning("rebuilt {0}".format(heap)) notify.warning("l {0}".format(l)) heap2 = MaxHeap() for n in l: notify.warning("n {0}".format(n)) heap2.push(n) notify.warning("heap2 {0}".format(heap2)) notify.warning("isMaxHeap {0}".format(MaxHeap.isMaxHeap(heap2))) heap2.heapSort() notify.warning("after sort isMaxHeap {0}".format(MaxHeap.isMaxHeap(heap2)))
def get_height(self): self.__commandCheck() notify = DirectNotify().newCategory("") notify.warning(self.__heading)
def __commandCheck(self): if (self.__commanding == False): notify = DirectNotify().newCategory("") notify.warning("The drone is not set to command") self.disconnect() exit()
class Vehicle(object): ''' ''' def __init__(self, ode_world, ode_space, name="standard"): ''' ''' self._notify = DirectNotify().newCategory("Vehicle") self._notify.info("New Vehicle-Object created: %s" % (self)) self._ode_world = ode_world self._ode_space = ode_space self._model = None self._physics_model = None self._physics_mass = None self._collision_model = None self._speed = 0.0 # the actual speed of the vehicle (forward direction) self._direction = Vec3(0, 0, 0) # the direction the car is heading self._boost_direction = Vec3(0, 0, 0) self._boost_strength = 10.0 # the boost propertys of the vehicle self._control_strength = 1.5 # impact on the steering behaviour self._grip_strength = 0.5 # impact on the steering behaviour self._track_grip = 0.8 # impact on the steering behaviour self._energy = 100.0 self._armor = 100.0 self._max_energy = 100.0 self._max_armor = 100.0 self._weight = 10.0 self._description = "The best vehicle ever" self._name = "The flying egg" self._brake_strength = 10.0 self._hit_ground = True self._model_loading = False self._blowout = [] self._blowout_on = False self._streetnormal = Vec3(0, 0, 1) # set up the propertys of the vehicle that schould be loaded # the methods get called because the data is immutable and # wouldnt get updated when calling the objects directly # the last entry is the function to convert the string self._tags = [["name", self.setName, str], ["description", self.setDescription, str], ["control_strength", self.setControlStrength, float], ["grip_strength", self.setGripStrength, float], ["track_grip", self.setTrackGrip, float], ["max_energy", self.setMaxEnergy, float], ["max_armor", self.setMaxArmor, float], ["weight", self.setWeight, float], ["brake_strength", self.setBrakeStrength, float], ["boost_strength", self.setBoostStrength, float]] # --------------------------------------------------------- def setVehicle(self, model): ''' Choose what vehicle the player has chosen. This method initializes all data of this vehicle ''' self.cleanResources() self._notify.debug("Set new vehicle: %s" % model) # Load the attributes of the vehicle attributes = model.find("**/Attributes") if attributes.isEmpty(): self._notify.warning("No Attribute-Node found") for tag in self._tags: value = attributes.getNetTag(tag[0]) if value: self._notify.debug("%s: %s" % (tag[0], value)) # translate the value if its a string if type(tag[2](value)) == str: tag[1](_(tag[2](value))) else: tag[1](tag[2](value)) else: self._notify.warning("No value defined for tag: %s" % (tag[0])) self._weight = 10 # for testing purposes blowout = model.find("**/Blowout") if not blowout.isEmpty(): self._notify.debug("Loading Blowout-Particles") for node in blowout.getChildren(): particle = ParticleEffect() self._blowout.append(particle) particle.loadConfig('./data/particles/blowout_test.ptf') try: # try to read out the particle scale scale = float(node.getTag("scale")) except Exception: # default is 0.5 scale = .5 renderer = particle.getParticlesList()[0].getRenderer() renderer.setInitialXScale(scale) renderer.setInitialYScale(scale) particle.setLightOff() particle.start(node) particle.softStop() else: self._notify.warning("No Blowout-Node found") if self._model is not None: heading = self._model.getH() self._model.removeNode() else: heading = 160 # display the attributes text = model.getParent().find("AttributeNode") if not text.isEmpty(): node = text.find("name") if not node.isEmpty(): node = node.node() node.setText(self._name) node.update() text.show() node = text.find("description") if not node.isEmpty(): node = node.node() node.setText(self._name) node.update() text.show() self._model = model self._model.setPos(0, 0, 2) self._model.setHpr(heading, 0, 0) # #Test # plightCenter = NodePath( 'plightCenter' ) # plightCenter.reparentTo( render ) # self.interval = plightCenter.hprInterval(12, Vec3(360, 0, 0)) # self.interval.loop() # # plight = PointLight('plight') # plight.setColor(VBase4(0.8, 0.8, 0.8, 1)) # plight.setAttenuation(Vec3(1,0,0)) # plnp = plightCenter.attachNewNode(plight) # plnp.setPos(5, 5, 10) # render.setLight(plnp) # # alight = AmbientLight('alight') # alight.setColor(VBase4(0,0,0, 1)) # alnp = render.attachNewNode(alight) # render.setLight(alnp) # GlowTextur # self.glowSize=10 # self.filters = CommonFilters(base.win, self._model) # self.filters.setBloom(blend=(0,self.glowSize,0,0) ,desat=1, intensity=1, size='medium') # tex = loader.loadTexture( 'data/textures/glowmap.png' ) # ts = TextureStage('ts') # ts.setMode(TextureStage.MGlow) # self._model.setTexture(ts, tex) # Initialize the physics-simulation for the vehicle self._physics_model = OdeBody(self._ode_world) self._physics_model.setPosition(self._model.getPos(render)) self._physics_model.setQuaternion(self._model.getQuat(render)) # Initialize the mass of the vehicle physics_mass = OdeMass() physics_mass.setBoxTotal(self._weight, 1, 1, 1) self._physics_model.setMass(physics_mass) # Initialize the collision-model of the vehicle # for use with blender models # try: # col_model = loader.loadModel("data/models/vehicles/%s.collision" %(self._model.getName())) # self.collision_model = OdeTriMeshGeom(self._ode_space, OdeTriMeshData(col_model, True)) # self._notify.info("Loading collision-file: %s" %("data/models/vehicles/%s.collision" %(self._model.getName()))) # for fast collisions # except: # self._notify.warning("Could not load collision-file. Using standard collision-box") # self.collision_model = OdeTriMeshGeom(self._ode_space, OdeTriMeshData(model, False)) # self._collision_model = OdeBoxGeom(self._ode_space, 3,3,2) self._collision_model = OdeBoxGeom(self._ode_space, 3, 3, 2) self._collision_model.setBody(self._physics_model) self._collision_model.setCollideBits(7) self._collision_model.setCategoryBits(2) # Add collision-rays for the floating effect self._ray = CollisionRay(Vec3(5, 0, 0), Vec3(0, 0, -1), self._ode_space, parent=self._collision_model, collide_bits=0, length=20.0) # This one is used for the floating effect but also for slipstream self._frontray = CollisionRay(Vec3(0, 0, 0), Vec3(1, 0, 0), self._ode_space, parent=self._collision_model, collide_bits=0, length=15.0) # Overwrite variables for testing purposes self._grip_strength = 0.9 self._track_grip = 0.2 self._boost_strength = 1400 self._control_strength = 2.5 # Loading finished self._model_loading = False def toggleGlow(self): self.glowSize += .1 print((self.glowSize)) if (self.glowSize == 4): self.glowSize = 0 self.filters.setBloom(blend=(0, self.glowSize, 0, 0), desat=-2, intensity=3, size='medium') def boggleGlow(self): self.glowSize -= .1 print((self.glowSize)) if (self.glowSize == 4): self.glowSize = 0 self.filters.setBloom(blend=(0, self.glowSize, 0, 0), desat=-2, intensity=3.0, size='medium') # --------------------------------------------------------- def setPos(self, x, y, z): ''' ''' self._model.setPos(x, y, z) def getPos(self): ''' ''' return self._model.getPos() position = property(fget=getPos, fset=setPos) # --------------------------------------------------------- def startBlowout(self): ''' ''' if not self._blowout_on: self._blowout_on = True for particle in self._blowout: particle.softStart() def stopBlowout(self): ''' ''' if self._blowout_on: self._blowout_on = False for particle in self._blowout: particle.softStop() # --------------------------------------------------------- def setModel(self, model): ''' ''' self._model = model def getModel(self): ''' ''' return self._model model = property(fget=getModel, fset=setModel) # --------------------------------------------------------- def setCollisionModel(self, model): ''' ''' self._collision_model = model def getCollisionModel(self): ''' ''' return self._collision_model collision_model = property(fget=getCollisionModel, fset=setCollisionModel) # --------------------------------------------------------- def setPhysicsModel(self, model): ''' ''' self._physics_model = model def getPhysicsModel(self): ''' ''' return self._physics_model physics_model = property(fget=getPhysicsModel, fset=setPhysicsModel) # --------------------------------------------------------- def setBoost(self, strength=1): ''' Boosts the vehicle by indicated strength ''' self.startBlowout() if self._hit_ground: direction = self._streetnormal.cross( self._collision_model.getQuaternion().xform(Vec3(1, 0, 0))) self._physics_model.addForce( direction * ((self._boost_strength * self.physics_model.getMass().getMagnitude() * strength))) self._hit_ground = False self._collision_model.setCollideBits(7) else: direction = self._streetnormal.cross( self._collision_model.getQuaternion().xform(Vec3(1, 0, 0))) self._physics_model.addForce( direction * self._boost_strength * 0.5 * self.physics_model.getMass().getMagnitude() * strength) # --------------------------------------------------------- def setDirection(self, dir): ''' Steers the vehicle into the target-direction ''' rel_direction = self._collision_model.getQuaternion().xform( Vec3(dir[1], 0, dir[0])) # rel_position = self._collision_model.getQuaternion().xform(Vec3(5,0,0)) # force = Vec3(rel_direction[0]*self.direction[0]*self._control_strength*self.speed,rel_direction[1]*self.direction[1]*self._control_strength*self.speed,rel_direction[2]*self.direction[2]*self._control_strength*self.speed) self._physics_model.addTorque( -rel_direction * self._control_strength * self.physics_model.getMass().getMagnitude()) def getDirection(self): return self._direction direction = property(fget=getDirection, fset=setDirection) # --------------------------------------------------------- def getBoostDirection(self): return self._boost_direction boost_direction = property(fget=getBoostDirection) # --------------------------------------------------------- def getSpeed(self): return self._speed speed = property(fget=getSpeed) # --------------------------------------------------------- def setEnergy(self, energy): ''' Boosts the vehicle by indicated strength ''' self._energy = energy def getEnergy(self): return self._energy energy = property(fget=getEnergy, fset=setEnergy) # --------------------------------------------------------- def setModelLoading(self, bool): ''' ''' self._model_loading = bool def getModelLoading(self): return self._model_loading model_loading = property(fget=getModelLoading, fset=setModelLoading) # --------------------------------------------------------- def doStep(self): ''' Needs to get executed every Ode-Step ''' # refresh variables linear_velocity = self._physics_model.getLinearVel() direction = self._streetnormal.cross( self._collision_model.getQuaternion().xform(Vec3(1, 0, 0))) self._boost_direction[0], self._boost_direction[ 1], self._boost_direction[2] = self.physics_model.getLinearVel( )[0], self.physics_model.getLinearVel( )[1], self.physics_model.getLinearVel()[2] # This needs to be done, so we dont create a new object but only change the existing one. else the camera wont update self._direction[0], self._direction[1], self._direction[2] = direction[ 0], direction[1], direction[2] xy_direction = self.collision_model.getQuaternion().xform(Vec3( 1, 1, 0)) self._speed = Vec3(linear_velocity[0] * xy_direction[0], linear_velocity[1] * xy_direction[1], linear_velocity[2] * xy_direction[2]).length() # calculate air resistance self._physics_model.addForce( -linear_velocity * linear_velocity.length() / 10) # *((self._speed/2)*(self._speed/2)))#+linear_velocity) # calculate delayed velocity changes linear_velocity.normalize() self._direction.normalize() self._physics_model.addForce( self._direction * (self._speed * self._grip_strength * self.physics_model.getMass().getMagnitude())) # +linear_velocity) self._physics_model.addForce( -linear_velocity * (self._speed * self._grip_strength * self.physics_model.getMass().getMagnitude())) # +linear_velocity) # calculate the grip self._physics_model.addTorque( self._physics_model.getAngularVel() * -self._track_grip * self.physics_model.getMass().getMagnitude()) # refresh the positions of the collisionrays self._ray.doStep() self._frontray.doStep() self._physics_model.setGravityMode(1) # --------------------------------------------------------- def getRay(self): return self._ray ray = property(fget=getRay) # --------------------------------------------------------- def getFrontRay(self): return self._frontray frontray = property(fget=getFrontRay) # ----------------------------------------------------------------- def getHitGround(self): return self._hit_ground def setHitGround(self, value): if type(value) != bool: raise TypeError("Type should be %s not %s" % (bool, type(value))) self._hit_ground = value hit_ground = property(fget=getHitGround, fset=setHitGround) # ----------------------------------------------------------------- def getControlStrength(self): return self._control_strength def setControlStrength(self, value): self._control_strength = value control_strength = property(fget=getControlStrength, fset=setControlStrength) # ----------------------------------------------------------------- def getBoostStrength(self): return self._boost_strength def setBoostStrength(self, value): self._boost_strength = value boost_strength = property(fget=getBoostStrength, fset=setBoostStrength) # ----------------------------------------------------------------- def getGripStrength(self): return self._grip_strength def setGripStrength(self, value): self._grip_strength = value grip_strength = property(fget=getGripStrength, fset=setGripStrength) # ----------------------------------------------------------------- def getTrackGrip(self): return self._track_grip def setTrackGrip(self, value): self._track_grip = value track_grip = property(fget=getTrackGrip, fset=setTrackGrip) # ----------------------------------------------------------------- def getMaxEnergy(self): return self._max_energy def setMaxEnergy(self, value): self._max_energy = value max_energy = property(fget=getMaxEnergy, fset=setMaxEnergy) # ----------------------------------------------------------------- def getMaxArmor(self): return self._max_armor def setMaxArmor(self, value): self._max_armor = value max_armor = property(fget=getMaxArmor, fset=setMaxArmor) # ----------------------------------------------------------------- def getWeight(self): return self._weight def setWeight(self, value): self._weight = value weight = property(fget=getWeight, fset=setWeight) # ----------------------------------------------------------------- def getDescription(self): return self._description def setDescription(self, value): self._description = value description = property(fget=getDescription, fset=setDescription) # ----------------------------------------------------------------- def getBrakeStrength(self): return self._brake_strength def setBrakeStrength(self, value): self._brake_strength = value brake_strength = property(fget=getBrakeStrength, fset=setBrakeStrength) # ----------------------------------------------------------------- def getName(self): return self._name def setName(self, value): self._name = value name = property(fget=getName, fset=setName) # ----------------------------------------------------------------- def getStreetNormal(self): return self._streetnormal def setStreetNormal(self, value): self._streetnormal = value streetnormal = property(fget=getStreetNormal, fset=setStreetNormal) # ----------------------------------------------------------------- def cleanResources(self): ''' Removes old nodes, gets called when a new vehcile loads ''' for node in self._blowout: node.removeNode() self._blowout = [] if self._model is not None: for node in self._model.getChildren(): node.removeNode() self._model.removeNode() self._model = None # self._physics_model.destroy() # self._collision_model.destroy() # temporary fix because destroy() doesnt work self._physics_model.disable() self._collision_model.disable() self._notify.info("Vehicle-Object cleaned: %s" % (self)) def __del__(self): ''' Destroy unused nodes ''' for node in self._blowout: node.removeNode() if self._model is not None: for node in self._model.getChildren(): node.removeNode() self._model.removeNode() self._model = None self._physics_model.destroy() self._collision_model.destroy() # temporary fix because destroy() doesnt work self._physics_model.disable() self._collision_model.disable() self._notify.info("Vehicle-Object deleted: %s" % (self))
class Grabber(object): def __init__( self, levitNP): """ A widget to position, rotate, and scale Panda 3D Models and Actors * handleM1 decides what to do with a mouse1 click -- object selection by calling handleSelection when the grabModel is inactive (hidden) -- object manipulation by calling handleManipulationSetup (sets the stage for and launches the dragTask) isHidden() when nothing is selected isDragging means not running collision checks for selection setup and LMB is pressed call handleM1 from another class to push control up in the program hierarchy (remove inner class calls) """ # TODO remove selection functionality from grabber and put it in a selector class self.levitorNP = levitNP # TODO remove this and use barebonesNP self.selected = None self.initialize() def initialize(self): """Reset everything except LevitorNP and selected, also called inside __init__""" self.notify = DirectNotify().newCategory('grabberErr') self.currPlaneColNorm = Vec3(0.0) self.isCameraControlOn = False self.isDragging = False self.isMultiselect = False self.grabScaleFactor = .075 self.currTransformDir = Point3(0.0) self.interFrameMousePosition = Point3(0.0) self.init3DemVal = Point3(0.0) # initCommVal holds the value before a command operation has taken place self.initialCommandTrgVal = None # To load the grabber model, this climbs up the absolute path to /barebones/ to gain access to the model folder self.grabModelNP = loader.loadModel(Filename.fromOsSpecific( ntpath.split( ntpath.split(inspect.stack()[0][1])[0] )[0]) + '/EditorModels/widget') self.grabModelNP.setPos(0.0, 0.0, 0.0) self.grabModelNP.setBin("fixed", 40) self.grabModelNP.setDepthTest(False) self.grabModelNP.setDepthWrite(False) self.transformOpEnum = Enum('rot, scale, trans') self.currTransformOperation = None # TODO For readability, use this enum in the nested if/else as was the original intent. self.grabInd = Enum('xRot, yRot, zRot, xScaler, yScaler, zScaler, xTrans, yTrans, zTrans, xyTrans, xzTrans, zyTrans, grabCore') grbrNodLst = [self.grabModelNP.find("**/XRotator;+h-s-i"), # 0 self.grabModelNP.find("**/YRotator;+h-s-i"), # 1 self.grabModelNP.find("**/ZRotator;+h-s-i"), # 2 end rotate self.grabModelNP.find("**/XScaler;+h-s-i"), # 3 self.grabModelNP.find("**/YScaler;+h-s-i"), # 4 self.grabModelNP.find("**/ZScaler;+h-s-i"), # 5 end scale self.grabModelNP.find("**/XTranslator;+h-s-i"), # 6 self.grabModelNP.find("**/YTranslator;+h-s-i"), # 7 self.grabModelNP.find("**/ZTranslator;+h-s-i"), # 8 end translate / end single dir operations self.grabModelNP.find("**/XYTranslator;+h-s-i"), # 9 self.grabModelNP.find("**/XZTranslator;+h-s-i"), # 10 self.grabModelNP.find("**/ZYTranslator;+h-s-i"), # 11 end bi-directional operations self.grabModelNP.find("**/WidgetCore;+h-s-i")] # 12 #Mat4.yToZUpMat() # change coordinate to z up grbrNodLst[12].getParent().setHprScale(0, 0, 0, 1, 1, -1) self.grabModelNP.setPythonTag('grabberRoot', grbrNodLst) self.grabModelNP.reparentTo(BBGlobalVars.bareBonesObj.levitorNP) self.grabModelNP.hide() #self.grabIntoBitMask = COLLISIONMASKS self.grabModelNP.setCollideMask(COLLISIONMASKS['default']) self.grabModelNP.setPythonTag('grabber', self) ############################################################################## # This whole section is the basics for setting up mouse selection # --The mouse events are added in the events section (next) # Create the collision node for the picker ray to add traverser as a 'from' collider self.grabberColNode = CollisionNode('grabberMouseRay') # Set the collision bitmask # TODO: define collision bitmask (let user define thiers? likely not) self.defaultBitMask = GeomNode.getDefaultCollideMask() self.grabberColNode.setFromCollideMask(self.defaultBitMask) self.grabberRayColNP = camera.attachNewNode(self.grabberColNode) # Create the grabberRay and add it to the picker CollisionNode self.grabberRay = CollisionRay(0.0, 0.0, 0.0, 0.0, 1.0, 0.0) self.grabberRayNP = self.grabberColNode.addSolid(self.grabberRay) # create a collision queue for the traverser self.colHandlerQueue = CollisionHandlerQueue() # Create collision traverser self.colTraverser = CollisionTraverser('grabberTraverser') # Set the collision traverser's 'fromObj' and handler # e.g. trav.addCollider( fromObj, handler ) self.colTraverser.addCollider(self.grabberRayColNP, self.colHandlerQueue) ############################################################ # setup event handling with the messenger # URGENT remove all of this messenger code throughout Grabber, especially the camera control # disable the mouse when the ~ is pressed (w/o shift) self.disableCamera() # disable camera control by the mouse messenger.accept('`', self, self.enableCamera) # enable camera control when the ~ key is pressed w/o shift messenger.accept('`-up', self, self.disableCamera) # disable camera control when the ~ key is released # handle mouse selection/deselection & manipulating the scene messenger.accept('mouse1', self, self.handleM1, persistent=1) # deselect in event handler taskMgr.add(self.scaleGrabber, 'scaleGrabber') # //////////////////////////////////////////////////////////////////// # comment out: good for debug info #taskMgr.add(self.watchMouseColl, name='grabberDebug') #this is only good for seeing types and hierarchy #self.grabModelNP.ls() #render.ls() # self.frames = 0 #remove # self.axis = loader.loadModel("zup-axis") # self.axis.reparentTo(self.grabModelNP) # self.axis.setScale(.15) # self.axis.setPos(0.0) # self.grabModelNP.append( 'newAttrib', self) # setattr( self.grabModelNP, 'newAttrib', self) def prepareForPickle(self): self.colTraverser = None # Traversers are not picklable self.defaultBitMask = None # BitMasks "..." # self.grabIntoBitMask = None # "..." self.colHandlerQueue = None # CollisonHandlerQueue "..." self.grabModelNP.removeNode() self.grabModelNP = None taskMgr.remove('scaleGrabber') def recoverFromPickle(self): self.initialize() if self.selected is not None: self.grabModelNP.setPos(render, self.selected.getPos(render)) self.grabModelNP.show() print "grabber sel ", self.selected, " isHidden() ", self.grabModelNP.isHidden(), '\n' taskMgr.add(self.scaleGrabber, 'scaleGrabber') #### May use to gain control over pickling. # def __repr__(self): # for pickling purposes # if self.colTraverser: # self.colTraverser = None # # dictrepr = dict.__repr__(self.__dict__) # dictrepr = '%r(%r)' % (type(self).__name__, dictrepr) # print dictrepr # REMOVE # return dictrepr def watchMouseColl(self, task): """ This exists for debugging purposes to perpetually watch mouse collisions. """ # TODO make this highlight objects under the mouse for predictable object selection/grabber operations self.colTraverser.showCollisions(render) if base.mouseWatcherNode.hasMouse() and False == self.isCameraControlOn: # This gives the screen coordinates of the mouse. mPos = base.mouseWatcherNode.getMouse() # This makes the ray's origin the camera and makes the ray point # to the screen coordinates of the mouse. self.grabberRay.setFromLens(base.camNode, mPos.getX(), mPos.getY()) # traverses the graph for collisions self.colTraverser.traverse(render) return task.cont def scaleGrabber(self, task): if self.grabModelNP.isHidden(): return task.cont coreLst = self.grabModelNP.getPythonTag('grabberRoot') camPos = self.grabModelNP.getRelativePoint(self.grabModelNP, camera.getPos()) if camPos.z >= 0: # 1-4 if camPos.x > 0.0 <= camPos.y: # quad 1 coreLst[12].getParent().setScale( 1, 1, -1) elif camPos.x < 0.0 <= camPos.y: # quad 2 coreLst[12].getParent().setScale( -1, 1, -1) elif camPos.x < 0.0 >= camPos.y: # quad 3 coreLst[12].getParent().setScale( -1, -1, -1) elif camPos.x > 0.0 >= camPos.y: # quad 4 coreLst[12].getParent().setScale( 1, -1, -1) else: self.notify.warning("if-else default, scaleGrabber cam.z > 0") else: # 5-8 if camPos.x > 0.0 <= camPos.y: # quad 5 coreLst[12].getParent().setScale( 1, 1, 1) elif camPos.x < 0.0 <= camPos.y: # quad 6 coreLst[12].getParent().setScale( -1, 1, 1) elif camPos.x < 0.0 >= camPos.y: # quad 7 coreLst[12].getParent().setScale( -1, -1, 1) elif camPos.x > 0.0 >= camPos.y: # quad 8 coreLst[12].getParent().setScale( 1, -1, 1) else: self.notify.warning("if-else default, scaleGrabber cam.z z < 0") distToCam = (camera.getPos() - render.getRelativePoint(BBGlobalVars.currCoordSysNP, self.grabModelNP.getPos())).length() self.grabModelNP.setScale(self.grabScaleFactor * distToCam, self.grabScaleFactor * distToCam, self.grabScaleFactor * distToCam) # keep the position identical to the selection # for when outside objects like undo/redo move selected self.grabModelNP.setPos(render, self.selected.getPos(render)) return task.cont # TODO find a way to move camera control to a proper camera handler, perhaps move these to a global def enableCamera(self): self.isCameraControlOn = True PanditorEnableMouseFunc() def disableCamera(self): self.isCameraControlOn = False PanditorDisableMouseFunc() def handleM3(self): """Deselect the selected object.""" if not self.grabModelNP.isHidden() and not self.isCameraControlOn: # if the grab model is in the scene and the camera is not in control if base.mouseWatcherNode.hasMouse() and not self.isDragging: # we're ignoring accidental mouse3 clicks while dragging here with not isDragging self.selected = None # empty the selected, will be turned back on once something's selected messenger.ignore('mouse3', self) # turn the deselect event off self.grabModelNP.hide() # hide the grab model and set it back to render's pos self.grabModelNP.setPos(0.0) def handleM1Up(self): """Stop dragging the selected object.""" taskMgr.remove('mouse1Dragging') self.isDragging = False self.currTransformOperation = None # NOTE other references have been added, but no other object references them # record the mouse1 operation BBGlobalVars.undoHandler.record(self.selected, CommandUndo([self.initialCommandTrgVal], self.selected.setMat, self.selected.getMat(render))) messenger.ignore('mouse1-up', self) def handleM1(self): """Decides how to handle a mouse1 click.""" if self.isCameraControlOn: return if base.mouseWatcherNode.hasMouse(): # give the grabber first chance if self.grabModelNP.isHidden(): # no collisions w/ grabber or nothing selected # handle selection with scene objects self.handleSelection() elif not self.isDragging: # The grabber is in place but not dragging. Get ready to drag. self.handleManipulationSetup() # it'll call self.handleSelection() if no collision w/ grabber # TODO (if warranted) make self.handleManipulationSetup() return false if no col w/ grabber, call selection here instead def handleManipulationSetup(self): """Sets up all the attributes needed for the mouse dragging task.""" # This makes the ray's origin the camera and makes the ray point # to the screen coordinates of the mouse. if self.isDragging: return camVec = self.grabModelNP.getRelativeVector(self.grabModelNP, camera.getPos()) mPos = base.mouseWatcherNode.getMouse() self.grabberRay.setFromLens(base.camNode, mPos.getX(), mPos.getY()) self.colTraverser.traverse(self.grabModelNP) # look for collisions on the grabber if not self.isCameraControlOn and self.colHandlerQueue.getNumEntries() > 0 and not self.grabModelNP.isHidden(): # see if collided with the grabber if not handle re or multi selection self.colHandlerQueue.sortEntries() grabberObj = self.colHandlerQueue.getEntry(0).getIntoNodePath() grabberLst = self.grabModelNP.getPythonTag('grabberRoot') # see __init__ # the index gives the operations rot < 3 scale < 6 trans < 9 trans2D < 12 # mod index gives axis 0 == x, 1 == y, 2 == z ind = -1 for i in range(0, 13): if grabberObj == grabberLst[i]: ind = i grabberObj = grabberLst[i] # ensure we are not picking ourselves, ahem, the grabber assert(not self.grabModelNP.isAncestorOf(self.selected)) mPos3D = Point3(0.0) xVec = Vec3(1, 0, 0) yVec = Vec3(0, 1, 0) zVec = Vec3(0, 0, 1) # TODO: ??? break this up into translate rotate and scale function to make it readable if -1 < ind < 3: # rotate if ind % 3 == 0: # x self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.rot, Point3(mPos.getX(), mPos.getY(), 0.0)) elif ind % 3 == 1: # y self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.rot, Point3(mPos.getX(), mPos.getY(), 0.0)) else: # z self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.rot, Point3(mPos.getX(), mPos.getY(), 0.0)) elif ind < 6: # scale if ind % 3 == 0: # x self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.scale, Point3(mPos.getX(), mPos.getY(), 0.0)) elif ind % 3 == 1: # y # self.currTransformDir = Point3( 0.0, 1.0, 0.0) self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.scale, Point3(mPos.getX(), mPos.getY(), 0.0)) else: # z # self.currTransformDir = Point3( 0.0, 0.0, 1.0) self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.scale, Point3(mPos.getX(), mPos.getY(), 0.0)) elif ind < 9: # translate if ind % 3 == 0: # x # if the camera's too flat to the collision plane bad things happen if camVec.angleDeg( zVec) < 89.0 and self.getMousePlaneIntersect(mPos3D, zVec): self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.trans, mPos3D, zVec) elif self.getMousePlaneIntersect(mPos3D, yVec): self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.trans, mPos3D, yVec) elif ind % 3 == 1: # y if camVec.angleDeg( zVec) < 89.0 and self.getMousePlaneIntersect(mPos3D, zVec): self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.trans, mPos3D, zVec) elif self.getMousePlaneIntersect(mPos3D, xVec): self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.trans, mPos3D, xVec) else: # z if camVec.angleDeg( yVec) < 89.0 and self.getMousePlaneIntersect(mPos3D, yVec): self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.trans, mPos3D, yVec) elif self.getMousePlaneIntersect(mPos3D, xVec): self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.trans, mPos3D, xVec) elif ind < 12: # translate 2D if ind % 3 == 0: # xy if self.getMousePlaneIntersect(mPos3D, zVec): self.initializeManipVars(Point3(1.0, 1.0, 0.0), self.transformOpEnum.trans, mPos3D, zVec) elif ind % 3 == 1: # xz if self.getMousePlaneIntersect(mPos3D, yVec): self.initializeManipVars(Point3(1.0, 0.0, 1.0), self.transformOpEnum.trans, mPos3D, yVec) else: # zy if self.getMousePlaneIntersect(mPos3D, xVec): self.initializeManipVars(Point3(0.0, 1.0, 1.0), self.transformOpEnum.trans, mPos3D, xVec) elif ind == 12: # scale in three directions self.initializeManipVars(Point3(1.0, 1.0, 1.0), self.transformOpEnum.scale, Point3(mPos.getX(), mPos.getY(), 0.0)) else: self.notify.warning("Grabber Err: no grabber collision when col entries > 0 AND grabber not hidden") # Save initial value for save/undo. # The end result of the operation is sent to the undo handler on mouse up event. if self.selected: self.initialCommandTrgVal = self.selected.getMat(render) else: # no collisions w/ grabber or nothing selected # handle reselection or multi-selection (not yet implemented) with other scene obj self.handleSelection() def handleSelection(self): if self.isDragging: return # First check that the mouse is not outside the screen. if base.mouseWatcherNode.hasMouse() and False == self.isCameraControlOn: self.grabberColNode.setFromCollideMask(self.defaultBitMask) # This gives the screen coordinates of the mouse. mPos = base.mouseWatcherNode.getMouse() # This makes the ray's origin the camera and makes the ray point # to the screen coordinates of the mouse. self.colHandlerQueue.clearEntries() self.grabberRay.setFromLens(base.camNode, mPos.getX(), mPos.getY()) self.colTraverser.traverse(render) # look for collisions if self.colHandlerQueue.getNumEntries() > 0: self.colHandlerQueue.sortEntries() grabbedObj = self.colHandlerQueue.getEntry(0).getIntoNodePath() if not grabbedObj.findNetTag('pickable').isEmpty(): grabbedObj = grabbedObj.findNetTag('pickable') self.selected = grabbedObj self.grabModelNP.setPos(render, grabbedObj.getPos(render).x, grabbedObj.getPos(render).y, grabbedObj.getPos(render).z) self.grabModelNP.show() messenger.accept('mouse3', self, self.handleM3) def handleDragging(self, task): """ Does the actual work of manipulating objects, once the needed attributes have been setup by handleManipulationSetup(). """ if not self.isDragging: return task.done mPos3D = Point3(0.0) # # This section handles the actual translating rotating or scale after it's been set up in mouse1SetupManip...() # ONLY one operation is preformed per frame if self.currTransformOperation == self.transformOpEnum.trans: # 1st translation, rotation's section is at next elif if self.getMousePlaneIntersect(mPos3D, self.currPlaneColNorm): # get the difference between the last mouse and this frames mouse selectedNewPos = mPos3D - self.interFrameMousePosition # store this frames mouse self.interFrameMousePosition = mPos3D # add the difference to the selected object's pos self.selected.setPos(render, self.selected.getPos(render).x + self.currTransformDir.x * selectedNewPos.x, self.selected.getPos(render).y + self.currTransformDir.y * selectedNewPos.y, self.selected.getPos(render).z + self.currTransformDir.z * selectedNewPos.z) self.grabModelNP.setPos(render, self.selected.getPos(render)) elif self.currTransformOperation == self.transformOpEnum.rot: # 2nd rotation, followed finally by scaling # if operating on the z-axis, use the y (vertical screen coordinates otherwise use x (horizontal) mPos = base.mouseWatcherNode.getMouse() #rotMag = 0.0 if self.currTransformDir == Vec3( 0.0, 0.0, 1.0): rotMag = (mPos.x - self.interFrameMousePosition.x) * 1000 else: rotMag = (self.interFrameMousePosition.y - mPos.y) * 1000 initPos = self.selected.getPos() initPar = self.selected.getParent() self.selected.wrtReparentTo(render) self.selected.setMat(self.selected.getMat() * Mat4.rotateMat(rotMag, self.currTransformDir)) self.selected.wrtReparentTo(initPar) self.selected.setPos(initPos) self.interFrameMousePosition = Point3(mPos.x, mPos.y, 0.0) elif self.currTransformOperation == self.transformOpEnum.scale: # 3rd and final is scaling mPos = base.mouseWatcherNode.getMouse() # TODO: make dragging away from the object larger and to the object smaller (not simply left right up down) # td The problem with this MAY come if negative, mirrored, scaling is implemented. # if operating on the z-axis, use the y (vertical screen coordinates otherwise use x (horizontal) if self.currTransformDir == Point3( 0.0, 0.0, 1.0): sclMag = (mPos.y - self.interFrameMousePosition.y) * 5.5 elif self.currTransformDir == Point3( 0.0, 1.0, 0.0): sclMag = (mPos.x - self.interFrameMousePosition.x) * 5.5 else: sclMag = (self.interFrameMousePosition.x - mPos.x) * 5.5 # This is the line that prevents scaling past the origin. Flipping the faces doesn't seem to work. if -0.0001 < sclMag < 0.0001: sclMag = 0.000001 # create a dummy node to parent to and position such that applying scale to it will scale selected properly dummy = self.levitorNP.attachNewNode('dummy') initScl = dummy.getScale() # Don't forget the parent. Selected needs put back in place initPar = self.selected.getParent() initPos = self.selected.getPos() self.selected.wrtReparentTo(dummy) dummy.setScale(initScl.x + sclMag * self.currTransformDir.x, initScl.y + sclMag * self.currTransformDir.y, initScl.z + sclMag * self.currTransformDir.z) # reset selected's parent then destroy dummy self.selected.wrtReparentTo(initPar) self.selected.setPos(initPos) dummy.removeNode() dummy = None self.interFrameMousePosition = Point3( mPos.x, mPos.y, 0.0) else: self.notify.error("Err: Dragging with invalid curTransformOperation enum in handleDragging") return task.cont # ended by handleM1Up(), the mouse1-up event handler def initializeManipVars(self, transformDir, transformOp, mPos3D, planeNormVec=None): self.currTransformDir = transformDir self.currPlaneColNorm = planeNormVec # set the norm for the collision plane to be used in mouse1Dragging self.interFrameMousePosition = mPos3D self.currTransformOperation = transformOp self.isDragging = True taskMgr.add(self.handleDragging, 'mouse1Dragging') messenger.accept('mouse1-up', self, self.handleM1Up) def getMousePlaneIntersect(self, mPos3Dref, normVec): mPos = base.mouseWatcherNode.getMouse() plane = Plane(normVec, self.grabModelNP.getPos()) nearPoint = Point3() farPoint = Point3() base.camLens.extrude(mPos, nearPoint, farPoint) if plane.intersectsLine(mPos3Dref, render.getRelativePoint(camera, nearPoint), render.getRelativePoint(camera, farPoint)): return True return False def destroy(self): raise NotImplementedError('Make sure messenger etc are cleared of refs and the model node is deleted') self.grabModelNP.clearPythonTag('grabberRoot') self.grabModelNP.clearPythonTag('grabber') self.grabModelNP = None messenger.ignoreAll(self)
def printHeading(self): notify = DirectNotify().newCategory("") notify.warning(self.__heading)
def command(self): if (self.__commanding == True): notify = DirectNotify().newCategory("") notify.warning("You are already commanding a drone") exit() self.__commanding = True
class PlaneView(FSM, DirectObject): """Give this class a plane as argument and it will create some nodes around it which you can parent the camera to (if there are no such nodes yet). Usage: plane_camera = PlaneCamera(aeroplane, camera) plane_camera.setView("ThirdPerson") plane_camera.setView("Next") """ def __init__(self, camera, parent): """Arguments: camera -- Camera to be used parent -- Aeroplane which the camera should follow """ self.notifier = DirectNotify().newCategory("azure-camera") self.camera = camera self.parent = parent # This gets replaced by a NodePath with all available cameras as # children and plane node as parent in createCamNodes() self.cameras = None #if parent.__class__.__name__ is not "Aeroplane": if not isinstance(self.parent, Aeroplane): raise ParamError, "Parent must be an Aeroplane instance, " + \ "but is %s" % type(self.parent) FSM.__init__(self, "PlaneCamera: %s" % self.parent.name) DirectObject.__init__(self) self.cameras = self.parent.node.find("cameras") if self.cameras.isEmpty(): self.createCamNodes() self.updateCamArray() self.sideview_direction = 0 # Set up the default camera self.setView("ThirdPerson") def createCamNodes(self): """Creates a few empty nodes around a plane which the camera might be parented to. It looks if there are cameras inside the model file and uses those if possible. Where everything named "camera CamType" is considered a camera. At least ThirdPerson, FirstPerson and Cockpit should be defined inside the egg file, otherwise some guessed defaults are taken. """ # Look for cameras inside the model (loaded egg file) self.cameras = NodePath("cameras") found_cams = self.parent.node.findAllMatches("**/camera ?*") found_cams.removeDuplicatePaths() found_cams.reparentTo(self.cameras) if not found_cams.isEmpty(): self.notifier.info("Cameras found under model:\n%s" % found_cams) else: self.notifier.info("No cameras found under model.") # FirstPerson camera is a must-have. Set up a guessed one if none # defined yet. if self.cameras.find("camera FirstPerson").isEmpty(): assert self.notifier.debug("No first person camera found in %s. " "Guessing best position." % self.parent.name) first_person = NodePath("camera FirstPerson") # TODO: Guess best position based on bounding box. first_person.setY(5) first_person.reparentTo(cameras) # ThirdPerson camera is a must-have. Set up a guessed one if none # defined yet. if self.cameras.find("camera ThirdPerson").isEmpty(): assert self.notifier.debug("No third person camera found in %s. " "Guessing best position." % self.parent.name) third_person = NodePath("camera ThirdPerson") # TODO: Guess best position based on bounding box. third_person.setPos(0, -30, 5) #third_person.setP(-80) third_person.reparentTo(cameras) # Cockpit needs to be accurate. Don't try to guess it. if self.cameras.find("camera Cockpit").isEmpty(): assert self.notifier.debug("No cockpit camera found in " "%s. Cockpit camera disabled." % self.parent.name) self.sideview_cam = NodePath("camera Sideview") self.sideview_cam.reparentTo(render) # Store the cams at parent node.. # You can edit the camera nodes from outside as well. # If you attach new camera nodes, though, you'll have to call this # function again. self.cameras.reparentTo(self.parent.node) def updateCamArray(self, cameramodes=None): """Set the cameras which next and previous will switch to. Expects a list or tuple. Defaults to all available cameras.""" a = [] if not cameramodes: for c in self.cameras.getChildren(): if c.getName().startswith("camera "): a.append(c.getName().strip("camera ")) self.setStateArray(a) else: self.setStateArray(cameramodes) def getView(self): """Returns the current view mode.""" return self.getCurrentOrNextState() def setView(self, mode, *args): """Convenience function.""" return self.request(mode, args) def defaultEnter(self, *args): """Executed by the FSM every time an undefined state is entered. Note: this function is called AFTER the responsible filter.""" assert self.notifier.debug("Changing state from %s to %s with args: %s." % (self.oldState, self.newState, args)) request = self.newState target_cam = self.cameras.find("camera " + request) if not target_cam.isEmpty(): try: self.camera.reparentTo(target_cam) self.camera.setPosHpr(0, 0, 0, 0, 0, 0) except: self.notifier.warning( "Ok, now this really shouldn't happen! Filter said the " "camera is there and enter can't find it...") def defaultFilter(self, request, args): """Executed by the FSM every time an undefined state is requested.""" assert self.notifier.debug("Requested %s with args: %s" % (request, args)) self.camera.setPosHpr(0, 0, 0, 0, 0, 0) # Always available. if request == "Off": # implemented in FSM.py return (request,) + args if request == "Next": # implemented in FSM.py return self.requestNext(args) if request == "Prev": # implemented in FSM.py return self.requestPrev(args) if request == "Detached": return (request,) + args if request == "Sideview": return (request,) + args # Depending on airplane. if not self.cameras.find("camera " + request).isEmpty(): return (request,) + args assert self.notifier.info("Sorry, no %s camera found." % request) return None def enterOff(self, *args): """Clean up everything by reparenting the camera to the airplane.""" self.camera.reparentTo(self.parent.node) self.camera.setPosHpr(0, 0, 0, 0, 0, 0) def enterSideview(self, *args): self.sideview_direction += 90 self.camera.reparentTo(self.sideview_cam) self.camera.setY(-30) self.sideview_cam.setH(self.sideview_direction) #self.addTask(self.updateSideview, "sideview camera", taskChain="world") self.task = self.updateSideview def exitSideview(self, *args): #self.removeTask("sideview camera") self.task = lambda x: Task.cont def updateSideview(self, task): self.sideview_cam.setPos(self.parent.node.getPos()) return Task.cont def enterDetached(self, *args): """Lets the camera view the plane from far away.""" self.camera.reparentTo(render) self.camera.setPosHpr(0, 0, 10, 0, 0, 0) #self.addTask(self.updateDetachedCam, "detached camera", # taskChain="world") self.task = self.updateDetachedCam def exitDetached(self, *args): #self.removeTask("detached camera") self.task = lambda x: Task.cont def updateDetachedCam(self, task): """Updates camera position and rotation for Detached camera.""" try: self.camera.lookAt(self.parent.node) except: self.notifier.warning("Error on detached cam task. Exit.") return Task.done return Task.cont def enterThirdPerson(self, *args): """Lets the camera view the plane from far away.""" self._hist = [] self.camera.reparentTo(self.cameras.find("camera ThirdPerson")) self.cameras.find("camera ThirdPerson").setPos(0, -30, 0) #self.addTask(self.updateThirdPersonCam, "third person camera", # taskChain="world") self.task = self.updateThirdPersonCam #print "entering third person" def exitThirdPerson(self, *args): #self.removeTask("third person camera") self.task = lambda x: Task.cont del self._hist def updateThirdPersonCam(self, task): """Updates camera position and rotation for ThirdPerson camera.""" speed = self.parent.physics.speed() velocity = self.parent.physics.velocity() #v = Point3(self.parent.physics.angVelVector()) v = Point3(self.parent.physics.angVelBodyHpr()) print round(v.getX(), 2), round(v.getY(), 2), round(v.getZ(), 2) #self.segs = LineSegs("lines"); #self.segs.setColor(1,1,1,1) #self.segs.drawTo(-1, 0) #self.segsnode = self.segs.create() #render2d.attachNewNode(self.segsnode) vec = Point3(self.parent.physics.angVelBodyHpr()) # Y hiervon ist pitch, Z ist roll #print round(vec.getY(), 2), round(vec.getZ(), 2) self.camera.lookAt(self.parent.node) self.camera.setR(self.camera, vec.getZ()*3) #self.camera.setPos(abs(v.getX()), 0, vec.getY()) #plane = self.parent.node #self._hist.insert(0, [task.time, camera.getPos(plane)]) #while len(self._hist) > 50: # self._hist.pop() # #for snapshot in self._hist: # if snapshot[0] > task.time: # break #time_delta = snapshot[0] - task.time #self.camera.setPos(plane, snapshot[1]) #print snapshot #self.camera.setPos(render, snapshot[1]) #self.camera.lookAt(plane, (0, 20+1*speed, 0)) #self.camera.setY(5+0.1*speed) #self.camera.setZ(5-0.1*speed) return Task.cont def update(self, task): return self.task(task) def destroy(self): self.removeAllTasks() self.demand("Off")