예제 #1
0
 def line_model(self, r, g, b):
     line = LineNodePath(self.render2d, 'box', 2)
     line.reparentTo(self.render)
     line.setColor(r, g, b, 1.)
     line.setTransparency(TransparencyAttrib.MAlpha)
     line.setAlphaScale(0.5)
     return line
예제 #2
0
def draw_lines(lines: LineNodePath, *paths: dict, origin=None, relative=True):
    if origin is None:
        origin = lines.getCurrentPosition()
    lines.reset()
    for path in paths:
        if 'color' in path:
            lines.setColor(*path['color'])
        points = path['points']
        lines.moveTo(*origin)
        for point in points:
            if relative:
                point += origin
            lines.drawTo(*point)
    lines.create()
예제 #3
0
class NodeConnector:
    def __init__(self, socketA, socketB):
        self.connectorID = uuid4()
        self.socketA = socketA
        self.socketB = socketB
        self.line = LineNodePath(ShowBaseGlobal.aspect2d,
                                 thickness=2,
                                 colorVec=(0.8, 0.8, 0.8, 1))
        self.draw()

        self.show = self.line.show
        self.hide = self.line.hide

    def update(self):
        self.line.reset()
        self.draw()

    def draw(self):
        self.line.moveTo(self.socketA.plug.getPos(ShowBaseGlobal.aspect2d))
        self.line.drawTo(self.socketB.plug.getPos(ShowBaseGlobal.aspect2d))
        self.line.create()

    def has(self, socket):
        """Returns True if one of the sockets this connector connects is
        the given socket"""
        return socket == self.socketA or socket == self.socketB

    def connects(self, a, b):
        """Returns True if this connector connects socket a and b"""
        return (a == self.socketA or a
                == self.socketB) and (b == self.socketA or b == self.socketB)

    def disconnect(self):
        self.line.reset()
        self.socketA.setConnected(False)
        self.socketB.setConnected(False)

    def setChecked(self):
        self.line.setColor(0, 1, 0, 1)
        self.update()

    def setError(self, hasError):
        self.line.setColor(1, 0, 0, 1)
        self.update()

    def __str__(self):
        return f"Connection {self.socketA.name} to {self.socketB.name}"
