예제 #1
0
def getPath(iconName):
    folder = FilePath(os.path.dirname(__file__))
    for fmt in FORMATS:
        path = folder.join(iconName + '.' + fmt)
        if path.exists():
            return path
    raise Exception('Icon not found: %s' % iconName)
예제 #2
0
 def __onNewProject(self):
     currentPath = self.__changeProjectHelper('Creating new project')
     if currentPath is None:
         return
     res = FileDialog.getSaveFileName(self, 'Create new project', currentPath, 'Project folder')
     if not res:
         return
     shutil.copytree(DEFAULT_PROJECT, res, ignore=lambda p, f: [] if os.path.basename(p).lower() == 'Scenes' else [n for n in f if os.path.splitext(n)[-1].lower() in IGNORED_EXTENSIONS])
     projectFile = FilePath(res).join(os.path.basename(res) + PROJ_EXT)
     projectFile.ensureExists()
     self.__openProject(projectFile)
예제 #3
0
 def readCameraData(self):
     if self.__cameraData is None:
         userFile = FilePath(currentProjectFilePath() + '.user')
         xCamera = None
         if userFile.exists():
             xRoot = parseXMLWithIncludes(userFile)
             for xSub in xRoot:
                 if xSub.attrib['name'] == self.__filePath.name():
                     xCamera = xSub
                     break
         if xCamera is None:  # legacy support
             xCamera = parseXMLWithIncludes(self.__filePath)
         self.__cameraData = CameraTransform(
             *[float(x) for x in xCamera.attrib['camera'].split(',')])
     return self.__cameraData
예제 #4
0
 def __openProject(self, path):
     setCurrentProjectFilePath(FilePath(path))
     self.__sceneList.projectOpened()
     self.__shotsManager.projectOpened()
     self._timer.projectOpened()
     self.__models.loadFromProject()
     self.__modelsOutliner.reset()
     self.__modeler.viewport.loadState()
예제 #5
0
    def initializeGL(self):
        print(glGetString(GL_VERSION))

        glEnable(GL_DEPTH_TEST)
        glDepthFunc(GL_LEQUAL)
        # glDepthMask(GL_TRUE)

        IMAGE_EXTENSIONS = '.png', '.bmp', '.tga'
        textureFolder = FilePath(__file__).join('..', 'Textures').abs()
        if textureFolder.exists():
            for texture in textureFolder.iter():
                if texture.ext() in IMAGE_EXTENSIONS:
                    self._textures[texture.name()] = loadImage(
                        textureFolder.join(texture))

        self._prevTime = time.time()
        self._timer.kick()
예제 #6
0
 def saveStaticTextures(self):
     exportDir = QFileDialog.getExistingDirectory(None, 'Choose destination folder to save static textures as .png files.', '.')
     if not exportDir:
         return
     for passData in self._scene.passes:
         if passData.realtime:
             continue
         for index, cbo in enumerate(self._scene.colorBuffers[passData.targetBufferId]):
             cbo.save(FilePath(os.path.join(exportDir, '{}{}.png'.format(passData.name, index))))
