def main(): global OutputObject global runcount global min_Frame global max_Frame op.SetName("--- OBJ Sequence Reader by George Adamon ---") SetupUserData() OutputObject = c4d.BaseObject(c4d.Onull) multifile = ud.GetUserDataValue(op, "Load All") if not multifile: currentPath = ResolveFilename( ud.GetUserDataValue(op, "First Object FileName")) ImportToCinema(currentPath) else: for i in range(min_Frame, max_Frame): currentPath = ResolveFilename( ud.GetUserDataValue(op, "First Object FileName"), i) ImportToCinema(currentPath) print str.format("The generator has run {0} times.", runcount) return OutputObject
def ReadUserData(): global fileContainsHeaders global filePath global fileName global isQuad global size global referencedCloner fileContainsHeaders = ud.GetUserDataValue(op, "Data Has Headers") filePath = ud.GetUserDataValue(op, "Transformation Matrices File") fileName = os.path.basename(filePath).split(".")[0] isQuad = ud.GetUserDataValue(op, "Display Matrices As") == 0 size = ud.GetUserDataValue(op, "Display Size") referencedCloner = ud.GetUserDataValue(op, "Attach to Cloner")
def ConstructFrame(Frame=-1): """ Accepts a provided FileName pointing to the first object of the sequence to import, and figures out the apporppriate filename to load based on the current animation frame. Args: filename: The filename of the first object in the OBJ sequence Returns: Path: the filename of the actual object to load. """ global min_Frame global max_Frame global digitCount if Frame <= -1: first = max(ud.GetUserDataValue(op, "First Frame"), min_Frame) last = min(ud.GetUserDataValue(op, "Last Frame"), max_Frame) ud.SetUserDataValue(op, "First Frame", first) ud.SetUserDataValue(op, "Last Frame", last) step = ud.GetUserDataValue(op, "Frame Step") offset = ud.GetUserDataValue(op, "Frame Offset") after = ud.GetUserDataValue(op, "After Last Frame") frame = doc.GetTime().GetFrame(doc.GetFps()) + offset if frame % step != 0: frame = frame - (frame % step) #Frame skipping if after == 0: if last <= first: frame = max(frame, first) #open ended sequence, no max limit else: frame = max(min(frame, last), first) # Min and Max limit applied elif after == 1: frame = frame % last elif after == 2: if (frame // last) % 2 == 0: frame = frame % last else: frame = last - (frame % last) elif after == 3: if frame > last or frame < first: return -1 else: frame = Frame formatted_frame = str(frame).zfill( digitCount) # Fill number with zeros if necessary return formatted_frame
def SetupUserData(): #1.1: UI Header if not ud.UserDataExists(op, "File Handling"): ud.CreateUserData(op, "File Handling", c4d.DTYPE_SEPARATOR) #1.2: "Filename" text box if not ud.UserDataExists(op, "Transformation Matrices File"): ud.CreateUserData(op, "Transformation Matrices File", c4d.DTYPE_FILENAME) #1.3 if not ud.UserDataExists(op, "Data Has Headers"): ud.CreateUserData(op, "Data Has Headers", c4d.DTYPE_BOOL) #2.1: UI Header if not ud.UserDataExists(op, "Display"): ud.CreateUserData(op, "Display", c4d.DTYPE_SEPARATOR) #2.2: "Object Type" text box if not ud.UserDataExists(op, "Display Matrices As"): ud.CreateDropDown(op, "Display Matrices As", c4d.CUSTOMGUI_CYCLE, ["Quad", "Triangle"]) #2.3: "Display Size" slider if not ud.UserDataExists(op, "Display Size"): ud.CreateFloatData(op, "Display Size", "Float Slider", 0, 100, 0.01, "Meters") #3.1: UI Header if not ud.UserDataExists(op, "Pipeline"): ud.CreateUserData(op, "Pipeline", c4d.DTYPE_SEPARATOR) #3.2: "Filename" text box if not ud.UserDataExists(op, "Attach to Cloner"): ud.CreateUserData(op, "Attach to Cloner", c4d.DTYPE_BASELISTLINK)
def ImportToCinema(PATH): #global Polygon global OutputObject global runcount global prev_filename #SetupUserData() #PATH = ResolveFilename(ud.GetUserDataValue(op, "First Object FileName")) if PATH != None and PATH != -1: N = os.path.basename(PATH) FaceUV = [] # LOAD OBJ FILE Vertices, \ Faces, \ Colors, \ VertexNormals, \ VertexUV, \ FaceNormals, \ FaceUV = OBJ.ParseObj(PATH, ud.GetUserDataValue(op, "Swap Y/Z"), ud.GetUserDataValue(op, "Flip Z"), ud.GetUserDataValue(op, "Scale")) ud.SetUserDataValue(op, "Vertices", str(len(Vertices))) ud.SetUserDataValue(op, "Colors", str(len(Colors))) ud.SetUserDataValue(op, "Faces", str(len(Faces))) Polygon = c4d.BaseObject(c4d.Opolygon) Polygon.ResizeObject( len(Vertices), len(Faces)) #New number of points, New number of polygons Polygon.SetName(N) UpdateVertexCoordinates(Polygon, Vertices) UpdateFaces(Polygon, Faces) if len(FaceUV) > 0: UpdateUV(Polygon, FaceUV, VertexUV) if ud.GetUserDataValue(op, "Import Vertex Colors"): UpdateVertexColors(Polygon, Colors) if ud.GetUserDataValue(op, "Create Test Material"): UpdateMaterial(Polygon) if ud.GetUserDataValue(op, "Phong Smoothing"): Polygon.CreatePhongNormals() Polygon.SetPhong(True, True, 90) else: Polygon.SetPhong(False, True, 90) if len(Vertices) == 0 and len(Faces) == 0: msg = ">>> Mesh Succesfully Loaded, but has no Vertices, neither Faces. It's OK, though." ud.SetUserDataValue(op, "Mesh Handling Message", msg) elif len(Vertices) == 0: msg = ">>> Mesh Succesfully Loaded, but has no Vertices. It's OK, though." ud.SetUserDataValue(op, "Mesh Handling Message", msg) elif len(Faces) == 0: msg = ">>> Mesh Succesfully Loaded, but has no Faces. It's OK, though." ud.SetUserDataValue(op, "Mesh Handling Message", msg) else: msg = ">>> Mesh Succesfully Loaded! It should appear in the Viewport." ud.SetUserDataValue(op, "Mesh Handling Message", msg) runcount += 1 prev_filename = ud.GetUserDataValue(op, "First Object FileName") Polygon.InsertUnder(OutputObject) return elif PATH == -1: msg = "Outside of Frame Range." ud.SetUserDataValue(op, "Mesh Handling Message", msg) return else: msg = "No Mesh Loaded, because of faulty Filename. Check the File Handling Message above." ud.SetUserDataValue(op, "Mesh Handling Message", msg) return
def SetupUserData(): """ Setup the UI of the Python Generator object """ # ------------------------------------------------------------------------------------------------------------------ # 1 - FILE HANDLING UI --------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ # 1.1: UI Header if not ud.UserDataExists(op, "File Handling"): ud.CreateUserData(op, "File Handling", c4d.DTYPE_SEPARATOR) # 1.2: "Filename" text box if not ud.UserDataExists(op, "First Object FileName"): ud.CreateUserData(op, "First Object FileName", c4d.DTYPE_FILENAME, True) # 1.3: "Load All" Boolean, determines whether to load all files in the folder at once if not ud.UserDataExists(op, "Load All"): ud.CreateUserData(op, "Load All", c4d.DTYPE_BOOL) # 1.4 if not ud.UserDataExists(op, "First Frame"): ud.CreateIntegerData(op, "First Frame", "Integer") # 1.5 if not ud.UserDataExists(op, "Last Frame"): ud.CreateIntegerData(op, "Last Frame", "Integer") # 1.6 if not ud.UserDataExists(op, "Frame Step"): ud.CreateIntegerData(op, "Frame Step", "Integer Slider") ud.SetUserDataValue(op, "Frame Step", 1) # 1.7 if not ud.UserDataExists(op, "Frame Offset"): ud.CreateIntegerData(op, "Frame Offset", "Integer Slider") ud.SetUserDataValue(op, "Frame Offset", 0) # 1.8 if not ud.UserDataExists(op, "After Last Frame"): ud.CreateDropDown(op, "After Last Frame", "Cycle", ["Freeze", "Loop", "Ping Pong", "Disappear"]) ud.SetUserDataValue(op, "After Last Frame", 0) # 1.9 if not ud.UserDataExists(op, "File Handling Message"): ud.CreateUserData(op, "File Handling Message", c4d.DTYPE_STATICTEXT, True) # ------------------------------------------------------------------------------------------------------------------ # 2 - MESH HANDLING UI --------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ # 2.1 if not ud.UserDataExists(op, "Mesh Handling"): ud.CreateUserData(op, "Mesh Handling", c4d.DTYPE_SEPARATOR) # 2.2 if not ud.UserDataExists(op, "Phong Smoothing"): ud.CreateUserData(op, "Phong Smoothing", c4d.DTYPE_BOOL) # 2.3 if not ud.UserDataExists(op, "Import Vertex Colors"): ud.CreateUserData(op, "Import Vertex Colors", c4d.DTYPE_BOOL) # 2.4 if not ud.UserDataExists(op, "Create Test Material"): ud.CreateUserData(op, "Create Test Material", c4d.DTYPE_BOOL) # 2.5 if not ud.UserDataExists(op, "Mesh Handling Message"): ud.CreateUserData(op, "Mesh Handling Message", c4d.DTYPE_STATICTEXT, True) # 2.6 if not ud.UserDataExists(op, "Vertices"): ud.CreateUserData(op, "Vertices", c4d.DTYPE_STATICTEXT, True) # 2.7 if not ud.UserDataExists(op, "Colors"): ud.CreateUserData(op, "Colors", c4d.DTYPE_STATICTEXT, True) # 2.8 if not ud.UserDataExists(op, "Faces"): ud.CreateUserData(op, "Faces", c4d.DTYPE_STATICTEXT, True) # ------------------------------------------------------------------------------------------------------------------ # 3 - COORDINATE HANDLING UI --------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ # 3.1 if not ud.UserDataExists(op, "Coordinate Handling"): ud.CreateUserData(op, "Coordinate Handling", c4d.DTYPE_SEPARATOR) # 3.2 if not ud.UserDataExists(op, "Swap Y/Z"): ud.CreateUserData(op, "Swap Y/Z", c4d.DTYPE_BOOL) # 3.3 if not ud.UserDataExists(op, "Flip Z"): ud.CreateUserData(op, "Flip Z", c4d.DTYPE_BOOL) # 3.4 if not ud.UserDataExists(op, "Scale"): ud.CreateFloatData(op, "Scale", "Float Slider", 0.0, 1000.0, 0.1) ud.SetUserDataValue(op, "Scale", 1)
def ResolveFilename(filename, Frame=-1): """ Accepts a provided FileName pointng to the first object of the sequence to import, and figures out the apporppriate filename to load based on the current animation frame. Args: filename: The filename of the first object in the OBJ sequence Returns: Path: the filename of the actual object to load. """ global runcount global prev_filename global min_Frame global max_Frame global digitCount # ------------------------------------------------------------------------------------------------------------------ # FILE ERROR HANDLING ---------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ if not filename: msg = ">>> Empty Filename. Please provide a link to the FIRST item of the sequence you want to import" ud.SetUserDataValue(op, "File Handling Message", msg) return if not exists(filename): msg = ">>> Invalid FileName. Please provide a link to an existing file or folder." ud.SetUserDataValue(op, "File Handling Message", msg) return if not isfile(filename): msg = ">>> Invalid FileType. Please provide a link to an .obj file, not to a folder." ud.SetUserDataValue(op, "File Handling Message", msg) return if not splitext(filename)[1] == ".obj": msg = ">>> Invalid FileType. Please provide an .obj file." ud.SetUserDataValue(op, "File Handling Message", msg) return directory, fullname, name, extension = SplitPath(filename) parts = filter(None, re.split( r'(\d+)', name)) # Split the digit and non-digit parts of the name if parts[-1].isdigit(): #if the last part is digit, use it digit = parts[-1] else: msg = ">>> Invalid Naming Convention. Please make sure that no other characters exist after your file numbering." ud.SetUserDataValue(op, "File Handling Message", msg) return # ------------------------------------------------------------------------------------------------------------------ # RESET RUN COUNT ON FILE CHANGE ----------------------------------------------------------------------------------- # ------------------------------------------------------------------------------------------------------------------ if not runcount == 0: if not prev_filename == filename: runcount = 0 if len(parts[:-1]) > 1: nonDigitName = " ".join(parts[:-1]).replace(" ", "") else: nonDigitName = parts[0] if runcount == 0: files = GetFiles(directory, ".obj") _digit = 0 for f in files: _d, _f, _n, _e = SplitPath(f) _parts = filter(None, re.split( r'(\d+)', _n)) # Split the digit and non-digit parts of the name if len(_parts[:-1]) > 1: _nonDigitName = " ".join(_parts[:-1]).replace(" ", "") else: _nonDigitName = _parts[0] if _parts[-1].isdigit(): #if the last part is digit, use it _digit = _parts[-1] if _nonDigitName == nonDigitName: if int(_digit) < min_Frame: min_Frame = int(digit) digitCount = len(_digit) if int(_digit) >= max_Frame: max_Frame = int(_digit) ud.SetUserDataValue(op, "First Frame", int(min_Frame)) ud.SetUserDataValue(op, "Last Frame", int(max_Frame)) if Frame <= -1: formatted_frame = ConstructFrame() else: formatted_frame = ConstructFrame(Frame) if formatted_frame != -1: Path = os.path.join(directory, nonDigitName + formatted_frame + extension) msg = ">>> File: ' " + nonDigitName + formatted_frame + extension + " ' succesfully located." ud.SetUserDataValue(op, "File Handling Message", msg) return Path else: return -1
def ResolveFilename(filename): """ Accepts a provided FileName pointng to the first object of the sequence to import, and figures out the apporppriate filename to load based on the current animation frame. Args: filename: The filename of the first object in the OBJ sequence Returns: Path: the filename of the actual object to load. """ first = ud.GetUserDataValue(op.GetObject(), "First Frame") last = ud.GetUserDataValue(op.GetObject(), "Last Frame") step = ud.GetUserDataValue(op.GetObject(), "Frame Step") frame = doc.GetTime().GetFrame(doc.GetFps()) if last <= first: frame = max(frame, first) #op.GetObject()en ended sequence, no max limit else: frame = max(min(frame, last), first) # Min and Max limit applied if frame % step != 0: frame = frame - (frame % step) #Frame skipping if filename == None or filename == "": msg = ">>> Empty Filename. Please provide a link to the FIRST item of the sequence you want to import" ud.SetUserData(op.GetObject(), "File Handling Message", msg) return if os.path.exists(filename) == False: msg = ">>> Invalid FileName. Please provide a link to an existing file or folder." ud.SetUserData(op.GetObject(), "File Handling Message", msg) return if os.path.isfile(filename): directory = os.path.dirname(filename) #Directory of the file fullname = os.path.basename( filename) #Fullname of the file, including extension name, extension = os.path.splitext( fullname) #Split the actual name from the extension if extension != ".obj": msg = ">>> Invalid FileType. Please provide an .obj file." ud.SetUserData(op.GetObject(), "File Handling Message", msg) return parts = filter(None, re.split( r'(\d+)', name)) # Split the digit and non-digit parts of the name if parts[-1].isdigit(): #if the last part is digit, use it digit = parts[-1] else: msg = ">>> Invalid Naming Convention. Please make sure that no other characters exist after your file numbering." ud.SetUserData(op.GetObject(), "File Handling Message", msg) return formatted_frame = str(frame).zfill( len(digit)) # Fill number with zeros if necessary if len(parts[:-1]) > 1: nonDigitName = " ".join(parts[:-1]).replace(" ", "") else: nonDigitName = parts[0] Path = os.path.join(directory, nonDigitName + formatted_frame + extension) msg = ">>> File: ' " + nonDigitName + formatted_frame + extension + " ' succesfully located." ud.SetUserData(op.GetObject(), "File Handling Message", msg) return Path else: msg = ">>> Invalid FileType. Please provide a link to an .obj file, not to a folder." ud.SetUserData(op.GetObject(), "File Handling Message", msg) return
def ImportToCinema(): global Polygon SetupUserData() PATH = ResolveFilename( ud.GetUserDataValue(op.GetObject(), "First Object FileName")) N = os.path.basename(PATH) if PATH != None: Vertices, Faces, Colors = ParseObj(PATH, ud.GetUserDataValue( op.GetObject(), "Swap Y/Z")) #LOAD OBJ FILE children = op.GetObject().GetChildren() if len(children) == 0: Polygon = c4d.BaseObject( c4d.Opolygon) #Create an empty polygon object doc.InsertObject(Polygon, op.GetObject(), None) else: Polygon = children[0] Polygon.ResizeObject(0, 0) Polygon.ResizeObject( len(Vertices), len(Faces)) #New number of points, New number of polygons Polygon.SetName(N) UpdateVertexCoordinates(Vertices) UpdateFaces(Faces) if ud.GetUserDataValue(op.GetObject(), "Import Vertex Colors"): UpdateVertexColors(Colors) if ud.GetUserDataValue(op.GetObject(), "Create Test Material"): UpdateMaterial() if ud.GetUserDataValue(op.GetObject(), "Phong Smoothing"): Polygon.CreatePhongNormals() Polygon.SetPhong(True, True, 90) else: Polygon.SetPhong(False, True, 90) if len(Vertices) == 0 and len(Faces) == 0: msg = ">>> Mesh Succesfully Loaded, but has no Vertices, neither Faces. It's OK, though." ud.SetUserData(op.GetObject(), "Mesh Handling Message", msg) elif len(Vertices) == 0: msg = ">>> Mesh Succesfully Loaded, but has no Vertices. It's OK, though." ud.SetUserData(op.GetObject(), "Mesh Handling Message", msg) elif len(Faces) == 0: msg = ">>> Mesh Succesfully Loaded, but has no Faces. It's OK, though." ud.SetUserData(op.GetObject(), "Mesh Handling Message", msg) else: msg = ">>> Mesh Succesfully Loaded! It should appear in the Viewport." ud.SetUserData(op.GetObject(), "Mesh Handling Message", msg) return Polygon else: msg = "No Mesh Loaded, because of faulty Filename. Check the File Handling Message above." ud.SetUserData(op.GetObject(), "Mesh Handling Message", msg) return
def SetupUserData(): #1 if not ud.UserDataExists(op.GetObject(), "File Handling"): ud.CreateUserData(op.GetObject(), "File Handling", c4d.DTYPE_SEPARATOR, True) #2 if not ud.UserDataExists(op.GetObject(), "First Object FileName"): ud.CreateUserData(op.GetObject(), "First Object FileName", c4d.DTYPE_FILENAME, True) #3 if not ud.UserDataExists(op.GetObject(), "First Frame"): ud.CreateIntegerData(op.GetObject(), "First Frame", "Integer", 0, 100, 1) #4 if not ud.UserDataExists(op.GetObject(), "Last Frame"): ud.CreateIntegerData(op.GetObject(), "Last Frame", "Integer", 0, 100, 1) #5 if not ud.UserDataExists(op.GetObject(), "Frame Step"): ud.CreateIntegerData(op.GetObject(), "Frame Step", "Integer Slider", 1, 100, 1) ud.SetUserData(op.GetObject(), "Frame Step", 1) #6 if not ud.UserDataExists(op.GetObject(), "File Handling Message"): ud.CreateUserData(op.GetObject(), "File Handling Message", c4d.DTYPE_STATICTEXT, True) #7 if not ud.UserDataExists(op.GetObject(), "Mesh Handling"): ud.CreateUserData(op.GetObject(), "Mesh Handling", c4d.DTYPE_SEPARATOR, True) #8 if not ud.UserDataExists(op.GetObject(), "Swap Y/Z"): ud.CreateUserData(op.GetObject(), "Swap Y/Z", c4d.DTYPE_BOOL, True) #9 if not ud.UserDataExists(op.GetObject(), "Phong Smoothing"): ud.CreateUserData(op.GetObject(), "Phong Smoothing", c4d.DTYPE_BOOL, True) #10 if not ud.UserDataExists(op.GetObject(), "Import Vertex Colors"): ud.CreateUserData(op.GetObject(), "Import Vertex Colors", c4d.DTYPE_BOOL, True) #11 if not ud.UserDataExists(op.GetObject(), "Create Test Material"): ud.CreateUserData(op.GetObject(), "Create Test Material", c4d.DTYPE_BOOL, True) #12 if not ud.UserDataExists(op.GetObject(), "Mesh Handling Message"): ud.CreateUserData(op.GetObject(), "Mesh Handling Message", c4d.DTYPE_STATICTEXT, True)