(New Coder) I'm trying it create a basic GUI which allows the user to create a sphere and choose the radius and rotation. I managed to do the radius however i am a bit stuck with the rotation; the xform command. Like i said the radius is working but not the rotation.
Heres the GUI at the moment: https://gyazo.com/5f3626443334da1abdecaea434fe4e03
Any help appreciated:)
Heres my code:
import maya.cmds as cmds
def shapeTool ():
ram = 'RenamerWin'
if cmds.window(ram, q = True, exists =True):
cmds.deleteUI(ram)
ram = cmds.window("RenamerWin",t = "Shape Tool", w=300, h=300)
cmds.columnLayout(adj = True)
cmds.separator(h=20)
cmds.text("Welcome to the Shape Creator")
cmds.separator(h=20)
sphR = cmds.intSliderGrp(l = "Radius", min =0, max = 10, field = True)
sphA = cmds.intSliderGrp(l = "Rotate", field = True)
def mySphere(_):
mySphereRadius = cmds.intSliderGrp(sphR , q= True,value =True)
mySphereRotate = cmds.intSliderGrp(sphA , q= True,value =True)
finalSphere = cmds.polySphere(r=mySphereRadius, n = "mySphere")
finalSphere = cmds.xform( r=True, ro=(0, 90, 0) )
cmds.button(l = "Create a Sphere",c=mySphere)
cmds.showWindow(ram)
shapeTool()
Your rotate function will always rotate the new sphere 90 degrees in Y. Is that the intent? it ignores the rotate slider.
As written, it will rotate the sphere you create -- but for clarity and to understand what's really going on you might want to do this:
finalSphere, finalShape = cmds.polySphere(r=mySphereRadius, n = "mySphere")
cmds.xform(finalSphere, r=True, ro=(0, mySphereRotate, 0))
Related
I'm trying to straiting out a ring using Manim Community. I want to acheive an animation exactly like this straiting a ring. I followed the code source of this video but the out put is not exactly the same (I used Manim Community and manimgl). Here is the code
class CircleScene(Scene):
def get_ring(self, radius=1, dR=0.1, color = GREEN):
ring = Circle(radius = radius + dR)
inner_ring = Circle(radius = radius)
inner_ring.rotate(np.pi,RIGHT)
ring.append_vectorized_mobject(inner_ring)
ring.set_stroke(width = 0)
ring.set_fill(color,1)
ring.R = radius
ring.dR = dR
return ring
def get_unwrapped(self, ring, to_edge = LEFT, **kwargs):
R = ring.R
R_plus_dr = ring.R + ring.dR
n_anchors = ring.get_num_curves()
result = VMobject()
points=[
interpolate(np.pi*R_plus_dr*LEFT, np.pi*R_plus_dr*RIGHT, a)
for a in np.linspace(0, 1, n_anchors // 2)
]+[
interpolate(np.pi*R*RIGHT+ring.dR*UP, np.pi*R*LEFT+ring.dR*UP, a)
for a in np.linspace(0, 1, n_anchors//2)
]
result.set_points_as_corners(points)
result.set_stroke(color=ring.get_fill_color(), width= ring.get_stroke_width()),
result.set_fill( color=ring.get_fill_color() , opacity=ring.get_fill_opacity()),
return result
class Example(CircleScene):
def construct(self,**kwargs):
circle=self.get_ring(1.5,0.1).rotate(PI/2);
line=self.get_unwrapped(circle).to_edge(DOWN)
self.play(Transform(circle,line))
I know that we can strait a circle to a line using the following code
circle=Circle(1).rotate(PI/2);
line=Line((-PI,-2,0),(PI,-2,0))
self.play(Transform(circle,line))
I have a fonction that create a rugby field :
from matplotlib.patches import Rectangle
from matplotlib.patches import Arc
from matplotlib.patches import ConnectionPatch
def draw_pitch_horizontal():
# focus on only half of the pitch
#Pitch Outline & Centre Line
fig=plt.figure() #set up the figures
fig.set_size_inches(10, 7)
ax=fig.add_subplot(1,1,1)
Pitch = Rectangle([0,0], width = 120, height = 70, fill = False)
essai1 = Rectangle([0,0], width = 10, height = 70, fill = False, color='gray',hatch='/')
essai2 = Rectangle([110,0], width = 1070, height = 70, fill = False, color='gray',hatch='/')
en_but1 = ConnectionPatch([10,0], [10,80], "data", "data")
en_but2 = ConnectionPatch([110,0], [110,70], "data", "data")
cinq_metres1 = ConnectionPatch([15,0], [15,70], "data", "data",ls='--',color='gray')
cinq_metres2 = ConnectionPatch([105,0], [105,70], "data", "data",ls='--',color='gray')
midline = ConnectionPatch([60,0], [60,70], "data", "data")
vingtdeux_metres1 = ConnectionPatch([32,0], [32,70], "data", "data")
vingtdeux_metres2 = ConnectionPatch([88,0], [88,70], "data", "data")
dix_metres1 = ConnectionPatch([50,0], [50,70], "data", "data",ls='--',color='gray')
dix_metres2 = ConnectionPatch([70,0], [70,70], "data", "data",ls='--',color='gray')
centreCircle = plt.Circle((60,35),0.5,color="black", fill = True)
poteau1a = plt.Circle((10,32.2),0.5,color="black", fill = True)
poteau1b = plt.Circle((10,37.8),0.5,color="black", fill = True)
poteau2a = plt.Circle((110,32.2),0.5,color="black", fill = True)
poteau2b = plt.Circle((110,37.8),0.5,color="black", fill = True)
element = [essai1, essai2, Pitch, en_but1, en_but2, cinq_metres1, cinq_metres2, midline, vingtdeux_metres1,
vingtdeux_metres2,centreCircle,poteau1a,poteau1b,poteau2a,poteau2b,dix_metres1,dix_metres2]
for i in element:
ax.add_patch(i)
return fig,ax
I created a function with a team in argument and the function plots the average start and end of a sequence on a pitch thanks to the previous function.
def plot_sequence_moyenne(TEAM):
df_team = df_summary[((df_summary.hometeam == TEAM)|(df_summary.awayteam == TEAM))].reset_index(drop=True)
df_timeline = pd.concat([prg.Match(df_team['url'][i]).timeline for i in range(len(df_team))],axis=0)
df_timeline_team = df_timeline[df_timeline.team_name == TEAM].reset_index(drop=True)
print(df_timeline_team.x_coord.mean())
print(df_timeline_team.x_coord_end.mean())
(fig,ax) = draw_pitch_horizontal() #overlay our different objects on the pitch
plt.ylim(-2, 72)
plt.xlim(-0.2, 120.4)
ax = plt.gca()
ax.set_facecolor('#c2dff4')
plt.axis('off')
zone_sequence = Rectangle([df_timeline_team.x_coord.mean(),0], width = (df_timeline_team.x_coord_end.mean()-df_timeline_team.x_coord.mean()), height = 70, fill = True, color='darkseagreen',alpha=0.7,edgecolor='black')
ax.add_patch(zone_sequence)
plt.title("TEAM 1" + " - Séquences moyennes")
plt.show()
This is what I obtain with this :
However, I would like to know how to create a huge subplot in order to have a graph with 10 subplots of pitch if I have ten teams for exemple.
Thanks in advance for your help and your time
I generate the 4x4 transformation matrices over time for each object in a scene and use the VectorKeyframeTrack to set the transform matrix on a Mesh object. I am able to animate the objects individually with an AnimateAction for each object but cannot figure out how to have all objects animate simultaneously with a single .play() call and keep them in sync. This is as far as I've gotten, hoping that starting with the second loop the objects would be time synchronized, but they aren't:
import pythreejs as pjs
rod_mesh = pjs.Mesh(
pjs.CylinderBufferGeometry(0.005, 0.005, sys.constants[lB] - sys.constants[h] / 2,),
pjs.MeshStandardMaterial(color='red')
)
plate_mesh = pjs.Mesh(pjs.PlaneBufferGeometry(sys.constants[h], sys.constants[w]),
pjs.MeshStandardMaterial(color='blue', side='DoubleSide'))
# Animation will not update without this set.
rod_mesh.matrixAutoUpdate = False
plate_mesh.matrixAutoUpdate = False
# Set initial position/orientation
rod_mesh.matrix = rod_matrices[0]
plate_mesh.matrix = plate_matrices[0]
# Setup scene
view_width = 600
view_height = 400
camera = pjs.PerspectiveCamera(position=[0.25, 0.25, 0.25], aspect=view_width/view_height)
key_light = pjs.DirectionalLight(position=[0, 10, 10])
ambient_light = pjs.AmbientLight()
scene_pjs = pjs.Scene(children=[rod_mesh, plate_mesh, camera, key_light, ambient_light])
controller = pjs.OrbitControls(controlling=camera)
renderer = pjs.Renderer(camera=camera, scene=scene_pjs, controls=[controller], width=view_width, height=view_height)
# Specify KeyframeTracks
rod_track = pjs.VectorKeyframeTrack(name='.matrix', times=list(sys.times), values=rod_matrices)
plate_track = pjs.VectorKeyframeTrack(name='.matrix', times=list(sys.times), values=plate_matrices)
rod_clip = pjs.AnimationClip(tracks=[rod_track])
plate_clip = pjs.AnimationClip(tracks=[plate_track])
rod_mixer = pjs.AnimationMixer(rod_mesh)
plate_mixer = pjs.AnimationMixer(plate_mesh)
rod_action = pjs.AnimationAction(rod_mixer, rod_clip, rod_mesh)
plate_action = pjs.AnimationAction(plate_mixer, plate_clip, plate_mesh)
# Try to enforce syncronization among actions at each loop start
plate_action.exec_three_obj_method('syncWith', 'IPY_MODEL_' + rod_action.get_view_spec()['model_id'])
rod_action.exec_three_obj_method('syncWith', 'IPY_MODEL_' + plate_action.get_view_spec()['model_id'])
listener_func = '() => {{ {}.syncWith({}); }}'.format('IPY_MODEL_' + plate_action.get_view_spec()['model_id'], 'IPY_MODEL_' + rod_action.get_view_spec()['model_id'])
rod_mixer.exec_three_obj_method('addEventListener', 'loop', listener_func)
syncWith() must need to be called at every frame transition but I'm not sure how to affect the animation frame loop from pythreejs.
A solution was given here:
https://github.com/jupyter-widgets/pythreejs/issues/262
The key is to animate the scene instead of the individual meshes and the trick to do so is to name the meshes and then use scene/<mesh name>.<attribute to change> when setting up the KeyFrameTracks. Here is my example that was reworked:
rod_mesh = pjs.Mesh(pjs.CylinderBufferGeometry(0.005, 0.005, sys.constants[lB] - sys.constants[h] / 2),
pjs.MeshStandardMaterial(color='red'),
name='rod' # name each mesh!
)
plate_mesh = pjs.Mesh(pjs.PlaneBufferGeometry(sys.constants[h], sys.constants[w]),
pjs.MeshStandardMaterial(color='blue', side='DoubleSide'),
name="plate" # name each mesh!
)
# For updating the transform matrices directly set:
rod_mesh.matrixAutoUpdate = False
plate_mesh.matrixAutoUpdate = False
# Scene setup
view_width = 600
view_height = 400
camera = pjs.PerspectiveCamera(position=[0.25, 0.25, 0.25], aspect=view_width/view_height)
key_light = pjs.DirectionalLight(position=[0, 10, 10])
ambient_light = pjs.AmbientLight()
scene_pjs = pjs.Scene(children=[rod_mesh, plate_mesh, camera, key_light, ambient_light])
controller = pjs.OrbitControls(controlling=camera)
renderer = pjs.Renderer(camera=camera, scene=scene_pjs, controls=[controller], width=view_width, height=view_height)
# Key thing here is to set the attribute you want to change as a sub-item of the scene. Use the names of the meshes above.
rod_track = pjs.VectorKeyframeTrack(name='scene/rod.matrix',
times=list(sys.times),
values=rod_matrices)
plate_track = pjs.VectorKeyframeTrack(name='scene/plate.matrix',
times=list(sys.times),
values=plate_matrices)
# Now create a single clip with both tracks and animate the scene:
clip = pjs.AnimationClip(tracks=[rod_track, plate_track], duration=sys.times[-1])
action = pjs.AnimationAction(pjs.AnimationMixer(scene_pjs), clip, scene_pjs)
Here is my fully working example:
https://gist.github.com/moorepants/c5ebb846499c4002744b8c101705015f
I have this code
joint_name = cmds.ls(sl=1)[0]
circle_name = cmds.circle(name = joint_name + "_CTL", nr=(1, 0, 0) )
group_name = cmds.group(name = joint_name + "_OFFSET")
cmds.select(joint_name, group_name)temp_constraint = cmds.parentConstraint()
cmds.delete(temp_constraint)
cmds.select(circle_name, joint_name)
cmds.pointConstraint()
cmds.orientConstraint()
When you select a joint and run this code you will get a circle that will control that joint. While going down the hierarchy you have to select that joint and then run the code.
How would I be able to have all the joints to have circles controlling them without having to go through the outliner selection a joint?
run this on your chain of joint :
for x, joint_name in enumerate(cmds.ls(sl=1, dag=True, type='joint')):
circle_name = cmds.circle(name = '{}_CTL{:02d}'.format(joint_name,x), nr=(1, 0, 0) )
group_name = cmds.group(name = '{}_OFFSET{:02d}'.format(joint_name,x))
cmds.select(joint_name, group_name)
temp_constraint = cmds.parentConstraint()
cmds.delete(temp_constraint)
cmds.select(circle_name, joint_name)
cmds.pointConstraint()
cmds.orientConstraint()
Note that instead of use select, you could feed pointConstraint :
cmds.pointConstraint(circle_name, joint_name, n='something')
I'm trying to make a custom script that replicates/imitates the Maya Sculpt Geometry Tool. Basically I have 2 radio buttons, Push and Relax[which imitates the push and relax from the sculpt parameters obviously], a value slider[replicates the max displacement slider]. The radio and reset button works perfectly however I'm having problems with coding the slider. Any help for this one? Thanks in advance.
Please see images for further clarification.
Click here for image
Here is my code:
import maya.cmds as cmds
import maya.mel as mel
if cmds.window("cusWin", exists = True):
cmds.deleteUI("cusWin")
customwindow = cmds.window("cusWin",t= "Push/Relax", wh = (200, 117), s= False, mnb= False, mxb= False)
cmds.frameLayout( label='Push/Relax Modifier', borderStyle='in', cll= False)
cmds.columnLayout(adj = True, columnOffset= ("both", 3))
cmds.radioCollection()
cmds.radioButton(l = "Push", onc= "mel.eval('artUpdatePuttyOperation artPuttyCtx push ;')")
cmds.radioButton(l = "Relax", onc= "mel.eval('artUpdatePuttyOperation artPuttyCtx relax ;')")
cmds.separator(style= "none", h= 3)
DynFsgCol1 = 30
DynFsgCol2 = 50
DynFsgCol3 = 100
valSlider = cmds.floatSliderGrp(l = "Value", field = True, min = 0, max= 5, precision = 4, cw3= (DynFsgCol1, DynFsgCol2, DynFsgCol3 ))
cmds.separator(style= "none", h= 3)
cmds.rowColumnLayout(numberOfColumns=2, columnWidth=[(1,98),(2,100)], columnOffset=[(1,'left',1),(2,'right',95)])
cmds.button(l = "Apply", w= 92, c= 'slider()')
cmds.button(l = "Reset", w= 91, c= 'resetButton()')
cmds.showWindow( customwindow )
def slider():
valueSlider = cmds.floatSliderGrp(valSlider, q= True, value= True)
mel.eval('artPuttyCtx -e -maxdisp valueSlider `currentCtx`;')
def resetButton():
mel.eval('resetTool artPuttyContext;')
There's two different things going on here.
First, by using the string form of the callbacks you lose control over the scope of your functions. It's better to pass the python objects directly. This version does what it looks like your's is intended to do using the callbacks:
import maya.cmds as cmds
import maya.mel as mel
if cmds.window("cusWin", exists = True):
cmds.deleteUI("cusWin")
customwindow = cmds.window("cusWin",t= "Push/Relax", wh = (200, 117), s= False, mnb= False, mxb= False)
cmds.frameLayout( label='Push/Relax Modifier', cll= False)
cmds.columnLayout(adj = True, columnOffset= ("both", 3))
cmds.radioCollection()
push = lambda _: cmds.artPuttyCtx(cmds.currentCtx(), e = True, mtm='push')
relax = lambda _: cmds.artPuttyCtx(cmds.currentCtx(), e = True, mtm='relax')
cmds.radioButton(l = "Push", onc= push)
cmds.radioButton(l = "Relax", onc=relax)
cmds.separator(style= "none", h= 3)
DynFsgCol1 = 30
DynFsgCol2 = 50
DynFsgCol3 = 100
valSlider = cmds.floatSliderGrp(l = "Value", field = True, min = 0, max= 5, precision = 4, cw3= (DynFsgCol1, DynFsgCol2, DynFsgCol3 ))
cmds.separator(style= "none", h= 3)
cmds.rowColumnLayout(numberOfColumns=2, columnWidth=[(1,98),(2,100)], columnOffset=[(1,'left',1),(2,'right',95)])
# put the defs here, where the names of the slider are known
def slider(*_):
valueSlider = cmds.floatSliderGrp(valSlider, q = True, value = True)
cmds.artPuttyCtx(cmds.currentCtx(), e = True, maxdisp = valueSlider)
def resetButton(*_):
cmds.resetTool(cmds.currentCtx())
cmds.button(l = "Apply", w= 92, c= slider)
cmds.button(l = "Reset", w= 91, c= resetButton)
cmds.showWindow( customwindow )
The thing to note is that order in which things are defined allows you to reference the names of controls you've made. (As an aside, you need to handle the nonsense arguments Maya passes on the button and slider callbacks). It's also a good idea to clean up dangling Mel scripts where you can, if you want to make this tool more complex in future it's much harder if you have to work in two languages at once. In this case artUpdatePuttyOperation looks like it's defined when the sculpt tool UI opens, so if you ran this script without the UI I don't think it would work correctly.
The second issue is that you're not explicitly setting an artPuttyCtx with setTool, so this won't work unless the user has already created the right context and activated it.