Пример #1
0
class MyApp(ShowBase):
    def __init__(self, markerImage='marker.jpg', calib_file='test.npz'):
        ShowBase.__init__(self)

        base.disableMouse()

        self.marker = cv2.imread(markerImage)
        self.marker = cv2.flip(self.marker, 0)

        self.kp_marker, self.des_marker = getDes(self.marker)

        if useCamera:
            self.cap = cv2.VideoCapture(0)
            ret, frame = self.cap.read()
        else:
            ret, frame = True, cv2.imread("sample_0.jpg")

        if ret:
            self.frame = frame

        self.criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,
                         30, 0.001)

        with np.load(calib_file) as calib_File:
            self.K = calib_File['mtx']
            self.D = calib_File['coef']

        (h, w) = frame.shape[0:2]
        print w, h

        far = 100
        near = 0.1

        fovx, fovy, f, (cx, cy), a = cv2.calibrationMatrixValues(
            self.K, (w, h), w, h)
        print fovx, fovy, f, cx, cy
        base.camLens.setFilmSize(w, h)
        base.camLens.setFilmOffset(w * 0.5 - cx, h * 0.5 - cy)
        base.camLens.setFocalLength(f)
        base.camLens.setFov(fovx, fovy)
        base.camLens.setNearFar(near, far)

        #base.camLens.setCoordinateSystem(4)
        base.camLens.setCoordinateSystem(4)
        #base.camLens.setViewVector(Vec3(0,0,1), Vec3(0,1,0))
        #self.render.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullCounterClockwise))

        self.tex = Texture("detect")  #self.buff.getTexture()
        self.tex.setCompression(Texture.CMOff)
        self.tex.setup2dTexture(w, h, Texture.TUnsignedByte, Texture.FRgb)

        self.b = OnscreenImage(parent=render2d, image=self.tex)
        base.cam.node().getDisplayRegion(0).setSort(20)

        self.taskMgr.add(self.updateFrameTask, "UpdateCameraFrameTask")

        self.modelroot = NodePath('ARRootNode')
        self.modelroot.reparentTo(self.render)
        '''
        self.x = self.loader.loadModel("models/box")
        self.x.reparentTo(self.modelroot)
        self.x.setScale(3, 0.1, 0.1)
        self.x.setPos(0, -0.05, -0.05)
        self.x.setColor(1,0,0,1,1)

        self.y = self.loader.loadModel("models/box")
        self.y.reparentTo(self.modelroot)
        self.y.setScale(0.1, 3, 0.1)
        self.y.setPos(-0.05, 0, -0.05)
        self.y.setColor(0,1,0,1,1)

        self.z = self.loader.loadModel("models/box")
        self.z.reparentTo(self.modelroot)
        self.z.setScale(0.1, 0.1, 3)
        self.z.setPos(-0.05, -0.05, 0)
        self.z.setColor(0,0,1,1,1)
        '''

        self.panda = NodePath('PandaRoot')
        self.panda.reparentTo(self.modelroot)

        # Load and transform the panda actor.
        self.pandaActor = Actor("models/panda-model",
                                {"walk": "models/panda-walk4"})
        self.pandaActor.setScale(0.003, 0.003, 0.003)
        self.pandaActor.reparentTo(self.panda)
        self.pandaActor.loop("walk")
        self.pandaActor.setH(180)

        #self.pandaMotion = MopathInterval("Panda Path", self.panda, "Interval Name")

        self.pathCurve = createNurbsCurve()
        for i in range(0, 30):
            self.pathCurve.addPoint(
                (random.uniform(1, 7), random.uniform(1, 7), 0))
        '''
        self.pathCurve.addPoint((1, 5, 0))
        self.pathCurve.addPoint((5, 5, 0))
        self.pathCurve.addPoint((5, 1, 0))
        self.pathCurve.addPoint((1, 1, 0))
        '''

        curveNode = self.pathCurve.getNodepath()

        self.myMopath = Mopath()
        self.myMopath.loadNodePath(curveNode)
        self.myMopath.fFaceForward = True
        myInterval = MopathInterval(self.myMopath,
                                    self.panda,
                                    duration=100,
                                    name="Name")
        myInterval.loop()

    # This task runs for two seconds, then prints done
    def updateFrameTask(self, task):
        if useCamera:
            ret, frame = self.cap.read()
        else:
            ret, frame = True, self.frame

        if ret:
            frame = cv2.flip(frame, 0)
            kp_frame, des_frame = getDes(frame)
            matches = getMatches(self.des_marker, des_frame)
            if not matches or len(matches) < 5:
                return task.cont

            pattern_points = [self.kp_marker[pt.trainIdx].pt for pt in matches]
            pattern_points = np.array([(x / 50.0, y / 50.0, 0)
                                       for x, y in pattern_points],
                                      dtype=np.float32)
            image_points = np.array(
                [kp_frame[pt.queryIdx].pt for pt in matches], dtype=np.float32)

            #ret, rvecs, tvecs = cv2.solvePnP(pattern_points, image_points, self.K, None)
            rvecs, tvecs, inliers = cv2.solvePnPRansac(pattern_points,
                                                       image_points, self.K,
                                                       None)
            #print "Tadam!",rvecs, tvecs
            #img_pts, jac = cv2.projectPoints(axis, rvecs, tvecs, camera_matrix, dist_coefs)
            #draw_lines(image, img_pts)

            T = tvecs.ravel()
            R = rvecs.ravel()

            RotM, _ = cv2.Rodrigues(R)
            RotM = RotM.T
            RotM = Mat3(
                RotM[0, 0],
                RotM[0, 1],
                RotM[0, 2],
                RotM[1, 0],
                RotM[1, 1],
                RotM[1, 2],
                #                          RotM[2,0],RotM[2,1],RotM[2,2])
                -RotM[2, 0],
                -RotM[2, 1],
                -RotM[2, 2])
            self.modelroot.setMat(Mat4(RotM, Vec3(T[0], T[1], T[2])))

            self.tex.setRamImage(frame)
            self.b.setImage(image=self.tex, parent=render2d)

        self.camera.setPos(0, 0, 0)
        self.camera.setHpr(0, 0, 0)
        self.camera.setScale(1, 1, 1)

        return task.cont