예제 #4
0
class Fisherman(Toon.Toon):
    numFishTypes = 3

    def __init__(self, id, toNpcId=20001, fAutonomous=1):
        # Default NPC ID is Flippy
        Toon.Toon.__init__(self)
        self.id = id
        self.fAutonomous = fAutonomous
        npcInfo = NPCToons.NPCToonDict[toNpcId]
        dnaList = npcInfo[2]
        gender = npcInfo[3]
        dna = ToonDNA.ToonDNA()
        dna.newToonFromProperties(*dnaList)
        self.setDNA(dna)
        self.reparentTo(render)
        self.angleNP = self.find('**/actorGeom')
        # Create pole
        self.pole = Actor.Actor()
        self.pole.loadModel('phase_4/models/props/fishing-pole-mod')
        self.pole.loadAnims({'cast': 'phase_4/models/props/fishing-pole-chan'})
        # Get the top of the pole.
        self.ptop = self.pole.find('**/joint_attachBill')
        self.pole.pose('cast', 0)
        # Prepare Pole
        self.poleNode = []
        self.holdPole()
        self.createCastTrack()
        self.castIval = None
        # Prepare actor
        self.setupNeutralBlend()
        self.targetInterval = None
        # Start automatic casting or create cast button
        if self.fAutonomous:
            self.castButton = None
            self.targetButton = None
            self.startCasting()
        else:
            # Starts casting mode when mouse enters button region
            self.castButton = DirectButton(text='CAST',
                                           relief=None,
                                           scale=0.1,
                                           pos=(0, 0, -0.2))
            self.castButton.bind(DGG.ENTER, self.showCancelFrame)
            # A big screen encompassing frame to catch the button releases
            self.cancelFrame = DirectFrame(parent=self.castButton,
                                           frameSize=(-1, 1, -1, 1),
                                           relief=None,
                                           state='normal')
            # Make sure this is on top of all the other widgets
            self.cancelFrame.setBin('gui-popup', 0)
            self.cancelFrame.bind(DGG.B1PRESS, self.startAdjustingCastTask)
            self.cancelFrame.bind(DGG.B1RELEASE, self.finishCast)
            self.cancelFrame.hide()
            # Create bob
            self.bob = loader.loadModel('phase_4/models/props/fishing_bob')
            self.bobSpot = Point3(0)
            # Parameters to control bob motion
            self.vZeroMax = 30.0
            self.angleMax = 30.0
            # Ripple effect
            self.ripples = Ripples.Ripples(self.angleNP)
            self.ripples.hide()
            # Target
            self.buttonFrame = DirectFrame()
            self.target = base.distributedFishingTarget.fishingTargetNode

            self.fishPivot = self.attachNewNode('fishPivot')
            self.fish = loader.loadModel('models/misc/smiley')
            self.fish.reparentTo(self.fishPivot)
            self.fish.setScale(0.3, 1, 0.3)
            self.wiggleIval = None
            self.circleIval = None
            self.initFish()

            self.targetButton = DirectButton(parent=self.buttonFrame,
                                             text='MOVE',
                                             relief=DGG.RAISED,
                                             scale=0.1,
                                             pos=(0, 0, -0.9),
                                             command=self.moveTarget)
            self.targetTypeButton = DirectCheckButton(parent=self.buttonFrame,
                                                      text='MOVING',
                                                      relief=DGG.RAISED,
                                                      scale=0.085,
                                                      pos=(0.4, 0, -0.895),
                                                      command=self.setfMove)
            self.fMovingTarget = 0
            self.targetModeButton = DirectCheckButton(
                parent=self.buttonFrame,
                text='dTASK',
                relief=DGG.RAISED,
                scale=0.085,
                pos=(0.8, 0, -0.895),
                command=self.setfTargetMode)
            self.fTargetMode = 0
            # Vector line
            self.line = LineNodePath(render2d)
            self.line.setColor(VBase4(1, 0, 0, 1))
            self.line.moveTo(0, 0, 0)
            self.line.drawTo(1, 0, 0)
            self.line.create()
            self.moveTarget()

    def showCancelFrame(self, event):
        # Also display cancel frame to catch clicks outside of the popup
        self.cancelFrame.show()

    def startAdjustingCastTask(self, event):
        # Start task to adjust power of cast
        self.getMouse()
        self.initMouseX = self.mouseX
        self.initMouseY = self.mouseY
        self.initMouseX = 0
        self.initMouseY = -0.2
        self.line.lineSegs.setVertex(0, self.initMouseX, 0, self.initMouseY)
        self.angleNP.setH(0)
        self.__hideBob()
        taskMgr.remove('distCheck')
        # Position and scale cancel frame to fill entire window
        self.cancelFrame.setPos(render2d, 0, 0, 0)
        self.cancelFrame.setScale(render2d, 1, 1, 1)
        self.castTrack.finish()
        self.castTrack.setT(0)
        self.castTrack.start(startT=0, endT=0.4)
        self.castIval = Sequence(
            Wait(0.4),
            Func(taskMgr.add, self.adjustingCastTask, 'adjustCastTask'))
        self.castIval.start()

    def adjustingCastTask(self, state):
        self.getMouse()
        deltaX = self.mouseX - self.initMouseX
        deltaY = self.mouseY - self.initMouseY
        self.line.lineSegs.setVertex(1, self.mouseX, 0, self.mouseY)
        dist = math.sqrt(deltaX * deltaX + deltaY * deltaY)
        delta = (dist / 0.5)
        if deltaY > 0:
            delta *= -1
        p = max(min(delta, 1.0), 0.0)
        self.power = p
        self.castTrack.setT(0.4 + p * 0.5)
        self.bobSpot = Point3(0, 6.5 + p * 25.0, -1.9)
        # Calc angle
        if deltaY == 0:
            angle = 0
        else:
            angle = rad2Deg(math.atan(deltaX / deltaY))
        self.angleNP.setH(-angle)
        return Task.cont

    def stopAdjustingCastTask(self):
        taskMgr.remove('adjustingTask')

    def setupNeutralBlend(self):
        self.stop()
        self.loop('neutral')
        self.enableBlend()
        self.pose('cast', 0)
        self.setControlEffect('neutral', 0.2)
        self.setControlEffect('cast', 0.8)

    def startCasting(self):
        if self.fAutonomous:
            self.castIval = Sequence(
                ActorInterval(self, 'cast'), Func(self.catchFish),
                Parallel(
                    ActorInterval(self, 'neutral', loop=1, duration=100),
                    Sequence(
                        Wait(random.random() * 20.0),
                        Func(self.startCasting),
                    )))
        else:
            self.castIval = Sequence(
                ActorInterval(self, 'cast'), Func(self.catchFish),
                ActorInterval(self, 'neutral', loop=1, duration=100))
        self.castIval.play()

    def stopCasting(self):
        if self.castIval:
            self.castIval.pause()
        if self.targetInterval:
            self.stopTargetInterval()
        taskMgr.remove('distCheck')

    def catchFish(self):
        fishNum = int(round(random.random() * self.numFishTypes))
        messenger.send('caughtFish', sentArgs=[self.id, fishNum])

    def setupNeutralBlend(self):
        self.stop()
        self.loop('neutral')
        self.enableBlend()
        self.pose('cast', 0)
        self.setControlEffect('neutral', 0.2)
        self.setControlEffect('cast', 0.8)

    def getPole(self):
        toonTrack = Sequence(
            # Blend in neutral anim
            Func(self.setupNeutralBlend),
            # Pull out pole
            Func(self.holdPole),
            Parallel(
                ActorInterval(self, 'cast', playRate=0.5, duration=27. / 12.),
                ActorInterval(self.pole,
                              'cast',
                              playRate=0.5,
                              duration=27. / 12.),
                LerpScaleInterval(self.pole,
                                  duration=2.0,
                                  scale=1.0,
                                  startScale=0.01)),
        )
        toonTrack.play()

    def putAwayPole(self):
        Sequence(
            Parallel(
                ActorInterval(self,
                              'cast',
                              duration=1.0,
                              startTime=1.0,
                              endTime=0.0),
                ActorInterval(self.pole,
                              'cast',
                              duration=1.0,
                              startTime=1.0,
                              endTime=0.0),
                LerpScaleInterval(self.pole,
                                  duration=0.5,
                                  scale=0.01,
                                  startScale=1.0)),
            Func(self.dropPole)).start()

    def holdPole(self):
        if self.poleNode != []:
            self.dropPole()

        # One node, instanced to each of the toon's three right hands,
        # will hold the pole.
        np = NodePath('pole-holder')
        hands = self.getRightHands()
        for h in hands:
            self.poleNode.append(np.instanceTo(h))

        self.pole.reparentTo(self.poleNode[0])

    def dropPole(self):
        self.__hideBob()
        #self.__hideLine()
        if self.pole != None:
            self.pole.clearMat()
            self.pole.detachNode()

        for pn in self.poleNode:
            pn.removeNode()
        self.poleNode = []

    def createCastTrack(self):
        self.castTrack = Sequence(
            Parallel(
                ActorInterval(self, 'cast', duration=2.0, startTime=1.0),
                ActorInterval(self.pole, 'cast', duration=2.0, startTime=1.0),
            ))

    def cast(self):
        self.castTrack.start()

    def finishCast(self, event=None):
        #self.line.lineSegs.setVertex(1,self.initMouseX,0,self.initMouseY)
        self.cancelFrame.hide()
        if not self.castTrack:
            self.createCastTrack()
        self.castIval.finish()
        taskMgr.remove('adjustCastTask')
        taskMgr.remove('moveBobTask')
        self.castTrack.pause()
        #self.castTrack.start(self.castTrack.getT())
        p = self.power
        startT = 0.9 + (1 - p) * 0.3
        self.castTrack.start(startT)
        self.bobStartPos = Point3(0.017568, 7.90371, 6.489)
        Sequence(Wait(1.2 - startT), Func(self.startMoveBobTask)).start()

    def startMoveBobTask(self):
        self.__showBob()
        self.bobStartT = globalClock.getFrameTime()
        taskMgr.add(self.moveBobTask, 'moveBobTask')

    def moveBobTask(self, state):
        # Accel due to gravity
        g = 32.2
        # Elapsed time of cast
        t = globalClock.getFrameTime() - self.bobStartT
        # Scale bob velocity and angle based on power of cast
        vZero = self.power * self.vZeroMax
        angle = deg2Rad(self.power * self.angleMax)
        # How far has bob moved from start point?
        deltaY = vZero * math.cos(angle) * t
        deltaZ = vZero * math.sin(angle) * t - (g * t * t) / 2.0
        deltaPos = Point3(0, deltaY, deltaZ)
        # Current bob position
        pos = self.bobStartPos + deltaPos
        # Have we reached end condition?
        if pos[2] < -1.9:
            pos.setZ(-1.9)
            self.ripples.reparentTo(self.angleNP)
            self.ripples.setPos(pos)
            self.ripples.play()
            returnVal = Task.done
            if self.fTargetMode:
                taskMgr.add(self.distCheck, 'distCheck')
            else:
                self.distCheck()
        else:
            returnVal = Task.cont
        self.bob.setPos(pos)
        return returnVal

    def distCheck(self, state=None):
        # Check to see if we hit the target
        bPos = self.bob.getPos()
        # Check target
        returnVal = self.__distCheck(bPos, self.target)
        if returnVal == Task.done:
            return returnVal
        # Check fish
        return self.__distCheck(bPos, self.fish)

    def __distCheck(self, bPos, target):
        def flashTarget():
            self.stopTargetInterval()
            self.target.getChild(0).setColor(0, 0, 1)

        def flashFish():
            taskMgr.remove('turnTask')
            self.fish.lerpScale(Point3(0.01), 0.5, task='flashFish')

        tPos = target.getPos(self.angleNP)
        tDist = Vec3(tPos - bPos)
        tDist.setZ(0)
        dist = tDist.length()
        if target == self.target:
            flashFunc = flashTarget
            moveFunc = self.moveTarget
        else:
            flashFunc = flashFish
            moveFunc = self.turnFish
        if dist < 2.5:
            fBite = (random.random() < 0.4) or (not self.fTargetMode)
            delay = self.fTargetMode * 0.25
            if fBite:
                print('BITE')
                Sequence(
                    Wait(random.random() * delay),
                    Func(flashFunc),
                    Func(self.catchFish),
                    Wait(2.0),
                    Func(moveFunc),
                ).play()
            else:
                print('MISS')

                def moveIt():
                    moveFunc(targetPos=target.getPos())

                Sequence(Wait(random.random() * delay), Func(moveIt)).play()
            return Task.done
        return Task.cont

    def stopTargetInterval(self):
        if self.targetInterval:
            self.targetInterval.pause()
        self.targetInterval = None

    def __showBob(self):
        # Put the bob in the water and make it gently float.
        self.__hideBob()
        self.bob.reparentTo(self.angleNP)
        self.bob.setPos(self.ptop, 0, 0, 0)

    def __hideBob(self):
        if self.bob != None:
            self.bob.detachNode()

    def getMouse(self):
        if (base.mouseWatcherNode.hasMouse()):
            self.mouseX = base.mouseWatcherNode.getMouseX()
            self.mouseY = base.mouseWatcherNode.getMouseY()
        else:
            self.mouseX = 0
            self.mouseY = 0

    def setfMove(self, fMoving):
        self.fMovingTarget = fMoving

    def setfTargetMode(self, fTargetMode):
        self.fTargetMode = fTargetMode

    def moveTarget(self, targetPos=None):
        base.distributedFishingTarget.sendUpdate('bobEnter', [])


