1#!/usr/bin/env python 2 3# A game with VTK and tkinter. :) 4 5import sys 6if sys.hexversion < 0x03000000: 7 # for Python2 8 import Tkinter as tkinter 9else: 10 # for Python3 11 import tkinter 12import vtk 13from vtk.tk.vtkTkRenderWindowInteractor import vtkTkRenderWindowInteractor 14 15# Create the pipeline 16puzzle = vtk.vtkSpherePuzzle() 17mapper = vtk.vtkPolyDataMapper() 18mapper.SetInputConnection(puzzle.GetOutputPort()) 19actor = vtk.vtkActor() 20actor.SetMapper(mapper) 21 22arrows = vtk.vtkSpherePuzzleArrows() 23mapper2 = vtk.vtkPolyDataMapper() 24mapper2.SetInputConnection(arrows.GetOutputPort()) 25actor2 = vtk.vtkActor() 26actor2.SetMapper(mapper2) 27 28renWin = vtk.vtkRenderWindow() 29ren = vtk.vtkRenderer() 30renWin.AddRenderer(ren) 31 32# Add the actors to the renderer, set the background and size 33ren.AddActor(actor) 34ren.AddActor(actor2) 35ren.SetBackground(0.1, 0.2, 0.4) 36 37ren.ResetCamera() 38cam = ren.GetActiveCamera() 39cam.Elevation(-40) 40 41 42## Generate the GUI 43root = tkinter.Tk() 44root.withdraw() 45 46# Define a quit method that exits cleanly. 47def quit(obj=root): 48 obj.quit() 49 50# Create the toplevel window 51top = tkinter.Toplevel(root) 52top.title("Sphere Puzzle") 53top.protocol("WM_DELETE_WINDOW", quit) 54 55# Create some frames 56f1 = tkinter.Frame(top) 57f2 = tkinter.Frame(top) 58 59f1.pack(side="top", anchor="n", expand=1, fill="both") 60f2.pack(side="bottom", anchor="s", expand="t", fill="x") 61 62# Create the Tk render widget, and bind the events 63rw = vtkTkRenderWindowInteractor(f1, width=400, height=400, rw=renWin) 64rw.pack(expand="t", fill="both") 65 66def reset(evt=None): 67 puzzle.Reset() 68 renWin.Render() 69 70# Display some information 71l1 = tkinter.Label(f2, text="Position cursor over the rotation plane.") 72l2 = tkinter.Label(f2, text="Moving pieces will be highlighted.") 73l3 = tkinter.Label(f2, text="Press 'm' to make a move.") 74reset = tkinter.Button(f2, text="Reset", command=reset) 75 76b1 = tkinter.Button(f2, text="Quit", command=quit) 77 78for i in (l1, l2, l3, reset, b1): 79 i.pack(side="top", expand="t", fill="x") 80 81# Done with the GUI. Create callback functions. 82 83in_piece_rotation = 0 84LastVal = None 85 86# Highlight pieces 87def MotionCallback(obj, event): 88 global in_piece_rotation 89 global LastVal 90 if in_piece_rotation: 91 return 92 93 iren = renWin.GetInteractor() 94 istyle = iren.GetInteractorStyle().GetCurrentStyle() 95 96 # Return if the user is performing interaction 97 if istyle.GetState(): 98 return 99 100 # Get mouse position 101 pos = iren.GetEventPosition() 102 x, y = pos 103 104 # Get world point 105 ren.SetDisplayPoint(x, y, ren.GetZ(x, y)) 106 ren.DisplayToWorld() 107 pt = ren.GetWorldPoint() 108 val = puzzle.SetPoint(pt[0], pt[1], pt[2]) 109 110 if (not LastVal) or val != LastVal: 111 renWin.Render() 112 LastVal = val 113 114# Rotate the puzzle 115def CharCallback(obj, event): 116 iren = renWin.GetInteractor() 117 118 keycode = iren.GetKeyCode() 119 if keycode != "m" and keycode != "M": 120 return 121 122 pos = iren.GetEventPosition() 123 ButtonCallback(pos[0], pos[1]) 124 125 126def ButtonCallback(x, y): 127 global in_piece_rotation 128 if in_piece_rotation: 129 return 130 in_piece_rotation = 1 131 132 # Get world point 133 ren.SetDisplayPoint(x, y, ren.GetZ(x,y)) 134 ren.DisplayToWorld() 135 pt = ren.GetWorldPoint() 136 x, y, z = pt[:3] 137 138 for i in range(0, 101, 10): 139 puzzle.SetPoint(x, y, z) 140 puzzle.MovePoint(i) 141 renWin.Render() 142 root.update() 143 144 in_piece_rotation = 0 145 146root.update() 147 148# Modify some bindings, use the interactor style 'switch' 149iren = renWin.GetInteractor() 150istyle = vtk.vtkInteractorStyleSwitch() 151 152iren.SetInteractorStyle(istyle) 153istyle.SetCurrentStyleToTrackballCamera() 154 155iren.AddObserver("MouseMoveEvent", MotionCallback) 156iren.AddObserver("CharEvent", CharCallback) 157 158# Shuffle the puzzle 159ButtonCallback(218, 195) 160ButtonCallback(261, 128) 161ButtonCallback(213, 107) 162ButtonCallback(203, 162) 163ButtonCallback(134, 186) 164 165iren.Initialize() 166renWin.Render() 167iren.Start() 168 169root.mainloop() 170