EDIT; Seems like I found the solution already
Just replace the "
EditPolyMod.SetSelection ePoly_obj #Face face_savedSelection" with "
Edit_Poly.select ePoly_obj #Face face_savedSelection"..need to test some more, hopefully it wont break anything else.
Yeah, this weekend I really feel like wanted to learn some maxscript to improve my workflow, some of you guys might notice my other maxscript threads here recently, heh!
So, straight to the point; Save/ Load here is not a save selected object to .max file or something, but is save to memory to be recalled later on. Forgive me if it's a brute force code...
The code for save selection into memory;
( -- save SO selection into memory
global vert_savedSelection = #{}
global edge_savedSelection = #{}
global face_savedSelection = #{}
if (selection.count == 1) then
(
case (classOf $.modifiers[1]) of
(
undefinedClass:
(
global base_obj = $.baseobject
case subobjectlevel of
(
1:
(
num_vert = polyOp.getVertSelection base_obj
for sel in num_vert do
(
vert_savedSelection[sel] = true
)
)
2:
(
num_edge = polyOp.getEdgeSelection base_obj
for sel in num_edge do
(
edge_savedSelection[sel] = true
)
)
4:
(
num_faces = polyOp.getFaceSelection base_obj
for sel in num_faces do
(
face_savedSelection[sel] = true
)
)
)
)
Edit_Poly:
(
global ePoly_obj = $.Edit_Poly
case subobjectlevel of
(
1:
(
num_vert = EditPolyMod.GetSelection ePoly_obj #Vertex
for sel in num_vert do
(
vert_savedSelection[sel] = true
)
)
2:
(
num_edge = EditPolyMod.GetSelection ePoly_obj #Edge
for sel in num_edge do
(
edge_savedSelection[sel] = true
)
)
4:
(
num_faces = EditPolyMod.GetSelection ePoly_obj #Face
for sel in num_faces do
(
face_savedSelection[sel] = true
)
)
)
)
)
)
)
And to recall it back;
( -- load SO selection from memory
if (selection.count == 1) then
(
case (classOf $.modifiers[1]) of
(
undefinedClass:
(
case subobjectlevel of
(
1:
(
if (vert_savedSelection != undefined) do
(
polyop.setVertSelection base_obj vert_savedSelection
max modify mode
modPanel.setCurrentObject base_obj
subobjectlevel = 1
)
)
2:
(
if (edge_savedSelection != undefined) do
(
polyop.setEdgeSelection base_obj edge_savedSelection
max modify mode
modPanel.setCurrentObject base_obj
subobjectlevel = 2
)
)
4:
(
if (face_savedSelection != undefined) do
(
polyop.setFaceSelection base_obj face_savedSelection
max modify mode
modPanel.setCurrentObject base_obj
subobjectlevel = 4
)
)
)
)
Edit_Poly:
(
case subobjectlevel of
(
1:
(
if (vert_savedSelection != undefined) do
(
EditPolyMod.SetSelection ePoly_obj #Vertex vert_savedSelection
max modify mode
modPanel.setCurrentObject ePoly_obj
subobjectlevel = 1
)
)
2:
(
if (edge_savedSelection != undefined) do
(
EditPolyMod.SetSelection ePoly_obj #Edge edge_savedSelection
max modify mode
modPanel.setCurrentObject ePoly_obj
subobjectlevel = 2
)
)
4:
(
if (face_savedSelection != undefined) do
(
EditPolyMod.SetSelection ePoly_obj #Face face_savedSelection
max modify mode
modPanel.setCurrentObject ePoly_obj
subobjectlevel = 4
)
)
)
)
)
)
)
Editable Poly object works as expected, but Edit Poly just can't recall the selection somehow, I know that it did put the face selection into the array because when I type face_savedSelection on the listener, it come up with the array of the selected polys. I'm guessing the line of "
EditPolyMod.SetSelection ePoly_obj #Face face_savedSelection" didn't do the task that I intended it to do.
Does anyone have any idea for this?
Replies
Do not use:
global vert_SavedSelection = #{}
global vert_savedSelection = #{}
global face_savedSelection = #{}
because when you use the script to save the currently selected verts they will ba saved. When you use the script again to save the currently selected faces, the vert_SavedSelection will become an empty bitarray ana you will loose the saved vertices and edges.
1. With sub objects selected just type a name into the Selection Sets drop down. Then to retrieve a selection just use the drop down list. You can modify stored sub object selections by pressing the button next to the drop down.
2. In the ribbon the Stored Selections Panel. Is similar to the scripts you wrote.
Hmmmm...about the array #{}, so you mean that max can only save 1 array? why does the vert_savedSelection array can overwrite the content of edge_savedSelection array? since both refer to different array variable, no?
And does the "BA" at the end of the vert_savedSelectionBA has any meaning?
Thanks so much again miauu!
@monster - hey man, thanks for the tips about selection sets drop down, to be honest I never used it before O_O but I guess with a shortcut key it'll be much more faster rather then navigating to the top toolbar to manage my selection sets, but I'm sure it'll be come in handy for a larger scene with many complex object
The "BA" at the end probably just means this will be a "bitArray". Just a coding style.
I've written some selection set scripts in the past that assigned random names automatically for me so I never had to type anything in. This was nice because you just select some mesh parts and then hit the hotkey to assign them to a new selection set. I dont care what they are called and retrieving them isnt a big deal either. Just select one polygon on the part I want to recall and then use another script to search the named selection sets that contain the poly and then set the selection to that selection set. Much faster than typing in names and browsing the drop down list. Although I hardly ever use the script because the selection sets tend to break during modeling when the vert/edge/poly ids get renumbered.
For example. the two scripts below are shorter and avoid extra global variables.
And of course now that I go back and check the documentation for the case expression it clearly shows it being used that way in their example...
Is it good? bad? or any other way to trim it some more? (currently I trim 56 lines of code using this approach compare to my earlier brute force version, and it sure does looks more pretty haha!)
Thanks guys, couldn't do it without your help
OR
Now as far as the actual code you're writing and what you're trying to accomplish? That can be improved upon but it of course takes time and experience. I'm still learning everyday. I'm sure this code i'm about to post can be improved upon even more.
Try to think of better ways for compacting or re-suing your code, look for tricks in other scripts that you may not already know about to help you improve.
Here's a way of storing selections to a variable and recalling them all from the same function without specifying edit poly mod or editable poly base case expressions. Im able to do this because of the 'PolyBGetSel' and 'PolyBSetSel' functions work in either case. The help for these functions seem to be missing from the help files though
Haven't really read anything about defining a function though, so might come back here in the future after I more familiar with function
Anyway, is it a good idea to define these codes below as a global on 1 file for other scripts use? So I don't have to type case of keyboard.controlPressed or other common one each time I want to use it inside my script? EDIT_01: woops all the above need to wrap inside "if selection.count == 1 do" otherwise it will throw modifiers is undefined on max start.
EDIT_02: seems like it's not working, assign it to the global variable like that just wont work as expected..oh well..
Wrapping your global code inside a selection.count block will not work because max will only define those globals if your selection.count == 1 so if you want to use xKeyPressed on multiple objects but have not yet used it on a single object then it would not be defined and would throw a undefined error.
Also your xCurMod code doesnt work correctly. Its currently on looking at the top level modifier not the currently selected modifer.
^is what you want to use to get the currently selected modifier
Check out the maxscript help tutorials and also check out these videos http://vimeo.com/album/1514565
By the way here's a way to get a single global variable for all those functions by using structs. I know this may be too complex for you right now but its the way a lot of scripters have been defining larger libraries in the past few years.
Anyway Bryan, does the script above suppose to work if I put on startup folder? so it auto run everytime, but currently it gives me;
Found something that doesn't work with the previous code and manage to make it to work properly, but thought I'd like ask the other experienced maxscripter of what's actually going on here;
The problem is on the keyPressed, if I use the code; And on my script: It just won't work, but if I use like below; And on my script; It is doing what I ask it to do.
Is this the correct way of doing it? Actually I found the tips from bigley's script.
PS: note that if I didn't use # before the ctrl/shift/alt/none, the script become not working.
But it doesn't work like that on subobjectlevel, without # still able to detect; subLevel 1 -- "vertex"
subLevel 2 and 3 --"edge"
subLevel 4 and 5 -- "face"
If you want to use those variables and not name values then assign the keyboard pressed code to those variables and use them in your case of expression.
But why do you feel the need to do it this way? I would suggest using it the way that works already as I described here http://www.polycount.com/forum/showpost.php?p=1656293&postcount=92
Nah, I didn't feel like want to use it without # though, the question is just out of curiosity.
Thanks so much, Bryan!
Oh man, maxscript just keep on refuse to be friend with me T_T
Here's the situation; I got the following code on my startup script based on Bryan suggestion and organize stuff using struct and function; And I have this on the individual script; Any reason why my "case of" always goes into the "genericMode"? even though the "print (classOf (modPanel.getCurrentObject()))" inside of it saying it is indeed "Unwrap_UVW"? why won't it enter the "uvMode" instead?
Already tried with or without the "return #" also tried putting "uvMode: Unwrap_UVW" instead of "Unwrap_UVW: uvMode" and seems like nothing can help it to run properly...:(
PS: Bryan, so sorry if my questions takes too much of your time
Here's what's happening:
- Your case of in the function fnRevel_curClass is returning 'undefined'
- The case of in the other code is testing if case of undefined equals genericMode , which does not exist here either so its returning undefined and making the expression true
- Since it is true the case of expression executes the code for that and as it says in the help for case expressions So that's the only one that executed.
If you moved the uvMode above the genericMode it would of executed that first but this is all wrong. You need to learn about the most basic concept in maxscript 'varaibles', then 'if 'else', then 'loops' then functions and so on. You're trying to run before you can crawl.
Another thing your doing is creating code that does the same thing in other code. You're using a case of expression to get the current modifer and then testing it again using another case of expression but its essentially doing the same code again with a little extra to execute what you wanted it to do in the first place.
You also don't need to append the Revel prefix to every bit of code. That is something for objects in global scope so its only needed on the glRevel variable.
Instead of It would be
Yeah, I know I'm probably won't creating script that will be used by many people, mostly my script will be just to support my personal modeling need and workflow, so it will be revolve around editable poly/edit poly/ unwrap uv/ turbosmooth/ and stardard modeling tools like cut/ weld/ bridge/etc.
And about code that checking similar thing on another code, I assume you're saying about the keyPressed declared on global script and re-check on the other script, correct? well it's just for cleanness purpose actually, probably it doesn't make sense to do that?hehe..
I'm trying to create the setup like Perna's suggested here so it's many set of scripts that using the value of the variable that we declared as global. Instead of typing "keyboard.controlPressed and not ..." every time, now I can just type #ctrl.
The main drawback is that the selection sets are not saved with the scene.
I have plans to do almost the same, but first I need to find the best approach.
There is no way using maxscript to delete subobjects Named Selection Sets.This can lead to long, long list with sub objects selection sets, and this can be very frustrating.
Funny thing is the same exact thing work on my home computer. Even more funny thing is that it work once before on my office but after restart, Max start throw me an error again...Is there any huge different on how Max 2014 and Max 2009 treat a maxscript file?
FYI: my office use Max 2014, my home computer Max 2009, and its not just about modKey, but subLevel and curClass as well...
Did you guys experienced this before?
You need to place your global.ms file in a user-defined plugin folder.
Please read this article on the script evaluation order.
http://docs.autodesk.com/3DSMAX/16/ENU/MAXScript-Help/files/GUID-615D14FB-0F2D-4801-B381-1128C4128C70.htm
I have all my personal scripts in my dropbox folder that I set the system path to at work and home so I always have them up to date.
The folder has a global struct that has includes from a (lib) folder and on creating that struct it installs all my macroscripts from the (macro) folder.
I should look into it further as currently I still abit blank of what is happening on your folder structure. What if you put all the macros in d folder specified on the system path? Is it because related to this sentence from the help file "The 3ds Max scene has not been created and the viewports have not been created at this point. You cannot create scene objects or do anything UI related in these scripts"?
Honestly I have the macroscript install here just so I can uninstall them easily if I decided to get rid of one later on. I hate having my "BCTools" category cluttered with macroscripts that I no longer use so I have an uninstall command that uninstalls them and re-installs them at start up. I forgot to add that to the code in the above post.
I would like to hear from others on how they handle these things. I also just found the macros.load() function which fixes the problem of someone trying to edit macros outside of their app directory when right clicking on their name in the customize dialog. I just add it to my create event after my install and pass it the usermacros directory. The only downside is it loads the macros again when max loads them in its next start up step. Doesnt seem to be a hit on loading time for me. Might become an issue if you have a ton of macroscripts though.
Not sure if there is one. I use perforce and do a query to see if it has been updated and if not it deletes the mcr and re-evaluates from the depot (an ms file). This is done as the menu of max is being built (as i create a menu and attach the scripts to it)