Advice Needed for Asset Management Script


#8

so nobody knows of any commercial plugin or script that does this?


#9

Commercial eh? How much you willing to pay. :smiley: I’ll make a commercial script.


#10

Hi thatoneguy.

You want to make a commercial script?? did you know the vrayscatter made by icube. this will be sale 100 euro. If you can make out this , how much do you think It’s fine to sale.


#11

I don’t know what VRay Scatter does. I presume it’s more sophisticated than this. But this’ll merge in a file from a small asset library. Note you’ll need to create your own scene library following the included examples. Also note this will crash if you don’t have a C: est\etc

EDIT: REMOVED and UPDATED


#12

Ok. I added a button which parses a directory full of directories… which is full of scenes and thumbnails (100x100 pixels)

Or you can hard code in your libraries as before:

 
---------------------------------------------
-- Basic Asset Manager by Gavin Greenwalt  --
---- Straightface Studios :| Seattle, WA ----
---------- version 2.0 kind of --------------
---------------------------------------------
Global AssetManager, ScenesDialog
Struct AssetManagerStruct (Categories=#(), Scenes=#())
Struct SceneStruct (ID, CategoryID, Name,Path,Thumbnail)
Struct CategoryStruct (ID,Name)
try(destroydialog AssetManagerDialog)catch()
AssetManager = AssetManagerStruct()
AssetManager.Categories = #(
--- Template Categories ---
-- CategoryStruct ID:1 Name:"Category One",
-- CategoryStruct ID:2 Name:"Category Two"
--- End Template Categories -- 
)
	   
AssetManager.Scenes = #(
--- Template Scenes ---
-- SceneStruct ID:1 CategoryID:1 Name:"Box One" path:"C:\	est\\Box_01.max" Thumbnail:"C:\	est\\Box_01.jpg",
-- SceneStruct ID:2 CategoryID:2 Name:"Box One" path:"C:\	est\\Box_01.max" Thumbnail:"C:\	est\\Box_01.jpg"
--- End Template Scenes -- 
)	   
	   
Rollout AssetManagerDialog "Manage Your Assets" width:450 height:400
(
 fn QuadifyString stringvar =
 (
  stringvar = filterstring stringvar "\\"
  assembly = ""
  for i =1 to stringvar.count - 1 do
  (
   append assembly (stringvar[i]+"[\\\\\\\\](http://forums.cgsociety.org/)")
  )
  append assembly stringvar[stringvar.count]
  assembly
 )
 DropDownList CategoryDropDown "Categories:" across:2
 Button CustomLibraryButton "Load New Library From Path" height:40 offset:[0,5]
 subrollout ScenesSubrollout "Scenes" width:440 height:335
 
 on AssetManagerDialog open do
 (
  CategoryDropDown.items = #("")
  CategoryDropDown.items = (join CategoryDropDown.items (for o in AssetManager.Categories collect o.name))
 )
 
 on CustomLibraryButton pressed do
 (
  thumbnailtypes = #(".jpg",".tif",".png",".bmp")
  newpath  = getsavepath()
  newcats = getdirectories (newpath+"\\*")
  AssetManager.Categories = #()
  AssetManager.Scenes = #()
  for i = 1 to newcats.count do
  (
   catname = (filterstring newcats[i] "\\")
   catname = catname[catname.count]
   append AssetManager.Categories (CategoryStruct ID:i Name:catName)
   scenes = getfiles (newcats[i]+"*")
   maxfiles = (for o in scenes where (getfilenametype o == ".max") collect o)
   thumbnails = (for o in scenes where (finditem thumbnailtypes (getfilenametype o)) != 0 collect o)
   for o in maxfiles do
   (
	idval = (AssetManager.Scenes.count + 1)
	scenename = getfilenamefile o
	thumb = (for t in thumbnails where (matchpattern (getfilenamefile t) pattern:(getfilenamefile o)) collect t)[1]
	append AssetManager.Scenes (SceneStruct ID:idval CategoryID:i Name:scenename path:o Thumbnail:thumb)
   )
  )
  CategoryDropDown.items = #("")
  CategoryDropDown.items = (join CategoryDropDown.items (for o in AssetManager.Categories collect o.name))
  try(removeSubRollout AssetManagerDialog.ScenesSubRollout ScenesDialog)catch()
 )
 
 on CategoryDropDown selected s do
 (
   s -= 1
  try(removeSubRollout AssetManagerDialog.ScenesSubRollout ScenesDialog)catch()
  ScenesString = "" as stringstream 
  format "Rollout ScenesDialog \"Assets\" (
" to:ScenesString
  scenes = for o in AssetManager.Scenes where o.CategoryID == s collect o
  if (scenes).count != 0 then
  (
   for o in scenes do
   (
	format "Button Button% \"%\" images:#(\"%\", undefined, 1, 1, 1, 1, 1) width:100 height:100 align:#left across:4
" o.id o.name (QuadifyString o.thumbnail) to:ScenesString
   )
   for o in scenes do
   (
	format "on button% pressed do
" o.id to:ScenesString
	format "(
" to: ScenesString
	format "mergemaxfile \"%\" #Select 
" (QuadifyString o.path) to: ScenesString
	format ")
" to: ScenesString
   )
  )
  else
  (
   format "label NoMapsLabel \"No Scenes Found\"" to:ScenesString
  )
  format ")" to:ScenesString
  execute (ScenesString as string)
  AddSubRollout AssetManagerDialog.ScenesSubRollout ScenesDialog
 )
)

createdialog AssetManagerDialog


#13

well done, thatoneguy~!!
that’s great, I think you can do it whole.