#        self.stopTargetInterval()
#        self.target.clearColor()
#        if not targetPos:
#            x = -87.0 + random.random() * 15.0
#            y = 25.0 + random.random() * 20.0
#            z = -4.8
#            self.targetPos = Point3(x,y,z)
#        else:
#            self.targetPos.assign(targetPos)
#        if self.fMovingTarget:
#            self.makeTargetInterval()
#        else:
#            #self.target.setPos(self.targetPos)

    def initFish(self):
        x = -10.0 + random.random() * 20.0
        y = 00.0 + random.random() * 30.0
        z = -1.6
        self.fishPivot.setPos(x, y, z)
        self.turningRadius = 5.0 + random.random() * 5.0
        self.fish.setPos(self.turningRadius, 0, -0.4)
        if self.wiggleIval:
            self.wiggleIval.pause()
        self.wiggleIval = Sequence(
            self.fish.hprInterval(0.5,
                                  hpr=Point3(10, 0, 0),
                                  startHpr=Point3(-10, 0, 0),
                                  blendType='easeInOut'),
            self.fish.hprInterval(0.5,
                                  hpr=Point3(-10, 0, 0),
                                  startHpr=Point3(10, 0, 0),
                                  blendType='easeInOut'))
        self.wiggleIval.loop()
        if self.circleIval:
            self.circleIval.pause()
        self.circleIval = self.fishPivot.hprInterval(20,
                                                     Point3(360, 0, 0),
                                                     startHpr=Point3(0))
        self.circleIval.loop()
        taskMgr.remove('turnTask')
        taskMgr.doMethodLater(3.0 + random.random() * 3.0, self.turnFish,
                              'turnTask')
        taskMgr.remove('fishBoundsCheck')
        taskMgr.add(self.fishBoundsCheck, 'fishBoundsCheck')

    def fishBoundsCheck(self, state):
        pos = self.fish.getPos(self)
        if pos[0] < -20:
            self.fishPivot.setX(self.fishPivot.getX() + 40.0)
        elif pos[0] > 20:
            self.fishPivot.setX(self.fishPivot.getX() - 40.0)
        if pos[1] < -10:
            self.fishPivot.setY(self.fishPivot.getY() + 50.0)
        elif pos[1] > 40:
            self.fishPivot.setY(self.fishPivot.getY() - 50.0)
        return Task.cont

    def turnFish(self, state=None, targetPos=None):
        self.fish.setScale(0.3, 1, 0.3)
        if self.circleIval:
            self.circleIval.pause()
        newTurningRadius = 5.0 + random.random() * 5.0
        fRightTurn = random.random() < 0.5
        if fRightTurn:
            newTurningRadius *= -1.0
        offset = self.turningRadius - newTurningRadius
        self.fishPivot.setX(self.fishPivot, offset)
        self.turningRadius = newTurningRadius
        self.fish.setX(self.turningRadius)
        currH = self.fishPivot.getH() % 360.0
        if fRightTurn:
            self.circleIval = self.fishPivot.hprInterval(
                20, Point3(currH - 360, 0, 0), startHpr=Point3(currH, 0, 0))
        else:
            self.circleIval = self.fishPivot.hprInterval(
                20, Point3(currH + 360, 0, 0), startHpr=Point3(currH, 0, 0))
        self.circleIval.loop()
        taskMgr.doMethodLater(3.0 + random.random() * 3.0, self.turnFish,
                              'turnTask')
        return Task.done

    def makeTargetInterval(self):
        x = -10.0 + random.random() * 20.0
        y = 0.0 + random.random() * 30.0
        z = -1.6
        self.targetEndPos = Point3(x, y, z)
        dist = Vec3(self.targetEndPos - self.targetPos).length()
        dur = dist / 1.5
        dur = dur * (0.75 + random.random() * 0.5)
        self.targetInterval = Sequence(
            self.target.posInterval(dur,
                                    self.targetEndPos,
                                    startPos=self.targetPos,
                                    blendType='easeInOut'),
            self.target.posInterval(dur,
                                    self.targetPos,
                                    startPos=self.targetEndPos,
                                    blendType='easeInOut'),
            name='moveInterval')
        offsetDur = dur / random.randint(1, 4)
        amplitude = 0.1 + random.random() * 1.0
        self.targetInterval.loop()

    def destroy(self):
        if not self.fAutonomous:
            self.castButton.destroy()
            self.buttonFrame.destroy()
            self.line.removeNode()
            taskMgr.remove('turnTask')
            taskMgr.remove('fishBoundsCheck')
        self.stopCasting()
        self.removeNode()
