[Solved] [Maxscript] How to use regular expression to associate an object with a proxy?


#1

Hello !

I need some help because I’m working on a maxscript file with regular expressions.

I have a Max scene with a huge amount of objects. I have 2 layers. 1 with my objects and 1 with my proxys. I need to align each object with the right proxy.

Currently I have 2 variables : 2 arrays. The first list contains the name of each object and the second list contains the name of each proxy.

This is the format of each name :

PROXYS LAYER
    proxy_001_1200x300
    proxy_002_1200x300
    proxy_001_1200x400
    proxy_650x350
    ...

OBJECTS LAYER
    object_1200x300
    object_1300x300
    object_300x1200
    object_650x350
    ...

As you can see, I have similarities in names : 0000x0000. So I would like to use a regular expression to extract those similarities and use it to match each object with the right proxy.

I read the Maxscript documentation but I don’t understand how it’s work.

Could you help me please to create this expression ? Thanks a lot.


#2

Maybe this will help you:

(
	proxysArr = #("proxy_001_1200x300","proxy_002_1200x300","proxy_001_1200x400","proxy_650x350")
	objsArr = #("object_1200x300","object_1300x300","object_300x1200","object_650x350")
	
	for o in objsArr do
	(
		fs = filterString o "_"
		dimStr = fs[fs.count]
		for p in proxysArr where matchPattern p pattern:("*" + dimStr) do
		(
			format ": % \n" #(o, p)
		)
	)
	
)

#3

Thank you for you anwser.

I can’t use the _ as filter because some names don’t have this character. I’m sorry, I just realize it :frowning:

So I think I need to use this regular expression to do that :

my_regex = "[0-9]+x[0-9]+"

Could you explain your code please ? I don"t understand those lines :

dimStr = fs[fs.count]
for p in proxysArr where matchPattern p pattern:("*" + dimStr) do
(
    format ": % \n" #(o, p)
)

#4
proxy_names  = #("proxy_001_1200x300","proxy_002_1200x300","proxy_001_1200x400","proxy_650x350")
object_names = #("object_1200x300","object_1300x300","object_300x1200","object_650x350")
	
RE_Match   = (dotnetclass "system.text.regularexpressions.regex").match
RE_Matches = (dotnetclass "system.text.regularexpressions.regex").matches
RE_Options = (dotnetclass "system.text.regularexpressions.regexoptions").multiline
RE_Pattern = "\d+[xX]\d+$"  -- one or more digits + letter 'x' or 'X' + one or more digits + end of the line

for entry in proxy_names do
(
	local match = RE_Match entry RE_Pattern RE_Options
	
	if match.Success do
	(
		format "%  -->  %\n" entry match.Value
	)
	
)

if you need more information on how this works check out msdn site

for multiple matches in a string use Matches method

for entry in proxy_names do 
(
	local matches = RE_Matches entry "\d+[xX]\d+" -- one or more digits + letter 'x' or 'X' + one or more digits
	
	if matches.Count > 0 do
	(
		format "'%'\n" entry
		for i = 0 to matches.Count - 1 do
		(
			format "	%: %\n" i (matches.Item i).Value
		)
		
	)
	
)
'proxy_001_1200x300 42x666'
	0: 1200x300
	1: 42x666
'proxy_002_1200x300'
	0: 1200x300
'proxy_001_1200x400'
	0: 1200x400
'proxy_650x350'
	0: 650x350

#5

Thank you for your answer :slight_smile: ! I used the second code.

/*Declarate variables :*/
proxys_names = #("proxy_001_1200x300","proxy_002_1200x300","proxy_001_1200x400","proxy_650x350")
doors_names = #("object_1200x300","object_1300x300","object_300x1200","object_650x350")
RE_Matches = (dotnetclass "system.text.regularexpressions.regex").matches


/*Extract proxys sizes :*/
for entry in proxys_names do (
    local matches = RE_Matches entry "\d+[xX]\d+" -- one or more digits + letter 'x' or 'X' + one or more digits

    if matches.Count > 0 do (

        format "'%'\n" entry

        for i = 0 to matches.Count - 1 do (
            /*format "    %: %\n" i (matches.Item i).Value*/
            print (matches.Item i).Value /* I just want this format : numberxnumber*/
        )
    )
)

I did the same thing with my array : objects.

Now I need to compare thoses results because I would like to duplicate each object and align them with the right proxy. An object can be align with one or more proxys.

Not sure if I very clear.
Should I use a for with an if structure to do that ?

Thank you for your help I appreciate that :smiley: !


#6

You can make and use some sort of a dictionary for that purpose.

proxy_names = #("proxy_001_1200x300","proxy_002_1200x300","proxy_001_1200x400","proxy_650x350")
object_names = #("object_1200x300","object_1300x300","object_300x1200","object_650x350")
RE_Matches = (dotnetclass "system.text.regularexpressions.regex").matches


re_pattern = "\d+[xX]\d+"
-- 1. creating sort of hashmap
data = DataPair keys:#() indexes:#()

for j = 1 to proxy_names.Count do
(
	local matches = RE_Matches proxy_names[ j ] re_pattern
	
	for i = 0 to matches.Count - 1 do
	(
		local suffix = (matches.Item i).Value
		local index = findItem data.keys suffix
		
		if index == 0 then -- such key doesn't exist yet
		(
			append data.keys suffix
			append data.indexes #( j )
		)
		else
		(
			appendIfUnique data.indexes[ index ] j -- add another index that is valid for such suffix
		)
	)
)


-- 2. determine corresponding proxies for particular object
for entry in object_names do
(
	local matches = RE_Matches entry re_pattern
	
	for i = 0 to matches.Count - 1 do
	(	
		local index = findItem data.keys (matches.Item i).Value -- find index of this suffix
		
		if index > 0 do
		(
			format "Object: '%'\n" entry
			
			for j in data.indexes[ index ] do
			(
				format "    Proxy: '%'\n" proxy_names[ j ]
			)
		)
	)

)