I used the following code based on the information given in help.autodesk.com for executing maxscript in Python:
import MaxPlus
test = MaxPlus.FPValue()
#The target node has only one morpher and I want to retrieve it using
# .morpher[1]
bool = MaxPlus.Core.EvalMAXScript("WM3_MC_BuildFromNode $node.morpher[1] 1 $target", test)
print bool
If I print the boolean, this always print: "false". However the following code works (aka the print statement returns true):
import MaxPlus
test = MaxPlus.FPValue()
#The target node has only one morpher
bool = MaxPlus.Core.EvalMAXScript("WM3_MC_BuildFromNode $node.morpher 1 $target", test)
print bool
However I cannot use the latter code since it must be possible in my code that a node has multiple morphers.
Is there a better way using the Python api for maxscript (I didn't find a method) or can anyone give suggestions how the first code can be improved.
Thank you
The solution to my problem is:
MaxPlus.Core.EvalMAXScript(WM3_MC_BuildFromNode(for mod in $node.modifiers where isKindOf mod Morpher collect mod)[1] 3 $target)
This solution is found by Swordslayer on the autodesk forum for 3ds Max
Related
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"
I am facing challenges implementing OOP in python to enable me to call the functions whenever i want , so far i have no syntax errors which makes quite challenging for me . The first part of the code runs ehich is to accept data but the function part does not run.
I have tried different ways of calling the function by creating an instance of it.
print (list)
def tempcheck(self,newList):
temp=newList[0]
if temp==27:
print ("Bedroom has ideal temperature ")
elif temp>=28 or temp<=26:
print ("Bedroom Temperature is not ideal ,either too low or too cold. ")
print ("Please to adjust the temperature to the optimum temperature which is 27 degree Celsuis")
# now to initialize args
def __init__(self,temp,puri1,bedwashroom,newList):
self.temp=temp
self.puri1=puri1
self.bedwashroom=bedwashroom
tempcheck(newList)
# now calling the functions
newvalue=tempcheck(list)
# where list contains the values from the input function.
I expected the function to to check the specific value at the location in the list provided which is called list and also for the function to return a string based on the if statements.
i got it right ,i figured out an alternative to my bug thanks for the critique however any further addition is welcome,
the main goal was to create a function that takes input and passes it to list to be used later i guess this code is less cumbersome
the link to the full code is pasted below
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)
I have a lldb python module with a simple setup:
def __lldb_init_module (debugger, dict):
target = debugger.GetSelectedTarget()
target.DeleteAllBreakpoints()
process = target.GetProcess()
I can easily set a breakpoint at the start of a function using:
breakpoint = target.BreakpointCreateByName("functionName", "moduleName")
breakpoint.SetScriptCallbackFunction( "python_module.bp_hit" )
and I know this works because my bp_hit function is called correctly.
However, I really need the breakpoint set at X number of bytes from the start of the address of functionName. If I knew the address of the functionName, I could simply add X to the address and use BreakpointCreateByAddress.
What is the python code that will provide me the address of the functionName?
Use SBTarget::FindFunctions to find the SBSymbolContext(s) that match a your function name. That returns a list of SBSymbolContext matches (since there may be more than one.) SBSymbolContext::GetStartAddress will give you an SBAddress for the start of that symbol. Then use SBAddress::OffsetAddress to add your offset. There is a SBTarget::CreateBreakpointByAddress but annoyingly enough it only takes an lldb::addr_t not an SBAddress. You can get an lldb::addr_t from an SBAddress with SBAddress::GetLoadAddress() passing in your target.
An alternative to Jim's answer is to use the FindSymbols function of SBTarget.
I am writing some Python unit tests using the "unittest" framework and run them in PyCharm. Some of the tests compare a long generated string to a reference value read from a file. If this comparison fails, I would like to see the diff of the two compared strings using PyCharms diff viewer.
So the the code is like this:
actual = open("actual.csv").read()
expected = pkg_resources.resource_string('my_package', 'expected.csv').decode('utf8')
self.assertMultiLineEqual(actual, expected)
And PyCharm nicely identifies the test as a failure and provides a link in the results window to click which opens the diff viewer. However, due to how unittest shortens the results, I get results such as this in the diff viewer:
Left side:
'time[57 chars]ercent
0;1;1;1;1;1;1;1
0;2;1;3;4;2;3;1
0;3;[110 chars]32
'
Right side:
'time[57 chars]ercen
0;1;1;1;1;1;1;1
0;2;1;3;4;2;3;1
0;3;2[109 chars]32
'
Now, I would like to get rid of all the [X chars] parts and just see the whole file(s) and the actual diff fully visualized by PyCharm.
I tried to look into unittest code but could not find a configuration option to print full results. There are some variables such as maxDiff and _diffThreshold but they have no impact on this print.
Also, I tried to run this in py.test but there the support in PyCharm was even less (no links even to failed test).
Is there some trick using the difflib with unittest or maybe some other tricks with another Python test framework to do this?
The TestCase.maxDiff=None answers given in many places only make sure that the diff shown in the unittest output is of full length. In order to also get the full diff in the <Click to see difference> link you have to set MAX_LENGTH.
import unittest
# Show full diff in unittest
unittest.util._MAX_LENGTH=2000
Source: https://stackoverflow.com/a/23617918/1878199
Well, I managed to hack myself around this for my test purposes. Instead of using the assertEqual method from unittest, I wrote my own and use that inside the unittest test cases. On failure, it gives me the full texts and the PyCharm diff viewer also shows the full diff correctly.
My assert statement is in a module of its own (t_assert.py), and looks like this
def equal(expected, actual):
msg = "'"+actual+"' != '"+expected+"'"
assert expected == actual, msg
In my test I then call it like this
def test_example(self):
actual = open("actual.csv").read()
expected = pkg_resources.resource_string('my_package', 'expected.csv').decode('utf8')
t_assert.equal(expected, actual)
#self.assertEqual(expected, actual)
Seems to work so far..
A related problem here is that unittest.TestCase.assertMultiLineEqual is implemented with difflib.ndiff(). This generates really big diffs that contain all shared content along with the differences. If you monkey patch to use difflib.unified_diff() instead, you get much smaller diffs that are less often truncated. This often avoids the need to set maxDiff.
import unittest
from unittest.case import _common_shorten_repr
import difflib
def assertMultiLineEqual(self, first, second, msg=None):
"""Assert that two multi-line strings are equal."""
self.assertIsInstance(first, str, 'First argument is not a string')
self.assertIsInstance(second, str, 'Second argument is not a string')
if first != second:
firstlines = first.splitlines(keepends=True)
secondlines = second.splitlines(keepends=True)
if len(firstlines) == 1 and first.strip('\r\n') == first:
firstlines = [first + '\n']
secondlines = [second + '\n']
standardMsg = '%s != %s' % _common_shorten_repr(first, second)
diff = '\n' + ''.join(difflib.unified_diff(firstlines, secondlines))
standardMsg = self._truncateMessage(standardMsg, diff)
self.fail(self._formatMessage(msg, standardMsg))
unittest.TestCase.assertMultiLineEqual = assertMultiLineEqual