def __init__(self, name, parent): super(PathNode, self).__init__(name, parent) self._setSliceable(True) self._inPath = StringAttribute("input", self) self._op = EnumAttribute("operation", self) self._out = StringAttribute("output", self) self._allOps = [("split", os.path.split, "StringArray"), ("splitAll", None, "StringArray"), ("dirname", os.path.dirname, "Path"), ("basename", os.path.basename, "String"), ("splitext", os.path.splitext, "StringArray")] for n, op in enumerate(self._allOps): self._op.value().addEntry(n, op[0]) self._setAttributeAllowedSpecializations(self._inPath, ["Path", "PathArray"]) self._setAttributeAllowedSpecializations( self._out, ["String", "Path", "StringArray"]) self.addInputAttribute(self._inPath) self.addInputAttribute(self._op) self.addOutputAttribute(self._out) self._setAttributeAffect(self._inPath, self._out) self._setAttributeAffect(self._op, self._out) # self._catchAttributeDirtied(self._inPath, True) self._catchAttributeDirtied(self._op, True)
def __init__(self, name, parent): super(PathNode, self).__init__(name, parent) self._setSliceable(True) self._inPath = StringAttribute("input", self) self._op = EnumAttribute("operation", self) self._out = StringAttribute("output", self) self._allOps = [("split", os.path.split, "StringArray"), ("splitAll", None, "StringArray"), ("dirname", os.path.dirname, "Path"), ("basename", os.path.basename, "String"), ("splitext", os.path.splitext, "StringArray") ] for n, op in enumerate(self._allOps): self._op.value().addEntry(n, op[0]) self._setAttributeAllowedSpecializations(self._inPath, ["Path", "PathArray"]) self._setAttributeAllowedSpecializations(self._out, ["String", "Path", "StringArray"]) self.addInputAttribute(self._inPath) self.addInputAttribute(self._op) self.addOutputAttribute(self._out) self._setAttributeAffect(self._inPath, self._out) self._setAttributeAffect(self._op, self._out) # self._catchAttributeDirtied(self._inPath, True) self._catchAttributeDirtied(self._op, True)
def __init__(self, name, parent): Node.__init__(self, name, parent) self._path = StringAttribute('filename', self) self._points = NumericAttribute('points', self) self._data = NumericAttribute('data', self) self._format = EnumAttribute('format', self) self._frame = NumericAttribute('frame', self) self._startFrame = NumericAttribute('startFrame', self) self._endFrame = NumericAttribute('endFrame', self) #self._geo = GeoAttribute('geo', self) self.addInputAttribute(self._path) self.addInputAttribute(self._points) self.addInputAttribute(self._data) self.addInputAttribute(self._format) self.addInputAttribute(self._frame) self.addInputAttribute(self._startFrame) self.addInputAttribute(self._endFrame) self._format.value().addEntry(0, 'pc2') self._format.value().addEntry(1, 'ascii') self._format.value().setCurrentIndex(0) self._setAttributeAllowedSpecializations(self._path, ['Path-write']) self._setAttributeAllowedSpecializations(self._points, ['Vec3Array']) self._setAttributeAllowedSpecializations(self._data, ['Float']) self._setAttributeAllowedSpecializations(self._frame, ['Float']) self._setAttributeAllowedSpecializations(self._startFrame, ['Float']) self._setAttributeAllowedSpecializations(self._endFrame, ['Float'])
class PathNode(Node): """Node for doing different pathing operations """ def __init__(self, name, parent): super(PathNode, self).__init__(name, parent) self._setSliceable(True) self._inPath = StringAttribute("input", self) self._op = EnumAttribute("operation", self) self._out = StringAttribute("output", self) self._allOps = [("split", os.path.split, "StringArray"), ("splitAll", None, "StringArray"), ("dirname", os.path.dirname, "Path"), ("basename", os.path.basename, "String"), ("splitext", os.path.splitext, "StringArray")] for n, op in enumerate(self._allOps): self._op.value().addEntry(n, op[0]) self._setAttributeAllowedSpecializations(self._inPath, ["Path", "PathArray"]) self._setAttributeAllowedSpecializations( self._out, ["String", "Path", "StringArray"]) self.addInputAttribute(self._inPath) self.addInputAttribute(self._op) self.addOutputAttribute(self._out) self._setAttributeAffect(self._inPath, self._out) self._setAttributeAffect(self._op, self._out) # self._catchAttributeDirtied(self._inPath, True) self._catchAttributeDirtied(self._op, True) def attributeDirtied(self, attribute): if attribute == self._op: index = self._op.value().currentIndex() self._out._setSpecialization([self._allOps[index][2]]) def updateSlice(self, attribute, slice): logger.debug("PathNode - updateSlice") inPaths = self._inPath.value().stringValuesSlice(slice) opIndex = self._op.value().currentIndex() for ip in inPaths: if ip == "": continue out = [] if self._allOps[opIndex][1] == None: if self._allOps[opIndex][0] == "splitAll": out = ip.split(os.sep) else: op = self._allOps[opIndex] out = op[1](ip) if isinstance(out, tuple): out = list(out) if not isinstance(out, list): out = [out] self._out.outValue().setPathValuesSlice(slice, out) logger.debug("PathNode - updateSlice: complete")
class PathNode(Node): """Node for doing different pathing operations """ def __init__(self, name, parent): super(PathNode, self).__init__(name, parent) self._setSliceable(True) self._inPath = StringAttribute("input", self) self._op = EnumAttribute("operation", self) self._out = StringAttribute("output", self) self._allOps = [("split", os.path.split, "StringArray"), ("splitAll", None, "StringArray"), ("dirname", os.path.dirname, "Path"), ("basename", os.path.basename, "String"), ("splitext", os.path.splitext, "StringArray") ] for n, op in enumerate(self._allOps): self._op.value().addEntry(n, op[0]) self._setAttributeAllowedSpecializations(self._inPath, ["Path", "PathArray"]) self._setAttributeAllowedSpecializations(self._out, ["String", "Path", "StringArray"]) self.addInputAttribute(self._inPath) self.addInputAttribute(self._op) self.addOutputAttribute(self._out) self._setAttributeAffect(self._inPath, self._out) self._setAttributeAffect(self._op, self._out) # self._catchAttributeDirtied(self._inPath, True) self._catchAttributeDirtied(self._op, True) def attributeDirtied(self, attribute): if attribute == self._op: index = self._op.value().currentIndex() self._out._setSpecialization([self._allOps[index][2]]) def updateSlice(self, attribute, slice): logger.debug("PathNode - updateSlice") inPaths = self._inPath.value().stringValuesSlice(slice) opIndex = self._op.value().currentIndex() for ip in inPaths: if ip == "": continue out = [] if self._allOps[opIndex][1] == None: if self._allOps[opIndex][0] == "splitAll": out = ip.split(os.sep) else: op = self._allOps[opIndex] out = op[1](ip) if isinstance(out, tuple): out = list(out) if not isinstance(out, list): out = [out] self._out.outValue().setPathValuesSlice(slice, out) logger.debug("PathNode - updateSlice: complete")
class WriteNode(Node): def __init__(self, name, parent): Node.__init__(self, name, parent) self._path = StringAttribute('filename', self) self._points = NumericAttribute('points', self) self._data = NumericAttribute('data', self) self._format = EnumAttribute('format', self) self._frame = NumericAttribute('frame', self) self._startFrame = NumericAttribute('startFrame', self) self._endFrame = NumericAttribute('endFrame', self) #self._geo = GeoAttribute('geo', self) self.addInputAttribute(self._path) self.addInputAttribute(self._points) self.addInputAttribute(self._data) self.addInputAttribute(self._format) self.addInputAttribute(self._frame) self.addInputAttribute(self._startFrame) self.addInputAttribute(self._endFrame) self._format.value().addEntry(0, 'pc2') self._format.value().addEntry(1, 'ascii') self._format.value().setCurrentIndex(0) self._setAttributeAllowedSpecializations(self._path, ['Path-write']) self._setAttributeAllowedSpecializations(self._points, ['Vec3Array']) self._setAttributeAllowedSpecializations(self._data, ['Float']) self._setAttributeAllowedSpecializations(self._frame, ['Float']) self._setAttributeAllowedSpecializations(self._startFrame, ['Float']) self._setAttributeAllowedSpecializations(self._endFrame, ['Float']) def update(self, attribute): pass def write(self): # first we check if something is connected to the frame attr if self._frame.input() is None: raise RuntimeError('A time node isn\'t connected to \'frame\'') time_node = self._frame.input().parent() # and is it a time node? if time_node.className() != 'Time': raise RuntimeError('Input of \'frame\' is not a Time node.') time_attr = time_node.findAttribute('time') # check the output path and range attrs output_path = self._path.value().stringValue() if output_path.strip() == '': raise RuntimeError('No output path specified.') start_frame = self._startFrame.value().floatValueAt(0) end_frame = self._endFrame.value().floatValueAt(0) if start_frame >= end_frame: raise RuntimeError('End is before start.') # create the folder for the output try: os.makedirs(os.path.dirname(output_path)) except os.error: pass except Exception, err: raise RuntimeError('Unable to create folder %s: %s' % (os.path.dirname(output_path), str(err))) selected_format = self._format.value().entries()[self._format.value().currentIndex()] if selected_format == 'pc2': # I learned how to write pc 2 caches in python from Matt Ebb's script for blender:http://mattebb.com/projects/bpython/pointcache/export_pc2.py import struct if self._points.input() is not None: num_points = len(self._points.value().vec3Values()) sample_rate = 1.0 # TODO:support various sample rates? num_samples = int(end_frame) - int(start_frame) pc2_path = os.path.splitext(output_path)[0] + '.pc2' f = open(pc2_path, 'wt') header = struct.pack('<12ciiffi', 'P','O','I','N','T','C','A','C','H','E','2','\0', 1, num_points, int(start_frame), sample_rate, num_samples) f.write(header) for i in range(int(start_frame), int(end_frame+1)): time_attr.value().setFloatValueAt(0,i) time_attr.forceDirty() for p in self._points.value().vec3Values(): point = struct.pack('<fff', p.x, p.y, p.z) f.write(point) f.flush() f.close() else: raise RuntimeError('No data to write!') elif selected_format == 'ascii': f = open(output_path, 'wt') ''' I decided to check what input to use from inside the loop because it makes things a bit clearer and a simple speed comparison show it isn't _that_ much of a slowdown. With 100000 frames (the points array was 10 elements) I got these write times: points: 14.098s (loop inside input check) vs 14.34s (check inside loop) float: 4.036 (loop inside input check) vs 4.55 (check inside loop) ''' for i in range(int(start_frame), int(end_frame+1)): time_attr.value().setFloatValueAt(0,i) time_attr.forceDirty() if self._points.input() is not None: for p in self._points.value().vec3Values(): f.write('<%f %f %f>, ' % (p.x, p.y, p.z)) f.write('\n') elif self._data.input() is not None: f.write('%s\n' % str(self._data.value().floatValueAt(0))) else: f.close() raise RuntimeError('No data to write!') f.close()