def test_001(self): print("test_001:") sg = Singulersum(1.0) test = """ yaml: application: Singulersum url: https://github.com/frazy81/Singulersum min-version: 2021-04-02 min-yaml-version: 2021-04-02 sg: scale: 5.0 animator: type: animation stop: 1.0 start: 0.0 camera: cam begin: [1.2, 2.0, 1.0] end: [1.6, 0.1, 0.5] x: begin[0] + (time*(end[0] - begin[0])) y: begin[1] + (time*(end[1] - begin[1])) z: begin[2] + (time*(end[2] - begin[2])) """ sg.yaml(data=test) self.assertEqual(sg.scale, 5.0) print("test_001 end.") print() pass
def test_001(self): sg = Singulersum() cam = sg.camera(1, 0, 0, 0, 0, 0, name="cam1") P = (1, 0, 0) print("P:", cam.vec_show(P)) P_prime = cam.rotate(P, 90, 0) print("P_prime:", cam.vec_show(P_prime)) self.assertTrue(P_prime[0]-0.0<1e-6) # x=0, y=1, z=0 self.assertTrue(P_prime[1]-1.0<1e-6) self.assertTrue(P_prime[2]-0.0<1e-6) P_prime = cam.rotate(P, 90, 90) print("P_prime:", cam.vec_show(P_prime)) # what here? (0,1,0) 90° on Y-axis??? #self.assertTrue(P_prime[0]-0.0<1e-6) # x=0, y=1, z=1 #self.assertTrue(P_prime[1]-1.0<1e-6) #self.assertTrue(P_prime[2]-0.0<1e-6) P_prime = cam.rotate(P, 10, 0) print("P_prime 10° rotated: ", cam.vec_show(P_prime)) P_prime = cam.rotate(P_prime, -10, 0) print("P_prime 10° rotated back again: ", cam.vec_show(P_prime)) self.assertTrue(abs(P_prime[0]-P[0])<1e-6) self.assertTrue(abs(P_prime[1]-P[1])<1e-6) self.assertTrue(abs(P_prime[2]-P[2])<1e-6) pass
def test_006(self): print("test_006:") sg = Singulersum(1.0, callback=self.callback) file = "../yaml/singulersum.yaml" data = sg.yaml(file=file) print("test_006 end.") print()
def test_003(self): print("test_003:") sg = Singulersum(1.0, callback=self.callback) file = "../yaml/sine_waves.yaml" self.animated = False data = sg.yaml(file=file) self.assertEqual(self.animated, True) print("test_003 end.") print()
def __init__(self, verbose=True, exitImmediate=False, quitAfterAnimation=False, quitAfter=None, inputFile=None): super().__init__() self.startTime = time.time() # configureCanvas is changing these to the actual canvas size self.width = 2048 self.height = 2048 self.cam = None self.verbose = verbose self.quitAfterAnimation = quitAfterAnimation self.quitAfter = quitAfter self.isShowing = True # self.show() running? self.isTerminating = False if exitImmediate is True: self.isTerminating = True self.animated = False # this is set by a yaml. calling callback() self.framesShown = 0 self.isPlaying = True self.objectBrowser = False self.settingsBrowser = False self.selectedItem = None # sg def first self.sg = Singulersum(scale=(5.0, 5.0, 5.0), callback=self.callback) self.sg.logfile("./singulersum_gui.log") # setup default camera self.cam = self.sg.camera(1.0, 0.3, 0.4, 0.0, 0.0, 0.0, name="default") self.camera = "default" self.canvasInteract = CanvasInteract(self, self.cam) self.newCamera(self.camera) if inputFile is not None: # load the file self.open(inputFile) else: # load default self.sg.yaml("../yaml/lighttest.yaml") # each call to yaml will callback to self.callback and sets the camera that # is defined within the yaml file. pass self.selectedItem = self.sg self.sg.setTime(0) self.createWidgets() self.show()
def test_005(self): print("test_005:") sg = Singulersum(1.0, callback=self.callback) file = "../yaml/singulersum.yaml" data = sg.yaml(file=file) self.assertEqual(sg.scale, 5.0) print("tangential_plane_e.x:", sg.objects["tangential_plane_e"].x) self.assertEqual(sg.objects["tangential_plane_e"].x, -1.0) print("test_005 end.") print()
def test_004(self): print("test_004:") sg = Singulersum(1.0, callback=self.callback) file = "../yaml/tiny_house.yaml" self.animated = False data = sg.yaml(file=file) print(data) self.assertEqual(self.animated, True) self.assertEqual(self.camera, "cam1") print("test_004 end.") print()
def test_002(self): sg = Singulersum() cam = sg.camera(1, 0, 0, 0, 0, 0, name="cam1") self.V = [-1, 0, 0] print("V initial:", cam.vec_show(self.V)) self.V = cam.rotate(self.V, 40) self.V = cam.rotate(self.V, 0, 60) print("V rotated:", cam.vec_show(self.V)) self.lV = cam.vec_len(self.V) self.T = self.V self.T = cam.rotate(self.T, 0, -60) self.T = cam.rotate(self.T, -40, 0) print("V test reversed:", cam.vec_show(self.T)) # ah, not commutative! print("testing V:") azimuth = atan2(self.V[1], self.V[0]) #if azimuth<0.0: # azimuth = 2*pi+azimuth self.view_azimuth = azimuth/pi*180 self.view_radius = self.lV self.view_altitude = atan2(self.V[2], sqrt(self.V[0]**2+self.V[1]**2))/pi*180 print("View vector azimuth ", "{:4f}".format(self.view_azimuth)) print("View vector altitude: ", "{:4f}".format(self.view_altitude)) print("View vector 'radius'=length(V): ", "{:4f}".format(self.view_radius)) print("after rotation:") # now we back transform View Vector and Camera position print("rotate back") print(180-self.view_azimuth) print(-1*self.view_altitude) self.V_prime = cam.rotate(self.V, 180-self.view_azimuth, -1*self.view_altitude, 0.0) print("Camera View Vector V_prime: ", cam.vec_show(self.V_prime)) print("Camera V_prime length: ", "{:4f}".format(cam.vec_len(self.V_prime))) assert(abs(self.V_prime[0]-(-1.0))<0.5) assert(abs(self.V_prime[1]-0.0)<0.5) assert(abs(self.V_prime[2]-0.0)<0.5) self.V_prime = (-1.0, 0, 0)
def test_007(self): print("test_007:") sg = Singulersum(1.0, callback=self.callback) self.versionOk = True self.testing = False test = """ yaml: application: Singulersum url: https://github.com/frazy81/Singulersum min-version: 9999-12-31 min-yaml-version: 9999-12-31 gui: testing: True sg: scale: 5.0 animator: type: animation stop: 1.0 start: 0.0 camera: cam begin: [1.2, 2.0, 1.0] end: [1.6, 0.1, 0.5] x: begin[0] + (time*(end[0] - begin[0])) y: begin[1] + (time*(end[1] - begin[1])) z: begin[2] + (time*(end[2] - begin[2])) """ sg.yaml(data=test) self.assertFalse(self.versionOk) self.assertTrue(self.testing) self.assertEqual(sg.scale, 5.0) print("test_007 end.") print() pass
def __init__(self): super().__init__() self.isPaused = False sg = Singulersum(scale=(5, 5, 5), callback=self.callback) self.sg = sg #sg.yaml("../yaml/sine_waves.yaml") #sg.yaml("../yaml/tiny_house.yaml") #sg.yaml("../yaml/sphericon_ascii_stl.yaml") #sg.yaml("../yaml/utah_teapot_stl.yaml") #sg.yaml("../yaml/millennium_falcon_stl.yaml") #sg.yaml("../yaml/heart_curve.yaml") #sg.yaml("../yaml/sink.yaml") #sg.yaml("../yaml/cube.yaml") sg.yaml("../yaml/lighttest.yaml") self.cam = self.sg.cameras[self.camera] self.createWidgets() self.mainloop_singulversum()
def test_002(self): print("test_002:") sg = Singulersum(1.0, callback=self.callback) test = """ gui: isPlaying: True sg: scale: 5.0 stop: 1.0 animator: type: animation stop: 1.0 start: 0.0 begin: [0, 0, 0] end: [1, 1, 1] x: begin[0] + (time*(end[0] - begin[0])) y: begin[1] + (time*(end[1] - begin[1])) z: begin[2] + (time*(end[2] - begin[2])) cam: type: camera position: [1.0, 0.1, 0.2] lookat: [0.0, 0.0, 0.0] update: animator f1: type: function visibility: True fx: x fy: y fz: sin(x)+sin(y) rel: z scale: 5.0 size: 2.0 f2: type: function visibility: False fx: x fy: y fz: sin(x)+sin(y) rel: z scale: 5.0 size: 2.0 p1: type: point point: [5.0, 5.0, 5.0] """ data = sg.yaml(data=test) print(data) self.assertEqual(sg.scale, 5) self.assertEqual(sg.cameras["cam"].x, 1) self.assertEqual(sg.cameras["cam"].y, 0.1) self.assertEqual(sg.cameras["cam"].z, 0.2) self.assertEqual(sg.objects["f1"].visibility, True) self.assertEqual(sg.objects["f2"].visibility, False) sg.setTime(0.5) self.assertEqual(sg.time, 0.5) print("update 1 for time=0.5") sg.update() print(sg.cameras["cam"].x, "=?", 0.5) self.assertTrue(abs(sg.cameras["cam"].x - 0.5) < 0.1) print("done update 1") sg.setTime(0.9) print("update 2 for time=0.9") sg.update() print(sg.cameras["cam"].x, "=?", 0.9) self.assertTrue(abs(sg.cameras["cam"].x - 0.9) < 0.1) print("done update 2") print("test_002 end.") print()
def test_001(self): sg = Singulersum() cam = sg.camera(1, 0, 0, 0, 0, 0, name="cam1") cube = sg.cube(r=1.0, name="test") self.assertTrue("top1" in cube.objects) top = cube.objects["top1"] self.assertTrue(top) print(top.points) p0 = top.points[0] p1 = top.points[1] p2 = top.points[2] self.assertEqual(p0[0], 1.0) self.assertEqual(p0[1], -1.0) self.assertEqual(p0[2], 1.0) self.assertEqual(p1[0], 1.0) self.assertEqual(p1[1], 1.0) self.assertEqual(p1[2], 1.0) self.assertEqual(p2[0], -1.0) self.assertEqual(p2[1], 1.0) self.assertEqual(p2[2], 1.0) print("p0", p0) print("p1", p1) print("p2", p2) print("vector p0p1", cam.vec_sub(p1,p0)) print("vector p0p2", cam.vec_sub(p2,p0)) normalvector = cam.poly_normalvector(p0, p1, p2) print("normalvector", normalvector) self.assertEqual(normalvector[0], 0.0) self.assertEqual(normalvector[1], 0.0) self.assertEqual(normalvector[2], 1.0) # same for the second poly of "top" print("top2") top = cube.objects["top2"] self.assertTrue(top) print(top.points) p0 = top.points[0] p1 = top.points[1] p2 = top.points[2] self.assertEqual(p0[0], 1.0) self.assertEqual(p0[1], -1.0) self.assertEqual(p0[2], 1.0) self.assertEqual(p1[0], -1.0) self.assertEqual(p1[1], 1.0) self.assertEqual(p1[2], 1.0) self.assertEqual(p2[0], -1.0) self.assertEqual(p2[1], -1.0) self.assertEqual(p2[2], 1.0) print("p0", p0) print("p1", p1) print("p2", p2) print("vector p0p1", cam.vec_sub(p1,p0)) print("vector p0p2", cam.vec_sub(p2,p0)) normalvector = cam.poly_normalvector(p0, p1, p2) print("normalvector", normalvector) self.assertEqual(normalvector[0], 0.0) self.assertEqual(normalvector[1], 0.0) self.assertEqual(normalvector[2], 1.0) pass
class SingulersumGUI(Tk): def __init__(self, verbose=True, exitImmediate=False, quitAfterAnimation=False, quitAfter=None, inputFile=None): super().__init__() self.startTime = time.time() # configureCanvas is changing these to the actual canvas size self.width = 2048 self.height = 2048 self.cam = None self.verbose = verbose self.quitAfterAnimation = quitAfterAnimation self.quitAfter = quitAfter self.isShowing = True # self.show() running? self.isTerminating = False if exitImmediate is True: self.isTerminating = True self.animated = False # this is set by a yaml. calling callback() self.framesShown = 0 self.isPlaying = True self.objectBrowser = False self.settingsBrowser = False self.selectedItem = None # sg def first self.sg = Singulersum(scale=(5.0, 5.0, 5.0), callback=self.callback) self.sg.logfile("./singulersum_gui.log") # setup default camera self.cam = self.sg.camera(1.0, 0.3, 0.4, 0.0, 0.0, 0.0, name="default") self.camera = "default" self.canvasInteract = CanvasInteract(self, self.cam) self.newCamera(self.camera) if inputFile is not None: # load the file self.open(inputFile) else: # load default self.sg.yaml("../yaml/lighttest.yaml") # each call to yaml will callback to self.callback and sets the camera that # is defined within the yaml file. pass self.selectedItem = self.sg self.sg.setTime(0) self.createWidgets() self.show() def callback(self, event, **args): print("TkGUI, got callback from Singulersum:", event, args) if event=="set": setattr(self, args["name"], args["value"]) if args["name"]=="animated": if args["value"]==True: print("TkGUI.callback() got an animated=True, therefore start playing") self.isPlaying=True self.isShowing=True else: self.isShowing=True self.isPlaying=False if args["name"]=="camera": # set the camera, so that the GUI knows which camera to get images from. self.newCamera(args["value"]) elif event=="animation_start": # TODO: this is nowhere fired! self.play() elif event=="animation_stop": self.pause() print("sleep (end of animation). Press play to play again.") self.isPaused=True self.pauseVar.set('play') self.sg.setTime(0.0) self.update() self.update_idletasks() if self.quitAfterAnimation is True: print("quitAfterAnimation is True: quit application now.") self.quit() pass def newCamera(self, value): current_width = self.width current_height = self.height if self.cam is not None: current_width = self.cam.width current_height = self.cam.height # singulversum updated it's default camera, so we need to setup the new # camera and make a new CanvasInteract for mouse operations. self.cam = self.sg.cameras[value] # initialize camera with the current canvas width/height self.cam.width = current_width self.cam.height = current_height self.canvasInteract.camera(self.cam) def showImage(self): self.framesShown += 1 imgdata = self.cam.image() self.sg.debug("Tk picture import") timeit = self.sg.timeit() image = Image.frombuffer("RGBA", (self.cam.draw2d.width,self.cam.draw2d.height), imgdata, decoder_name="raw").convert("RGB") self.img = PhotoImage(image) self.sg.debug("Tk picture import complete.", timeit=timeit) timeit = self.sg.timeit() self.canvas.create_image(0, 0, anchor=NW, image=self.img) self.updateWidgets() self.sg.debug("update Tk Tasks") self.sg.debug("Tk Tasks updated, picture outlined", timeit=timeit) # show(), the mainloop for SingulversumGUI! def show(self): while True: print("state: isShowing=", self.isShowing, "isPlaying=", self.isPlaying) if self.quitAfter is not None and self.startTime+self.quitAfter<=time.time(): print("quitAfter "+str(self.quitAfter)+"s elapsed. Terminating in 2s.") time.sleep(2) self.isTerminating=True if self.isTerminating is True: # terminating is stepping out of this while! print("show(): received terminate instruction. Finish work and close application") # needs to be done here, since everything else is async and only this method is actually always running. Therefore a sleep() in quit() does not change anything... Kind of. Well it's strange... print(self.framesShown, "frames shown.") self.destroy() return True if self.isShowing is False: print("idle") self.update() self.update_idletasks() print("sleep 0.5") time.sleep(0.5) continue else: print() if self.isPlaying is False: self.isShowing=False # set early! if mouse event occurs in between print("stop playing") self.sg.update() # stl air intake problem, no update before show self.showImage() self.update() self.update_idletasks() continue self.sg.timeAdvance() self.sg.update() self.showImage() def play(self): print("TkGUI: play clicked") # TODO: reinitialize camera update function which might have been destroyed by # CanvasInteract() class if self.isPlaying is False: self.isShowing=True self.isPlaying=True self.pauseVar.set('pause') def pause(self): self.isPlaying=False self.pauseVar.set('play') def rewind(self): print("TkGUI: rewind clicked") # TODO: reinitialize camera update function which might have been destroyed by # CanvasInteract() class self.isPlaying=False self.sg.setTime(0.0) self.sg.update() print("start to play again") self.isPlaying=True self.isShowing=True self.pauseVar.set('pause') def repaint(self): print("TkGUI: repaint clicked") self.isShowing=True def createWidgets(self): self.resizable( height=True, width=True ) self.geometry( "{:d}x{:d}".format(self.width, self.height) ) self.title("Singulersum V{:s}".format(Singulersum.version)) # to minimize on close #self.protocol("WM_DELETE_WINDOW", self.iconify) self.protocol("WM_DELETE_WINDOW", self.quit) # menu menubar = Menu(self) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label="New", command=lambda: self.newFile()) filemenu.add_command(label="Open", command=lambda: self.openFile()) filemenu.add_command(label="Save (not implemented)", command=lambda: self.notImpl()) filemenu.add_command(label="Save as... (not implemented)", command=lambda: self.notImpl()) filemenu.add_command(label="Close", command=lambda: self.newFile()) filemenu.add_separator() filemenu.add_command(label="Exit", command=self.quit) menubar.add_cascade(label="File", menu=filemenu) editmenu = Menu(menubar, tearoff=0) editmenu.add_command(label="add point", command=lambda: self.addObject("point", x=0.0, y=0.0, z=0.0, color="#ff0000")) editmenu.add_command(label="add line", command=lambda: self.addObject("line", x1=0.0, y1=0.0, z1=0.0, x2=0.0, y2=0.0, z2=0.0, color="#ff0000")) # TODO: sphere gets distorted, x=0, y=1, z=0.5, r=0.3 editmenu.add_command(label="add sphere", command=lambda: self.addObject("sphere", x=0.0, y=0.0, z=0.0, r=0.3, size=1.0, color="#ff0000")) editmenu.add_command(label="add cube", command=lambda: self.addObject("cube", x=0.0, y=0.0, z=0.0, r=0.3, size=1.0, color="#aaaaaa")) editmenu.add_separator() editmenu.add_command(label="Cut (not implemented)", command=lambda: self.notImpl()) editmenu.add_command(label="Copy (not implemented)", command=lambda: self.notImpl()) #editmenu.add_command(label="Undo (not implemented)", command=lambda: self.notImpl()) #editmenu.add_command(label="Paste", command=lambda: self.notImpl()) #editmenu.add_command(label="Delete", command=lambda: self.notImpl()) #editmenu.add_command(label="Select All", command=lambda: self.notImpl()) menubar.add_cascade(label="Edit", menu=editmenu) examplesmenu = Menu(menubar, tearoff=0) examplesmenu.add_command(label="singulersum", command=lambda: self.openYaml("../yaml/singulersum.yaml")) examplesmenu.add_command(label="test", command=lambda: self.openYaml("../yaml/test.yaml")) examplesmenu.add_command(label="tiny house", command=lambda: self.openYaml("../yaml/tiny_house.yaml")) examplesmenu.add_command(label="lighttest", command=lambda: self.openYaml("../yaml/lighttest.yaml")) examplesmenu.add_command(label="cube", command=lambda: self.openYaml("../yaml/cube.yaml")) examplesmenu.add_command(label="sine waves", command=lambda: self.openYaml("../yaml/sine_waves.yaml")) examplesmenu.add_command(label="sphericon", command=lambda: self.openYaml("../yaml/sphericon_ascii_stl.yaml")) examplesmenu.add_command(label="utah teapot", command=lambda: self.openYaml("../yaml/utah_teapot_stl.yaml")) examplesmenu.add_command(label="millennium falcon", command=lambda: self.openYaml("../yaml/millennium_falcon_stl.yaml")) examplesmenu.add_command(label="heart curve", command=lambda: self.openYaml("../yaml/heart_curve.yaml")) examplesmenu.add_command(label="sink", command=lambda: self.openYaml("../yaml/sink.yaml")) menubar.add_cascade(label="Examples", menu=examplesmenu) settings = Menu(menubar, tearoff=0) settings.add_command(label="Singulersum", command=lambda: self.configSingulersum(Toplevel(self))) settings.add_separator() menubar.add_cascade(label="Settings", menu=settings) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label="Help Index (not implemented)", command=lambda: self.notImpl()) helpmenu.add_command(label="About...", command=lambda: self.help()) menubar.add_cascade(label="Help", menu=helpmenu) self.config(menu=menubar) # main panel self.functionbar = Frame(self, highlightbackground="black", highlightthickness=1) self.functionbar.pack(side=TOP, anchor=W) self.center = Frame(self) self.center.pack(side=TOP, fill=BOTH, expand=True) self.objectBrowserPanel = Frame(self) self.content = Frame(self.center, highlightbackground="black", highlightthickness=1) self.content.pack(side=LEFT, fill=BOTH, expand=True) self.settingsBrowserPanel = Frame(self) # function bar (top) bar = self.functionbar Button(bar, text="objects", command=lambda: self.guiUpdate("objectBrowser") ).pack(side=LEFT, anchor=W) Button(bar, text="settings", command=lambda: self.guiUpdate("settingsBrowser") ).pack(side=LEFT, anchor=W) # controlls self.controlls = Frame(self, highlightbackground="black", highlightthickness=1) self.controlls.pack(side=TOP) self.pauseVar = StringVar() self.pauseVar.set("pause") self.pauseBtn = Button(self.controlls, textvariable=self.pauseVar, command=lambda: self.pause() if self.isPlaying else self.play()) self.pauseBtn.pack(side=LEFT) self.rewindBtn = Button(self.controlls, text="rewind", command=self.rewind) self.rewindBtn.pack(side=LEFT) self.repaintBtn = Button(self.controlls, text="repaint", command=self.repaint) self.repaintBtn.pack(side=LEFT) # status self.status = Frame(self) self.status.pack(side=TOP) self.statusLine = Label(self.status, text="Status: Ready") self.statusLine.pack(side=LEFT) self.fpsNum = StringVar() self.fps = Label(self.status, textvariable=self.fpsNum) self.fps.pack(side=LEFT) self.camPos = StringVar() self.lcamPos = Label(self.status, textvariable=self.camPos) self.lcamPos.pack(side=LEFT) self.viewVec = StringVar() self.lviewVec = Label(self.status, textvariable=self.viewVec) self.lviewVec.pack(side=LEFT) self.sphericalVec = StringVar() self.lsphericalVec = Label(self.status, textvariable=self.sphericalVec) self.lsphericalVec.pack(side=LEFT) self.createViewer() def guiUpdate(self, name=None): if name is not None: val = getattr(self, name) if val is False: val = True else: val = False setattr(self, name, val) if self.objectBrowser is True: self.objectBrowserPanel.place(anchor=NW, x=0, y=100, relwidth=0.4, relheight=0.9) else: for child in self.settingsBrowserPanel.winfo_children(): child.destroy() self.objectBrowserPanel.place_forget() if self.settingsBrowser is True: self.settingsBrowserPanel.place(anchor=NE, relx=1, y=100, relwidth=0.4, relheight=0.9) f=Frame(self.settingsBrowserPanel) f.pack(side=TOP, anchor=NW) if self.selectedItem==self.sg: self.configSingulersum(f) else: self.settingsBrowserPanel.place_forget() for child in self.settingsBrowserPanel.winfo_children(): child.destroy() def addObject(self, object_type, **args): row = 0 column = 0 top = Toplevel(self) # coming from menu, settings placed in a Toplevel (new Window) top.title("add a new singulersum object") top.geometry( "{:d}x{:d}".format(800, int(800/4*2)) ) top.bind('<Escape>', lambda e: top.destroy()) entries = [] label = Label(top, text="") label.grid(row=row, column=column, sticky=W) row+=1 for name, value in args.items(): label = Label(top, text=name) label.grid(row=row, column=column, sticky=W) column+=1 objectsetting = Entry(top) objectsetting.insert(0, value) entries.append( { "object_type":object_type, "name":name, "value":objectsetting, "type":type(value).__name__ } ) objectsetting.grid(row=row, column=column, sticky=W) column=0 row+=1 button = Button(top, text="Apply", command=lambda: self.addObjectMake(top, entries, True)) button.grid(row=row, column=column, sticky=W) column+=1 button = Button(top, text="Cancel", command=lambda: self.addObjectMake(top, entries, False)) button.grid(row=row, column=column, sticky=W) def addObjectMake(self, top, entries, apply=False): if apply is True: args = {} for entry in entries: value = entry["value"].get() if entry["type"]=="float": value = float(value) elif entry["type"]=="bool": value = bool(value) elif entry["type"]=="string": value = str(value) name = entry["name"] args[name]=value type = entries[0]["object_type"] obj=getattr(self.sg, type)(**args) print("TkGUI.addObjectMake(): made a new object", obj) top.destroy() self.isShowing=True def quit(self): print("terminating the application") self.isTerminating=True self.sg.quit() print("wait for show() to finish.") self.update() self.update_idletasks() def updateWidgets(self): self.fpsNum.set("fps="+"{:0.2f}".format(self.sg.fps)) self.camPos.set("cam=[{:0.2f}, {:0.2f}, {:0.2f}]".format(self.cam.x, self.cam.y, self.cam.z)) self.viewVec.set("view at [{:0.2f}, {:0.2f}, {:0.2f}]".format(self.cam.V[0], self.cam.V[1], self.cam.V[2])) self.sphericalVec.set("sherical [{:0.2f}, {:0.2f}, {:0.2f}]".format(self.cam.cam_azimuth, self.cam.cam_altitude, self.cam.cam_radius)) self.update() self.update_idletasks() def openYaml(self, file): print("TkGUI(): open yaml file", file) self.sg.reset() self.sg.yaml(file) self.isPlaying=True self.isShowing=True def openStl(self, file): print("TkGUI(): open stl file", file) self.sg.reset() self.sg.stl(file) self.isPlaying=False self.isShowing=True def newFile(self): print("TkGUI(): newFile") self.pause() self.sg.reset() self.sg.setTime(0) self.isShowing=True self.isPlaying=False def open(self, file): if file[-4:]==".stl": self.openStl(file) elif file[-5:]==".yaml": self.openYaml(file) else: self.debug("don't know how to handle this file type (must be .yaml or .stl)", file) def openFile(self): dlg = filedialog.Open(self, filetypes=(("all files", "*.*"), ("YAML files", "*.yaml"), ("STL files", "*.stl"))) file = dlg.show() self.open(file) def notImpl(self): top = Toplevel(self) top.bind('<Escape>', lambda e: top.destroy()) top.title("Not Implemented") top.geometry( "{:d}x{:d}".format(600, int(600/4*2)) ) label = Label(top, text="") label.pack(side=TOP) label = Label(top, text="Not yet implemented.") label.pack(side=TOP) label = Label(top, text="") label.pack(side=TOP) button = Button(top, text="Cancel", command=lambda: top.destroy()) button.pack(side=TOP) def help(self): top = Toplevel(self) top.bind('<Escape>', lambda e: top.destroy()) top.title("Singulersum help") top.geometry( "{:d}x{:d}".format(600, int(600/4*2)) ) label = Label(top, text="") label.pack(side=TOP) label = Label(top, text="2021-03-05 Philipp Hasenfratz") label.pack(side=TOP) label = Label(top, text="Singulersum is a prototype for a") label.pack(side=TOP) label = Label(top, text="3D rendering engine") label.pack(side=TOP) label = Label(top, text="") label.pack(side=TOP) button = Button(top, text="Cancel", command=lambda: top.destroy()) button.pack(side=TOP) def configSingulersum(self, top): row = 0 column = 0 if top!=self and isinstance(top, Toplevel) is True: # coming from menu, settings placed in a Toplevel (new Window) top.title("configure Singulersum object") top.geometry( "{:d}x{:d}".format(800, int(800/4*2)) ) top.bind('<Escape>', lambda e: top.destroy()) else: # in settingsPanel, set title l=Label(top, text="settings panel") l.grid(row=row, column=column, sticky=W) row+=2 entries = [] label = Label(top, text="") label.grid(row=row, column=column, sticky=W) row+=1 label = Label(top, text="set time") label.grid(row=row, column=column, sticky=W) column+=1 time = Entry(top) time.insert(0, self.sg.time) entries.append( { "object":self.sg, "name":"time", "value":time, "type":"f" } ) time.grid(row=row, column=column, sticky=W) column=0 row+=1 label = Label(top, text="show coordinate system") label.grid(row=row, column=column, sticky=W) column+=1 coord = IntVar() coord.set(self.sg.showCoordinateSystem) coordck = Checkbutton(top, variable=coord) entries.append( { "object":self.sg, "name":"showCoordinateSystem", "value":coord, "type":"b" } ) coordck.grid(row=row, column=column, sticky=W) column=0 row+=1 label = Label(top, text="show bounding boxes") label.grid(row=row, column=column, sticky=W) column+=1 bbs = IntVar() bbs.set(self.sg.showBoundingBox) bbsck = Checkbutton(top, variable=bbs) entries.append( { "object":self.sg, "name":"showBoundingBox", "value":bbs, "type":"b" } ) bbsck.grid(row=row, column=column, sticky=W) column=0 row+=1 label = Label(top, text="show backside") label.grid(row=row, column=column, sticky=W) column+=1 bs = IntVar() bs.set(self.sg.showBackside) bsck = Checkbutton(top, variable=bs) entries.append( { "object":self.sg, "name":"showBackside", "value":bs, "type":"b" } ) bsck.grid(row=row, column=column, sticky=W) column=0 row+=1 column=0 row+=1 label = Label(top, text="polyOnlyGrid") label.grid(row=row, column=column, sticky=W) column+=1 po = IntVar() po.set(self.sg.polyOnlyGrid) pock = Checkbutton(top, variable=po) entries.append( { "object":self.sg, "name":"polyOnlyGrid", "value":po, "type":"b" } ) pock.grid(row=row, column=column, sticky=W) column=0 row+=1 button = Button(top, text="Apply", command=lambda: self.apply(top, entries, True)) button.grid(row=row, column=column, sticky=W) column+=1 button = Button(top, text="Cancel", command=lambda: self.apply(top, entries, False)) button.grid(row=row, column=column, sticky=W) def apply(self, top, entries, apply=False): if apply is True: for entry in entries: value = entry["value"].get() if entry["type"]=="f": value = float(value) elif entry["type"]=="b": value = bool(value) elif entry["type"]=="s": value = str(value) setattr(entry["object"], entry["name"], value) val=getattr(entry["object"], entry["name"]) print("set", entry["name"], "to", val) if isinstance(top, Frame): self.settingsBrowser=False self.isShowing=True top.destroy() self.guiUpdate() def configureCanvas(self, event): self.width = self.winfo_width()-2 self.height = self.winfo_height()-2 print("TkGUI(): reinitialize camera width/height") self.cam.width = self.width self.cam.height = self.height pass def createViewer(self): canvas = Canvas(self.content) self.canvas = canvas self.content.bind("<Configure>", self.configureCanvas) canvas.pack(side=LEFT, fill=BOTH, expand=True) canvas.bind("<Button-1>", self.canvasInteract.start) canvas.bind("<Button-2>", self.canvasInteract.start) canvas.bind("<B1-Motion>", self.canvasInteract.rotate) canvas.bind("<B2-Motion>", self.canvasInteract.walk) canvas.bind("<ButtonRelease-1>", self.canvasInteract.release) canvas.bind("<ButtonRelease-2>", self.canvasInteract.release) pass