예제 #5
0
class DirectGrid(NodePath, DirectObject):
    def __init__(self,
                 parent,
                 gridSize=100.0,
                 gridSpacing=5.0,
                 planeColor=(0.5, 0.5, 0.5, 0.5)):
        # Initialize superclass
        NodePath.__init__(self)
        self.assign(hidden.attachNewNode('DirectGrid'))
        # Don't wireframe or light
        #useDirectRenderStyle(self)
        self.setLightOff(0)
        self.setRenderModeFilled()
        self.parent = parent

        # Load up grid parts to initialize grid object
        # Polygon used to mark grid plane
        self.gridBack = loader.loadModel('models/misc/gridBack.egg.pz')
        self.gridBack.reparentTo(self)
        self.gridBack.setColor(*planeColor)

        # Grid Lines
        self.lines = self.attachNewNode('gridLines')
        self.minorLines = LineNodePath(self.lines)
        self.minorLines.lineNode.setName('minorLines')
        self.minorLines.setColor(VBase4(0.3, 0.55, 1, 1))
        self.minorLines.setThickness(1)

        self.majorLines = LineNodePath(self.lines)
        self.majorLines.lineNode.setName('majorLines')
        self.majorLines.setColor(VBase4(0.3, 0.55, 1, 1))
        self.majorLines.setThickness(5)

        self.centerLines = LineNodePath(self.lines)
        self.centerLines.lineNode.setName('centerLines')
        self.centerLines.setColor(VBase4(1, 0, 0, 0))
        self.centerLines.setThickness(3)

        # Small marker to hilight snap-to-grid point
        self.snapMarker = loader.loadModel('models/misc/sphere.egg.pz')
        self.snapMarker.node().setName('gridSnapMarker')
        self.snapMarker.reparentTo(self)
        self.snapMarker.setColor(1, 0, 0, 1)
        self.snapMarker.setScale(0.3)
        self.snapPos = Point3(0)

        # Initialize Grid characteristics
        self.fXyzSnap = 1
        self.fHprSnap = 1
        self.gridSize = gridSize
        self.gridSpacing = gridSpacing
        self.snapAngle = 15.0
        self.enable()

    def enable(self):
        self.reparentTo(self.parent)
        self.updateGrid()
        self.fEnabled = 1

    def disable(self):
        self.reparentTo(hidden)
        self.fEnabled = 0

    def toggleGrid(self):
        if self.fEnabled:
            self.disable()
        else:
            self.enable()

    def isEnabled(self):
        return self.fEnabled

    def updateGrid(self):
        # Update grid lines based upon current grid spacing and grid size
        # First reset existing grid lines
        self.minorLines.reset()
        self.majorLines.reset()
        self.centerLines.reset()

        # Now redraw lines
        numLines = int(math.ceil(self.gridSize / self.gridSpacing))
        scaledSize = numLines * self.gridSpacing

        center = self.centerLines
        minor = self.minorLines
        major = self.majorLines
        for i in range(-numLines, numLines + 1):
            if i == 0:
                center.moveTo(i * self.gridSpacing, -scaledSize, 0)
                center.drawTo(i * self.gridSpacing, scaledSize, 0)
                center.moveTo(-scaledSize, i * self.gridSpacing, 0)
                center.drawTo(scaledSize, i * self.gridSpacing, 0)
            else:
                if (i % 5) == 0:
                    major.moveTo(i * self.gridSpacing, -scaledSize, 0)
                    major.drawTo(i * self.gridSpacing, scaledSize, 0)
                    major.moveTo(-scaledSize, i * self.gridSpacing, 0)
                    major.drawTo(scaledSize, i * self.gridSpacing, 0)
                else:
                    minor.moveTo(i * self.gridSpacing, -scaledSize, 0)
                    minor.drawTo(i * self.gridSpacing, scaledSize, 0)
                    minor.moveTo(-scaledSize, i * self.gridSpacing, 0)
                    minor.drawTo(scaledSize, i * self.gridSpacing, 0)

        center.create()
        minor.create()
        major.create()
        if (self.gridBack):
            self.gridBack.setScale(scaledSize)

    def setXyzSnap(self, fSnap):
        self.fXyzSnap = fSnap

    def getXyzSnap(self):
        return self.fXyzSnap

    def setHprSnap(self, fSnap):
        self.fHprSnap = fSnap

    def getHprSnap(self):
        return self.fHprSnap

    def computeSnapPoint(self, point):
        # Start of with current point
        self.snapPos.assign(point)
        # Snap if necessary
        if self.fXyzSnap:
            self.snapPos.set(ROUND_TO(self.snapPos[0], self.gridSpacing),
                             ROUND_TO(self.snapPos[1], self.gridSpacing),
                             ROUND_TO(self.snapPos[2], self.gridSpacing))

        # Move snap marker to this point
        self.snapMarker.setPos(self.snapPos)

        # Return the hit point
        return self.snapPos

    def computeSnapAngle(self, angle):
        return ROUND_TO(angle, self.snapAngle)

    def setSnapAngle(self, angle):
        self.snapAngle = angle

    def getSnapAngle(self):
        return self.snapAngle

    def setGridSpacing(self, spacing):
        self.gridSpacing = spacing
        self.updateGrid()

    def getGridSpacing(self):
        return self.gridSpacing

    def setGridSize(self, size):
        # Set size of grid back and redraw lines
        self.gridSize = size
        self.updateGrid()

    def getGridSize(self):
        return self.gridSize
