Notifications
Clear all

[Closed] How to determine if a string is a keyword?

Hi guys,
I need to determine if a string is equal to an internal 3ds Max keyword. In example I need to know if “getEdgeVertex” is a keyword. It actually is an Editable_Poly method, but how do I determine it by MaxScript? I tried the apropos() function with no luck, it seems to ignore object methods. Every other function, like showInterfaces() requires an object to query, but I got only a string. Is there a way to do this? Thank you very much.

  • Enrico
4 Replies
1 Reply
(@bobo)
Joined: 11 months ago

Posts: 0

getEdgeVertex by itself is not a valid method, as you noted yourself. The full specification is Editable_Poly.getEdgeVertex and you can check for that easily by just asking for its class.

Editable_Poly.getEdgeVertex –> InterfaceFunction –> != undefined –> true

But

getEdgeVertex –> undefined

so without checking each possible struct and Function Publishing Interface for it, you cannot be sure.

If you suspect it could be in several FPS or structs, you could run through them and check, like

theFPS = "Editable_Poly"
 execute ("classof " + theFPS + "." + "getEdgeVertex") != undefined
 --> true

Now you could make theFPS a FOR loop variable, like

for theFPS in #("Editable_Poly","meshop","polyop") where \
   try(execute ("classof " + theFPS + "." + "getEdgeVertex") != undefined)catch(false) collect theFPS
 -->#("Editable_Poly")
 
 
 for theFPS in #("Editable_Poly","meshop","polyop") where \
   try(execute ("classof " + theFPS + "." + "getVert") != undefined)catch(false) collect theFPS
 -->#("meshop", "polyop")
 

Package this in a function, pass the string as argument and possibly use apropos to build an array of ALL possible structs and classes in MAXScript (!) and you could check that string against pretty much cases…

Thank you Bobo,
the workaround you’re showing is exactly what I’ve been doing so far. I hoped for a more general hidden ninja method, to be sure to handle every possible case without so much effort. Right now I’m working on a code obfuscator, and I need to prevent the substitution of custom function names if they match those of 3ds Max standard methods. The “getEdgeVertex” is an example of these. Thanks again.

  • Enrico
1 Reply
(@bobo)
Joined: 11 months ago

Posts: 0

Here is a more expanded version:

(
local theClassesArray  = #()
	
fn initSearchFunction =
(
	local st = timestamp()
	theClassesArray  = #()
	local str = stringStream ""
	apropos "*" to:str
	seek str 0
	while not eof str do
	(
		local theLine = readLine str
		if matchPattern theLine pattern:"*Struct*" or matchPattern theLine pattern:"*Interface*" or matchPattern theLine pattern:"*MAXSuperClass*" or matchPattern theLine pattern:"*MAXClass*"  do
			append theClassesArray (filterString theLine " ")[1]
	)
	format "Initialized in % ms.
" (timestamp()-st)
	theClassesArray.count
)

fn isValidFunction theFunctionString =
(
	local st = timestamp()
	local theResult = for theFPS in theClassesArray where \
		try(execute ("classof " + theFPS + "." + theFunctionString) != undefined)catch(false) collect theFPS
	format "% Found in % ms.
" theResult.count (timestamp()-st)
	theResult
)

initSearchFunction()
isValidFunction "getVertex"

-->Initialized in 289 ms.
-->6 Found in 468 ms.
-->#("Editable_Poly", "EditablePolyMesh", "Edit_Normals", "EditNormals", "Edit_Poly", "EditPolyMod")
)

Excellent! Thank you very much for your effort! Right now I’m not concerned about calculation timings. It doesn’t matter if the script requires one minute to encode a 100Kb file, as soon as the obfuscation is accurate and doesn’t tear the code apart. I’m going to test your work right now. The script isn’t tuned to digest every kind of coding style yet, in example locals variables need to be fully declared like “local varName” to be collected, but as soon as I can make it more flexible, will publish it, with credits of course.

  • Enrico