예제 #7
0
    def paintGL(self):
        newTime = time.time()
        deltaTime = newTime - self._prevTime

        # work around double repaint events collecting in the queue
        if deltaTime == 0.0:
            return

        self._prevTime = newTime

        width, height = self.calculateAspect(self.width(), self.height())
        viewport = (int((self.width() - width) * 0.5),
                    int((self.height() - height) * 0.5),
                    width,
                    height)

        if self._scene:
            uniforms = self._animator.evaluate(self._timer.time)
            textureUniforms = self._animator.additionalTextures(self._timer.time)

            cameraData = self._cameraData
            scene = self._scene
            modifier = currentProjectDirectory().join('animationprocessor.py')
            if modifier.exists():
                beats = self._timer.time
                execfile(modifier, globals(), locals())

            for name in self._textures:
                uniforms[name] = self._textures[name]._id

            self._scene.drawToScreen(self._timer.beatsToSeconds(self._timer.time), self._timer.time, uniforms, viewport, additionalTextureUniforms=textureUniforms)

        else:
            # no scene active, time cursor outside any enabled shots?
            global _noSignalImage
            if _noSignalImage is None:
                _noSignalImage = loadImage(FilePath(__file__).parent().join('icons', 'nosignal.png'))
            glDisable(GL_DEPTH_TEST)
            if _noSignalImage:
                glEnable(GL_BLEND)
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
                Scene.drawColorBufferToScreen(_noSignalImage, viewport)
                glDisable(GL_BLEND)

        if self.__overlays:
            image = self.__overlays.colorBuffer()
            if image:
                color = (self.__overlays.overlayColor().red() / 255.0,
                         self.__overlays.overlayColor().green() / 255.0,
                         self.__overlays.overlayColor().blue() / 255.0,
                         self.__overlays.overlayColor().alpha() / 255.0)
                glDisable(GL_DEPTH_TEST)
                glEnable(GL_BLEND)
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
                Scene.drawColorBufferToScreen(image, viewport, color)
                glDisable(GL_BLEND)
예제 #8
0
    def initializeGL(self):
        # TODO: Handle re-parenting of the widget in PySide6, it invalidates the context so we need to dirty every cache, or maybe just setCentralWidget and not dock the 3D view,
        #       but it is a fundamental dual monitor or beamer feature so we might just have to deal with it. Lazy choice on Qt's part though, we have to reload EVERY model and texture and buffer.
        print(glGetString(GL_VERSION))

        glEnable(GL_DEPTH_TEST)
        glDepthFunc(GL_LEQUAL)
        # glDepthMask(GL_TRUE)

        IMAGE_EXTENSIONS = '.png', '.bmp', '.tga'
        textureFolder = FilePath(__file__).join('..', 'Textures').abs()
        if textureFolder.exists():
            for texture in textureFolder.iter():
                if texture.ext() in IMAGE_EXTENSIONS:
                    self._textures[texture.name()] = loadImage(textureFolder.join(texture))

        self._prevTime = time.time()
        self._timer.kick()

        if qt_wrapper == 'PySide6':
            SceneView.screenFBO = self.defaultFramebufferObject()
예제 #9
0
    def _reload(self, path):
        if path:
            path = FilePath(path)
            time.sleep(0.01)
            if not path.exists():
                # the scene has been deleted, stop watching it
                return
            self.fileSystemWatcher_scene.addPath(path)

        self.passes = _deserializePasses(self.__filePath)

        self.fileSystemWatcher = FileSystemWatcher()
        self.fileSystemWatcher.fileChanged.connect(self._rebuild)
        watched = set()
        for passData in self.passes:
            newStitches = (set(passData.vertStitches)
                           | set(passData.fragStitches)) - watched
            if newStitches:
                self.fileSystemWatcher.addPaths(list(newStitches))
                watched |= newStitches

        self._rebuild(None)
        self.__cameraData = None
예제 #10
0
    def export(self, path):
        filePath = FilePath(path)
        filePath = filePath.join("%s.glsl" % self._name)
        filePath.ensureExists()

        str = self.getFieldFragmentShaderText()

        with filePath.edit() as fh:
            fh.write(str)

        return
예제 #11
0
    def __changeProjectHelper(self, title):
        """
        Utility that shows a dialog if we're changing projects with potentially unsaved changes.
        Returns the current project directory, or the current working directory if no such project.
        """
        currentPath = FilePath(os.getcwd())

        project = currentProjectFilePath()
        if project is not None:
            # propose to save near current project
            dir = project.parent()
            if dir.exists():
                currentPath = dir

            # check if unsaved changes
            if QMessageBox.No == QMessageBox.warning(self, title, 'Any unsaved changes will be lost. Continue?', QMessageBox.Yes | QMessageBox.No):
                return

        return currentPath
