From 215842c30a0eb989a1ea337a75db755a6a50d9b3 Mon Sep 17 00:00:00 2001 From: nicelifeBS Date: Sun, 29 Dec 2013 12:39:31 +1300 Subject: [PATCH] BJs ToolBox v1.3 first version on GitHub --- configs/BJS_Tools_palette.cfg | 21 ++ configs/MARI_Tools.cfg | 149 ++++++++++++ configs/Thread_Tools.cfg | 92 +++++++ icons/BJsToolbox_btn.png | Bin 0 -> 3632 bytes icons/innerThread_btn.png | Bin 0 -> 8454 bytes icons/outerThread_btn.png | Bin 0 -> 7563 bytes index.CFG | 54 +++++ scripts/CreateThreads.py | 252 +++++++++++++++++++ scripts/MARI_Tools.py | 346 +++++++++++++++++++++++++++ scripts/MARI_Tools_createPolySets.py | 146 +++++++++++ 10 files changed, 1060 insertions(+) create mode 100644 configs/BJS_Tools_palette.cfg create mode 100644 configs/MARI_Tools.cfg create mode 100644 configs/Thread_Tools.cfg create mode 100644 icons/BJsToolbox_btn.png create mode 100644 icons/innerThread_btn.png create mode 100644 icons/outerThread_btn.png create mode 100644 index.CFG create mode 100644 scripts/CreateThreads.py create mode 100644 scripts/MARI_Tools.py create mode 100644 scripts/MARI_Tools_createPolySets.py diff --git a/configs/BJS_Tools_palette.cfg b/configs/BJS_Tools_palette.cfg new file mode 100644 index 0000000..f56c259 --- /dev/null +++ b/configs/BJS_Tools_palette.cfg @@ -0,0 +1,21 @@ + + + + + BJ's Tools + forcetabs + 1 + BJs_Tools + + MARI Tools + 0 + 56836215643:sheet + + + Thread Tools + 0 + 27723702610:sheet + + + + diff --git a/configs/MARI_Tools.cfg b/configs/MARI_Tools.cfg new file mode 100644 index 0000000..426e8a5 --- /dev/null +++ b/configs/MARI_Tools.cfg @@ -0,0 +1,149 @@ + + + + + MARI Tools + 0 + + Import + 0 + 06062216127:sheet + + + Tools + 0 + 85460216309:sheet + + + Options + 68981216109:sheet + + + full + 0 + 24242216782:control + + + + Import + + Delimiter + The delimiter is used to find the UDMI in the filename. MARI default is ".". E.g. DIFF.layer.1013.tif + 0 + 52734614257:control + + + checkmark + Ignore 8x8 Textures + Delete images that are 8x8 pixels + 0 + 85734215749:control + + + checkmark + Gamma Correction + if active gamma of textures is leveled + 0 + 85734215749:control + + + full + 0 + 87730614291:control + + + Import Textures + 0 + 02933216073:control + + + + Tools + vtoolbar + both + large + + Set UV offset + Sets the UV offset according to the selected clip name + 0 + 78298216338:control + + + Gamma Correct Selection + Corrects gamma value of selected images + 0 + 99260216663:control + + + Sort Selection + 0 + 39980216861:control + + + Reload All Textures + 0 + 0 + 10284216883:control + + + Create Selection Sets + 0 + 42241317968:control + + + + Options + 1 + + Delimiter + The delimiter is used to find the UDMI in the filename. MARI default is ".". E.g. DIFF.layer.1013.tif + 0 + 41475216426:control + + + UV Map + 0 + 32639613735:control + + + Gamma Value + 0 + 77976371124:control + + + + + + + true + + boolean + + true + + boolean + + 0.4546 + + float + + + integer + MARI_TOOLS_delimiter-list + option1;option2 + + + + + + + MARI TOOLS Delimiter Options + + Period "." + + + Underscore "_" + + + + diff --git a/configs/Thread_Tools.cfg b/configs/Thread_Tools.cfg new file mode 100644 index 0000000..d88c60d --- /dev/null +++ b/configs/Thread_Tools.cfg @@ -0,0 +1,92 @@ + + + + + + + Thread Tools + Set diameter, side and number of threads then choose to create which thread type you want to create. The profile is currently not cusomizable! + Creates threads automatically. User can choose to create inner or outer thread. + both + large + + Settings + inline + 0 + 37896717548:sheet + + + + Settings + inline + + Diameter + Set diameter of thread + 0 + 12351717978:control + + + Sides + Set sides for thread + 0 + 43214702647:control + + + Number of Steps + Set how many steps you like. Basically the height of the thread. + 0 + 50790700363:control + + + full + 0 + 02181717756:control + + + Create Threads + inline + 0 + 26272784711:sheet + + + + Create Threads + inline + htoolbar + right + both + large + + Create Inner Threads + Creates an inner thread + kit_BJsToolbox:icons/innerThread_btn.png + 0 + 46672717392:control + + + Create Outer Threads + Creates an outer thread + kit_BJsToolbox:icons/outerThread_btn.png + 0 + 26841784972:control + + + + + + + 0.02 + + distance + + 5 + + integer + + 12 + + integer + + + + diff --git a/icons/BJsToolbox_btn.png b/icons/BJsToolbox_btn.png new file mode 100644 index 0000000000000000000000000000000000000000..0b792ae9c71474f911f1df989e2404c3281623cf GIT binary patch literal 3632 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 + + kit_BJsToolbox: + scripts + configs + icons + + + + + 255 390 + attrform 0 1 0 1 BJsToolbox_layout_vp0 + + + + + 170 180 + attrform 0 1 0 1 BJsToolbox_layout_vp0 + + + 11851693841:sheet + 0 + + 64059337038:StartCollapsed + 0 0 + 1 + 0 + BJ's Toolbox + vpapplication + + + + + + + BJ's Toolbox Button + inline + htoolbar + left + icon + small + + 124 + + + BJ's Toolbox + kit_BJsToolbox:icons/BJsToolbox_btn.png + 0 + 55377745542:control + + + + + diff --git a/scripts/CreateThreads.py b/scripts/CreateThreads.py new file mode 100644 index 0000000..07c06aa --- /dev/null +++ b/scripts/CreateThreads.py @@ -0,0 +1,252 @@ +#python + +""" +Create Threads v1.1 + +Script creates an inner or an outer thread. The thread profile is hard coded in the function profileInner() and profileOuter(). +Script has + +Script was inspired by the modelling techniques of Peter Stammbach + +Bjoern Siegert aka nicelife + +Last edit: +29.11.2013 +""" + + +import math + +class vector_class(object): + """ Let's you do math with vectors in a list""" + def __init__(self, data): + self.data = data + + def __repr__(self): + return repr(self.data) + + def __add__(self, other): + data = [] #start with an empty list + for i in range(len(self.data)): + data.append(self.data[i] + other.data[i]) + return vector_class(data) + + def __sub__(self, other): + data = [] #start with an empty list + for i in range(len(self.data)): + data.append(self.data[i] - other.data[i]) + return vector_class(data) + + def __mul__(self, other): + data = [] #start with an empty list + for i in range(len(self.data)): + data.append(self.data[i] * other.data[i]) + return vector_class(data) + + def __div__(self, other): + data = [] #start with an empty list + for i in range(len(self.data)): + data.append(self.data[i] / other.data[i]) + return vector_class(data) + + def __getitem__(self, key): + return self.data[key] + + +### FUNCTIONS #### +def checkExistence(itemList, name): + if name in itemList: + return True + else: + return False + +def createMesh(itemList, name): + """Create a mesh layer with a name. If mesh already exists all polys will be deleted.""" + if checkExistence(itemList, name) == False: + lx.eval("item.create mesh {%s}" %name) + elif checkExistence(itemList, name) == True: + lx.eval("select.item {%s} set mesh" %name) + lx.eval("select.typeFrom polygon true") + lx.eval("delete") + else: + pass + +def profileInner(): + """Creates a profile poly for an inner side of a thread""" + layer_index = lx.eval("query layerservice layer.index ? selected") + # create a cube + lx.eval("tool.set prim.cube on") + lx.eval("tool.reset prim.cube") + lx.eval("tool.attr prim.cube cenX 0.0") + lx.eval("tool.attr prim.cube cenY 0.0") + lx.eval("tool.attr prim.cube cenZ 0.0") + lx.eval("tool.attr prim.cube sizeX 0.001") + lx.eval("tool.attr prim.cube sizeY 0.005") + lx.eval("tool.attr prim.cube sizeZ 0.0") + lx.eval("tool.apply") + lx.eval("tool.set prim.cube off 0") + + # modify the cube to a thread profile + lx.eval("select.typeFrom edge true") + + lx.eval("select.element %s edge set 3 2" %layer_index) + lx.eval("tool.set edge.extend on") + lx.eval("tool.reset edge.extend") + lx.eval("tool.attr edge.extend offX 0.005") + lx.eval("tool.apply") + lx.eval("tool.set edge.extend off 0") + + lx.eval("select.element %s edge set 4 5" %layer_index) + lx.eval("tool.set TransformScale on") + lx.eval("tool.reset xfrm.transform") + lx.eval("tool.set actr.select on") + lx.eval("tool.setattr xfrm.transform SY 0.7") + lx.eval("tool.apply") + lx.eval("tool.set actr.select off 0") + lx.eval("tool.set TransformScale off 0") + + lx.eval("select.element %s edge set 2 1" %layer_index) + + lx.eval("tool.set edge.extend on") + lx.eval("tool.reset edge.extend") + lx.eval("tool.attr edge.extend offY 0.004") + lx.eval("tool.apply") + lx.eval("tool.set edge.extend off 0") + + lx.eval("select.drop edge") + + # center profile + lx.eval("vert.center all") + +def profileOuter(): + """Creates a profile poly for an outer side of a thread. It uses the profileInner() function and then mirrors the geometry.""" + profileInner() + lx.eval("tool.set TransformScale on") + lx.eval("tool.reset xfrm.transform") + lx.eval("tool.setattr xfrm.transform SX -1.0") + lx.eval("tool.apply") + lx.eval("tool.set TransformScale off 0") + lx.eval("vert.center all") + +def profileLength(bounding_box): + """Get the length/height of the created profile by using the two points of the bounding box""" + POS_A = bounding_box[0:3] + POS_C = [bounding_box[0],bounding_box[4],bounding_box[2]] + vector_C = vector_class(POS_C) - vector_class(POS_A) + length = math.sqrt(vector_C[0]**2 + vector_C[1]**2 + vector_C[2]**2) + return length + +def radial_sweep(diameter, sides, num_threads): + """Create a radial sweep with the profile. Diameter, sides and the number of threads(height) must be given.""" + # get the bounds of the profile + bounding_box = list(lx.eval("query layerservice layer.bounds ? selected")) #[X_A,Y_A,Z_A,X_B,Y_B,Z_B]) + + #select the mesh layer with the thread + layer_index = lx.eval("query layerservice layer.index ? selected") + + #select all polys of the thread for later use + lx.eval("select.typeFrom polygon true") # set selection mode + lx.eval("select.all") + + # move the profile to the specified diameter + lx.eval("tool.set TransformMove on") + lx.eval("tool.reset xfrm.transform") + lx.eval("tool.attr xfrm.transform TX %s" %( - (diameter / 2))) + lx.eval("tool.apply") + lx.eval("tool.set TransformMove off 0") + + # select edges for radial sweep + lx.eval("select.typeFrom edge true") # set selection mode + lx.eval("select.drop edge") # clear selection + lx.eval("select.element %s edge add 2 6" %layer_index) + lx.eval("select.element %s edge add 2 5" %layer_index) + lx.eval("select.element %s edge add 4 5" %layer_index) + lx.eval("select.element %s edge add 3 4" %layer_index) + + # radial sweep with origin as center + lx.eval("tool.set {Radial Sweep} on") + lx.eval("tool.reset gen.helix") + lx.eval("tool.set actr.origin on") + lx.eval("tool.attr gen.helix axis 1") + lx.eval("tool.attr gen.helix sides %s" %(sides * num_threads)) + lx.eval("tool.attr gen.helix end %s" %(360 * num_threads)) + lx.eval("tool.attr gen.helix offset %s" %(profileLength(bounding_box) * num_threads)) + lx.eval("tool.apply") + lx.eval("tool.set actr.origin off") + + lx.eval("tool.set {Radial Sweep} on") #otherwise tool is not cleared correctly + lx.eval("tool.set {Radial Sweep} off") + + # get rid of the profile poyls + lx.eval("select.typeFrom polygon true") # set selection mode + lx.eval("delete") + + # zoom all + lx.eval("viewport.fit") + +### DIALOGS ### +def overwrite_msg(): + """Warning message if mesh item is already in scene""" + try: + lx.eval("dialog.setup yesNo") + lx.eval("dialog.title {Confirm Operation}") + lx.eval("dialog.msg {There is already a thread. Do you want to overwrite it?}") + lx.eval("dialog.result ok") + lx.eval("dialog.open") + + lx.eval("dialog.result ?") + return True + + except RuntimeError: + return False + +def warning(): # Depricated! + """Warning message if no profile mesh is in scene""" + try: + lx.eval("dialog.setup warning") + lx.eval("dialog.title {Warning}") + lx.eval("dialog.msg {Please create a profile first}") + lx.eval("dialog.result ok") + lx.eval("dialog.open") + + except RuntimeError: + pass + + +### VARIABLES ### +args = lx.args() +layer_list = lx.evalN("query layerservice layer.name ? all") #get all mesh items in scene +bounding_box = list(lx.eval("query layerservice layer.bounds ? selected")) #[X_A,Y_A,Z_A,X_B,Y_B,Z_B]) +mesh_name_thread = "BJ_Tools_thread" + +### USER VALUES ### +diameter = lx.eval("user.value thread_diameter ?") +sides = lx.eval("user.value num_segments ?") +num_threads = lx.eval("user.value num_threads ?") + +# Check if mesh_name_thread already in scene and ask user +if checkExistence(layer_list, mesh_name_thread) == True: + userinput = overwrite_msg() + +else: + userinput = True + +# creates actual thread with the radial sweep tool +if args[0] == "innerThread" and userinput == True: + createMesh(layer_list, mesh_name_thread) + profileInner() + radial_sweep(diameter, sides, num_threads) + +elif args[0] == "outerThread" and userinput == True: + createMesh(layer_list, mesh_name_thread) + profileOuter() + radial_sweep(diameter, sides, num_threads) + lx.eval("poly.flip") + +elif args[0] == "createThread" and mesh_name_thread not in layer_list: + warning() + +else: + lx.out("42") + + diff --git a/scripts/MARI_Tools.py b/scripts/MARI_Tools.py new file mode 100644 index 0000000..d07dc1b --- /dev/null +++ b/scripts/MARI_Tools.py @@ -0,0 +1,346 @@ +#python + +""" +MARI TOOLs v1.2 +Bjoern Siegert aka nicelife + +Last edited 2013-12-06 + +Arguments: +loadFiles, gammaCorrect, setUVoffset, sortSelection, createPolySets + +Import textures from MARI and some tools to manage these: +For import the user can choose: +- a delimiter so that the script can find the UDIM number +- to ignore the 8x8 pixel textures from import +- if the textures should be gamma corrected + +Tools: +- Sets the UV offset automatically from the file name +- Gamma correction of imported texutres if needed +- Sort the images in scene tree in alphabetic order +- Create polygon sets for each UDIM + + +Version History: +v1.2 +New Feature: +- Create selection sets for the different UDIMs + +v1.1 +Bugfixes: +- Creating the image maps didn't work reliable because of a selection in the shader tree. Clears selection (only select the Mesh) before creating the image maps now +- Sorting fixed +- Added some logging +""" + + +### FUNCTIONS #### + +def locator_ID(imageMap_ID): + """ + Find ID of the texture locator of an image map. The ID of the image map in the shadertree is needed as argument. + """ + texture_num = lx.eval("query layerservice texture.N ? all") + # Parse through all textures until texture ID of layer matches the selected one. + for i in range(texture_num): + + texture_ID = lx.eval("query layerservice texture.id ? %s" %i) + lx.out("(%s) texture ID: %s" %(i, texture_ID)) + + if texture_ID == imageMap_ID: + return lx.eval("query layerservice texture.locator ? %s" %i) #retruns the texture locator ID + break + else: + lx.out("no match") + +def create_imageMap(clipPath): + """ + Create material in shader tree. Change it to an image map and set up UV projection type and tiling + """ + lx.out("Create Image: texture.N ", lx.eval("query layerservice texture.N ?")) + + lx.eval("clip.addStill %s" %clipPath) + lx.eval("shader.create constant") + lx.eval("item.setType imageMap textureLayer") + lx.eval("texture.setIMap {%s}" %get_filename(clipPath)) + lx.eval("item.channel imageMap$aa false") + lx.eval("item.channel txtrLocator$projType uv") + lx.eval("item.channel txtrLocator$tileU reset") + lx.eval("item.channel txtrLocator$tileV reset") + layer_index = lx.eval("query layerservice layer.index ? main") + + + +def load_files(): + """ + Load in files and save complete paths in a list + """ + try: + lx.eval("dialog.setup fileOpenMulti") + lx.eval("dialog.title {Import MARI textures}") + lx.eval("dialog.result ok") + lx.eval("dialog.open") + + return lx.evalN("dialog.result ?") + + except RuntimeError: + return False + +def get_file_extension(filename): + """returns the file extension, e.g. ".tif". Searches from end until it finds "." """ + file_extension = "" + + for i in filename[::-1]: # reverse the filename and walkthrough all chars and add each one to variable until finding the first period + if i !=".": + file_extension += i + else: + break + + return "." + file_extension[::-1] # return the saved extension by reversing it back and adding the period + +def get_filename(filePath): + """returns the file name without the extension -> clip name""" + filename = filePath.split("/")[-1] + return filename.replace(get_file_extension(filename), "") + +def get_clipPath(selection): + """Returns a dictionary. The key is the actual file path of the image map. Per key the current + position number and the texture ID are saved.""" + list = {} + for imap in selection: + for number in range(lx.eval("query layerservice texture.N ?")): + if lx.eval("query layerservice texture.id ? %s" %number) == imap: + list [lx.eval("query layerservice texture.clipFile ? %s" %number)] = [number,imap] + return list + +def get_UDIM(file_name, delimiter): + """Extract the UDIM value from file name. A file name and a delimiter must be given. Returns False if it is not a MARI texture.""" + for item in file_name.split(delimiter): # try if string is a number and if the length is 4 chars long it is identified as UDIM + try: + int(item) + if len(item) == 4: + U_offset = -(int(item[3]) - 1) + V_offset = -(int(item[1:3])) + return U_offset, V_offset + + except ValueError: + pass + + +def check_clip_size(clip_name): + """Checks the size of a clip and return True if it is 8x8 pixels""" + + clip_size = "w:8" + for i in range(lx.eval("query layerservice clip.N ?")): + if lx.eval("query layerservice clip.id ? %s" %i) == clip_name: + clip_info = lx.eval("query layerservice clip.info ? %s" %i) + clip_info = clip_info.split(" ") + + if clip_size in clip_info[1]: + lx.out("%s deleted" %clip_name) + return True + else: + lx.out("%s correct size" %clip_name) + return False + +def set_gamma(value): + """Set gamma with given value for selected images.""" + if not lx.eval("query sceneservice selection ? imageMap"): + lx.out("nothing selected") + else: + lx.eval("item.channel imageMap$gamma %s" %value) + +def get_texture_parent(item_ID): + """Returns the parent of an image map""" + return lx.eval("query sceneservice textureLayer.parent ? %s" %item_ID) + +def warning_msg(name): + """A modal warning dialog. Message text can be set through name var.""" + try: + lx.eval("dialog.setup warning") + lx.eval("dialog.title {Error}") + lx.eval("dialog.msg {Ooopsy. %s.}" %name) + lx.eval("dialog.result ok") + lx.eval("dialog.open") + + except RuntimeError: + pass + +def vmap_selected(vmap_num, layer_index): + """See if a UV map of the current layer is selected and returns the name. + Also returns false if no vmaps are in scene""" + + if vmap_num == 0: + return False + + else: + for i in range(vmap_num): + vmap_layer = lx.eval("query layerservice vmap.layer ? %s" %i) + 1 # Layer index starts at 1 and not at 0 -> +1 to shift index + vmap_type = lx.eval("query layerservice vmap.type ? %s" %i) + + if vmap_type == "texture" and vmap_layer == layer_index: + if lx.eval("query layerservice vmap.selected ? %s" %i) == True: + + #lx.out("layer_index: ", layer_index) + #lx.out("vmap_layer: ", vmap_layer) + #lx.out("vmap_type: ", vmap_type) + + vmap_name = lx.eval("query layerservice vmap.name ? %s" %i) + return vmap_name + break + + else: + pass + +def test(test): + lx.out(test) + +### FUNCTIONS END ### + + +### VARIABLES ### +args = lx.args()[0] # Arguments. Only the first argument is passed. + +layer_index = lx.eval("query layerservice layer.index ? main") #select the current mesh layer +layer_id = lx.eval("query layerservice layer.id ? main") +scene_index = lx.eval("query sceneservice scene.index ? current") +imap_selection = lx.evalN("query sceneservice selection ? imageMap") # get the name of the selected images +vmap_num = lx.eval("query layerservice vmap.N ?") # Number of vertex maps of selected mesh + +## USER VALUES ## +gamma_correction = lx.eval("user.value MARI_TOOLS_gamma ?") # Gamma correction on/off +gamma_value = lx.eval("user.value MARI_TOOLS_gammavalue ?") # Gamma value from UI +delimiter = lx.eval("user.value MARI_TOOLS_delimiter ?") # Delimiter form UI +filter_clips = lx.eval("user.value MARI_TOOLS_filter_clips ?") # Delete 8x8 clips on/off + + +## Delimiter Interpreter ## +if delimiter == "option1": + delimiter = "." +elif delimiter == "option2": + delimiter = "_" + + +### ARGS parsing ### + +# Import Files including name check +if args == "loadFiles": + + # Check if a UV set is selected + lx.out(vmap_selected(vmap_num, layer_index)) + + if vmap_selected(vmap_num, layer_index) == False or not vmap_selected(vmap_num, layer_index): + warning_msg("Please select a UV map.") + + else: + UVmap_name = vmap_selected(vmap_num, layer_index) + + # Create folder + lx.eval("shader.create shaderFolder") # Create Folder for imported Textures + lx.eval("texture.parent Render 0") # Move created folder to bottom of shader tree + folder_ID = lx.eval("query sceneservice selection ? shaderFolder") + #lx.out("folder_ID: ", folder_ID + + fileList = load_files() # Open dialog to load image files + + # Create the image maps in shader tree + for filePath in fileList: + lx.eval("select.item %s set" %layer_id) # Select only the Mesh for a fresh start + + file_name = get_filename(filePath) + + # Debuging + lx.out("File Path: ", filePath) + lx.out("File Name: ", file_name) + lx.out("UDIM: ", get_UDIM(file_name, delimiter)) + + if get_UDIM(file_name, delimiter): + + # Create image maps in shadertree + create_imageMap(filePath) + lx.out("Selection: ", lx.eval("query sceneservice selection ? all")) + + # Check the image size and ignore it if it's 8x8 pixels + clip_name = lx.eval("query sceneservice selection ? mediaClip") + if check_clip_size(clip_name) == True and filter_clips == True: + lx.eval("clip.delete") + lx.eval("texture.delete") + break + else: + pass + + # Gamma correction + if gamma_correction == True: + set_gamma(gamma_value) + + #Set UV map + lx.eval("texture.setUV %s" %UVmap_name) + + # Set the UV offset values + imap_ID = lx.eval("query sceneservice selection ? imageMap") + lx.eval("select.subItem %s set txtrLocator" %locator_ID(imap_ID)) + lx.eval("item.channel txtrLocator$m02 %s" %get_UDIM(file_name, delimiter)[0]) + lx.eval("item.channel txtrLocator$m12 %s" %get_UDIM(file_name, delimiter)[1]) + lx.eval("texture.parent %s 0" %folder_ID) # Move texture to the bottom of the created folder + + else: + lx.eval("item.delete shaderFolder") # Delete created folder to clean up scene + warning_msg("Please select file(s) with an UDIM or change delimiter") + + +## Gamma Correction: Correct Gamma of textures 1.0/2.2 = 0.4546 ## +elif args == "gammaCorrect": + + set_gamma(gamma_value) + +## set the UVoffset according to image file name ## +elif args == "setUVoffset": + for imap in imap_selection: + for i in range(lx.eval("query layerservice texture.N ?")): + if lx.eval("query layerservice texture.id ? %s" %i) == imap: + lx.out("setting UV offset for ", imap) + file_name = get_filename(lx.eval("query layerservice texture.clipFile ? %s" %i)) + lx.eval("select.subItem %s set txtrLocator" %lx.eval("query layerservice texture.locator ? %s" %i)) + lx.eval("item.channel txtrLocator$m02 %s" %get_UDIM(file_name, delimiter)[0]) + lx.eval("item.channel txtrLocator$m12 %s" %get_UDIM(file_name, delimiter)[1]) + lx.eval("item.channel txtrLocator$tileU reset") + lx.eval("item.channel txtrLocator$tileV reset") + +## Sort selected images top to bottom ## +elif args == "sortSelection": + clip_list = get_clipPath(imap_selection) + sorted_list= sorted(clip_list) # Sort keys of dict in alphabetic order + + for i in sorted_list: + lx.out("clip path: ", i) + + # If selection is directly parented under Render -> not in a sub group + if "Render" in get_texture_parent(clip_list[i][1]): + lx.eval("select.item %s set textureLayer" %clip_list[i][1]) + lx.eval("texture.parent %s 1" %get_texture_parent(clip_list[i][1])) + + # If selection is parented in a group + else: + lx.eval("select.item %s set textureLayer" %clip_list[i][1]) + lx.eval("texture.parent %s 0" %get_texture_parent(clip_list[i][1])) + +## Create poly selection set for each UDIM +elif args == "createPolySets": + + # Check if a UV map is selected + if vmap_selected(vmap_num, layer_index) == False or not vmap_selected(vmap_num, layer_index): + warning_msg("Please select a UV map.") + + # Proceed with MARI_Tools_createPolySets.py script + else: + lx.eval("@MARI_Tools_createPolySets.py") + + +elif args == "test": + lx.out("TESTING") + +else: + lx.out("Please choose one argument: loadFiles, gammaCorrect, setUVoffset, sortSelection, createPolySets") + + \ No newline at end of file diff --git a/scripts/MARI_Tools_createPolySets.py b/scripts/MARI_Tools_createPolySets.py new file mode 100644 index 0000000..cf33757 --- /dev/null +++ b/scripts/MARI_Tools_createPolySets.py @@ -0,0 +1,146 @@ +#python + +""" +UVselset v1.0 + +Author: Bjoern Siegert aka nicelife + +Last edit: 2013-12-06 + +Creates poly selection sets based on the UV offset values. Each sector sector containing polys will +get a selection set. The name follows the UDIM scheme of MARI. E.g.: If v = 0-1 the space 0-1 gets a selection set with the name UDIM_1001, +1-2: UDIM_1002. If v = 1-2 -> UDIM_1011, UDIM_1012,... + +Problems: +- Slow with big modells + +""" + +import time + +### LX SERVICE ### +layer_svc = lx.Service("layerservice") +progressbar = lx.Monitor() + +### LAYER SELECTION and index ### +layer_svc.select("layers", "main") +layer_index = layer_svc.query("layer.index") + +### VARIABLES ### +uv_dict = {} + +############################# +### Debugging: Start Time ### +t1 = time.time() +############################# + +# Select the UVs +layer_svc.select("uvs", "all") +uv_indices = layer_svc.query("uvs") + +# Assign UV the UDIMs to the different UVs. Save result in dictionary. +for index in uv_indices: + layer_svc.select("uv.index", str(index)) + uv_pos = layer_svc.query("uv.pos") + vert_index = layer_svc.query("uv.vert") + + # Convert to integers to identify the UV offset sector + u = int(uv_pos[0]) + v = int(uv_pos[1]) + ####################################### + # Code Change + # Use the following -> faster!: + # + # u, v = int(uv_pos) + ####################################### + + try: + uv_dict[1001 + (v * 10) + u ].append(vert_index) + + except KeyError: + uv_dict[1001 + (v * 10) + u ] = [vert_index] + +############################ +### Debugging: Stop Time ### +t2 = time.time() +dict_setup = t2 - t1 +############################ + +# Check if selection set already exists. If yes it is deleted. +lx.eval("select.type polygon") +layer_svc.select("polsets") +poly_set_num = layer_svc.query("polsets") +if poly_set_num: + delete_sets = [] + + for i in poly_set_num: + + layer_svc.select("polset.index", str(i)) + poly_set_name = layer_svc.query("polset.name") + + # Find a UDIM selection set and delete it + if "UDIM_" in poly_set_name: + delete_sets.append(poly_set_name) + + else: + pass + + lx.out("Delete Sets: ", delete_sets) + + # Delete Sets + layer_svc.select("layer.index", str(layer_index)) + for sets in delete_sets: + lx.eval("select.deleteSet %s" %sets) + lx.out("Deleted Selection Set: ", sets) + +############################# +### Debugging: Start Time ### +t1 = time.time() +############################# + +# Selection type +lx.eval("select.type vertex") + + +# Create selection sets + +################################ +# Code to change: +# Use following to get key and value at the same time. +# for key, value in uv_dict.iteritems(): +# +################################ +for key in uv_dict: + # Clear selection + lx.eval("select.drop polygon") + lx.eval("select.drop vertex") + + # Progress bar steps + progressbar.init(len(uv_dict[key])) + + # Select verts + for index in uv_dict[key]: + lx.eval("select.element %s vertex add %s" %(layer_index, index)) + + # Progressbar step + progressbar.step(1) + + # Convert selection to polys and create a new selection set with UDIM + lx.eval("select.convert polygon") + lx.eval("select.editSet UDIM_%s add" %key) + + # Logging + lx.out("New selection set created: UDIM_", key) + +############################# +### Debugging: Stop Time ### +t2 = time.time() +sets_creation = t2 - t1 +############################# + +# Debugging Speed +lx.out("Dictionary Setup: %s sec" %dict_setup) +lx.out("Selection Sets: %s sec" %sets_creation) + + +