uniqueName a part


Is there an easier way to make a unique name for section of a name.
Example being. I have these objects in the scene




I collect all the objects with same guide type name
guideType = “arm”
for obj in helpers where (matchPattern obj.name pattern:("" + guideType + "")) collect obj
now is there an easy way to version this number up. Scanning the collected objects and incremental it by 1 leaving the 3 digit padding and then returning the new name within a function.

so ideally ill supply a function a name and it will return the unique name.

resulting in

pat = "arm001"
execute ("select $helpers/*"+pat+"*")
for obj in selection do	obj.name = replace obj.name (pat.count-1 + findstring obj.name pat) 1 "2" 


What I came up with is more complex than it might need to be.

guideType = "spine"
exGroups = for obj in helpers where (matchPattern obj.name pattern:("*" + guideType + "*")) collect obj.name
txt = for itm in exGroups where (findString itm guideType) != undefined collect (findString itm guideType)
existingValues = #()
for v = 1 to exGroups.count do
	ver = (substring exGroups[v]  (txt[v]+guideType.count) 3) as integer + 1
	newVersion = (FormattedPrint ver format:"3.3d") as string --//Adds "v" plus 3 digit padding
	print newVersion


why is not [color=Red]doug_guide_arm001_l_005[/color]?


I first need to find the highest groupNumber before increment it by 1. Otherwise it would still be incorrect.


you rule is too special to be a general. so the function needs some guidance… about the part of the name that has to be incremented.


I want to group each arm so if there are multiples arms it would go

arm001_l_001 --left collarbone
arm001_l_002 --left shoulder
arm001_l_003 --left forearm
arm001_l_004 --left wrist

arm002_r_001 --right collarbone
arm002_r_002 --right shoulder
arm002_r_003 --right forearm
arm002_r_004 --right wrist

so if i created another arm it would be

arm003_r_001 --right collarbone
arm003_r_002 --right shoulder
arm003_r_003 --right forearm
arm003_r_004 --right wrist


so the function has to split a name on header, name, group index, type, and node index. after that we can talk about incrementing a part.


if you have group indexes 1,2,and 5 what the next available is 3 or 6?


This is my format


1.Character Name
2.Control “guide” --ex: guide,bone,control etc. doesn’t matter really for this.
3.Type + GroupNumber (3 digit padding)
4.Location --ex: l (left), m (middle), or r (right)
5.Node Index --UniqueName done in maxscript on point helper creation.


6 would be the next number.
It doesn’t matter if it is perfectly incremental by 1, as long as it is unique. That is more important.


definitely the regex might be a solution. we need to write the right one :slight_smile: let’s try


The main reason behind the whole grouping through is so i can add multiple limbs or whatever it may be and manage them in a way that I feel is best. I appreciate the help.


here is a regex solution. the most complicated part was to write the right expression.

 fn makeBoneRegex charname: bonename: type:#any = 
 	if charname == unsupplied do charname = ".*" 
 	if bonename == unsupplied do bonename = ".*" 
 	type = case type of
 		  #any: "[l,m,r]"
 		#right: "r"
 		 #left: "l"
 	   #middle: "m"
 	   default: "[a-z]" 
 	dotnetobject "System.Text.RegularExpressions.Regex" ("(^" + charname + "_?)(" + bonename + ")([0-9]{3}?)(_" + type + "_)([0-9]{1,}$)")
 struct BoneStruct (node, char, name, index, type, id)
 fn getBones nodes: charname: bonename: type:#any = 
 	if nodes == unsupplied do nodes = objects as array
 	rg = makeBoneRegex charname:charname bonename:bonename type:type
 	for node in nodes where rg.IsMatch node.name collect 
 		d = (rg.Match node.name).groups
 		BoneStruct node:node \
 			char:(trimright d.item[1].value "_") \
 			name:d.item[2].value \
 			index:(d.item[3].value as integer) \
 			type:d.item[4].value[2] \
 			id:(d.item[5].value as integer)
 	delete objects
 	local chars = #("Chip", "Dale", "Jack")
 	local bones = #("arm", "leg", "spine")
 	local types = #("l", "m", "r")
 	seed 0
 	for k=1 to 100 do 
 		name = chars[random 1 3] + "_" + bones[random 1 3] + (formattedprint (random 1 6) format:"03d") + "_" + types[random 1 3] + "_"
 		box name:(uniquename name)
 -- print all chip's right arms
 print (getBones charname:"Chip" bonename:"arm" type:#right)
 -- print all dale's bones
 print (getBones charname:"Dale") 

when we found all bones that matches the pattern it’s easy to sort them by index and find the highest. after that there’s no problem to make the unique name


While developing this and messing around with different ideas of my own that was something i was trying to grasp and understand as well. Meaning the best way to right a solution that would work well. I was unable to come up with a solid solution myself. I did begin reading up on the regex stuff once you mentioned it. I was un aware of what that brings to maxscript. It’s useful to know that is available. I’ll check out what you’ve written here. I’m excited to get this working and implemented. I appreciate the time you spent working on this Denis. I’ll let you know how it goes.


So I’m not entirely sure how to use what is written here.

Say i run what you’ve written and uncomment the loop which creates boxes.

ok so now I want to create an additional box but with a unique name. Where does that happen?

Do i increment the index?


you got all bones as structure

find item with maximum index (let’s call it b)

make new(unique) name as:

uniquename (b.char + "_" + b.name + (formattedprint (b.index+1) format:"03d") + "_" + b.type + "_")

that’s it


so I did something like this

 	exBones = (getBones charname:"Dale" bonename:"leg")
	b = exBones[exBones.count]
	newPt = point name:(uniquename (b.char + "_" + b.name + (formattedprint (b.index+1) format:"03d") + "_" + b.type + "_"))


for bug sake purposes it bugs out if no bone exists. using the code i pasted above.


you have to sort then exBones by index first