예제 #12
0
def _deserializeSceneShots(sceneName):
    sceneFile = currentScenesDirectory().join(sceneName.ensureExt(SCENE_EXT))
    xScene = parseXMLWithIncludes(sceneFile)

    for xShot in xScene:
        name = xShot.attrib['name']
        start = float(xShot.attrib['start'])
        end = float(xShot.attrib['end'])
        speed = float(xShot.attrib.get(
            'speed', 1.0))  # using get for legacy file support
        preroll = float(xShot.attrib.get('preroll', 0.0))

        curves = OrderedDict()
        textures = OrderedDict()
        for xEntry in xShot:
            if xEntry.tag.lower() == 'channel':
                curveName = xEntry.attrib['name']
                keys = []
                if xEntry.text:
                    keys = xEntry.text.split(',')
                curve = Curve()
                for i in range(0, len(keys), 8):
                    curve.addKeyWithTangents(
                        tangentBroken=int(keys[i + 6]),
                        tangentMode=int(keys[i + 7]),
                        *[float(x) for x in keys[i:i + 6]])
                curves[curveName] = curve

            if xEntry.tag.lower() == 'texture':
                textures[xEntry.attrib['name']] = FilePath(
                    xEntry.attrib['path'])

        shot = Shot(name, sceneName, start, end, curves, textures, speed,
                    preroll)
        if 'enabled' in xShot.attrib:
            shot.enabled = xShot.attrib['enabled'] == str(True)
        yield shot
예제 #13
0
class Overlays(QWidget):
    _overlayDir = FilePath(__file__).abs().parent()
    _overlayNames = ['None'] + list(
        sorted(
            os.path.splitext(x)[0]
            for x in _overlayDir.iter() if x.endswith('.png')))
    _overlayCache = {}

    changed = pyqtSignal()

    def __init__(self):
        super(Overlays, self).__init__()
        l = hlayout()
        self.setLayout(l)

        enm = EnumBox(Overlays._overlayNames)
        enm.setValue(self.overlayIndex())
        l.addWidget(enm)
        enm.valueChanged.connect(self.setOverlayIndex)
        l.addWidget(enm)

        clr = ColorBox(self.overlayColor())
        l.addWidget(clr)
        clr.valueChanged.connect(self.setOverlayColor)
        l.addWidget(clr)

    def colorBuffer(self):
        idx = self.overlayIndex()
        if idx <= 0:
            return
        img = Overlays._overlayCache.get(idx, None)
        if img:
            return img
        fpath = Overlays._overlayDir.join(Overlays._overlayNames[idx] + '.png')
        if not fpath.exists():
            return
        img = loadImage(fpath)
        Overlays._overlayCache[idx] = img
        return img

    def overlayIndex(self):
        """
        :rtype: int
        """
        return gSettings.value('overlayIndex', 0)

    def setOverlayIndex(self, index):
        """
        :type index: int
        """
        gSettings.setValue('overlayIndex', index)
        self.changed.emit()

    def overlayColor(self):
        """
        :rtype: QColor
        """
        return QColor(
            gSettings.value('overlayColor', qRgba(255, 255, 255, 255)))

    def setOverlayColor(self, color):
        """
        :type color: QColor
        """
        gSettings.setValue('overlayColor', color.rgba())
        self.changed.emit()