예제 #6
0
class DirectGrid(NodePath, DirectObject):
    def __init__(self,parent,gridSize=100.0,gridSpacing=5.0,planeColor=(0.5,0.5,0.5,0.5)):
        # Initialize superclass
        NodePath.__init__(self)
        self.assign(hidden.attachNewNode('DirectGrid'))
        # Don't wireframe or light
        #useDirectRenderStyle(self)
        self.setLightOff(0)
        self.setRenderModeFilled()
        self.parent = parent

        # Load up grid parts to initialize grid object
        # Polygon used to mark grid plane
        self.gridBack = loader.loadModel('models/misc/gridBack.egg.pz')
        self.gridBack.reparentTo(self)
        self.gridBack.setColor(*planeColor)

        # Grid Lines
        self.lines = self.attachNewNode('gridLines')
        self.minorLines = LineNodePath(self.lines)
        self.minorLines.lineNode.setName('minorLines')
        self.minorLines.setColor(VBase4(0.3, 0.55, 1, 1))
        self.minorLines.setThickness(1)

        self.majorLines = LineNodePath(self.lines)
        self.majorLines.lineNode.setName('majorLines')
        self.majorLines.setColor(VBase4(0.3, 0.55, 1, 1))
        self.majorLines.setThickness(5)

        self.centerLines = LineNodePath(self.lines)
        self.centerLines.lineNode.setName('centerLines')
        self.centerLines.setColor(VBase4(1, 0, 0, 0))
        self.centerLines.setThickness(3)

        # Small marker to hilight snap-to-grid point
        self.snapMarker = loader.loadModel('models/misc/sphere.egg.pz')
        self.snapMarker.node().setName('gridSnapMarker')
        self.snapMarker.reparentTo(self)
        self.snapMarker.setColor(1, 0, 0, 1)
        self.snapMarker.setScale(0.3)
        self.snapPos = Point3(0)

        # Initialize Grid characteristics
        self.fXyzSnap = 1
        self.fHprSnap = 1
        self.gridSize = gridSize
        self.gridSpacing = gridSpacing
        self.snapAngle = 15.0
        self.enable()

    def enable(self):
        self.reparentTo(self.parent)
        self.updateGrid()
        self.fEnabled = 1

    def disable(self):
        self.reparentTo(hidden)
        self.fEnabled = 0

    def toggleGrid(self):
        if self.fEnabled:
            self.disable()
        else:
            self.enable()

    def isEnabled(self):
        return self.fEnabled

    def updateGrid(self):
        # Update grid lines based upon current grid spacing and grid size
        # First reset existing grid lines
        self.minorLines.reset()
        self.majorLines.reset()
        self.centerLines.reset()

        # Now redraw lines
        numLines = int(math.ceil(self.gridSize/self.gridSpacing))
        scaledSize = numLines * self.gridSpacing

        center = self.centerLines
        minor = self.minorLines
        major = self.majorLines
        for i in range(-numLines, numLines + 1):
            if i == 0:
                center.moveTo(i * self.gridSpacing, -scaledSize, 0)
                center.drawTo(i * self.gridSpacing, scaledSize, 0)
                center.moveTo(-scaledSize, i * self.gridSpacing, 0)
                center.drawTo(scaledSize, i * self.gridSpacing, 0)
            else:
                if (i % 5) == 0:
                    major.moveTo(i * self.gridSpacing, -scaledSize, 0)
                    major.drawTo(i * self.gridSpacing, scaledSize, 0)
                    major.moveTo(-scaledSize, i * self.gridSpacing, 0)
                    major.drawTo(scaledSize, i * self.gridSpacing, 0)
                else:
                    minor.moveTo(i * self.gridSpacing, -scaledSize, 0)
                    minor.drawTo(i * self.gridSpacing, scaledSize, 0)
                    minor.moveTo(-scaledSize, i * self.gridSpacing, 0)
                    minor.drawTo(scaledSize, i * self.gridSpacing, 0)

        center.create()
        minor.create()
        major.create()
        if (self.gridBack):
            self.gridBack.setScale(scaledSize)

    def setXyzSnap(self, fSnap):
        self.fXyzSnap = fSnap

    def getXyzSnap(self):
        return self.fXyzSnap

    def setHprSnap(self, fSnap):
        self.fHprSnap = fSnap

    def getHprSnap(self):
        return self.fHprSnap

    def computeSnapPoint(self, point):
        # Start of with current point
        self.snapPos.assign(point)
        # Snap if necessary
        if self.fXyzSnap:
            self.snapPos.set(
                ROUND_TO(self.snapPos[0], self.gridSpacing),
                ROUND_TO(self.snapPos[1], self.gridSpacing),
                ROUND_TO(self.snapPos[2], self.gridSpacing))

        # Move snap marker to this point
        self.snapMarker.setPos(self.snapPos)

        # Return the hit point
        return self.snapPos

    def computeSnapAngle(self, angle):
        return ROUND_TO(angle, self.snapAngle)

    def setSnapAngle(self, angle):
        self.snapAngle = angle

    def getSnapAngle(self):
        return self.snapAngle

    def setGridSpacing(self, spacing):
        self.gridSpacing = spacing
        self.updateGrid()

    def getGridSpacing(self):
        return self.gridSpacing

    def setGridSize(self, size):
        # Set size of grid back and redraw lines
        self.gridSize = size
        self.updateGrid()

    def getGridSize(self):
        return self.gridSize