Пример #2
0
class Effect:
    baseWidth = 0
    baseHeight = 0
    effectWidth = 1
    effectHeight = 1
    effectTargetMS = 143
    noSampling = False
    tex = None
    loadedFormat = None
    # Animation variables
    internalFrameIndex = 1
    startIndex = 1
    endIndex = 1
    loopEffect = False
    # XML variables
    tree = None
    frames = None
    colors = None
    tweens = None
    compositeFrames = None
    # Nodes
    consumedNodesList = None
    # Accessible object (nodePath)
    effectCameraNodePath = None
    effectCardNodePath = None
    # Constant value; Unit comparison for card size; basis is from cure, which is [140x110]
    cardDimensionBasis = [-5.0, 5.0, 0.0, 10.0, 140.0, 110.0]
    pixelScaleX = cardDimensionBasis[4] / (cardDimensionBasis[1] - cardDimensionBasis[0])
    pixelScaleZ = cardDimensionBasis[5] / (cardDimensionBasis[3] - cardDimensionBasis[2])
    effectIsCentered = True
    effectAdjustment = [0, 0, 0]

    def __init__(self, effectFileName, parent=None, loop=False, effectIsCentered=True, effectAdjustment=[0, 0, 0]):
        self.effectAdjustment = effectAdjustment
        self.loopEffect = loop
        self.effectIsCentered = effectIsCentered
        self.loadedFormat = None
        if effectFileName != None:
            effectFileNameSplit = effectFileName.split(".")
            self.loadedFormat = effectFileNameSplit[len(effectFileNameSplit) - 2]  # Get value at penultimate index
            if self.loadedFormat == effectFileNameSplit[0]:
                self.loadedFormat = None  # Get rid of bad format name.
            pass

        # Load texture; supply alpha channel if it doesn't exist.
        p = transparencyKey(effectFileName)
        self.tex = Texture()
        self.tex.setup2dTexture(p.getXSize(), p.getYSize(), Texture.TUnsignedByte, Texture.FRgba)
        self.tex.load(p)
        if self.loadedFormat != None:
            try:
                self.tree = etree.parse("./" + GAME + "/effects/" + self.loadedFormat + "/sprite.xml")
            except IOError:
                self.loadedFormat = None
            pass
        if self.loadedFormat != None:
            root = self.tree.getroot()
            self.frames = root.find(".//frames")
            self.colors = root.find(".//colors")
            self.tweens = root.find(".//motion-tweens")
            self.compositeFrames = root.find(".//composite-frames")
            self.baseWidth = 0 if root.attrib.get("base-width") == None else float(root.attrib.get("base-width"))
            self.baseHeight = 0 if root.attrib.get("base-height") == None else float(root.attrib.get("base-height"))
            self.effectWidth = 1 if root.attrib.get("frame-width") == None else float(root.attrib.get("frame-width"))
            self.effectHeight = 1 if root.attrib.get("frame-height") == None else float(root.attrib.get("frame-height"))
            self.effectTargetMS = 143 if root.attrib.get("target-ms") == None else float(root.attrib.get("target-ms"))
            self.startIndex = 1 if root.attrib.get("target-start") == None else int(root.attrib.get("target-start"))
            self.endIndex = 1 if root.attrib.get("target-end") == None else int(root.attrib.get("target-end"))
            self.noSampling = False if root.attrib.get("no-sampling") == None else bool(root.attrib.get("no-sampling"))
            if self.noSampling == True:
                self.tex.setMagfilter(Texture.FTNearest)
                self.tex.setMinfilter(Texture.FTNearest)
            cm = CardMaker("card-" + effectFileName)
            cardDeltaX = self.effectWidth / self.pixelScaleX
            cardDeltaZ = self.effectHeight / self.pixelScaleZ
            if self.effectIsCentered == True:
                cm.setFrame(0, 0, 0, 0)
                deltaX = (cardDeltaX / 2.0) - (-cardDeltaX / 2.0)
                deltaY = 0
                deltaZ = (cardDeltaZ / 2.0) - (-cardDeltaZ / 2.0)
                # occluder = OccluderNode('effect-parent-occluder', Point3((-cardDeltaX/2.0), 0, (-cardDeltaZ/2.0)), Point3((-cardDeltaX/2.0), 0, (cardDeltaZ/2.0)), Point3((cardDeltaX/2.0), 0, (cardDeltaZ/2.0)), Point3((cardDeltaX/2.0), 0, (-cardDeltaZ/2.0)))
            else:
                cm.setFrame(0, 0, 0, 0)
                deltaX = (cardDeltaX / 2.0) - (-cardDeltaX / 2.0)
                deltaY = 0
                deltaZ = cardDeltaZ - 0
                # occluder = OccluderNode('effect-parent-occluder', Point3((-cardDeltaX/2.0), 0, 0), Point3((-cardDeltaX/2.0), 0, cardDeltaZ), Point3((cardDeltaX/2.0), 0, cardDeltaZ), Point3((cardDeltaX/2.0), 0, 0))
            self.effectCardNodePath = render.attachNewNode(cm.generate())
            self.effectCardNodePath.setBillboardPointEye()
            self.effectCardNodePath.reparentTo(parent)
            # occluder_nodepath = self.effectCardNodePath.attachNewNode(occluder)
            # self.effectCardNodePath.setOccluder(occluder_nodepath)
            emptyNode = NodePath("effect-parent-translator")
            emptyNode.reparentTo(self.effectCardNodePath)
            if effectIsCentered == True:
                emptyNode.setPos(
                    -deltaX / 2.0 + self.effectAdjustment[0],
                    0 + self.effectAdjustment[1],
                    deltaZ / 2.0 + self.effectAdjustment[2],
                )
            else:
                emptyNode.setPos(
                    -deltaX / 2.0 + self.effectAdjustment[0],
                    0 + self.effectAdjustment[1],
                    deltaZ + self.effectAdjustment[2],
                )
            # emptyNode.place()
            emptyNode.setSx(float(deltaX) / self.effectWidth)
            emptyNode.setSz(float(deltaZ) / self.effectHeight)
            self.effectCameraNodePath = emptyNode
            if parent != None:
                self.effectCardNodePath.reparentTo(parent)
            else:
                self.effectCardNodePath.reparentTo(render)
            # self.effectCardNodePath.place()
            self.effectCardNodePath.setBin("fixed", 40)
            self.effectCardNodePath.setDepthTest(False)
            self.effectCardNodePath.setDepthWrite(False)
        pass

    def getSequence(self):
        sequence = Sequence()
        for x in range(self.startIndex, self.endIndex, 1):
            sequence.append(Func(self.pandaRender))
            sequence.append(Func(self.advanceFrame))
            sequence.append(Wait(self.effectTargetMS * 0.001))
        sequence.append(Func(self.clearNodesForDrawing))
        sequence.append(Func(self.advanceFrame))
        sequence.append(Wait(self.effectTargetMS * 0.001))
        return sequence
        pass

    def hasEffectFinished(self):
        if self.internalFrameIndex > self.endIndex and self.loopEffect == False:
            return True
        else:
            return False
        pass

    def advanceFrame(self):
        if self.internalFrameIndex < self.endIndex:
            self.internalFrameIndex += 1
        elif self.internalFrameIndex == self.endIndex and self.loopEffect == True:
            self.internalFrameIndex = self.startIndex
        else:
            self.internalFrameIndex = self.endIndex + 1
            self.clearNodesForDrawing()
        pass

    def clearNodesForDrawing(self):
        if False:
            self.effectCameraNodePath.analyze()
        if self.consumedNodesList != None and self.consumedNodesList != []:
            for consumedNode in self.consumedNodesList:
                consumedNode.removeNode()
        self.consumedNodesList = []
        pass

    def pandaRender(self):
        frameList = []
        for node in self.compositeFrames.getiterator("composite-frame"):
            if node.tag == "composite-frame" and node.attrib.get("id") == str(self.internalFrameIndex):
                for frameCallNode in node:
                    for frameNode in self.frames.getiterator("frame"):
                        if frameNode.tag == "frame" and frameNode.attrib.get("id") == frameCallNode.attrib.get("id"):
                            offsetX = (
                                0
                                if frameCallNode.attrib.get("offset-x") == None
                                else float(frameCallNode.attrib.get("offset-x"))
                            )
                            offsetY = (
                                0
                                if frameCallNode.attrib.get("offset-y") == None
                                else float(frameCallNode.attrib.get("offset-y"))
                            )
                            tweenId = frameCallNode.attrib.get("tween")
                            frameInTween = (
                                0
                                if frameCallNode.attrib.get("frame-in-tween") == None
                                else int(frameCallNode.attrib.get("frame-in-tween"))
                            )
                            addWidth = 0 if frameNode.attrib.get("w") == None else float(frameNode.attrib.get("w"))
                            addHeight = 0 if frameNode.attrib.get("h") == None else float(frameNode.attrib.get("h"))
                            sInPixels = 0 if frameNode.attrib.get("s") == None else float(frameNode.attrib.get("s"))
                            tInPixels = 0 if frameNode.attrib.get("t") == None else float(frameNode.attrib.get("t"))
                            swInPixels = sInPixels + addWidth
                            thInPixels = tInPixels + addHeight
                            s = sInPixels / self.baseWidth
                            t = 1 - (
                                tInPixels / self.baseHeight
                            )  # Complemented to deal with loading image upside down.
                            S = swInPixels / self.baseWidth
                            T = 1 - (
                                thInPixels / self.baseHeight
                            )  # Complemented to deal with loading image upside down.
                            blend = (
                                "overwrite"
                                if frameCallNode.attrib.get("blend") == None
                                else frameCallNode.attrib.get("blend")
                            )
                            scaleX = (
                                1
                                if frameCallNode.attrib.get("scale-x") == None
                                else float(frameCallNode.attrib.get("scale-x"))
                            )
                            scaleY = (
                                1
                                if frameCallNode.attrib.get("scale-y") == None
                                else float(frameCallNode.attrib.get("scale-y"))
                            )
                            color = Color(1, 1, 1, 1)
                            tweenHasColor = False
                            frameCallHasColor = False
                            frameCallColorName = frameCallNode.attrib.get("color-name")
                            if frameCallColorName != None:
                                # Get color at frame call as first resort.
                                frameCallHasColor = True
                                for colorNode in self.colors.getiterator("color"):
                                    if colorNode.tag == "color" and colorNode.attrib.get("name") == frameCallColorName:
                                        R = 1 if colorNode.attrib.get("r") == None else float(colorNode.attrib.get("r"))
                                        G = 1 if colorNode.attrib.get("g") == None else float(colorNode.attrib.get("g"))
                                        B = 1 if colorNode.attrib.get("b") == None else float(colorNode.attrib.get("b"))
                                        A = 1 if colorNode.attrib.get("a") == None else float(colorNode.attrib.get("a"))
                                        color = Color(R, G, B, A)
                                        break  # leave for loop when we find the correct color
                                pass

                            if tweenId != None and tweenId != "0":
                                # Get color at tween frame as second resort.
                                thisTween = None
                                frameLength = 1
                                advancementFunction = "linear"
                                foundTween = False
                                pointList = []
                                colorList = []
                                for tweenNode in self.tweens.getiterator("motion-tween"):
                                    if tweenNode.tag == "motion-tween" and tweenNode.attrib.get("id") == tweenId:
                                        foundTween = True
                                        frameLength = (
                                            1
                                            if tweenNode.attrib.get("length-in-frames") == None
                                            else tweenNode.attrib.get("length-in-frames")
                                        )
                                        advancementFunction = (
                                            "linear"
                                            if tweenNode.attrib.get("advancement-function") == None
                                            else tweenNode.attrib.get("advancement-function")
                                        )
                                        for pointOrColorNode in tweenNode.getiterator():
                                            if pointOrColorNode.tag == "point":
                                                pX = (
                                                    0
                                                    if pointOrColorNode.attrib.get("x") == None
                                                    else float(pointOrColorNode.attrib.get("x"))
                                                )
                                                pY = (
                                                    0
                                                    if pointOrColorNode.attrib.get("y") == None
                                                    else float(pointOrColorNode.attrib.get("y"))
                                                )
                                                pointList.append(Point(pX, pY, 0))
                                            elif pointOrColorNode.tag == "color-state":
                                                colorName = (
                                                    "white"
                                                    if pointOrColorNode.attrib.get("name") == None
                                                    else pointOrColorNode.attrib.get("name")
                                                )
                                                for colorNode in self.colors.getiterator("color"):
                                                    if (
                                                        colorNode.tag == "color"
                                                        and colorNode.attrib.get("name") == colorName
                                                    ):
                                                        R = (
                                                            1
                                                            if colorNode.attrib.get("r") == None
                                                            else float(colorNode.attrib.get("r"))
                                                        )
                                                        G = (
                                                            1
                                                            if colorNode.attrib.get("g") == None
                                                            else float(colorNode.attrib.get("g"))
                                                        )
                                                        B = (
                                                            1
                                                            if colorNode.attrib.get("b") == None
                                                            else float(colorNode.attrib.get("b"))
                                                        )
                                                        A = (
                                                            1
                                                            if colorNode.attrib.get("a") == None
                                                            else float(colorNode.attrib.get("a"))
                                                        )
                                                        colorList.append(Color(R, G, B, A))
                                                        break  # leave for loop when we find the correct color reference
                                            pass  # Run through all child nodes of selected tween
                                        break  # Exit after finding correct tween
                                pass
                                if foundTween:
                                    thisTween = Tween(frameLength, advancementFunction, pointList, colorList)
                                    offset = thisTween.XYFromFrame(frameInTween)
                                    offsetFromTweenX = int(offset.X)
                                    offsetFromTweenY = int(offset.Y)
                                    offsetX += int(offset.X)
                                    offsetY += int(offset.Y)
                                    if thisTween.hasColorComponent():
                                        tweenHasColor = True
                                        if frameCallHasColor == False:
                                            color = thisTween.colorFromFrame(frameInTween)
                                    pass
                            if (
                                frameNode.attrib.get("color-name") != None
                                and frameCallHasColor == False
                                and tweenHasColor == False
                            ):
                                # Get color at frame definition as last resort.
                                for colorNode in colors.getiterator("color"):
                                    if colorNode.tag == "color" and colorNode.attrib.get(
                                        "name"
                                    ) == frameNode.attrib.get("color-name"):
                                        R = 1 if colorNode.attrib.get("r") == None else float(colorNode.attrib.get("r"))
                                        G = 1 if colorNode.attrib.get("g") == None else float(colorNode.attrib.get("g"))
                                        B = 1 if colorNode.attrib.get("b") == None else float(colorNode.attrib.get("b"))
                                        A = 1 if colorNode.attrib.get("a") == None else float(colorNode.attrib.get("a"))
                                        color = Color(R, G, B, A)
                                        break  # leave for loop when we find the correct color
                                pass
                            rotationZ = (
                                0
                                if frameCallNode.attrib.get("rotation-z") == None
                                else float(frameCallNode.attrib.get("rotation-z"))
                            )
                            frameList.append(
                                Frame(
                                    Bound(offsetX, offsetY, addWidth, addHeight),
                                    s,
                                    t,
                                    S,
                                    T,
                                    blend,
                                    scaleX,
                                    scaleY,
                                    color,
                                    rotationZ,
                                )
                            )
                    pass
                break  # Leave once we've found the appropriate frame

        # Prepare tracking list of consumed nodes.
        self.clearNodesForDrawing()
        # Make an identifier to tack onto primitive names in Panda3d's scene graph.
        frameIndexForName = 1

        # Loop through loaded frames that make up composite frame.
        for loadedFrame in frameList:
            # For debugging purposes, print the object.
            if False:
                loadedFrame.printAsString()

            # Set up place to store primitive 3d object; note: requires vertex data made by GeomVertexData
            squareMadeByTriangleStrips = GeomTristrips(Geom.UHDynamic)

            # Set up place to hold 3d data and for the following coordinates:
            #   square's points (V3: x, y, z),
            #   the colors at each point of the square (c4: r, g, b, a), and
            #   for the UV texture coordinates at each point of the square     (t2: S, T).
            vertexData = GeomVertexData(
                "square-" + str(frameIndexForName), GeomVertexFormat.getV3c4t2(), Geom.UHDynamic
            )
            vertex = GeomVertexWriter(vertexData, "vertex")
            color = GeomVertexWriter(vertexData, "color")
            texcoord = GeomVertexWriter(vertexData, "texcoord")

            # Add the square's data
            # Upper-Left corner of square
            vertex.addData3f(-loadedFrame.bound.Width / 2.0, 0, -loadedFrame.bound.Height / 2.0)
            color.addData4f(loadedFrame.color.R, loadedFrame.color.G, loadedFrame.color.B, loadedFrame.color.A)
            texcoord.addData2f(loadedFrame.s, loadedFrame.T)

            # Upper-Right corner of square
            vertex.addData3f(loadedFrame.bound.Width / 2.0, 0, -loadedFrame.bound.Height / 2.0)
            color.addData4f(loadedFrame.color.R, loadedFrame.color.G, loadedFrame.color.B, loadedFrame.color.A)
            texcoord.addData2f(loadedFrame.S, loadedFrame.T)

            # Lower-Left corner of square
            vertex.addData3f(-loadedFrame.bound.Width / 2.0, 0, loadedFrame.bound.Height / 2.0)
            color.addData4f(loadedFrame.color.R, loadedFrame.color.G, loadedFrame.color.B, loadedFrame.color.A)
            texcoord.addData2f(loadedFrame.s, loadedFrame.t)

            # Lower-Right corner of square
            vertex.addData3f(loadedFrame.bound.Width / 2.0, 0, loadedFrame.bound.Height / 2.0)
            color.addData4f(loadedFrame.color.R, loadedFrame.color.G, loadedFrame.color.B, loadedFrame.color.A)
            texcoord.addData2f(loadedFrame.S, loadedFrame.t)

            # Pass data to primitive
            squareMadeByTriangleStrips.addNextVertices(4)
            squareMadeByTriangleStrips.closePrimitive()
            square = Geom(vertexData)
            square.addPrimitive(squareMadeByTriangleStrips)
            # Pass primtive to drawing node
            drawPrimitiveNode = GeomNode("square-" + str(frameIndexForName))
            drawPrimitiveNode.addGeom(square)
            # Pass node to scene (effect camera)
            nodePath = self.effectCameraNodePath.attachNewNode(drawPrimitiveNode)
            # Linear dodge:
            if loadedFrame.blendMode == "darken":
                nodePath.setAttrib(
                    ColorBlendAttrib.make(
                        ColorBlendAttrib.MAdd,
                        ColorBlendAttrib.OOneMinusFbufferColor,
                        ColorBlendAttrib.OOneMinusIncomingColor,
                    )
                )
                pass
            elif loadedFrame.blendMode == "multiply":
                nodePath.setAttrib(
                    ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OFbufferColor, ColorBlendAttrib.OZero)
                )
                pass
            elif loadedFrame.blendMode == "color-burn":
                nodePath.setAttrib(
                    ColorBlendAttrib.make(
                        ColorBlendAttrib.MAdd, ColorBlendAttrib.OZero, ColorBlendAttrib.OOneMinusIncomingColor
                    )
                )
                pass
            elif loadedFrame.blendMode == "linear-burn":
                nodePath.setAttrib(
                    ColorBlendAttrib.make(
                        ColorBlendAttrib.MAdd, ColorBlendAttrib.OZero, ColorBlendAttrib.OIncomingColor
                    )
                )
                pass
            elif loadedFrame.blendMode == "lighten":
                nodePath.setAttrib(
                    ColorBlendAttrib.make(
                        ColorBlendAttrib.MMax, ColorBlendAttrib.OIncomingColor, ColorBlendAttrib.OFbufferColor
                    )
                )
                pass
            elif loadedFrame.blendMode == "color-dodge":
                nodePath.setAttrib(
                    ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OOne, ColorBlendAttrib.OOne)
                )
                pass
            elif loadedFrame.blendMode == "linear-dodge":
                nodePath.setAttrib(
                    ColorBlendAttrib.make(
                        ColorBlendAttrib.MAdd, ColorBlendAttrib.OOne, ColorBlendAttrib.OOneMinusIncomingColor
                    )
                )
                pass
            else:  # Overwrite:
                nodePath.setAttrib(
                    ColorBlendAttrib.make(
                        ColorBlendAttrib.MAdd, ColorBlendAttrib.OIncomingAlpha, ColorBlendAttrib.OOneMinusIncomingAlpha
                    )
                )
                pass
            nodePath.setDepthTest(False)
            # Apply texture
            nodePath.setTexture(self.tex)
            # Apply translation, then rotation, then scaling to node.
            nodePath.setPos(
                (
                    loadedFrame.bound.X + loadedFrame.bound.Width / 2.0,
                    1,
                    -loadedFrame.bound.Y - loadedFrame.bound.Height / 2.0,
                )
            )
            nodePath.setR(loadedFrame.rotationZ)
            nodePath.setScale(loadedFrame.scaleX, 1, loadedFrame.scaleY)
            nodePath.setTwoSided(True)
            self.consumedNodesList.append(nodePath)
            frameIndexForName = frameIndexForName + 1
        # Loop continues on through each frame called in the composite frame.
        pass