예제 #14
0
def run():
    shots = []
    scenes = []
    scenesDir = currentScenesDirectory()

    for scenePath in scenesDir.iter(join=True):
        if not scenePath.hasExt(SCENE_EXT):
            continue
        sceneDir = FilePath(scenePath.strip()).stripExt()
        xScene = parseXMLWithIncludes(scenePath)

        templatePath = scenesDir.join(scenesDir, xScene.attrib['template'])
        templateDir = templatePath.stripExt()
        xTemplate = Template(templatePath)

        scene = []

        for xPass in xTemplate:
            stitchIds = []
            uniforms = {}
            for xSection in xPass:
                baseDir = sceneDir
                if xSection.tag in ('global', 'shared'):
                    baseDir = templateDir
                shaderFile = baseDir.join(xSection.attrib['path']).abs()
                stitchIds.append(text.addFile(shaderFile))
                for xUniform in xSection:
                    name = xUniform.attrib['name']
                    values = [
                        float(x.strip())
                        for x in xUniform.attrib['value'].split(',')
                    ]
                    uniforms[text.addString(name)] = len(
                        values), floats.addFloats(values, name)

            programId = shaders.fromStitches(stitchIds)

            buffer = int(xPass.attrib.get('buffer', -1))
            outputs = int(xPass.attrib.get('outputs', 1))
            size = int(xPass.attrib.get('size', 0))
            width = int(xPass.attrib.get('width', size))
            height = int(xPass.attrib.get('height', size))
            factor = int(xPass.attrib.get('factor', 1))
            static = int(xPass.attrib.get('static', 0))
            is3d = int(xPass.attrib.get('is3d', 0))
            if buffer != -1:
                buffer = framebuffers.add(buffer, outputs, width, height,
                                          factor, static, is3d)

            i = 0
            key = 'input%s' % i
            inputs = []
            while key in xPass.attrib:
                v = xPass.attrib[key]
                if '.' in v:
                    a, b = v.split('.')
                else:
                    a, b = v, 0
                inputs.append((int(a), int(b)))
                i += 1
                key = 'input%s' % i

            scene.append(passes.add(programId, buffer, inputs, uniforms))

        sceneIndex = len(scenes)
        scenes.append(len(scene))
        scenes += scene

        for xShot in xScene:
            if xShot.attrib.get('enabled', 'True') == 'False':
                continue
            animations = {}
            for xChannel in xShot:
                uname = xChannel.attrib['name']
                n = uname
                x = 0
                if '.' in uname:
                    n, x = uname.rsplit('.', 1)
                    x = 'xyzw'.index(x)
                n = text.addString(n)
                if n not in animations:
                    animations[n] = []
                if not xChannel.text:
                    keyframes = []
                else:
                    keyframes = []
                    for i, v in enumerate(
                            float(v.strip())
                            for v in xChannel.text.split(',')):
                        j = i % 8
                        if j == 0 or j == 4 or j > 5:
                            continue
                        if j == 5:  # out tangent y
                            if v == float(
                                    'inf'
                            ):  # stepped tangents are implemented as out tangentY = positive infinity
                                v = 'FLT_MAX'
                        keyframes.append(v)
                    assert len(keyframes) / 4.0 == int(len(keyframes) /
                                                       4), len(keyframes)
                while len(animations[n]) <= x:
                    animations[n].append(None)
                assert animations[n][x] is None
                animations[n][x] = floats.addFloats(keyframes), len(keyframes)

            for channelStack in animations.values():
                # TODO we can not / do not check if the channelStack length matches the uniform dimensions inside the shader (e.g. are we sure we're not gonna call glUniform2f for a vec3?)
                assert None not in channelStack, 'Animation provided for multiple channels but there is one missing (Y if a vec3 or also Z if a vec4).'

            shots.append((float(xShot.attrib['start']),
                          float(xShot.attrib['end']), sceneIndex, animations))

    # sort shots by start time
    def _serializeShots(shots):
        shots.sort(key=lambda x: x[0])
        shotTimesStart = floats.addFloats(
            [x for shot in shots for x in (shot[0], shot[1])])
        yield '\n\n__forceinline int shotAtBeats(float beats, float& localBeats)\n{\n'
        if len(shots) == 1:
            yield '\tlocalBeats = beats - gFloatData[%s];\n' % shotTimesStart
            yield '\treturn 0;\n'
        else:
            yield '\tint shotTimeCursor = 0;\n'
            yield '\tdo\n\t{\n'
            yield '\t\tif(beats < gFloatData[shotTimeCursor * 2 + %s])\n\t\t{\n' % (
                shotTimesStart + 1)
            yield '\t\t\tlocalBeats = beats - gFloatData[shotTimeCursor * 2 + %s];\n' % shotTimesStart
            yield '\t\t\treturn shotTimeCursor;\n'
            yield '\t\t}\n'
            yield '\t}\n\twhile(++shotTimeCursor < %s);\n' % len(shots)
            yield '\treturn -1;\n'
        yield '}\n'

        global gShotScene
        gShotScene = ints.addInts([shot[2] for shot in shots])
        flatAnimationData = []
        animationDataPtrs = []
        for shot in shots:
            animationDataPtrs += [len(flatAnimationData), len(shot[3].keys())]
            global gAnimEntriesMax
            gAnimEntriesMax = max(gAnimEntriesMax, len(shot[3].keys()))
            for uniformStringId in shot[3]:
                animationData = shot[3][uniformStringId]
                flatAnimationData += [uniformStringId, len(animationData)]
                for pair in animationData:
                    flatAnimationData += pair
                flatAnimationData += [0] * (2 * (4 - len(animationData)))

        global gShotAnimationDataIds
        gShotAnimationDataIds = ints.addInts(animationDataPtrs)
        global gShotUniformData
        gShotUniformData = ints.addInts(flatAnimationData)

    def _serializeAll(scenes, shots):
        buffer = list(_serializeShots(shots))
        for serializable in (text, floats):
            for ln in serializable.serialize():
                yield ln
        buffer2 = []
        for serializable in (shaders, framebuffers, passes):
            buffer2 += list(serializable.serialize())
        global gScenePassIds
        gScenePassIds = ints.addInts(scenes)
        for ln in ints.serialize():
            yield ln
        for ln in buffer2:
            yield ln
        for ln in buffer:
            yield ln

    data = [''.join(_serializeAll(scenes, shots))]
    data.append(
        """\n\n__forceinline float evalCurve(const float* data, int numFloats, float beats)
{
\tif(numFloats == 4 || beats <= data[1]) // 1 key or evaluating before first frame
\t\treturn data[2];

\t// Find index of first key that has a bigger time than our current time
\t// if none, this will be the index of the last key.
\tint keyValueCount = numFloats;
\tint rightKeyIndex = 4;
\twhile (rightKeyIndex < keyValueCount - 4 && data[rightKeyIndex + 1] < beats)
\t\trightKeyIndex += 4;

\t// Clamp our sampling time to our range
\tfloat sampleTime = (beats > data[rightKeyIndex + 1]) ? data[rightKeyIndex + 1] : beats;

\t// Retrieve our spline points
\tfloat y0 = data[rightKeyIndex - 2];
\tfloat y1 = data[rightKeyIndex - 1]; 
\t// handle stepped tangents
\tif(y1 == FLT_MAX) return y0;
\tfloat y2 = data[rightKeyIndex];
\tfloat y3 = data[rightKeyIndex + 2];

\tfloat dy = y3 - y0;
\tfloat c0 = y1 + y2 - dy - dy;
\tfloat c1 = dy + dy + dy - y1 - y1 - y2;
\tfloat c2 = y1;
\tfloat c3 = y0;

\t// Determine factor
\tfloat dt = data[rightKeyIndex + 1] - data[rightKeyIndex - 3];
\tfloat t = (sampleTime - data[rightKeyIndex - 3]) / dt;

\treturn t * (t * (t * c0 + c1) + c2) + c3;
}

#define gAnimEntriesMax %s
#define gShotAnimationDataIds %s
#define gShotScene %s
#define gScenePassIds %s
#define gPassProgramsAndTargets %s
#define gShotUniformData %s
#define gFrameBufferData %s
#define gFrameBufferBlockSize %s
#define gProgramCount %s
""" % (gAnimEntriesMax, gShotAnimationDataIds, gShotScene, gScenePassIds,
       gPassProgramsAndTargets, gShotUniformData, gFrameBufferData,
       FrameBufferPool.BLOCK_SIZE, len(shaders.offsets)))

    dst = FilePath(__file__).abs().parent().parent().join(
        'Player', 'generated.hpp')
    with dst.edit() as fh:
        fh.write(''.join(data))