예제 #7
0
class World(ShowBase):

    fps_text = fps_text2 = fps_text3 = fps_text4 = None
    room_dimentions = [0, 0]
    camera_position = [290., 1609., 370, -1980, -15, 0]  # x y z h p r
    drone = None
    drone_instance = None
    markers = {}
    marker_lines = {}
    marker_lines_observed = {}
    active_keys = {}
    loop_callback = None
    joy = None
    simulation = True
    drone_started = False

    def __init__(self, width=6.78, length=5.82, simulation=True, video=True):
        ShowBase.__init__(self)

        width *= 100
        length *= 100
        self.room_dimentions = [width, length]
        self.simulation = simulation

        self.wall1 = self.wall_model(0, 0, 0, width, 0)
        self.wall2 = self.wall_model(0, 0, 0, length, 90)
        self.wall3 = self.wall_model(width, length, 0, width, 180)
        self.wall4 = self.wall_model(width, length, 0, length, -90)

        self.root_3d = self.marker_model(position=[0., 0., 0.],
                                         orientation=[90, 90, 0])

        self.drone = self.drone_model()
        self.drone_instance = Drone(simulation=simulation, video=video)

        self.lx_drone = LineNodePath(self.render2d, 'box', 2)
        self.lx_drone.reparentTo(self.drone)
        self.lx_drone.setColor(1., 0., 0., 1.)
        self.lx_drone.setTransparency(TransparencyAttrib.MAlpha)
        self.lx_drone.setAlphaScale(0.5)
        self.lx_drone.drawLines([[(0., 0., 0.), (4., 0., 0.)]])
        self.lx_drone.create()
        self.ly_drone = LineNodePath(self.render2d, 'box', 2)
        self.ly_drone.reparentTo(self.drone)
        self.ly_drone.setColor(0., 1., 0., 1.)
        self.ly_drone.setTransparency(TransparencyAttrib.MAlpha)
        self.ly_drone.setAlphaScale(0.5)
        self.ly_drone.drawLines([[(0., 0., 0.), (0., 0., 4.)]])
        self.ly_drone.create()
        self.lz_drone = LineNodePath(self.render2d, 'box', 2)
        self.lz_drone.reparentTo(self.drone)
        self.lz_drone.setColor(0., 0., 1., 1.)
        self.lz_drone.setTransparency(TransparencyAttrib.MAlpha)
        self.lz_drone.setAlphaScale(0.5)
        self.lz_drone.drawLines([[(0., 0., 0.), (0., 4., 0.)]])
        self.lz_drone.create()

        try:
            self.joy = xbox.Joystick()
            joy_ready = False
            if not self.joy.A():
                joy_ready = True
            if not joy_ready:
                raise Exception("Joy not ready!")
            else:
                print("ready")
        except:
            pass

        # Add the spinCameraTask procedure to the task manager.
        self.tick_loop = self.taskMgr.add(self.tick, "tick_loop")

        self.accept("space", self.control_drone, [" "])
        self.accept("c", self.control_drone, ["c"])
        self.accept("x", self.control_drone, ["x"])
        self.accept("w", self.control_drone, ["w"])
        self.accept("a", self.control_drone, ["a"])
        self.accept("s", self.control_drone, ["s"])
        self.accept("d", self.control_drone, ["d"])
        self.accept("q", self.control_drone, ["q"])
        self.accept("e", self.control_drone, ["e"])
        self.accept("m", self.control_drone, ["m"])
        self.accept("r", self.control_drone, ["r"])
        self.accept("f", self.control_drone, ["f"])
        self.keypress_repeat("4", self.move_camera, ["x", -1])
        self.keypress_repeat("6", self.move_camera, ["x", 1])
        self.keypress_repeat("8", self.move_camera, ["y", 1])
        self.keypress_repeat("5", self.move_camera, ["y", -1])
        self.keypress_repeat("1", self.move_camera, ["z", 1])
        self.keypress_repeat("3", self.move_camera, ["z", -1])
        self.keypress_repeat("7", self.move_camera, ["h", -1])
        self.keypress_repeat("9", self.move_camera, ["h", 1])
        self.keypress_repeat("arrow_up", self.move_camera, ["p", 1])
        self.keypress_repeat("arrow_down", self.move_camera, ["p", -1])

    def control_drone(self, key):
        if key == " ":
            if not self.drone_started:
                self.drone_started = True
                self.drone_instance.takeoff()
            else:
                self.drone_started = False
                self.drone_instance.land()
        if key == "x":
            self.drone_instance.emergency()
        elif key == "c":
            self.drone_instance.move(0., 0., 0., 0.)
        elif key == "w":
            self.drone_instance.move(0., 0.08, 0., 0.)
        elif key == "s":
            self.drone_instance.move(0., -0.08, 0., 0.)
        elif key == "d":
            self.drone_instance.move(0.08, 0., 0., 0.)
        elif key == "a":
            self.drone_instance.move(-0.08, 0., 0., 0.)
        elif key == "q":
            self.drone_instance.move(0., 0., 0., 0.3)
        elif key == "e":
            self.drone_instance.move(0., 0., 0., -0.3)
        elif key == "m":
            self.drone_instance.mtrim()
        elif key == "r":
            self.drone_instance.move(0., 0., 0.14, 0.)
        elif key == "f":
            self.drone_instance.move(0., 0., -0.15, 0.)

    def keypress_repeat(self, key, callback, parameter):
        self.accept(key, self.keypress_start, [key, callback, parameter])
        self.accept(key + "-up", self.keypress_stop, [key])

    def keypress_start(self, key, callback, parameter):
        self.active_keys[key] = [callback, parameter]

    def keypress_stop(self, key):
        self.active_keys[key] = None

    def move_camera(self, parameter):
        if parameter[0] == "x":
            self.camera_position[0] += 10 * np.cos(
                np.deg2rad(self.camera_position[3])) * parameter[1]
            self.camera_position[1] += -10 * np.sin(
                np.deg2rad(self.camera_position[3])) * parameter[1]
        if parameter[0] == "y":
            self.camera_position[0] += 10 * np.sin(
                np.deg2rad(self.camera_position[3])) * parameter[1]
            self.camera_position[1] += 10 * np.cos(
                np.deg2rad(self.camera_position[3])) * parameter[1]
        if parameter[0] == "z":
            self.camera_position[2] += 10 * parameter[1]
        if parameter[0] == "h":
            self.camera_position[3] += parameter[1]
        if parameter[0] == "p":
            self.camera_position[4] += parameter[1]

    def joy_block(self, xbox_key):
        """ blocks the xbox key until it's released """
        while xbox_key():
            pass

    def tick(self, task):

        for key in self.active_keys:
            if self.active_keys[key] is not None:
                self.active_keys[key][0](self.active_keys[key][1])

        if self.joy is not None:
            if self.joy.Back():
                self.closeWindow(self.win)
                self.userExit()
                self.shutdown()
                self.destroy()

            # takeoff:
            if self.joy.A():
                print "takeoff"
                self.drone_instance.takeoff()
                self.joy_block(self.joy.A)

            # emergency:
            if self.joy.X():
                print "emergency"
                self.drone_instance.emergency()
                self.joy_block(self.joy.X)

            # emergency:
            if self.joy.B():
                print "land"
                self.drone_instance.land()
                self.joy_block(self.joy.B)

            (roll, throttle) = self.joy.leftStick()
            (yaw, pitch) = self.joy.rightStick()
            print roll, pitch, throttle, yaw
            self.drone_instance.move(roll, pitch, throttle, yaw)

        if self.loop_callback is not None:
            self.loop_callback(self, task)

        self.camera.setPos(self.camera_position[0], self.camera_position[1],
                           self.camera_position[2])
        self.camera.setHpr(-self.camera_position[3], self.camera_position[4],
                           self.camera_position[5])

        drone_position = self.convert_position(
            self.drone_instance.get_position())
        drone_orientation = self.drone_instance.get_orientation()

        self.drone.setPos(drone_position[0], drone_position[1],
                          drone_position[2])
        self.drone.setHpr(drone_orientation[0], drone_orientation[1],
                          drone_orientation[2])

        if task.time > 0:
            if self.fps_text is not None:
                self.fps_text.destroy()
            self.fps_text = OnscreenText(text="Tick-Rate: " +
                                         str(int(task.frame / task.time)),
                                         pos=(0.05, 0.05),
                                         scale=0.05,
                                         align=TextNode.ALeft,
                                         parent=self.a2dBottomLeft)

            if self.fps_text2 is not None:
                self.fps_text2.destroy()
            self.fps_text2 = OnscreenText(text="Camera Position: " +
                                          str(self.camera_position),
                                          pos=(0.05, 0.1),
                                          scale=0.05,
                                          align=TextNode.ALeft,
                                          parent=self.a2dBottomLeft)

            if self.fps_text3 is not None:
                self.fps_text3.destroy()
            self.fps_text3 = OnscreenText(
                text="Drone Position: " +
                str(self.drone_instance.get_position()),
                pos=(0.05, 0.15),
                scale=0.05,
                align=TextNode.ALeft,
                parent=self.a2dBottomLeft)

        return Task.cont

    def drone_model(self):
        drone = self.loader.loadModel("resources/models_3d/drone")
        drone.setScale(15, 15, 10)
        drone.reparentTo(self.render)
        return drone

    def wall_model(self, x, y, z, length, orientation):
        wall = self.loader.loadModel("resources/models_3d/plane")
        wall.reparentTo(self.render)
        wall.setScale(length, 0, 290)
        wall.setPos(x, y, z)
        wall.setH(orientation)
        wall.setTransparency(TransparencyAttrib.MAlpha)
        wall.setAlphaScale(0.1)
        return wall

    def marker_model(self, position, orientation):
        marker = self.loader.loadModel("resources/models_3d/plane")
        marker.reparentTo(self.render)
        marker.setScale(21, 0, 21)
        marker.setPos(position[0], position[1], position[2])
        marker.setHpr(orientation[0], orientation[1], orientation[2])
        marker.setTransparency(TransparencyAttrib.MAlpha)
        marker.setAlphaScale(0.5)
        marker.setColor(1., 0., 0., 1.)
        return marker

    def line_model(self, r, g, b):
        line = LineNodePath(self.render2d, 'box', 2)
        line.reparentTo(self.render)
        line.setColor(r, g, b, 1.)
        line.setTransparency(TransparencyAttrib.MAlpha)
        line.setAlphaScale(0.5)
        return line

    def point_model(self, position, color):
        marker = self.loader.loadModel("resources/models_3d/sphere")
        marker.reparentTo(self.render)
        marker.setScale(5, 5, 5)
        marker.setPos(position[0], position[1], position[2])
        marker.setTransparency(TransparencyAttrib.MAlpha)
        marker.setAlphaScale(0.5)
        marker.setColor(color[0], color[1], color[2], 1.)

    def line_draw(self, line, from_position, to_position):
        line.reset()
        line.drawLines([[(from_position[0], from_position[1],
                          from_position[2]),
                         (to_position[0], to_position[1], to_position[2])]])
        line.create()

    def get_dimensions(self):
        return [self.room_dimentions[0] / 100., self.room_dimentions[1] / 100.]

    def get_drone(self):
        return self.drone_instance

    def set_markers(self, markers):
        self.markers = {}
        for key, marker in markers.iteritems():
            self.markers[key] = self.marker_model(
                self.convert_position(marker[0]), marker[1])

    def set_default_markers(self):
        dimensions = self.get_dimensions()

        self.set_markers({
            0: [[dimensions[0] / 2, 1.5, 0.01], [0, 0, 0]],
            1: [[dimensions[0] / 2, 1.5, dimensions[1] - 0.01], [0, 0, 0]],
            2: [[dimensions[0] - 0.01, 1.5, dimensions[1] / 2], [90, 0, 0]],
            3: [[0.01, 1.5, dimensions[1] / 2], [90, 0, 0]]
        })

    def get_markers(self):
        return self.markers

    def convert_position(self, position):
        return [position[0] * 100, position[2] * 100, position[1] * 100]

    def hook_init(self, callback):
        callback(self)

    def hook_loop(self, callback):
        self.loop_callback = callback