Toggle X-Ray Mode in Maya using Python - python

I'm trying to bind some Python code to a key so I can toggle X-Ray mode in Maya.
One thing that's confusing me is that when I run this line of code...
def xrayQuery():
cmds.modelEditor('modelPanel4', q=True, xr=True)
xrayQuery()
no result is returned, even though I've queried xray mode. But when I run just the command without the function...
cmds.modelEditor('modelPanel4', q=True, xr=True)
I get what I expected the first time, which is a boolean result based on whether or not xray mode is enabled. Can anyone tell me why this is?
I'm very new to python inside Maya, so any help will be much appreciated! Thanks!

You need to call return if you want the user-defined function to return the same output as called inside.
Like below:
def xrayQuery():
return cmds.modelEditor('modelPanel4', q=True, xr=True)
On a side note, if you could explain the purpose to write a function instead of calling the original function, it would be helpful to understand the use-case

So I've figured out a way to simplify what I was trying to achieve, which was a few lines of code to toggle the x-ray view mode on and off for a specific viewport. I was able to eliminate the need for if else statements by using the 'not' operator in this block of code:
import maya.cmds as cmds
def xray_toggle():
result = cmds.modelEditor('modelPanel4', q=True, xr=True)
cmds.modelEditor('modelPanel4', e=True, xr=not result)
xray_toggle()

Related

How to use the command "with" conditionally without duplication of code

I am trying to use with before executing a block of code, but only if a condition is met, but (at least the common) usage of with doesn't appear to support that unless I duplicate the block of code.
More concretely, I know I can do the following:
if condition:
with blah_blah():
my_code_block
else:
my_code_block
But that's unsatisfying during development since any change I make to my_code_block must be made twice. What I want to do (conceptually) is:
if condition:
with blah_blah():
else:
my_code_block
That doesn't work, though. Is there a way to accomplish what I'm trying to do?
For anyone that's interested in my particular use, I'm trying to write code that runs a batch of examples in pytorch, with torch.no_grad() if I'm in evaluation mode and without it if I'm in train mode. So what I want to do becomes
if mode == 'eval':
with torch.no_grad():
else:
run_batch(features, labels)
Use the with statement, but with a nullcontext context manager if necessary.
from contextlib import nullcontext
with blah_blah() if condition else nullcontext():
my_code_block
nullcontext takes an optional argument that it will return if your with statement expects something to be bound with as. For example,
with nullcontext("hello") as f:
print(f) # outputs "hello"
I was wondering if it could be accomplished with:
def myrunner(myfunc,usecontext=True):
if usecontext:
with blahblah():
myfunc()
else:
myfunc()
def myfunc()...
myrunner(myfunc,usecontext=false)
But looking at it, I don't see how the context can effect myfunc.

GSheet wrap strategy in pygsheet

In the Pygsheet reference doc here it shows a wrap_strategy property.
wrap_strategy
How to wrap text in this cell. Possible wrap strategies: ‘OVERFLOW_CELL’, ‘LEGACY_WRAP’, ‘CLIP’, ‘WRAP’. Reference: api docs
But in actual code if I were to cell.wrap_strategy = 'WRAP' I get an error TypeError: 'str' object is not callable
Actual code snippet:
for cell in wsheet.range("L3:L20").pop():
cell.wrap_strategy('WRAP')
I believe your goal as follows.
You want to set the wrap strategy using pygsheets.
Modification points:
When I saw the script of wrap_strategy of pygsheets, it seems that this is the Class Cell and in this case, I think that in the case of for cell in wsheet.range("L3:L20").pop():, you can use cell.wrap_strategy = 'WRAP'. (In this case, it sets to "L20".)
From this, how about modifying your script as follows?
Modified script:
for cell in wsheet.range("L3:L20").pop():
cell.wrap_strategy = "WRAP"
or, as other direction, how about using get_values as follows?
for cell in wsheet.get_values("L3", "L20", returnas="range")._data.pop():
cell.wrap_strategy = "WRAP"
Note:
If above modification was not the direct solution of your issue, can you provide your whole script without your personal information? By this, I would like to confirm it.
Reference:
wrap_strategy
Added:
From your following replying,
I was expecting it to wrap L3 to L20. But it seems only L20 is being read in this for loop. Would you know how to make it so?
When I saw your script in your question, you wanted to use the last element of wsheet.range("L3:L20") because of pop(). So I followed to it. From your replying, when you want to set the wap strategy for "L3:L20" by modifying your script, how about the following sample script?
Sample 1:
for cell in wsheet.range("L3:L20"):
cell[0].wrap_strategy = "WRAP"
Sample 2:
for cell in wsheet.get_values("L3", "L20", returnas="range")._data:
cell[0].wrap_strategy = "WRAP"

Getting a selection in 3ds Max into a list in Python

