ScriptSpot

Forum topic · General Scripting

convert: undefined to type: String PROBLEM [SOLVED]

By 3dwannab · 2015-05-11

Description
OldString = "Arch137" as string -- Change to suit
NewString = "AM137" as string -- Ditto
theMaps = getClassInstances BitmapTexture
for i in 1 to theMaps.count do (
	fileName = theMaps[i].filename
	if matchPattern fileName pattern:"AM*" ignoreCase:false == false then (
		newFilename = trimleft fileName OldString
		new2filename = NewString + newFilename
		theMaps[i].filename = new2Filename -- renames
	)
)

The above creates an error stated in the subject. I have tested this on 20+ scenes prior without any errors. I want to achieve is to replace 'string1' for 'string2' in the filename paths whilst not affecting the actual path.

As I've said it worked on 20 odd scenes prior.

Thanks for any help.

Comments (15)

Regexpression example (Greaaaat success - Borat)

3dwannab · 2015-05-25


OldString =@".+"
MapArray = getClassInstances BitmapTexture
for o in MapArray where doesFileExist(o.filename) == false do (
	rgx = dotnetObject "System.Text.RegularExpressions.Regex" OldString
	filename = rgx.Replace o.filename ""
	o.filename = Filename
	ATSOps.Refresh()
)

Strips filenames and paths only if missing from scene :) (much like relink bitmaps by colin senner)

FINISHED CODE (Case sensitive)

3dwannab · 2015-05-16

OldString = "XXX"
NewString = "HD"
MapArray = getClassInstances BitmapTexture
-- fix for missing names in maps help by pixamoon
for o in MapArray where o.filename != undefined do (
    fileName = (filenamefrompath o.filename)
    if fileName != undefined and matchPattern fileName pattern:("*"+OldString+"*") ignoreCase:false == true then
        try(
            newFilename = replace fileName (findstring fileName OldString) OldString.count NewString
            o.filename = pathConfig.normalizePath ((getfilenamepath o.filename) + "\\" + newFilename)
			ATSOps.Refresh() 
        )catch()
)

Code error in last code snippet NEW CODE HERE...

3dwannab · 2015-05-16

fileName = "HDM_04_09_testfilename"
OldString = "HDM"
NewString = "AM"
CombinedStrings = replace fileName (findstring fileName OldString) OldString.count NewString

Listener output:

"HDM_04_09_testfilename"
"HDM"
"AM"
"AM_04_09_testfilename"

`

pixamoon · 2015-05-12

Hello again :) maybe something like this:


OldString = "Arch137" as string -- Change to suit
NewString = "AM137" as string -- Ditto

for o in getClassInstances BitmapTexture do (
	if (fileN = getfilenamefile o.filename) != undefined and matchPattern fileN pattern:"AM*" ignoreCase:false == false then (
		newFilename =  trimleft fileN OldString
		if newFilename != fileN do (
			new2filename = NewString + newFilename
			o.filename = pathConfig.normalizePath ( getfilenamepath o.filename + "\\" + new2Filename + getfilenametype o) -- renames 
		)
	)
)

or just minimum addition to your code:


OldString = "Arch137" as string -- Change to suit
NewString = "AM137" as string -- Ditto
theMaps = getClassInstances BitmapTexture
for i in 1 to theMaps.count do (
	fileName = theMaps[i].filename
	if fileName != undefined and matchPattern fileName pattern:"AM*" ignoreCase:false == false then (
		newFilename = trimleft fileName OldString
		new2filename = NewString + newFilename
		theMaps[i].filename = new2Filename -- renames
	)
)

Hiiii, No...

3dwannab · 2015-05-12

First code you wrote still has that same error.

I've fixed the problem in my original code where it was replacing part of the filename with this particular scene by using 'fileName = (getfilenamefile theMaps[i].filename)' as opposed to 'fileName = theMaps[i].filename' but the error still crops up.

Full output from the listener using code:

OldString = "Arch137" as string -- Change to suit
NewString = "AM137" as string -- Ditto
theMaps = getClassInstances BitmapTexture
for i in 1 to theMaps.count do (
	--fileName = theMaps[i].filename
	fileName = (getfilenamefile theMaps[i].filename)
	if fileName != undefined and matchPattern fileName pattern:"AM*" ignoreCase:false == false then (
		newFilename = trimleft fileName OldString
		new2filename = NewString + newFilename
		fileName = new2filename -- renames
	)
)

Listener:

"Arch137"
"AM137"
#(Map #1:Bitmap, Map #1:Bitmap, Map #1:Bitmap, Map #1:Bitmap, Map #1:Bitmap, Map #1:Bitmap, Map #1:Bitmap, Map #1:Bitmap, Map #1:Bitmap, Map #1:Bitmap, Map #4411:Bitmap, Map #4412:Bitmap, Map #4413:Bitmap)
-- Error occurred in i loop; filename: ; position: 777; line: 19
--  Frame:
--   new2filename: undefined
--   i: 13
-- Unable to convert: undefined to type: FileName

BTW do you know why the listener stops outputting when you run evaluate or eval selected line/code. Have to restart max to get it working.

I can send the test scene if you're willing to help. The way I want the format of the jpgs filenames is 'AM66_*.jpg' so the pattern would need to match 'AM' 'digits' 'underscore' 'anychar' 'ext'. Maybe I'm tired learning maxscript but I can't figure it out, plus the error which is more important.

Getting this to work would be a great timesaver. I tried looking for wxample codes also where say I want:

OldString = "Arch137" as string -- Change to suit

to allow different options that support wildcards. I know this is asking a lot. :)

MANY THANKS FOR HELPING SO FAR.

`