예제 #15
0
def currentProjectFilePath():
    if not gSettings.contains('currentproject'):
        return None
    return FilePath(gSettings.value('currentproject'))
예제 #16
0
    def _rebuild(self, path, index=None):
        if path:
            path = FilePath(path)
            time.sleep(0.01)
            if not path.exists():
                # the scene has been deleted, stop watching it
                return
            self.fileSystemWatcher.addPath(path)
            path = path.abs()

        for i, passData in enumerate(self.passes):
            vert = True
            frag = True

            # make sure the changed path is in our dependencies
            if path:
                if not path in (stitch.abs()
                                for stitch in passData.vertStitches):
                    vert = False
                if not path in (stitch.abs()
                                for stitch in passData.fragStitches):
                    frag = False
                if not vert and not frag:
                    continue

            if index is not None and index != i:
                continue

            includePaths = set()
            errors = []

            vertCode = []
            for stitch in passData.vertStitches:
                try:
                    vertCode.append(_loadGLSLWithIncludes(
                        stitch, includePaths))
                except IOError as e:
                    errors.append(stitch.abs())

            fragCode = []
            for stitch in passData.fragStitches:
                try:
                    fragCode.append(_loadGLSLWithIncludes(
                        stitch, includePaths))
                except IOError as e:
                    errors.append(stitch.abs())

            if errors:
                QMessageBox.critical(
                    None, 'Missing files',
                    'A template or scene could not be loaded & is missing the following files:\n\n%s'
                    % '\n'.join(errors))
                return

            if includePaths:
                self.fileSystemWatcher.addPaths(list(includePaths))

            # not joining causes "unexpected $undefined" errors during shader compilation,
            # no idea why it injects invalid bytes
            if not vertCode:
                vertCode = Scene.STATIC_VERT
            else:
                vertCode = '\n'.join(vertCode)

            fragCode = '\n'.join(fragCode)

            try:
                program = gShaderPool.compileProgram(vertCode, fragCode)

            except RuntimeError as e:
                self.shaders = []
                errors = e.args[0].split('\n')
                try:
                    code = e.args[1][0].decode('ascii').split('\n')
                except IndexError:
                    print(e.args)
                    print('pass: '******'fragCode:')
                    print(fragCode)
                    return
                # html escape output
                errors = [Qt.escape(ln) for ln in errors]
                code = [Qt.escape(ln) for ln in code]
                log = []
                for error in errors:
                    try:
                        lineNumber = int(
                            error.split(' : ',
                                        1)[0].rsplit('(')[-1].split(')')[0])
                    except:
                        continue
                    lineNumber -= 1
                    log.append(
                        '<p><font color="red">%s</font><br/>%s<br/><font color="#081">%s</font><br/>%s</p>'
                        % (error, '<br/>'.join(
                            code[lineNumber - 5:lineNumber]), code[lineNumber],
                           '<br/>'.join(code[lineNumber + 1:lineNumber + 5])))
                self.__errorDialogText.setHtml('<pre>' + '\n'.join(log) +
                                               '</pre>')
                self.__errorDialog.setGeometry(100, 100, 800, 600)
                self.__errorDialog.exec_()
                return

            while len(self.shaders) <= i:
                self.shaders.append(0)
            self.shaders[i] = program

            # 3D texture dirties, let's reset it's buffers too
            if self.passes[i].is3d and self.colorBuffers:
                for j, buffer in enumerate(self.colorBuffers[i]):
                    if isinstance(buffer, Texture3D):
                        self.colorBuffers[i][j] = buffer.original
                        self.__passDirtyState[i] = True

        self.__passDirtyState = [True] * len(self.passes)
        self.__errorDialog.close()
