Maya Python:当对象是在另一个函数中创建时,如何在一个函数中调用和编辑该对象的属性?
Maya Python: How do i call on and edit attributes of an object in one function when that object was created in another function?
计划:
我一直在编写一个脚本,用于测量用户选择的 2 个顶点之间的距离,并根据这些顶点之间的所需长度放大或缩小对象。
问题:
错误指出它无法找到我在其中一个函数中创建的 textFieldButtonGrp 对象。
我基本上把我的 window 格式的东西放到一个函数中:
def window_presets():
'''
presets for UI window
'''
if mc.window("Distance Scale Tool", exists=True):
mc.deleteUI("Distance Scale Tool")
mc.window("Distance Scale Tool", t="Distance Based Scale Tool")
mc.rowColumnLayout(numberOfColumns=2,
columnAttach=(1, 'left', 0),
columnWidth=[(1,100), (2,300)])
mc.text(l="Current Length")
current_length = mc.textFieldButtonGrp("Current Length",
editable=False,
text="{0}".format(refresh_current_dist()),
buttonLabel="Refresh",
buttonCommand=refresh_current_dist)
mc.text(l="Desired Length")
desired_length = mc.textFieldButtonGrp("Desired Length",
buttonLabel="Scale",
buttonCommand=scale_dist,
tcc=refresh_scale_factor)
mc.showWindow()
我希望刷新按钮调用另一个函数来编辑我创建的 textFieldButtonGrp:
def refresh_textfield(distance):
if mc.textFieldButtonGrp("Current Length", exists=True):
mc.textFieldButtonGrp("Current Length",
edit=True,
text="{0}".format(distance))
else:
print "Current Length dont exist"
但是“当前长度”....它似乎不存在....
与“所需长度”相同......
这是完整的脚本:
## ((Ax - Bx)**2 + (Ay - By)**2 + (Az - Bz)**2)**0.5
import maya.cmds as mc
import math
def window_presets():
'''
presets for UI window
'''
if mc.window("Distance Scale Tool", exists=True):
mc.deleteUI("Distance Scale Tool")
mc.window("Distance Scale Tool", t="Distance Based Scale Tool")
mc.rowColumnLayout(numberOfColumns=2,
columnAttach=(1, 'left', 0),
columnWidth=[(1,100), (2,300)])
mc.text(l="Current Length")
current_length = mc.textFieldButtonGrp("Current Length",
editable=False,
text="{0}".format(refresh_current_dist()),
buttonLabel="Refresh", buttonCommand=refresh_current_dist)
mc.text(l="Desired Length")
desired_length = mc.textFieldButtonGrp("Desired Length",
buttonLabel="Scale",
buttonCommand=scale_dist,
tcc=refresh_scale_factor)
mc.showWindow()
def get_object_name():
selPoints = mc.ls(sl=True)
obj_name = selPoints[0].split('.')[0]
return obj_name
def get_coordinates():
'''
Gets coordinates of selected points and gets distance between them
'''
selPoints = mc.ls(sl=True)
obj_name = get_object_name()
print obj_name
vtxCoordList = mc.xform(selPoints,
query=True,
translation=True,
ws=True)
Ax, Ay, Az = vtxCoordList[:-3]
Bx, By, Bz = vtxCoordList[3:]
return (Ax, Bx, Ay, By, Az, Bz)
def calculate_distance(Ax, Bx, Ay, By, Az, Bz):
'''
Determines distance between 2 coordinates on single mesh.
Below are formulas for distance based on single axis:
dx = ((Ax - Bx)**2)**0.5
print "Distance on X axis is: {0}".format(dx) #distance on X axis
dy = ((Ay - By)**2)**0.5
print "Distance on Y axis is: {0}".format(dy) #distance on Y axis
dz = ((Az - Bz)**2)**0.5
print "Distance on Z axis is: {0}".format(dz) #distance on Z axis
'''
distance = math.sqrt((Ax - Bx)**2 + (Ay - By)**2 + (Az - Bz)**2)
print "the distance between points is {0}".format(distance)
return distance
def refresh_textfield(distance):
if mc.textFieldButtonGrp("Current Length", exists=True):
mc.textFieldButtonGrp("Current Length",
edit=True,
text="{0}".format(distance))
else:
print "Current Length dont exist"
def refresh_current_dist():
'''
returns current distance
'''
current_coordinates = get_coordinates()
current_distance = calculate_distance(*current_coordinates)
refresh_textfield(current_distance)
return current_distance
def refresh_scale_factor(sf):
'''
returns factor by which object will be scaled
'''
current_distance = refresh_current_dist()
scale_factor = (float(sf))/(float(current_distance))
print "dist btwn pnts is d: {0}".format(current_distance)
print "sf is {0}".format(sf)
print "user input is {0}".format(sf)
print "scale factor is {0}".format(scale_factor)
print "-"*10
return scale_factor
def scale_dist():
'''
scale object to match measurement
'''
user_input = float(mc.textFieldButtonGrp("Desired Length",
query=True,
text=True))
scale_factor = refreshScaleFactor(user_input)
mc.makeIdentity(get_object_name(),
apply=True,
translate=1,
rotate=1,
scale=1,
normal=0,
preserveNormals=1)#freeze transformations
mc.DeleteAllHistory()
mc.scale(scale_factor, scale_factor, scale_factor, get_object_name())
print "you scaled by {0}".format(scale_factor)
mc.makeIdentity(get_object_name(),
apply = True,
translate=1,
rotate=1,
scale=1,
normal=0,
preserveNormals=1)#freeze transformations
if __name__ == '__main__':
window_presets()
我想到的两种解决方法:
第一个 是创建一个CLASS 围绕所有函数并将textFieldButtonGrp 保存在class 变量self.textField = textFieldButtonGrp(...)
中。
这意味着创建一个 class 封装你所有的函数,添加一个 __init__(self,*args)
函数和其他函数,并且可能添加 self.到处都失败了(函数调用,调用变量......)。而且,作为一个加号,您将能够将 UI 中的每个项目保存在 class 变量中,并在使用 self.variableName
的任何函数中使用它
第二个方法是创建textField,将其保存在一个变量中,然后使用buttonCommand=partial(functionname,variable)
将其作为参数传递
部分来自哪里:
from functools import partial
但是这样做的方法是先创建不带 buttonCommand 的文本字段,然后使用编辑模式(而不是创建模式)执行文本字段的创建 Short explanation about execution modes
textFieldButtonGrp(variableName, edit=True, buttonCommand=partial(function,variableName)
)
因此您编辑文本字段以在之后添加此 buttonCommand。
我还没有测试过这个,但我相信它们中的任何一个都可以工作,特别是第一个。
希望这有帮助。
解法:
删除 "Current Length"
中的 space,这将修复您的错误。
命名注意事项:
考虑应用与您在函数上使用的名称相同的标签。我通常这样命名它们:
"<mine or company initials>_<ToolName>_<WidgetName>"
在你的情况下,这将类似于 "ak_VertexDistance_InputCurrentLength"
。
为什么这样命名?
几个月前,我正在编写一个脚本来将 Maya 场景保存在网络上的某个地方。我试图将一些项目添加到 optionMenu
到我的 window,但无论我如何尝试,optionMenu
仍然是空的。经过两个小时的不成功研究,我意识到该项目已添加到我的另一个工具中的另一个 optionMenu
。这些小部件具有相同的通用名称。
您的首字母是可选的,但如果您想区分不同工具的小部件,我认为添加 <ToolName>
是强制性的。
@DrHaze 是正确的,您的 UI 元素名称中不会有空格:当您创建
总的来说,。使用 class 是确保函数可以访问所需的 UI 元素的最简单方法:请参阅 or and extended discussion here
如果您不想使用 class,则需要确保函数获取 UI 元素的真实名称,而不是您期望的名称。
计划:
我一直在编写一个脚本,用于测量用户选择的 2 个顶点之间的距离,并根据这些顶点之间的所需长度放大或缩小对象。
问题:
错误指出它无法找到我在其中一个函数中创建的 textFieldButtonGrp 对象。
我基本上把我的 window 格式的东西放到一个函数中:
def window_presets():
'''
presets for UI window
'''
if mc.window("Distance Scale Tool", exists=True):
mc.deleteUI("Distance Scale Tool")
mc.window("Distance Scale Tool", t="Distance Based Scale Tool")
mc.rowColumnLayout(numberOfColumns=2,
columnAttach=(1, 'left', 0),
columnWidth=[(1,100), (2,300)])
mc.text(l="Current Length")
current_length = mc.textFieldButtonGrp("Current Length",
editable=False,
text="{0}".format(refresh_current_dist()),
buttonLabel="Refresh",
buttonCommand=refresh_current_dist)
mc.text(l="Desired Length")
desired_length = mc.textFieldButtonGrp("Desired Length",
buttonLabel="Scale",
buttonCommand=scale_dist,
tcc=refresh_scale_factor)
mc.showWindow()
我希望刷新按钮调用另一个函数来编辑我创建的 textFieldButtonGrp:
def refresh_textfield(distance):
if mc.textFieldButtonGrp("Current Length", exists=True):
mc.textFieldButtonGrp("Current Length",
edit=True,
text="{0}".format(distance))
else:
print "Current Length dont exist"
但是“当前长度”....它似乎不存在....
与“所需长度”相同......
这是完整的脚本:
## ((Ax - Bx)**2 + (Ay - By)**2 + (Az - Bz)**2)**0.5
import maya.cmds as mc
import math
def window_presets():
'''
presets for UI window
'''
if mc.window("Distance Scale Tool", exists=True):
mc.deleteUI("Distance Scale Tool")
mc.window("Distance Scale Tool", t="Distance Based Scale Tool")
mc.rowColumnLayout(numberOfColumns=2,
columnAttach=(1, 'left', 0),
columnWidth=[(1,100), (2,300)])
mc.text(l="Current Length")
current_length = mc.textFieldButtonGrp("Current Length",
editable=False,
text="{0}".format(refresh_current_dist()),
buttonLabel="Refresh", buttonCommand=refresh_current_dist)
mc.text(l="Desired Length")
desired_length = mc.textFieldButtonGrp("Desired Length",
buttonLabel="Scale",
buttonCommand=scale_dist,
tcc=refresh_scale_factor)
mc.showWindow()
def get_object_name():
selPoints = mc.ls(sl=True)
obj_name = selPoints[0].split('.')[0]
return obj_name
def get_coordinates():
'''
Gets coordinates of selected points and gets distance between them
'''
selPoints = mc.ls(sl=True)
obj_name = get_object_name()
print obj_name
vtxCoordList = mc.xform(selPoints,
query=True,
translation=True,
ws=True)
Ax, Ay, Az = vtxCoordList[:-3]
Bx, By, Bz = vtxCoordList[3:]
return (Ax, Bx, Ay, By, Az, Bz)
def calculate_distance(Ax, Bx, Ay, By, Az, Bz):
'''
Determines distance between 2 coordinates on single mesh.
Below are formulas for distance based on single axis:
dx = ((Ax - Bx)**2)**0.5
print "Distance on X axis is: {0}".format(dx) #distance on X axis
dy = ((Ay - By)**2)**0.5
print "Distance on Y axis is: {0}".format(dy) #distance on Y axis
dz = ((Az - Bz)**2)**0.5
print "Distance on Z axis is: {0}".format(dz) #distance on Z axis
'''
distance = math.sqrt((Ax - Bx)**2 + (Ay - By)**2 + (Az - Bz)**2)
print "the distance between points is {0}".format(distance)
return distance
def refresh_textfield(distance):
if mc.textFieldButtonGrp("Current Length", exists=True):
mc.textFieldButtonGrp("Current Length",
edit=True,
text="{0}".format(distance))
else:
print "Current Length dont exist"
def refresh_current_dist():
'''
returns current distance
'''
current_coordinates = get_coordinates()
current_distance = calculate_distance(*current_coordinates)
refresh_textfield(current_distance)
return current_distance
def refresh_scale_factor(sf):
'''
returns factor by which object will be scaled
'''
current_distance = refresh_current_dist()
scale_factor = (float(sf))/(float(current_distance))
print "dist btwn pnts is d: {0}".format(current_distance)
print "sf is {0}".format(sf)
print "user input is {0}".format(sf)
print "scale factor is {0}".format(scale_factor)
print "-"*10
return scale_factor
def scale_dist():
'''
scale object to match measurement
'''
user_input = float(mc.textFieldButtonGrp("Desired Length",
query=True,
text=True))
scale_factor = refreshScaleFactor(user_input)
mc.makeIdentity(get_object_name(),
apply=True,
translate=1,
rotate=1,
scale=1,
normal=0,
preserveNormals=1)#freeze transformations
mc.DeleteAllHistory()
mc.scale(scale_factor, scale_factor, scale_factor, get_object_name())
print "you scaled by {0}".format(scale_factor)
mc.makeIdentity(get_object_name(),
apply = True,
translate=1,
rotate=1,
scale=1,
normal=0,
preserveNormals=1)#freeze transformations
if __name__ == '__main__':
window_presets()
我想到的两种解决方法:
第一个 是创建一个CLASS 围绕所有函数并将textFieldButtonGrp 保存在class 变量self.textField = textFieldButtonGrp(...)
中。
这意味着创建一个 class 封装你所有的函数,添加一个 __init__(self,*args)
函数和其他函数,并且可能添加 self.到处都失败了(函数调用,调用变量......)。而且,作为一个加号,您将能够将 UI 中的每个项目保存在 class 变量中,并在使用 self.variableName
第二个方法是创建textField,将其保存在一个变量中,然后使用buttonCommand=partial(functionname,variable)
部分来自哪里:
from functools import partial
但是这样做的方法是先创建不带 buttonCommand 的文本字段,然后使用编辑模式(而不是创建模式)执行文本字段的创建 Short explanation about execution modes
textFieldButtonGrp(variableName, edit=True, buttonCommand=partial(function,variableName)
)
因此您编辑文本字段以在之后添加此 buttonCommand。
我还没有测试过这个,但我相信它们中的任何一个都可以工作,特别是第一个。 希望这有帮助。
解法:
删除 "Current Length"
中的 space,这将修复您的错误。
命名注意事项:
考虑应用与您在函数上使用的名称相同的标签。我通常这样命名它们:
"<mine or company initials>_<ToolName>_<WidgetName>"
在你的情况下,这将类似于 "ak_VertexDistance_InputCurrentLength"
。
为什么这样命名?
几个月前,我正在编写一个脚本来将 Maya 场景保存在网络上的某个地方。我试图将一些项目添加到 optionMenu
到我的 window,但无论我如何尝试,optionMenu
仍然是空的。经过两个小时的不成功研究,我意识到该项目已添加到我的另一个工具中的另一个 optionMenu
。这些小部件具有相同的通用名称。
您的首字母是可选的,但如果您想区分不同工具的小部件,我认为添加 <ToolName>
是强制性的。
@DrHaze 是正确的,您的 UI 元素名称中不会有空格:当您创建
总的来说,。使用 class 是确保函数可以访问所需的 UI 元素的最简单方法:请参阅
如果您不想使用 class,则需要确保函数获取 UI 元素的真实名称,而不是您期望的名称。