pixamoon · 2015-05-13

yes sure please send it.

But for renaming files or bitmap filenames in project you can use my Bitmap Tracking/Resizing... or cbuelter't Interactive Renamer

And yes, I know that "listener stops working" I had similar thing many times. What I found out only: it happens mostly if there is mistake in code and than it can't evaluate it or show error.
If I remember sometimes helps to delete what I changed last or try maybe to delete whole code, evaluate only with a = 1 and than undo detete ?? just an idea

also u have undefined error in other line:
new code:


OldString = "Arch137" as string -- Change to suit
NewString = "AM137" as string -- Ditto
theMaps = getClassInstances BitmapTexture
for i in 1 to theMaps.count do (
	--fileName = theMaps[i].filename
	fileName = (getfilenamefile theMaps[i].filename)
	if fileName != undefined and matchPattern fileName pattern:"AM*" ignoreCase:false == false then 
	try(
		newFilename = trimleft fileName OldString
		new2filename = NewString + newFilename
		fileName = new2filename -- renames
	)catch()
)

or


OldString = "Arch137" as string -- Change to suit
NewString = "AM137" as string -- Ditto
theMaps = getClassInstances BitmapTexture
for i in 1 to theMaps.count do (
	--fileName = theMaps[i].filename
	fileName = (getfilenamefile theMaps[i].filename)
	if fileName != undefined and matchPattern fileName pattern:"AM*" ignoreCase:false == false then (
		newFilename = trimleft fileName OldString
		new2filename = NewString + newFilename
		if new2filename != undefined do fileName = new2filename -- renames
	)
)