예제 #17
0
 def __openProject(self, path):
     setCurrentProjectFilePath(FilePath(path))
     self.__sceneList.projectOpened()
     self.__shotsManager.projectOpened()
     self._timer.projectOpened()
예제 #18
0
def _deserializePasses(sceneFile):
    """
    :type sceneFile: FilePath
    :rtype: list[PassData]
    """
    assert isinstance(sceneFile, FilePath)
    sceneDir = sceneFile.stripExt()
    templatePath = templatePathFromScenePath(sceneFile)
    templateDir = templatePath.stripExt()
    xTemplate = parseXMLWithIncludes(templatePath)
    passes = []
    frameBufferMap = {}
    for xPass in xTemplate:
        buffer = -1
        if 'buffer' in xPass.attrib:
            buffer = xPass.attrib['buffer']
            if buffer not in frameBufferMap:
                frameBufferMap[buffer] = len(frameBufferMap)

        size = None
        if 'size' in xPass.attrib:
            size = int(xPass.attrib['size']), int(xPass.attrib['size'])
        elif 'width' in xPass.attrib and 'height' in xPass.attrib:
            size = int(xPass.attrib['width']), int(xPass.attrib['height'])

        tile = size is not None
        if 'tile' in xPass.attrib:
            tile = xPass.attrib['tile'].lower() == 'true'

        factor = None
        if 'factor' in xPass.attrib:
            factor = int(xPass.attrib['factor'])

        realtime = int(xPass.attrib.get('static', 0)) == 0

        is3d = int(xPass.attrib.get('is3d', 0)) != 0
        if is3d:
            assert (size[0]**0.5) == size[1]
            size = size[0], size[1]

        outputs = int(xPass.attrib.get('outputs', 1))

        inputs = []
        i = 0
        key = 'input%s' % i
        while key in xPass.attrib:
            # input is filename?
            parentPath = currentProjectDirectory()
            fullName = parentPath.join(xPass.attrib[key])
            if fullName.exists():
                inputs.append(FilePath(xPass.attrib[key]))
            else:
                # input is buffer
                if '.' in xPass.attrib[key]:
                    frameBuffer, subTexture = xPass.attrib[key].split('.')
                    frameBuffer, subTexture = frameBuffer, int(subTexture)
                else:
                    frameBuffer, subTexture = xPass.attrib[key], 0

                if frameBuffer not in frameBufferMap:
                    frameBufferMap[frameBuffer] = len(frameBufferMap)
                inputs.append((frameBufferMap[frameBuffer], subTexture))

            i += 1
            key = 'input%s' % i
        vertStitches = []
        fragStitches = []
        uniforms = {}
        for xElement in xPass:
            path = FilePath(xElement.attrib['path'])
            stitches = vertStitches if path.hasExt('vert') else fragStitches
            if xElement.tag.lower() == 'section':
                stitches.append(sceneDir.join(path))
            elif xElement.tag.lower() in ('shared', 'global'):
                stitches.append(templateDir.join(path))
            else:
                raise ValueError('Unknown XML tag in pass: "******"' %
                                 xElement.tag)
            for xUniform in xElement:
                uniforms[xUniform.attrib['name']] = [
                    float(x.strip())
                    for x in xUniform.attrib['value'].split(',')
                ]

        passes.append(
            PassData(vertStitches, fragStitches, uniforms, inputs,
                     frameBufferMap.get(buffer, -1), realtime, size,
                     tile, factor, outputs,
                     xPass.attrib.get('drawcommand', None), is3d,
                     xPass.attrib.get('name', None)))
    return passes
