def __showInExplorer(self): if self.__contextMenuItem is None: return data = self.__contextMenuItem.data() if not data or not fileutil.exists(data): data = os.path.join(ScenesPath(), self.__contextMenuItem.text()) if not data or not fileutil.exists(data): return data = os.path.abspath(data) subprocess.Popen('explorer /select,"%s"' % data)
def Scenes(sub=''): scenesPath = ScenesPath(sub) if not fileutil.exists(scenesPath): return [] return [ scene for scene in os.listdir(scenesPath) if scene.endswith(SCENE_EXT) ]
def getPath(iconName): folder = os.path.dirname(__file__) for fmt in FORMATS: o = '%s/%s.%s' % (folder, iconName, fmt) if fileutil.exists(o): return o raise Exception('Icon not found: %s' % iconName)
def projectOpened(self): self.start = float(gSettings.value('TimerStartTime', 0.0)) endTime = float(gSettings.value('TimerEndTime', 8.0)) self.time = float(gSettings.value('TimerTime', 0.0)) project = ProjectFile() if project and fileutil.exists(project): with fileutil.read(project) as fh: text = fh.read() try: root = cElementTree.fromstring(text) except: root = None if root is not None: self.minTime = float(root.attrib.get('TimerMinTime', 0.0)) self.maxTime = float(root.attrib.get('TimerMaxTime', 8.0)) self.end = min(endTime, self.maxTime) self.__BPS = float(root.attrib.get('TimerBPS', 2.0)) self.__osc.setBpm(int(round(self.__BPS * 60))) self.bpmChanged.emit(self.__BPS * 60.0) return # legacy project / creating new project self.minTime = 0.0 self.maxTime = 4.0 self.end = min(endTime, self.maxTime) self.__BPS = float(gSettings.value('TimerBPS', 2.0)) self.__osc.setBpm(int(round(self.__BPS * 60))) self.bpmChanged.emit(self.__BPS * 60.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 = os.path.join(ProjectDir(), 'animationprocessor.py') if fileutil.exists(modifier): 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(os.path.join(os.path.dirname(os.path.abspath(__file__)), '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)
def __initializeProject(self): if gSettings.contains('currentproject'): project = str(gSettings.value('currentproject')) if fileutil.exists(project): self.__openProject(project) return project = [x for x in list(os.listdir(os.getcwd())) if x.endswith(PROJ_EXT)] if project: self.__openProject(os.path.join(os.getcwd(), project[0])) return
def _saveSceneShots(sceneName, shots): sceneFile = os.path.join(ScenesPath(), sceneName + SCENE_EXT) xScene = ParseXMLWithIncludes(sceneFile) # save user camera position per scene userFile = ProjectFile() + '.user' if fileutil.exists(userFile): xUser = ParseXMLWithIncludes(userFile) else: xUser = cElementTree.Element('user') if sceneFile in Scene.cache: cameraData = Scene.cache[sceneFile].cameraData() if cameraData: for xSub in xUser: if xSub.tag == 'scene' and xSub.attrib['name'] == sceneName: xSub.attrib['camera'] = ','.join([str(x) for x in cameraData]) break else: cElementTree.SubElement(xUser, 'scene', {'name': sceneName, 'camera': ','.join([str(x) for x in cameraData])}) with fileutil.edit(userFile) as fh: fh.write(toPrettyXml(xUser)) # remove old shots r = [] for xShot in xScene: r.append(xShot) for s in r: xScene.remove(s) targets = [] for shot in shots: if shot.sceneName == sceneName: targets.append(shot) for shot in targets: xShot = cElementTree.SubElement(xScene, 'Shot', {'name': shot.name, 'scene': sceneName, 'start': str(shot.start), 'end': str(shot.end), 'enabled': str(shot.enabled), 'speed': str(shot.speed), 'preroll': str(shot.preroll)}) for curveName in shot.curves: xChannel = cElementTree.SubElement(xShot, 'Channel', {'name': curveName, 'mode': 'hermite'}) data = [] for key in shot.curves[curveName]: data.append(str(key.inTangent.x)) data.append(str(key.inTangent.y)) data.append(str(key.point().x)) data.append(str(key.point().y)) data.append(str(key.outTangent.x)) data.append(str(key.outTangent.y)) data.append(str(int(key.tangentBroken))) data.append(str(key.tangentMode)) xChannel.text = ','.join(data) for texName in shot.textures: cElementTree.SubElement(xShot, 'Texture', {'name': texName, 'path': shot.textures[texName]}) with fileutil.edit(sceneFile) as fh: fh.write(toPrettyXml(xScene))
def Templates(sub=''): templatesPath = TemplatesPath(sub) for sub in os.listdir(templatesPath): if not sub.endswith(TEMPLATE_EXT): continue if not os.path.isfile( os.path.join(templatesPath, sub).replace('\\', '/')): continue name = os.path.splitext(sub)[0] if fileutil.exists(os.path.join(templatesPath, name)): yield name
def __onOpenProject(self): if gSettings.contains('currentproject') and QMessageBox.warning(self, 'Changing project', 'Any unsaved changes will be lost. Continue?', QMessageBox.Yes | QMessageBox.No) == QMessageBox.No: return currentPath = os.getcwd() if gSettings.contains('currentproject'): project = str(gSettings.value('currentproject')) if fileutil.exists(project): currentPath = os.path.dirname(project) res = QFileDialog.getOpenFileName(self, 'Open project', currentPath, 'Project files (*%s)' % PROJ_EXT) if not res: return self.__openProject(res)
def __onAddImage(self): uniformName = QInputDialog.getText(self, 'Add texture', 'Uniform name', QLineEdit.Normal, 'uTextures[0]') if not uniformName[0] or not uniformName[1]: return uniformName = uniformName[0] imagePath = QFileDialog.getOpenFileName(self, ProjectDir(), '', 'Image files (*.png;*.bmp;*.jpg;*.jpeg;*.tiff);;Raw Gray F32 map (*.r32)') if imagePath and fileutil.exists(imagePath): relPath = os.path.relpath(imagePath, ProjectDir()) self.__target.textures[uniformName] = relPath nameItem = QStandardItem(uniformName) nameItem.setIcon(QIcon(imagePath)) pathItem = QStandardItem(relPath) pathItem.setFlags(pathItem.flags() & ~Qt.ItemIsEditable) self.__model.appendRow([nameItem, pathItem])
def initializeGL(self): print glGetString(GL_VERSION) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LEQUAL) # glDepthMask(GL_TRUE) IMAGE_EXTENSIONS = '.png', '.bmp', '.tga' textureFolder = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Textures') if fileutil.exists(textureFolder): for texture in os.listdir(textureFolder.replace('\\', '/')): fname, ext = os.path.splitext(texture) if ext.lower() in IMAGE_EXTENSIONS: self._textures[fname] = loadImage(os.path.join(textureFolder, texture)) self._prevTime = time.time() self._timer.kick()
def saveState(self): gSettings.setValue('TimerStartTime', self.__start) gSettings.setValue('TimerEndTime', self.__end) gSettings.setValue('TimerTime', self.__time) project = ProjectFile() if not project or not fileutil.exists(project): # legacy project or no project open gSettings.setValue('TimerMinTime', self.__minTime) gSettings.setValue('TimerMaxTime', self.__maxTime) gSettings.setValue('TimerBPS', self.__BPS) return root = cElementTree.Element('Project') root.attrib['TimerMinTime'] = str(self.__minTime) root.attrib['TimerMaxTime'] = str(self.__maxTime) root.attrib['TimerBPS'] = str(self.__BPS) with fileutil.edit(project, 'w') as fh: fh.write(toPrettyXml(root))
def __onNewProject(self): if gSettings.contains('currentproject') and QMessageBox.warning(self, 'Creating new project', 'Any unsaved changes will be lost. Continue?', QMessageBox.Yes | QMessageBox.No) == QMessageBox.No: return currentPath = os.getcwd() if gSettings.contains('currentproject'): project = str(gSettings.value('currentproject')) if fileutil.exists(project): currentPath = os.path.dirname(project) res = QFileDialog.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 = os.path.join(res, os.path.basename(res) + PROJ_EXT) fileutil.create(projectFile) self.__openProject(projectFile)
def source_setup(setupshell,options='',envRE=None): """Extract (part of) the environment of setup shell script <setupshell> using regular expressions <envRE> to select which environment variables to setup. envRE=None (default) means all environment vars. The <options> are given as arguments to the setup script. The environment is added to os.environ.""" if not fileutil.exists(setupshell): raise EnvironmentError( 'setup script %s not found' % (setupshell) ) # make sure that path starts with . (dot) if no absolute path is given # This is needed and desired because when sourcing a file, it is looked for # in PATH, whereas this is never what people intend (always want local) if os.path.isabs(setupshell): fullsetup = setupshell elif not (setupshell.startswith(os.curdir) or setupshell.startswith(os.pardir)): fullsetup = os.path.join(os.curdir,setupshell) source_cmd = 'source %s %s' % ( fullsetup, options ) print source_cmd newenv = getenv_from_output( source_cmd + '; printenv', envRE ) update_env(newenv) return newenv
def runctx(cmdstr, globals={}, locals={}, outpath=None, executable=None): tmp = tempfile.mktemp() if outpath is not None: path = os.path.splitext(outpath)[0] + '.callgrind' dirpath = os.path.dirname(path) if not fileutil.exists(dirpath): os.makedirs(dirpath.replace('\\', '/')) cProfile.runctx(cmdstr, globals, locals, filename=tmp) pyprof2calltree.convert(pstats.Stats(tmp), path) if executable is not None: subprocess.Popen([executable, path]) os.unlink(tmp) return path cProfile.runctx(cmdstr, globals, locals, filename=tmp) pyprof2calltree.convert(pstats.Stats(tmp), tmp) if executable is not None: subprocess.Popen([executable, tmp]) return tmp
def __onAddScene(self): # request user for a template if there are multiple options templates = list(Templates(self.__subFolder)) if not templates: QMessageBox.critical( self, 'Could not create scene', 'Can not add scenes to this project until a template has been made to base them off.' ) return if len(templates) == 1: templateDir = TemplateSourceFolderFromName(templates[0], self.__subFolder) templatePath = TemplateFileFromName(templates[0], self.__subFolder) else: template = QInputDialog.getItem(self, 'Create scene', 'Select template', templates, 0, False) if not template[1] or not template[0] in templates: return templateDir = TemplateSourceFolderFromName(template[0], self.__subFolder) templatePath = TemplateFileFromName(template[0], self.__subFolder) name = QInputDialog.getText(self, 'Create scene', 'Scene name') if not name[1]: return scenesPath = ScenesPath(self.__subFolder) outFile = os.path.join(scenesPath, name[0] + SCENE_EXT) outDir = os.path.join(scenesPath, name[0]) if fileutil.exists(outFile): QMessageBox.critical( self, 'Could not create scene', 'A scene with name "%s" already exists. No scene was created.' % name[0]) return if fileutil.exists(outDir): if QMessageBox.warning( self, 'Scene not empty', 'A folder with name "%s" already exists. Create scene anyways?' % name[0], QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Cancel: return else: os.makedirs(outDir.replace('\\', '/')) with fileutil.edit(outFile) as fh: fh.write('<scene camera="0,1,-10,0,0,0" template="%s"/>' % os.path.relpath(templatePath, scenesPath)) # find required template inputs (sections) xTemplate = ParseXMLWithIncludes(templatePath) for xPass in xTemplate: for xElement in xPass: if xElement.tag.lower() != 'section': continue # given a section make a stub file so the scene is complete on disk resource = os.path.join(templateDir, xElement.attrib['path']) text = '' # copy template data if there is any if fileutil.exists(resource): with fileutil.read(resource) as fh: text = fh.read() with fileutil.edit( os.path.join(outDir, xElement.attrib['path'])) as fh: fh.write(text) self.appendSceneItem(name[0])
def __record(self): diag = QDialog() fId = gSettings.value('RecordFPS', 2) rId = gSettings.value('RecordResolution', 3) layout = QGridLayout() diag.setLayout(layout) layout.addWidget(QLabel('FPS: '), 0, 0) fps = QComboBox() fps.addItems(['12', '24', '30', '48', '60', '120']) fps.setCurrentIndex(fId) layout.addWidget(fps, 0, 1) layout.addWidget(QLabel('Vertical resolution: '), 1, 0) resolution = QComboBox() resolution.addItems(['144', '288', '360', '720', '1080', '2160']) resolution.setCurrentIndex(rId) layout.addWidget(resolution, 1, 1) ok = QPushButton('Ok') ok.clicked.connect(diag.accept) cancel = QPushButton('Cancel') cancel.clicked.connect(diag.reject) layout.addWidget(ok, 2, 0) layout.addWidget(cancel, 2, 1) diag.exec_() if diag.result() != QDialog.Accepted: return gSettings.setValue('RecordFPS', fps.currentIndex()) gSettings.setValue('RecordResolution', resolution.currentIndex()) FPS = int(fps.currentText()) HEIGHT = int(resolution.currentText()) WIDTH = (HEIGHT * 16) / 9 FMT = 'jpg' data = (ctypes.c_ubyte * (WIDTH * HEIGHT * 3))() # alloc buffer once flooredStart = self._timer.secondsToBeats(int(self._timer.beatsToSeconds(self._timer.start) * FPS) / float(FPS)) duration = self._timer.beatsToSeconds(self._timer.end - flooredStart) if not fileutil.exists('capture'): os.makedirs('capture') progress = QProgressDialog(self) progress.setMaximum(int(duration * FPS)) prevFrame = 0 for frame in xrange(int(duration * FPS)): deltaTime = (frame - prevFrame) / float(FPS) prevFrame = frame progress.setValue(frame) QApplication.processEvents() if progress.wasCanceled(): break beats = flooredStart + self._timer.secondsToBeats(frame / float(FPS)) shot = self.__shotsManager.shotAtTime(beats) if shot is None: continue sceneFile = os.path.join(ScenesPath(), shot.sceneName + SCENE_EXT) scene = Scene.getScene(sceneFile) scene.setSize(WIDTH, HEIGHT) uniforms = self.__shotsManager.evaluate(beats) textureUniforms = self.__shotsManager.additionalTextures(beats) self.__sceneView._cameraInput.setData(*(uniforms['uOrigin'] + uniforms['uAngles'])) # feed animation into camera so animationprocessor can read it again cameraData = self.__sceneView._cameraInput.data() modifier = os.path.join(ProjectDir(), 'animationprocessor.py') if fileutil.exists(modifier): execfile(modifier, globals(), locals()) for name in self.__sceneView._textures: uniforms[name] = self.__sceneView._textures[name]._id scene.drawToScreen(self._timer.beatsToSeconds(beats), beats, uniforms, (0, 0, WIDTH, HEIGHT), textureUniforms) scene.colorBuffers[-1][0].use() from OpenGL.GL import glGetTexImage, GL_TEXTURE_2D, GL_RGB, GL_UNSIGNED_BYTE glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, data) QImage(data, WIDTH, HEIGHT, QImage.Format_RGB888).mirrored(False, True).save('capture/dump_%s_%05d.%s' % (FPS, int(self._timer.beatsToSeconds(self._timer.start) * FPS) + frame, FMT)) progress.close() if not fileutil.exists('convertcapture'): os.makedirs('convertcapture') with fileutil.edit('convertcapture/convert.bat') as fh: start = '' start2 = '' if int(self._timer.start * FPS) > 0: start = '-start_number {} '.format(int(self._timer.beatsToSeconds(self._timer.start) * FPS)) start2 = '-vframes {} '.format(int(self._timer.beatsToSeconds(self._timer.end - self._timer.start) * FPS)) fh.write('cd "../capture"\n"../convertcapture/ffmpeg.exe" -framerate {} {}-i dump_{}_%%05d.{} {}-c:v libx264 -r {} -pix_fmt yuv420p "../convertcapture/output.mp4"'.format(FPS, start, FPS, FMT, start2, FPS)) with fileutil.edit('convertcapture/convertGif.bat') as fh: start = '' start2 = '' if int(self._timer.start * FPS) > 0: start = '-start_number {} '.format(int(self._timer.beatsToSeconds(self._timer.start) * FPS)) start2 = '-vframes {} '.format(int(self._timer.beatsToSeconds(self._timer.end - self._timer.start) * FPS)) fh.write('cd "../capture"\n"../convertcapture/ffmpeg.exe" -framerate {} {}-i dump_{}_%%05d.{} {}-r {} "../convertcapture/output.gif"'.format(FPS, start, FPS, FMT, start2, FPS)) sound = self.timeSlider.soundtrackPath() if not sound: return with fileutil.edit('convertcapture/merge.bat') as fh: startSeconds = self._timer.beatsToSeconds(self._timer.start) fh.write('ffmpeg -i output.mp4 -itsoffset {} -i "{}" -vcodec copy -shortest merged.mp4'.format(-startSeconds, sound))