:{([

3dwannab · 2015-05-13

Neither of those codes worked. I'm stumped. Sending scene and thanks for the trick. I tried evaluating a line of code I know was okay but I'll try your method next time. Don't mind the state of the scene I decimated the model.

Attachments

`

pixamoon · 2015-05-14

:( I don't have 2015 to test it

But looked in the the file with Library Track/Relink. And could see your assets list.
I test names in new scene with this new code:


OldString = "Arch137"
NewString = "AM137"
theMaps = getClassInstances BitmapTexture
for o in theMaps do (
    fileName = (filenamefrompath o.filename)
    --change file name only if match oldstring pattern  + "*"
    if fileName != undefined and matchPattern fileName pattern:(OldString+"*") ignoreCase:false then
        try(
            newFilename = trimleft fileName OldString
            o.filename = pathConfig.normalizePath ((getfilenamepath o.filename) + "\\" + NewString + newFilename)
        )catch()
)

Sorry I didn't noticed this before - you had:

if matchPattern fileName pattern:"AM*" ignoreCase:false == false then 

It was trying to trim and rename all files other then "AM*"
I think it should look for oldString to machtpattern. Than will try to trim only files you want to rename...

if fileName != undefined and matchPattern fileName pattern:(OldString+"*") ignoreCase:false then 

Also for renaming you can use Bitmap Tracking Resizing or Library Track/Relink...
They have much more options to rename files in proj or on HDD etc.

Just a small screenshot how to replace in filename:

3dwannab · 2015-05-14

Thanks, the idea behind this .ms file is to run it with Batch it max over multiple directories and therefore saving tonnes of time in the long run :)

So far I've done a script to clean the assets how I like them found here: http://www.scriptspot.com/3ds-max/scripts/asset-cleaner minus the UI of course to work with BatchItMax and rename objects based on 'Filename + node type' and others like using relink bitmaps to find missing maps. and of course filter set to none and blur to 0.0. Things I find myself doing all the time on an individual basis.

Thanks for spotting the AM. I could replace that with:

pattern:("*"+OldString+"*")

to search that string anywhere in the string replacing any instances of it. I'd love if I could get regular expressions to work seeing as I know how to do that :) but maxscript is a different league but baby steps, baby steps. I've attached the scene in '14 format.

The new code is still throwing an error at:

fileName = (filenamefrompath o.filename)

Bangs head!!

Attachments

`

pixamoon · 2015-05-16

oki,

Should be fixed now:


OldString = "Arch137"
NewString = "AM137"
theMaps = getClassInstances BitmapTexture
for o in theMaps where o.filename != undefined do (
    fileName = (filenamefrompath o.filename)
    --change file name only if match oldstring pattern  + "*"
    if fileName != undefined and matchPattern fileName pattern:(OldString+"*") ignoreCase:false then
        try(
            newFilename = trimleft fileName OldString
            o.filename = pathConfig.normalizePath ((getfilenamepath o.filename) + "\\" + NewString + newFilename)
        )catch()
)

there was one bitmap "Map #4413:Bitmap" without any filename in your scene. This will fix the problem:

 for o in theMaps where o.filename != undefined do ( 

This is if you want to make another rename script from scratch :)

If I understand you want to batch rename assets in multiple max files... Let me know if you want to try full version of Library Track/Relink? Its still not 100% finished but it does rename and repath job very easly...

Best,
Pixamoon

3dwannab · 2015-05-16

THANKS VERY MUCH that has solved that undefined problem. I didn't notice that. Oh the shame! Thanks so much, I'm learning a lot. Only problem now is the trimleft function doesn't seem to be the right method to replace text strings. I really only used this to test but now I want to actually just replace x with y and so fourth. With trimleft it returns and results in:

trimleft "HDM_04_wordhere" "HDM_04"
"wordhere"

It takes out the _ before wordhere which is not what I was looking for.

I'm looking for a function to replace just what I type as opposed to affecting characters. I can't see one in the MS help, unless I'm blind! Any help here would get this finished I hope. I've done more tests with your the script and its much better than the built in asset tracker! I'd love to test it for you. I've noticed a bug in it. It doesn't update the assest tracker when you rename files etc. ATSOps.Refresh() should do the trick. Also when you open a new scene it doesn't update the list like asset tracker does. Apart from that, bravo!! :]

My new code looks like:

OldString = "HDM_04_10"
NewString = "HDM04_10_"
theMaps = getClassInstances BitmapTexture
for o in theMaps where o.filename != undefined do (
    fileName = (filenamefrompath o.filename)
    --change file name only if match oldstring pattern  + "*"
    if fileName != undefined and not matchPattern fileName pattern:(NewString) ignoreCase:false then
        try(
            newFilename = trimleft fileName OldString
            o.filename = pathConfig.normalizePath ((getfilenamepath o.filename) + "\\" + NewString + newFilename)
			ATSOps.Refresh() 
        )catch()
)

I've changed:

if fileName != undefined and matchPattern fileName pattern:(OldString)

to

 if fileName != undefined and not matchPattern fileName pattern:(NewString)

So that it only affects strings that DON'T have the Newstring in it. Seems to make sense to me anyway. :] And also added a refresh to the ATSOps But it's the trimleft problem which is helpfully the last of my issues. :) Thanks mate for your invaluable help so far!

`

pixamoon · 2015-05-16

Good, so one problem away :)

and thanks for testing and suggestion... I'll add ATSOps.Refresh() to next version Thanks
and second - do u mean if you open new scene and Bitmap Tracking is still on it doesnt update.. thats true, I started as just resizing bitmaps script and it grows so much now... I'll add callback and if doesn't get slower. Actualy I think to remove hard Asset refresh on every open script, With big scenes it takes soem time to open it...

I send you also Library Track/Relink, let me know how it works...

and your code..
I used findSting instead of match pattern and then replace instead of trimleft or right
So then u can replace also in the middle of string

And u can keep not matchpattern to find it there is no new string but then use findstring ot matchpattern again to find out if there is old string. and than use replace... Hope this makes sense :)

Cheers,
Pixamoon

3dwannab · 2015-05-16

HA! My turn to help you! ;)

Thanks for the pointer. Here's my code snippet for that. With listener ouptut on last 3 lines.

fileName = "HDM04_09_testfilename"
OldString = "HDM"
NewString = replace fileName (findstring fileName OldString) OldString.count ""
"HDM04_09_testfilename"
"HDM"
"04_09_testfilename"

Different example code:

fileName = "HDM_04_09_testfilename"
OldString = "HDM"
NewString = "AM"
CombinedStrings = replace fileName (findstring fileName OldString) OldString.count ReplaceString

`

pixamoon · 2015-05-16

yes, exactly, this is the way to do that

FOUND A SOLUTION TO THE LISTENER NOT WORKING

3dwannab · 2015-06-21

Place the cursor in the listener and hit escape a couple of times. :]