I am using maya, and want to make a check script to see if the project is set or not based on what a set project button to show up ? is their any way to do it in python ?
workspace -q -active ( or cmds.workspace (q=True, active=True) ) will give you the name of the currently active project.
hey , I am stuck at a strange problem well, i need to work on the programming logic though but couldnt figure out how to…
I am working in python and I have a function that setprjCheck() that returns the path of the directory but before it returns the path it makes few checks if the scene file is saved if it is saved is the project set, so if the project is set and if it contains the sourceimages directory it returns the path of source images directory to a text field in the main function, but since I have 4 text field
and if i do tx=setprjCheck for each of the 4 text field just to fill them with the text being returned from setprjCheck() the save scene prompt shows up 4 times if the scene is not yet saved , is their any way if i dont get 4 checks and only 1 if scene is not saved…
Sounds like you’re trying to either shoehorn too many things into one function or your not using the functions return values properly.
You can either:
a)Break it off into multiple functions/methods
b)Function returns a list of results, or a dict if you prefer and you do this:
myList=setprjCheck()
tx1=myList[0]
tx2=myList[1] etc..
c)If the function is run only once and the next action is always to set those text fields, make it part of the function to set those text fields, instead of externalizing it.
It’s also a good idea to make multiple return values explicit. For example, your function could return a dictionary with keys that indicate all of the status info you need, then the logic for what do to with that info could be consolidated somewhere else:
{'saved':False, 'in_project':True, 'has_image_dir': True}
That way it’s really clear when reading the code what information you thought you were operating on. Plus, if you change your mind about what to do with the information, you don’t have to touch the code that finds the information. And of course the dictionary could contain lists:
{'saved':False, 'in_project':True, 'has_image_dir': True, 'images':['img_1.png', 'img_2.tif']}
well, I forgot to tell you in the beginning the value returned by setprjCheck() function to all the 4 textfield is actually same so why make a list or dictionary!!!
in the very beginning i was shoehorn-ing too many things inside one function later i realized if I split I can utilize my function in other scripts too so (eg then I made a sourceIn(…) function)and but still the task performed by setprjCheck() can be reused to pass value returned by it to the 4 textfield, so i cannot use the method myList=setprjCheck() coz thats calling a method while what i want is to take the value returned from that function…
so to have the code working I made a different function that returns the value to textfield, but since their are four text field it is called 4 times however i didn’t kept any prompt in this function that can become annoying…
I would link you up with the code(click here), and I would really appreciate if you can give me some suggestion, its just a small script made in python that can be used to set the imageplanes, I know its just another imageplane setting script but this one i made in python for the first time for maya…
This does nothing except display a window… but it saves a few lines by using the workspace function for path management and some of the built in stuff in the textField for display. Just a hacky quick example of a less wordy way to structure things.
I didn’t make much effort at pretty, its more about how the classes are structured to avoid the logic problem you were having and cut-n-paste code
import maya.cmds as cmds
import os
class ImgPlaneWindow(object):
'''
displays a dialog with a variable number of plane names and pickers
when the dialog closes, updates the Planes field with the values in the pickers (you might want to do this more actively if the dialog works while open rather than modally....)
'''
WIDTH = 512
HEIGHT = 384
MARGIN = 10
def __init__(self, **names):
'''
constructor. Pass in a dictionery with keys as image plane names and values as default image plane paths
'''
if len(names) < 1: raise ValueError, "must supply at least one plane name"
self.Planes = names
self.Pickers = []
def create_gui(self):
self._window = cmds.window(title='Choose image planes')
_form =cmds.formLayout()
_planes = cmds.columnLayout(width=self.WIDTH - 2*self.MARGIN)
names = self.Planes.keys()
names.sort()
for item in names:
self.Pickers.append(self.PickLine(item, self.Planes[item]))
cmds.setParent(_form)
_footer = cmds.rowLayout(nc=5, cw5 = [(self.WIDTH - 2*(self.MARGIN))/5] * 5)
cmds.button('example1')
cmds.button('example2')
cmds.button('example3')
cmds.button('example4')
cmds.button('example5', c=self.close)
cmds.formLayout(_form, e=True, af=(_planes, 'top', self.MARGIN), width=self.WIDTH, height = self.HEIGHT)
cmds.formLayout(_form, e=True, af=(_footer, 'bottom', self.MARGIN))
cmds.showWindow(self._window)
def close(self, *ignore):
for item in self.Pickers:
self.Planes[item.Name] = item.Image
cmds.deleteUI(self._window)
class PickLine(object):
'''
this wraps the textField/pickbutton combo. Pass in a name and a start path.
'''
LABEL_W = 64
FIELD_W = 324
BTN_W = 64
def __init__(self, name, seed):
self.Name, self.Seed = name, seed
cmds.columnLayout(width=self.FIELD_W + self.LABEL_W + self.BTN_W)
self._row = cmds.rowLayout(nc=3, cw3=(self.LABEL_W, self.FIELD_W, self.BTN_W), ct3=['right', 'both', 'both'], co3 = tuple([4]*3))
cmds.text(self.Name)
self._text = cmds.textField(self.Seed, width=self.FIELD_W, fi=self.Seed)
cmds.textField(self._text, e=True, ebg=0)
cmds.button('pick', c = self._pick)
cmds.setParent('..')
cmds.columnLayout(width=self.FIELD_W + self.LABEL_W + self.BTN_W, cal='center')
self._warn = cmds.text('', fn='tinyBoldLabelFont', align='center' )
cmds.setParent("..")
def _pick(self, *ignore):
filters = "Images(*.jpg *.gif *.png);;"
start_dir = cmds.workspace(en='sourceImages')
if not os.path.exists(start_dir): start_dir = cmds.workspace(en='') # fallback to project root if there is no source dir
user_picked = cmds.fileDialog2(cap = "Choose image for %s image plane" % self.Name, fileFilter=filters, sff = 'Images', dialogStyle=2, fm = 1, dir=start_dir)
if user_picked:
self.validate(user_picked[0])
def validate (self, filepath):
#here is where the validation logic would go
valid = True
if valid:
cmds.textField(self._text, e=True, fi=cmds.workspace(projectPath=filepath), ebg=False)
else:
cmds.textField(self._text, e=True, fi=cmds.workspace(projectPath=filepath), ebg=True)
cmds.text(self._warn, e=True, align='center', label='warning would go here' )
@property
def Image(self):
return cmds.textField(self._text, q=True, tx=True)
test = ImgPlaneWindow(**{'top':'', 'front':'test.jpg', 'side':'', 'persp':''})
test.create_gui()
# whenever you're done
print test.Planes
ImagePlaneWindow is a class to what you are passing keyworded areguments?
or u inst of ImagePlaneWindow i.e test ?
how those keyworded argumetns gets passed to the Pickline class and then through its constructor to seed ?
In the above example, ImagePlaneWindow is a class that wraps the GUI. You instantiated it by passing a dictionary ( or keywords/values) like this:
with_dict = ImgPlaneWindow(**{'top':'', 'front':'test.jpg', 'side':'', 'persp':''}) # using ** args and a dictionary, this will have 4 planes with 'front' pre-set
with_args = ImgPlaneWindow(top='', side='set_from_args.jpg', persp='') # this will have 3 planes with 'side' pre-set
The pickers are a nested class (I didnt’ bother to do it here, but that makes it easy to inherit things like the window width or margin settings via closure). Their constructor takes two values – the display name of the plane (‘name’) and the pre-set value if any (‘seed’). Since the constructor for the window has a dictionary of these, I looped through them to set up the pickers. I could have just done:
for plane_name, preset in self.Planes.items():
self.Pickers.append(self.PickLine ( plane_name, preset) ) # self.PickLine looks like a function, but it's really a class that happens to be nested....
but that would produced them in random order :)…
The only real point of the code is to ask the user for a set of imageplane <> file name relationships. The whole thing is just a graphic wrapper around that. It’s helpful to think of it that way to avoid going nuts with the GUI stuff – it’s always best to keep the real work out of the GUI code, since (a) you can swap it later without messing up your pretty buttons and (b) GUI code is always full of fiddly nonsense (like calculating column widths or toggling the active state of buttons) and you want to keep that junk away from your actual functional code.
So, the idea here is that ImagePlaneWindow instance will survive the life cycle of the visible GUI (the way it’s set up, it copies the contentes of the Picker objects into the the field called ‘Planes’ when closed – you could updated the values whenever the pickers fire if you wanted to, it’s just more code than I felt like writing). The sequence would be:
- make an ImagePlaneWindow with your desired list of possible planes
- wait for the user to accept the window
- look at the Planes field, and do what you want with the information. Planes is a dictionary mapping an image plane name to a (project relative) file path ; it’s just a field on the ImagePlaneWindow instance, so you can get to it with a simple property check:
print test.Planes
{'top':'sourceImages/front_plane.jpg', 'persp':'', 'side':'c:/users/steve/desktop/side_ref.png'}
- Now you know what planes the user did or didn’t want - go set them up with functional code.
I did not bother making an ‘accept’ or ‘cancel’ option, but it would be simple to stuff a value into a field in the ImagePlaneWindow that told you what the user had done:
def accept(self, *ignore): #hook to the accept button. BTW the button handler will get an argument by default, I'm just ignoring it here...
self.UserOK = True
for item in self.Pickers:
self.Planes[item.Name] = item.Image
cmds.deleteUI(self._window)
def cancel(self, *ignore): # hook this to the cancel button
self.UserOK = False
cmds.deleteUI(self._window)
There are a lot of other subtleties to consider – like do you want this to be a modal dialog or is it an open working window, how aggressive do you want to be about validating input (say, rejecting non-square textures or stuff that is not in the project), etc. But the real ‘lesson’ is that this kind of gui is really a very long-winded way to ask the user for a set of simple choices – so treat it that way On the code design front, using classes rather than funcs eliminates a lot of boring cut-and-paste code and all those if-thens. If/then is the #1 source of bugs, especially when you’re doing things like checking string names (which you can easily mis-spell). Using classes keeps related info together and eliminates a lot of those weak points – if you notice this chunk of code has like 3 if’/thens, where the original had many/more.
I think I am going to print this and read to remember important things , in my script, I have made one class that is reponsible for GUI creation rest of the stuff occurs outside the class, as i am wworking to release a non-gui version i guess it is the right way to do, however I have never used sub classes, but I like your concept…
Good luck
Looking at this all in the forum makes me realize that we really need python syntax highlighting in the code samples. Any volunteers!!?
We are working with python and We’ve a operate that setprjCheck() of which returns the way of the actual directory yet before the idea returns the way it can make few checks in the event the scene data file is saved whether it is saved may be the project arranged, so in the event the project is defined and if its full of the sourceimages index it returns the way of resource images directory to a text field in the primary function, but since i have 5 text discipline
well, JonesAbrsham if you download the script I have implemented this working fine(Download autoSetProj.mel) I call this script to set project if not set or if the user doesnt have that file I do a basic check and continue… with actual job of my python script…