Пример #3
0
class Effect:
    baseWidth = 0
    baseHeight = 0
    effectWidth = 1
    effectHeight = 1
    effectTargetMS = 143
    noSampling = False
    tex = None
    loadedFormat = None
    # Animation variables
    internalFrameIndex = 1
    startIndex = 1
    endIndex = 1
    loopEffect = False
    # XML variables
    tree = None
    frames = None
    colors = None
    tweens = None
    compositeFrames = None
    # Nodes
    consumedNodesList = None
    # Accessible object (nodePath)
    effectCameraNodePath = None
    effectCardNodePath = None
    # Constant value; Unit comparison for card size; basis is from cure, which is [140x110]
    cardDimensionBasis = [-5.0, 5.0, 0.0, 10.0, 140.0, 110.0]
    pixelScaleX = cardDimensionBasis[4]/(cardDimensionBasis[1]-cardDimensionBasis[0])
    pixelScaleZ = cardDimensionBasis[5]/(cardDimensionBasis[3]-cardDimensionBasis[2])
    effectIsCentered = True
    effectAdjustment = [0, 0, 0]
    def __init__(self, effectFileName, parent=None, loop=False, effectIsCentered=True, effectAdjustment=[0, 0, 0]):
        self.effectAdjustment = effectAdjustment
        self.loopEffect = loop
        self.effectIsCentered = effectIsCentered
        self.loadedFormat = None
        if effectFileName != None:
            effectFileNameSplit = effectFileName.split('.')
            self.loadedFormat = effectFileNameSplit[len(effectFileNameSplit)-2] # Get value at penultimate index
            if self.loadedFormat == effectFileNameSplit[0]:
                self.loadedFormat = None # Get rid of bad format name.
            pass
            
        # Load texture; supply alpha channel if it doesn't exist.
        p = transparencyKey(effectFileName)
        self.tex = Texture()
        self.tex.setup2dTexture(p.getXSize(), p.getYSize(), Texture.TUnsignedByte, Texture.FRgba)
        self.tex.load(p)
        if self.loadedFormat != None:
            try:
                self.tree = etree.parse("./"+GAME+"/effects/"+self.loadedFormat+"/sprite.xml")
            except IOError:
                self.loadedFormat = None
            pass
        if self.loadedFormat != None: 
            root = self.tree.getroot()
            self.frames = root.find('.//frames')
            self.colors = root.find('.//colors')
            self.tweens = root.find('.//motion-tweens')
            self.compositeFrames = root.find('.//composite-frames')
            self.baseWidth = 0 if root.attrib.get("base-width") == None else float(root.attrib.get("base-width"))
            self.baseHeight = 0 if root.attrib.get("base-height") == None else float(root.attrib.get("base-height"))
            self.effectWidth = 1 if root.attrib.get("frame-width") == None else float(root.attrib.get("frame-width"))
            self.effectHeight = 1 if root.attrib.get("frame-height") == None else float(root.attrib.get("frame-height"))
            self.effectTargetMS = 143 if root.attrib.get("target-ms") == None else float(root.attrib.get("target-ms"))
            self.startIndex = 1 if root.attrib.get("target-start") == None else int(root.attrib.get("target-start"))
            self.endIndex = 1 if root.attrib.get("target-end") == None else int(root.attrib.get("target-end"))
            self.noSampling = False if root.attrib.get("no-sampling") == None else bool(root.attrib.get("no-sampling"))
            if self.noSampling==True:
                self.tex.setMagfilter(Texture.FTNearest)
                self.tex.setMinfilter(Texture.FTNearest)
            cm = CardMaker('card-'+effectFileName)
            cardDeltaX = self.effectWidth / self.pixelScaleX
            cardDeltaZ = self.effectHeight / self.pixelScaleZ
            if self.effectIsCentered == True:
                cm.setFrame(0, 0, 0, 0)
                deltaX = (cardDeltaX/2.0) - (-cardDeltaX/2.0)
                deltaY = 0
                deltaZ = (cardDeltaZ/2.0) - (-cardDeltaZ/2.0)
                #occluder = OccluderNode('effect-parent-occluder', Point3((-cardDeltaX/2.0), 0, (-cardDeltaZ/2.0)), Point3((-cardDeltaX/2.0), 0, (cardDeltaZ/2.0)), Point3((cardDeltaX/2.0), 0, (cardDeltaZ/2.0)), Point3((cardDeltaX/2.0), 0, (-cardDeltaZ/2.0)))
            else:
                cm.setFrame(0, 0, 0, 0)
                deltaX = (cardDeltaX/2.0) - (-cardDeltaX/2.0)
                deltaY = 0
                deltaZ = cardDeltaZ - 0
                #occluder = OccluderNode('effect-parent-occluder', Point3((-cardDeltaX/2.0), 0, 0), Point3((-cardDeltaX/2.0), 0, cardDeltaZ), Point3((cardDeltaX/2.0), 0, cardDeltaZ), Point3((cardDeltaX/2.0), 0, 0))
            self.effectCardNodePath = render.attachNewNode(cm.generate())            
            self.effectCardNodePath.setBillboardPointEye()
            self.effectCardNodePath.reparentTo(parent)
            #occluder_nodepath = self.effectCardNodePath.attachNewNode(occluder)
            #self.effectCardNodePath.setOccluder(occluder_nodepath)
            emptyNode = NodePath('effect-parent-translator')
            emptyNode.reparentTo(self.effectCardNodePath)
            if effectIsCentered == True:
                emptyNode.setPos(-deltaX/2.0+self.effectAdjustment[0], 0+self.effectAdjustment[1], deltaZ/2.0+self.effectAdjustment[2])
            else:
                emptyNode.setPos(-deltaX/2.0+self.effectAdjustment[0], 0+self.effectAdjustment[1], deltaZ+self.effectAdjustment[2])
            #emptyNode.place()
            emptyNode.setSx(float(deltaX)/self.effectWidth)
            emptyNode.setSz(float(deltaZ)/self.effectHeight)
            self.effectCameraNodePath = emptyNode                        
            if parent != None:
                self.effectCardNodePath.reparentTo(parent)
            else:
                self.effectCardNodePath.reparentTo(render)
            #self.effectCardNodePath.place()
            self.effectCardNodePath.setBin("fixed", 40)
            self.effectCardNodePath.setDepthTest(False)
            self.effectCardNodePath.setDepthWrite(False)
        pass
    def getSequence(self):
        sequence = Sequence()
        for x in range(self.startIndex, self.endIndex, 1):
            sequence.append(Func(self.pandaRender))
            sequence.append(Func(self.advanceFrame))
            sequence.append(Wait(self.effectTargetMS * 0.001))
        sequence.append(Func(self.clearNodesForDrawing))
        sequence.append(Func(self.advanceFrame))
        sequence.append(Wait(self.effectTargetMS * 0.001))
        return sequence
        pass
    def hasEffectFinished(self):
        if self.internalFrameIndex > self.endIndex and self.loopEffect == False:
            return True
        else:
            return False
        pass
    def advanceFrame(self):
        if self.internalFrameIndex < self.endIndex:
            self.internalFrameIndex += 1
        elif self.internalFrameIndex == self.endIndex and self.loopEffect == True:
            self.internalFrameIndex = self.startIndex
        else:
            self.internalFrameIndex = self.endIndex + 1
            self.clearNodesForDrawing()
        pass
    def clearNodesForDrawing(self):
        if False:
            self.effectCameraNodePath.analyze()
        if self.consumedNodesList != None and self.consumedNodesList != []:
            for consumedNode in self.consumedNodesList:
                consumedNode.removeNode()
        self.consumedNodesList = []
        pass
    def pandaRender(self):
        frameList = []
        for node in self.compositeFrames.getiterator('composite-frame'):
            if node.tag == "composite-frame" and node.attrib.get("id") == str(self.internalFrameIndex):
                for frameCallNode in node:
                    for frameNode in self.frames.getiterator('frame'):
                        if frameNode.tag == "frame" and frameNode.attrib.get("id") == frameCallNode.attrib.get("id"):
                            offsetX = 0 if frameCallNode.attrib.get("offset-x") == None else float(frameCallNode.attrib.get("offset-x"))
                            offsetY = 0 if frameCallNode.attrib.get("offset-y") == None else float(frameCallNode.attrib.get("offset-y"))
                            tweenId = frameCallNode.attrib.get("tween")
                            frameInTween = 0 if frameCallNode.attrib.get("frame-in-tween") == None else int(frameCallNode.attrib.get("frame-in-tween"))
                            addWidth = 0 if frameNode.attrib.get("w") == None else float(frameNode.attrib.get("w"))
                            addHeight = 0 if frameNode.attrib.get("h") == None else float(frameNode.attrib.get("h"))
                            sInPixels = 0 if frameNode.attrib.get("s") == None else float(frameNode.attrib.get("s"))
                            tInPixels = 0 if frameNode.attrib.get("t") == None else float(frameNode.attrib.get("t"))
                            swInPixels = sInPixels + addWidth
                            thInPixels = tInPixels + addHeight
                            s = (sInPixels / self.baseWidth)
                            t = 1 - (tInPixels / self.baseHeight) # Complemented to deal with loading image upside down.
                            S = (swInPixels / self.baseWidth)
                            T = 1 - (thInPixels / self.baseHeight) # Complemented to deal with loading image upside down.
                            blend = "overwrite" if frameCallNode.attrib.get("blend") == None else frameCallNode.attrib.get("blend")
                            scaleX = 1 if frameCallNode.attrib.get("scale-x") == None else float(frameCallNode.attrib.get("scale-x"))
                            scaleY = 1 if frameCallNode.attrib.get("scale-y") == None else float(frameCallNode.attrib.get("scale-y"))
                            color = Color(1,1,1,1)
                            tweenHasColor = False
                            frameCallHasColor = False
                            frameCallColorName = frameCallNode.attrib.get("color-name")
                            if frameCallColorName != None:
                                # Get color at frame call as first resort.
                                frameCallHasColor = True
                                for colorNode in self.colors.getiterator('color'):
                                    if colorNode.tag == 'color' and colorNode.attrib.get("name") == frameCallColorName:
                                        R = 1 if colorNode.attrib.get("r") == None else float(colorNode.attrib.get("r"))
                                        G = 1 if colorNode.attrib.get("g") == None else float(colorNode.attrib.get("g"))
                                        B = 1 if colorNode.attrib.get("b") == None else float(colorNode.attrib.get("b"))
                                        A = 1 if colorNode.attrib.get("a") == None else float(colorNode.attrib.get("a"))
                                        color = Color(R, G, B, A)
                                        break # leave for loop when we find the correct color
                                pass

                            if tweenId != None and tweenId != "0":
                                # Get color at tween frame as second resort.
                                thisTween = None
                                frameLength = 1
                                advancementFunction = "linear"
                                foundTween = False
                                pointList = []
                                colorList = []
                                for tweenNode in self.tweens.getiterator('motion-tween'):
                                    if tweenNode.tag == "motion-tween" and tweenNode.attrib.get("id") == tweenId:
                                        foundTween = True
                                        frameLength = 1 if tweenNode.attrib.get("length-in-frames") == None else tweenNode.attrib.get("length-in-frames")
                                        advancementFunction = "linear" if tweenNode.attrib.get("advancement-function") == None else tweenNode.attrib.get("advancement-function")
                                        for pointOrColorNode in tweenNode.getiterator():
                                            if pointOrColorNode.tag == "point":
                                                pX = 0 if pointOrColorNode.attrib.get("x") == None else float(pointOrColorNode.attrib.get("x"))
                                                pY = 0 if pointOrColorNode.attrib.get("y") == None else float(pointOrColorNode.attrib.get("y"))
                                                pointList.append(Point(pX, pY, 0))
                                            elif pointOrColorNode.tag == "color-state":
                                                colorName = "white" if pointOrColorNode.attrib.get("name") == None else pointOrColorNode.attrib.get("name")
                                                for colorNode in self.colors.getiterator('color'):
                                                    if colorNode.tag == 'color' and colorNode.attrib.get("name") == colorName:
                                                        R = 1 if colorNode.attrib.get("r") == None else float(colorNode.attrib.get("r"))
                                                        G = 1 if colorNode.attrib.get("g") == None else float(colorNode.attrib.get("g"))
                                                        B = 1 if colorNode.attrib.get("b") == None else float(colorNode.attrib.get("b"))
                                                        A = 1 if colorNode.attrib.get("a") == None else float(colorNode.attrib.get("a"))
                                                        colorList.append(Color(R, G, B, A))
                                                        break # leave for loop when we find the correct color reference
                                            pass # Run through all child nodes of selected tween
                                        break # Exit after finding correct tween
                                pass
                                if foundTween:
                                    thisTween = Tween(frameLength, advancementFunction, pointList, colorList)
                                    offset = thisTween.XYFromFrame(frameInTween);
                                    offsetFromTweenX = int(offset.X);
                                    offsetFromTweenY = int(offset.Y);
                                    offsetX += int(offset.X);
                                    offsetY += int(offset.Y);
                                    if thisTween.hasColorComponent():
                                        tweenHasColor = True;
                                        if frameCallHasColor == False:
                                            color = thisTween.colorFromFrame(frameInTween);
                                    pass
                            if frameNode.attrib.get("color-name") != None and frameCallHasColor == False and tweenHasColor == False:
                                # Get color at frame definition as last resort.
                                for colorNode in colors.getiterator('color'):
                                    if colorNode.tag == 'color' and colorNode.attrib.get("name") == frameNode.attrib.get("color-name"):
                                        R = 1 if colorNode.attrib.get("r") == None else float(colorNode.attrib.get("r"))
                                        G = 1 if colorNode.attrib.get("g") == None else float(colorNode.attrib.get("g"))
                                        B = 1 if colorNode.attrib.get("b") == None else float(colorNode.attrib.get("b"))
                                        A = 1 if colorNode.attrib.get("a") == None else float(colorNode.attrib.get("a"))
                                        color = Color(R, G, B, A)
                                        break # leave for loop when we find the correct color
                                pass
                            rotationZ = 0 if frameCallNode.attrib.get("rotation-z") == None else float(frameCallNode.attrib.get("rotation-z"))
                            frameList.append(Frame(Bound(offsetX, offsetY, addWidth, addHeight), s, t, S, T, blend, scaleX, scaleY, color, rotationZ))
                    pass 
                break # Leave once we've found the appropriate frame

        # Prepare tracking list of consumed nodes.
        self.clearNodesForDrawing()
        # Make an identifier to tack onto primitive names in Panda3d's scene graph.
        frameIndexForName = 1
                
        # Loop through loaded frames that make up composite frame.
        for loadedFrame in frameList:              
            # For debugging purposes, print the object.
            if False:
                loadedFrame.printAsString()
            
            # Set up place to store primitive 3d object; note: requires vertex data made by GeomVertexData
            squareMadeByTriangleStrips = GeomTristrips(Geom.UHDynamic)
              
            # Set up place to hold 3d data and for the following coordinates:
            #   square's points (V3: x, y, z), 
            #   the colors at each point of the square (c4: r, g, b, a), and
            #   for the UV texture coordinates at each point of the square     (t2: S, T).
            vertexData = GeomVertexData('square-'+str(frameIndexForName), GeomVertexFormat.getV3c4t2(), Geom.UHDynamic)
            vertex = GeomVertexWriter(vertexData, 'vertex')
            color = GeomVertexWriter(vertexData, 'color')
            texcoord = GeomVertexWriter(vertexData, 'texcoord') 
              
            # Add the square's data
            # Upper-Left corner of square
            vertex.addData3f(-loadedFrame.bound.Width / 2.0, 0, -loadedFrame.bound.Height / 2.0)
            color.addData4f(loadedFrame.color.R,loadedFrame.color.G,loadedFrame.color.B,loadedFrame.color.A)
            texcoord.addData2f(loadedFrame.s, loadedFrame.T)

            # Upper-Right corner of square
            vertex.addData3f(loadedFrame.bound.Width / 2.0, 0, -loadedFrame.bound.Height / 2.0)
            color.addData4f(loadedFrame.color.R,loadedFrame.color.G,loadedFrame.color.B,loadedFrame.color.A)
            texcoord.addData2f(loadedFrame.S, loadedFrame.T)
            
            # Lower-Left corner of square
            vertex.addData3f(-loadedFrame.bound.Width / 2.0, 0, loadedFrame.bound.Height / 2.0)
            color.addData4f(loadedFrame.color.R,loadedFrame.color.G,loadedFrame.color.B,loadedFrame.color.A)
            texcoord.addData2f(loadedFrame.s, loadedFrame.t)
            
            # Lower-Right corner of square
            vertex.addData3f(loadedFrame.bound.Width / 2.0, 0, loadedFrame.bound.Height / 2.0)
            color.addData4f(loadedFrame.color.R,loadedFrame.color.G,loadedFrame.color.B,loadedFrame.color.A)
            texcoord.addData2f(loadedFrame.S, loadedFrame.t)

            # Pass data to primitive
            squareMadeByTriangleStrips.addNextVertices(4)
            squareMadeByTriangleStrips.closePrimitive()
            square = Geom(vertexData)
            square.addPrimitive(squareMadeByTriangleStrips)
            # Pass primtive to drawing node
            drawPrimitiveNode=GeomNode('square-'+str(frameIndexForName))    
            drawPrimitiveNode.addGeom(square)
            # Pass node to scene (effect camera)
            nodePath = self.effectCameraNodePath.attachNewNode(drawPrimitiveNode)
            # Linear dodge:
            if loadedFrame.blendMode == "darken":
                nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OOneMinusFbufferColor, ColorBlendAttrib.OOneMinusIncomingColor))
                pass
            elif loadedFrame.blendMode == "multiply":
                nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OFbufferColor, ColorBlendAttrib.OZero))
                pass
            elif loadedFrame.blendMode == "color-burn":
                nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OZero, ColorBlendAttrib.OOneMinusIncomingColor))
                pass
            elif loadedFrame.blendMode == "linear-burn":
                nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OZero, ColorBlendAttrib.OIncomingColor))
                pass
            elif loadedFrame.blendMode == "lighten":
                nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MMax, ColorBlendAttrib.OIncomingColor, ColorBlendAttrib.OFbufferColor))
                pass
            elif loadedFrame.blendMode == "color-dodge":
                nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OOne, ColorBlendAttrib.OOne))
                pass
            elif loadedFrame.blendMode == "linear-dodge":
                nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OOne, ColorBlendAttrib.OOneMinusIncomingColor))
                pass
            else: # Overwrite:
                nodePath.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd, ColorBlendAttrib.OIncomingAlpha, ColorBlendAttrib.OOneMinusIncomingAlpha))
                pass
            nodePath.setDepthTest(False)
            # Apply texture
            nodePath.setTexture(self.tex)
            # Apply translation, then rotation, then scaling to node.
            nodePath.setPos((loadedFrame.bound.X + loadedFrame.bound.Width / 2.0, 1, -loadedFrame.bound.Y - loadedFrame.bound.Height / 2.0))
            nodePath.setR(loadedFrame.rotationZ)
            nodePath.setScale(loadedFrame.scaleX, 1, loadedFrame.scaleY)
            nodePath.setTwoSided(True)
            self.consumedNodesList.append(nodePath)
            frameIndexForName = frameIndexForName + 1
        # Loop continues on through each frame called in the composite frame.
        pass