I am writing in Python, sometimes calling certain aspects of maxscript and I have gotten most of the basics to work. However, I still don't understand FPValues. I don't even understand while looking through the examples and the max help site how to get anything meaningful out of them. For example:
import MaxPlus as MP
import pymxs
MPEval = MP.Core.EvalMAXScript
objectList = []
def addBtnCheck():
select = MPEval('''GetCurrentSelection()''')
objectList.append(select)
print(objectList)
MPEval('''
try (destroyDialog unnamedRollout) catch()
rollout unnamedRollout "Centered" width:262 height:350
(
button 'addBtn' "Add Selection to List" pos:[16,24] width:88 height:38
align:#left
on 'addBtn' pressed do
(
python.Execute "addBtnCheck()"
)
)
''')
MP.Core.EvalMAXScript('''createDialog unnamedRollout''')
(I hope I got the indentation right, pretty new at this)
In the above code I successfully spawned my rollout, and used a button press to call a python function and then I try to put the selection of a group of objects in a variable that I can control through python.
The objectList print gives me this:
[<MaxPlus.FPValue; proxy of <Swig Object of type 'Autodesk::Max::FPValue *' at 0x00000000846E5F00> >]
When used on a selection of two objects. While I would like the object names, their positions, etc!
If anybody can point me in the right direction, or explain FPValues and how to use them like I am an actual five year old, I would be eternally grateful!
Where to start, to me the main issue seems to be the way you're approaching it:
why use MaxPlus at all, that's an low-level SDK wrapper as unpythonic (and incomplete) as it gets
why call maxscript from python for things that can be done in python (getCurrentSelection)
why use maxscript to create UI, you're in python, use pySide
if you can do it in maxscript, why would you do it in python in the first place? Aside from faster math ops, most of the scene operations will be orders of magnitude slower in python. And if you want, you can import and use python modules in maxscript, too.
import MaxPlus as MP
import pymxs
mySel = mp.SelectionManager.Nodes
objectList = []
for each in mySel:
x = each.Name
objectList.append(x)
print objectList
The easiest way I know is with the
my_selection = rt.selection
command...
However, I've found it works a little better for me to throw it into a list() function as well so I can get it as a Python list instead of a MAXscript array. This isn't required but some things get weird when using the default return from rt.selection.
my_selection = list(rt.selection)
Once you have the objects in a list you can just access its attributes by looking up what its called for MAXscript.
for obj in my_selection:
print(obj.name)

Python GTK get selected value from the treeview

I am working on a mini GUI project , I am currently struggling to figure out how to get selected value from the list and then return that value to the main function so that I can use that value in somewhere else . Can someone help me please !!!!
####
self.device_list_store = gtk.ListStore(str,str,str,str,str)
for device in self.get_dev_list():
self.device_list_store.append(list(device))
device_list_treeview = gtk.TreeView(self.device_list_store)
selected_row = device_list_treeview.get_selection()
selected_row.connect("changed",self.item_selected)
####
def item_selected(self,selection):
model,row = selection.get_selected()
if row is not None:
selected_device = model[row][0]
at the moment ,the item_selected function is not returning anything , I want to return selected_device back to the main function so I can use it in other functions as well .
EDIT: I've edited code above to remove formatting errors #jcoppens
As you can see in the documentation, the item_selected function is called with one parameter, tree_selection. But if you define the function inside a class, it requires the self parameter too, which is normally added automatically. In your (confusing) example, there is no class defined, so I suspect the problem is your program which is incomplete.
Also, I suspect you don't want device_list_treeview = gtk.T... in the for loop:
for device in self.get_dev_list():
self.device_list_store.append(list(device))
device_list_treeview = gtk.TreeView(self.device_list_store)
And I suspect you want selected_device = mod... indented below the if:
if row is not None:
selected_device = model[row][0]
Please convert your example in a complete program, and formatted correctly.
BTW: item_selected is not a good name for the signal handler. It is also called if the item is unselected (which is why the signal is called 'changed')!
And important: Even though you should first read the basic Python tutorials and Gtk tutorials, you should then consider using lazka's excellent reference for all the Python APIs. There's a link on the page to download it completely and have it at hand in your computer.

Clicking a link based on partial text match

I'm using Selenium 2/Webdriver with python and I want to click on the first link that starts with a string. Here's the code I came up with:
def click_link_partial(div_id, partial):
linkdiv = driver.find_element_by_id(div_id)
z = (a.click() for a in linkdiv.find_elements_by_tag_name('a') if a.text.startswith(partial))
z.next()
I'm not very familiar with generators in Python. Why isn't a.click() called immediately, instead of when z.next() executes?
Are there any drawbacks to using this code?
First and foremost, please, familiarize yourself with Python's generators, they are a very powerful tool in your Python arsenal. A great explanation by Thomas Wouters can be found by reading another question: What can you use Python generator functions for?
Once you're finished reading, you'll realize that a generator just gives you the ability to evaluate expressions lazily.
Relating this piece of information to your code above, you will find that a.click() will not actually execute right away, because it is expected that you iterate over the generator expression, which is what you've created. This is why you must issue z.next() to actually invoke the click() method.
If you do not want to issue a z.next(), and assuming you just want to click the first partially matched link, you would re-write your code above as follows:
def click_link_partial(div_id, partial):
linkdiv = driver.find_element_by_id(div_id)
for a in linkdiv.find_elements_by_tag_name('a'):
if a.text.startswith(partial):
a.click()
break # stop iterating over the partially matched elements.
However, if you want to click on all the partially linked elements, then you should remove the z.next() from your code above and return the generator expression to be used in an outer function/method. Here's an example:
def click_link_partial(div_id, partial):
linkdiv = driver.find_element_by_id(div_id)
return (a for a in linkdiv.find_elements_by_tag_name('a')
if a.text.startswith(partial))
for matched_clickable_anchor in click_link_partial('#some-div-id', 'spam'):
matched_clickable_anchor.click() # do click
# do something else.
Hope this helps!

Categories

Resources