cheer…


#14

Just to be clear here is the directory structure it expects:

…\LibraryPath<Category Names>\filename.jpg&.max

just did a cursory glance abouts the internets and found no documentation for creating a Vray proxy. So if someone would be so kind as to find that I would tack it on.


#15

I’ve been thinking about this for the exact same purpose. I thought a simple solution could be to use html (i.e. use a web page creation program) to create the directory tree with thumbnails etc and use i-drop links to drag and drop the max scenes (e.g. containing only a pre-textured vray proxy) into your current scene.

I’ll check out your script, thanks.


#16

Our Cat browser uses a dynamically generated html page, via an activeX controller, to display the contents. This allows drop and drop as well as controls to add to a list of items to merge.

A tree view shows all available directories, minus ones that begin with “Z-”.

A simple partial string function, for “seaching”, sorts on the filenames during the generation of the html page.

Wish I could share it, but it’s not mine…


#17

that loosk quite useful Kieth, if i may ask how are you generating the html? this is one of the couple projects that i’m looking at making in whatever spare time i can dig up also :wink: especially since the default max asset browser looks to be completely non-functional at the moment


#18

The webpage was initially designed in dreamwaver then I copied the html in the script line by line as strings to use as a template. There is also a function that looks in the directories and based on the files existing there and with the help of the html template builds the webpage and saves it in a temp folder from where it gets read by the activex. So everytime you change the directory that page is rebuilt.

Some extra functionality that the script has is to enlarge the thumbnail to a full size render, you can open the curent folder in windows explorer and you can add items to a merge queue and import them all at once.

I hope it made sense, it’s been a while since I wrote that and as Keith was saying I wish I could share it but it was done while at Focus so they have all the rights for it…


#19

i agree Gavin Greenwalt. any works should be pay in suitable .

im a max script developer for 3 years , used to work in Crystal CG shanghai for about 2 year .

in china , most animate studio using 3dsmax , and do not have a TD .

for this work , i can work it out in a month . but as for TD , i expect to serve a studio for long time , not just do one script tool when somebody needed . for simple script we can do for free , and for this one , we cant .


#20

i suggest u hire a TD like Gavin Greenwalt , it will be a great help for ur work pipline . a good TD can be freelance guy .


#21

Think I’m going to have to write my own one of these for our company, we could really do with one for browsing HDRs and models.


#22

Hey Anton;
How’z out there in the freelance world?

bingheturen;
Perhaps talk to Anton about him writing one of these for you, it’s a great tool and I’m sure he could make it even better the second time around, plus customize it to your file structures and workflow. He was here at focus360 for years and writes some nice code…


#23

Hey Keith, freelance world is pretty good, cannot complain. As from the writing nice code all I can say is that I’ve learned from the master :bowdown:. Any plans for siggraph?

hblan:
You are right, hiring a TD to help streamline the pipeline is one of the best moves a company can make if cannot afford to have one in house full time which is the proper thing to do!


#24

Thanks for the shot of what you have, and the tip on the dynamic web page, seems to be a pretty valid way to do it.

If i may ask, how are you sending info on which thumbnail or button was clicked back to the maxscript from the web control?


#25

Well, so far I’ve got my auto generation of the basic page (Fills an array of thumbnails into a table) based pretty heavily off of Gavin’s code above, I’ll post something about it when its a bit more stable after I get a few more minutes to toy with it.

I’ve also done a bit towards generating the thumbnails from our initial directory of props, using PEN’s BatchItMaxcombined with a couple scripts Description: here namely the Render Thumbnail script

now to figure out the rest of the UI :slight_smile: am I demented for enjoying figuring this junk out?


#26

The activex control has an event called “NavigateComplete2” and I’m using it to send the path back to maxscript. To find all the events just querry your activex using “showevents”


#27

Thanks for the reply Anton… I’ve got it running so far :wink:

As with most questions i find myself asking, i find myself finding the answers something like .27ms after posting the questions.

anyway! now the fun part is working up an easy way to throw a directory tree into a treeview. which is more or less working on the fly using a fun little struct here: albeit very slow for large directory structures. So… now figuring out the fun of saving that out to disk and only reloading the directory tree as needed. :slight_smile:

thats probably the last of the code for a while though as projects are ramping up again :wink:


(
Struct DirTreeItem (dir, depth, name, treenode)
Struct DirTree (
	Tree=#(),
	pathToParse = "",
	
	fn parseDirectories root depth =
	(
		local dir_array =#()
		dir_array = GetDirectories (root+"/*")
		for d in dir_array do
		(
			local splitName = filterstring d "\\"
			local dirName = splitName[(splitName.count)]
			append Tree (DirTreeItem dir:d depth:(depth+1) name:dirName)
			--try and add it to the child node if we have one, else add it to the parent
			try(parseDirectories d (depth+1)) catch(parseDirectories root depth)
		)
	), -- End fn

	fn selectPathToParse = 
	(
		pathToParse = (getSavePath caption:"Select which Directory to Parse into a Tree" initialDir:"C:/")
	),
	
	fn Run =
	(
		if pathToParse != "" then
		(
			st = timestamp()
			append Tree (DirTreeItem dir:pathToParse depth:0)
			parseDirectories pathToParse 0
			format "Directories.parseDirectories() completed in [% ms]
" (timestamp()-st)
		) else messagebox "set the DirTree.pathToParse before calling DirTree.Run()
 or Call DirTree.selectPathToParse() first to select it from a list"
	)
)
DT=DirTree()
DT.pathToParse = "Z:/Prop Catalog"
-- DT.selectPathToParse()
DT.Run()