예제 #19
0
def _deserializePasses(sceneFile, models):
    """
    :type sceneFile: FilePath
    :rtype: list[PassData]
    """
    assert isinstance(sceneFile, FilePath)
    sceneDir = sceneFile.stripExt()
    templatePath = templatePathFromScenePath(sceneFile)
    templateDir = templatePath.stripExt()
    modelsDir = currentModelsDirectory()
    xTemplate = parseXMLWithIncludes(templatePath)
    passes = []
    frameBufferMap = {}

    # # Start with adding the models here as passes. Stored by their model name
    # for model in models.models:
    #     inputs = []
    #     if model.name not in frameBufferMap:
    #         frameBufferMap[model.name] = len(frameBufferMap)
    #     size = 256,256
    #     fragStitches = []
    #     fragStitches.append(templateDir.join("header.glsl"))
    #     fragStitches.append(templateDir.join("noiselib.glsl"))
    #     fragStitches.append(templateDir.join("sdf.glsl"))
    #     #fragStitches.append(templateDir.join("test3d.glsl"))
    #     fragStitches.append(modelsDir.join("%s.glsl" % model.name))
    #
    #     # Add a pass for rendering a 3D texture
    #     passes.append(
    #         PassData([], fragStitches, {}, inputs, frameBufferMap.get(model.name, -1), False, size, False, False, 1, None, True, None))

    for xPass in xTemplate:
        buffer = -1
        if 'buffer' in xPass.attrib:
            buffer = xPass.attrib['buffer']
            if buffer not in frameBufferMap:
                frameBufferMap[buffer] = len(frameBufferMap)

        size = None
        if 'size' in xPass.attrib:
            size = int(xPass.attrib['size']), int(xPass.attrib['size'])
        elif 'width' in xPass.attrib and 'height' in xPass.attrib:
            size = int(xPass.attrib['width']), int(xPass.attrib['height'])

        tile = size is not None
        if 'tile' in xPass.attrib:
            tile = xPass.attrib['tile'].lower() == 'true'

        factor = None
        if 'factor' in xPass.attrib:
            factor = int(xPass.attrib['factor'])

        realtime = int(xPass.attrib.get('static', 0)) == 0

        is3d = int(xPass.attrib.get('is3d', 0)) != 0
        if is3d:
            assert (size[0] == size[1])
            size = size[0], size[0]

        outputs = int(xPass.attrib.get('outputs', 1))

        inputs = []
        inputsUniformOverrideNames = {}
        i = 0
        key = 'input%s' % i
        while key in xPass.attrib:
            # input is filename?
            parentPath = currentProjectDirectory()
            fullName = parentPath.join(xPass.attrib[key])
            if fullName.exists():
                inputs.append(FilePath(xPass.attrib[key]))
            else:
                # input is buffer
                if '.' in xPass.attrib[key]:
                    frameBuffer, subTexture = xPass.attrib[key].split('.')
                    frameBuffer, subTexture = frameBuffer, int(subTexture)
                else:
                    frameBuffer, subTexture = xPass.attrib[key], 0

                if frameBuffer not in frameBufferMap:
                    frameBufferMap[frameBuffer] = len(frameBufferMap)
                inputs.append((frameBufferMap[frameBuffer], subTexture))

            i += 1
            key = 'input%s' % i

        inputModels = False
        if 'inputModels' in xPass.attrib:
            inputModels = xPass.attrib['inputModels'].lower() == 'true'

        # Add all model's output buffers as inputs to this pass
        if inputModels:
            for model in models.models:
                bufferIndex = (frameBufferMap[model.name], 0)
                inputs.append(bufferIndex)
                inputsUniformOverrideNames[
                    bufferIndex] = "uModel%s" % model.name

        vertStitches = []
        fragStitches = []
        uniforms = {}
        for xElement in xPass:
            if xElement.tag.lower() == 'section':
                path = FilePath(xElement.attrib['path'])
                stitches = vertStitches if path.hasExt(
                    'vert') else fragStitches
                stitches.append(sceneDir.join(path))
            elif xElement.tag.lower() in ('shared', 'global'):
                path = FilePath(xElement.attrib['path'])
                stitches = vertStitches if path.hasExt(
                    'vert') else fragStitches
                stitches.append(templateDir.join(path))
            elif xElement.tag.lower() == 'models':
                for model in models.models:
                    fragStitches.append(modelsDir.join("%s.glsl" % model.name))
            else:
                raise ValueError('Unknown XML tag in pass: "******"' %
                                 xElement.tag)
            for xUniform in xElement:
                uniforms[xUniform.attrib['name']] = [
                    float(x.strip())
                    for x in xUniform.attrib['value'].split(',')
                ]

        passes.append(
            PassData(vertStitches, fragStitches, uniforms, inputs,
                     frameBufferMap.get(buffer, -1), realtime, size,
                     tile, factor, outputs,
                     xPass.attrib.get('drawcommand', None), is3d,
                     xPass.attrib.get('name',
                                      None), inputsUniformOverrideNames))
    return passes