class MyGui: def __init__(self, window): self.window = window # Must create or set the context before instantiating the renderer imgui.create_context() self.renderer = PygletRenderer(window) # Window variables self.test_input = 0 def render(self): imgui.new_frame() imgui.begin("Test Window") imgui.text("This is the test window.") changed, self.test_input = imgui.input_int("Integer Input Test", self.test_input) imgui.end() imgui.end_frame() imgui.render() self.renderer.render(imgui.get_draw_data())
class Scope(pyglet.window.Window): def __init__(self, port=DEFAULT_PORT): super().__init__(caption=f"oscosc (port {port})", resizable=True) self.y_per_div = 0.5 self.time_per_div = 0.5 self.y_per_div_selected = 3 self.time_per_div_selected = 3 self.num_divs_v = 8 self.num_divs_h = 10 self.grid_color = (0.7, 0.7, 0.7) self.lines = dict() self.line_colors = dict() self.gui_width = 0 # Use timestamp of the first received OSC message or bundle as t=0 self.time_offset = 0.0 self.time_offset_ready = False self.start_time = 0.0 # List of OSC addresses received self.addresses = set() # launch receiver thread self.receiver = receiver.Receiver() self.receiver.start_thread(port) # Initialize IMGUI for pyglet # (See https://github.com/swistakm/pyimgui/blob/master/doc/examples/integrations_pyglet.py) imgui.create_context() self.imgui_renderer = PygletRenderer(self) pyglet.clock.schedule_interval(self.update, 1 / 60) # called 60 times per second def update(self, dt): # In pyglet, state update is separated from drawing self.process_messages() self.do_gui() def on_close(self): super().on_close() # cleanup self.receiver.stop_thread() self.imgui_renderer.shutdown() def on_resize(self, width, height): glViewport(0, 0, width, height) # called each frame def on_draw(self): glClearColor(0.0, 0.0, 0.0, 1.0) glClear(GL_COLOR_BUFFER_BIT) glPushMatrix() glTranslated(-self.gui_width / self.width, 0, 0) grid_aspect = self.num_divs_h / self.num_divs_v grid_width = min(self.width - self.gui_width, grid_aspect * self.height) glScaled(grid_width / self.width, grid_width / grid_aspect / self.height, 1) glScaled(0.95, 0.95, 1) # for margin glScaled(2 / (self.time_per_div * self.num_divs_h), 2 / (self.y_per_div * self.num_divs_v), 1) self.draw_grid() self.plot() glPopMatrix() # If imgui.get_draw_data() is None, skip rendering # (Maybe on_draw is called before update on Linux) if imgui.get_draw_data() is not None: # GUI comes in front of other things self.imgui_renderer.render(imgui.get_draw_data()) def draw_grid(self): glColor3dv(self.grid_color) left = -self.time_per_div * self.num_divs_h / 2 right = self.time_per_div * self.num_divs_h / 2 bottom = -self.y_per_div * self.num_divs_v / 2 top = self.y_per_div * self.num_divs_v / 2 # Horizontal lines glBegin(GL_LINES) for i in range(-self.num_divs_v // 2, self.num_divs_v // 2 + 1): glVertex2d(left, i * self.y_per_div) glVertex2d(right, i * self.y_per_div) glEnd() # Vertical lines glBegin(GL_LINES) for i in range(-self.num_divs_h // 2, self.num_divs_h // 2 + 1): glVertex2d(i * self.time_per_div, bottom) glVertex2d(i * self.time_per_div, top) glEnd() # Plot data sequences def plot(self): glPushMatrix() # t=0 is the left end of the grid glTranslated(-self.num_divs_h * self.time_per_div / 2, 0, 0) # scroll glTranslated( -max(0, self.get_time() - self.num_divs_h * self.time_per_div), 0, 0) self.line_colors.clear() # TODO reconsider for i, pair in enumerate(self.lines.items()): addr, line = pair color = LINE_COLORS[i % len(LINE_COLORS)] self.plot_line(line, color) self.line_colors[addr] = color glPopMatrix() # Plot single line def plot_line(self, line, color): glColor3dv(color) glBegin(GL_LINE_STRIP) for t, value in line: glVertex2d(t - self.time_offset, value) glEnd() # Process incoming OSC messages def process_messages(self): while self.receiver.available(): msgs, timestamp, sender = self.receiver.get() if not self.time_offset_ready: self.time_offset = timestamp self.time_offset_ready = True self.start_time = time.time() for msg in msgs: self.add_data(msg, timestamp, sender) def add_data(self, msg, timestamp, sender): # TODO currently, wildcard in OSC address is not supported self.addresses.add(msg.address) if msg.address in self.lines: self.lines[msg.address].append((timestamp, msg.params[0])) def do_gui(self): imgui.new_frame() imgui.set_next_window_position(self.width, 0, pivot_x=1.0) imgui.begin("win", closable=False, flags=imgui.WINDOW_NO_TITLE_BAR | imgui.WINDOW_NO_MOVE | imgui.WINDOW_NO_RESIZE) changed, self.time_per_div_selected = imgui.combo( "TIME/DIV", self.time_per_div_selected, [str(option) for option in TIME_PER_DIV_OPTIONS]) if changed: self.time_per_div = TIME_PER_DIV_OPTIONS[ self.time_per_div_selected] changed, self.y_per_div_selected = imgui.combo( "Y/DIV", self.y_per_div_selected, [str(option) for option in Y_PER_DIV_OPTIONS]) if changed: self.y_per_div = Y_PER_DIV_OPTIONS[self.y_per_div_selected] imgui.text("Values") for addr in self.addresses: color_changed = False if addr in self.lines: # Change text color to indicate the color of plot r, g, b = self.line_colors[addr] imgui.push_style_color(imgui.COLOR_TEXT, r, g, b) color_changed = True changed, selected = imgui.selectable(addr, addr in self.lines) if changed and selected: self.lines[addr] = collections.deque(maxlen=MAX_POINTS) elif changed and not selected: del self.lines[addr] if color_changed: imgui.pop_style_color() self.gui_width = imgui.get_window_width() imgui.end() # imgui.render() in on_draw caused a "newFrame is not called" error on Windows, # therefore we invoke it here imgui.render() def get_time(self): return time.time() - self.start_time
class Interface: # --UI and Controls-- def __init__(self, window): imgui.create_context() self.impl = PygletRenderer(window) imgui.new_frame() # Required since on call, imgui needs to render once imgui.end_frame() # --Imgui Window Variables-- # --Format: Window Boolean followed by its variables, separate each window with one end line. self.showPlayerControls = True # self.showDummyControls = False # self.actStand = True self.actMove = False self.actAttack = False self.showControlHelp = False # self.showAbout = False # self.showTestWindow = False # self.test_checkbox = False self.test_input_int = 0 def render(self): imgui.render() self.impl.render(imgui.get_draw_data()) imgui.new_frame() # --Imgui Windows-- # --Note: Variables are defined in __init__ under Imgui Window Variables if self.showPlayerControls: imgui.begin("Player Controls") imgui.text("Current State:") imgui.text(wire_sponge.curState.name) imgui.new_line() imgui.begin_child("movement", 320, 180, border=True) imgui.text("Movement") if imgui.button("Turn to Opposite", 300, 20): if wire_sponge.facing == Facing.left: wire_sponge.facing == Facing.right else: wire_sponge.facing = Facing.left if imgui.button("Face Left", 140, 20): wire_sponge.facing = Facing.left imgui.same_line(spacing=20) if imgui.button("Face Right", 140, 20): wire_sponge.facing = Facing.right if imgui.button("Walk (Toggle)", 300, 20): pass if imgui.button("Walk Left", 140, 20): pass imgui.same_line(spacing=20) if imgui.button("Walk Right", 140, 20): pass if imgui.button("Jump", 300, 20): if wire_sponge.on_ground: wire_sponge.setState(SpongeState.leapBegin) wire_sponge.on_ground = False imgui.new_line() imgui.end_child() imgui.begin_child("skills", 320, 120, border=True) imgui.text("Attacks and Skills") if imgui.button("Attack", 300, 20): if wire_sponge.chain.curState == ChainState.NaN \ and wire_sponge.curState != SpongeState.throwHrz \ and wire_sponge.curState != SpongeState.throwHrzRelease \ and wire_sponge.curState != SpongeState.throwHrzPullGo: wire_sponge.setState(SpongeState.throwHrzBegin) if imgui.button("Chain Spin", 300, 20): if wire_sponge.on_ground and wire_sponge.curState != SpongeState.spin: wire_sponge.setState(SpongeState.spin) if imgui.button("Thunder Dance", 300, 20): pass imgui.new_line() imgui.end_child() imgui.end() if self.showDummyControls: imgui.begin("Dummy Controls") imgui.begin_child("spawn", 320, 80, border=True) imgui.text("Spawn Controls") if imgui.button("Respawn", 300, 20): pass if imgui.button("Spawn", 140, 20): pass imgui.same_line(spacing=20) if imgui.button("Despawn", 140, 20): pass imgui.new_line() imgui.end_child() imgui.begin_child("behaviour", 320, 80, border=True) imgui.text("Behaviour Controls") changed, self.actStand = imgui.checkbox("Stand", self.actStand) changed, self.actMove = imgui.checkbox("Move", self.actMove) changed, self.actAttack = imgui.checkbox("Attack", self.actAttack) imgui.new_line() imgui.end_child() imgui.end() if self.showControlHelp: imgui.begin("Control Help") imgui.text("Arrow Keys: Move") imgui.text("Space: Jump") imgui.text("Z: Thunder Dance") imgui.text("X: Spin Chain") imgui.text("C: Attack") imgui.end() if self.showTestWindow: imgui.begin("Test Window") imgui.text("This is the test window.") changed, self.test_checkbox = imgui.checkbox("Test Checkbox", self.test_checkbox) if imgui.button("Test Button", 100, 20): pass changed, self.test_input_int = imgui.input_int("Integer Input Test", self.test_input_int) imgui.end() # --This is where the fun begins-- if imgui.begin_main_menu_bar(): if imgui.begin_menu("Application", True): selected_test, clicked_test = imgui.menu_item( "Test Window", "", False, True ) if clicked_test: if not self.showTestWindow: self.showTestWindow = True else: self.showTestWindow = False if selected_test: pass selected_quit, clicked_quit = imgui.menu_item( "Quit", "", False, True ) if clicked_quit: exit(0) if selected_quit: pass imgui.end_menu() if imgui.begin_menu("Controls", True): selected_reset, clicked_reset = imgui.menu_item( "Reset All", "", False, True ) if clicked_reset: pass if selected_reset: pass selected_player, clicked_player = imgui.menu_item( "Player", "", False, True ) if clicked_player: if not self.showPlayerControls: self.showPlayerControls = True else: self.showPlayerControls = False if selected_player: pass selected_dummy, clicked_dummy = imgui.menu_item( "Dummy", "", False, True ) if clicked_dummy: if not self.showDummyControls: self.showDummyControls = True else: self.showDummyControls = False if selected_dummy: pass imgui.end_menu() if imgui.begin_menu("Help", True): selected_controls, clicked_controls = imgui.menu_item( "Keyboard Controls", "", False, True ) if clicked_controls: if self.showControlHelp: self.showControlHelp = False else: self.showControlHelp = True if selected_controls: pass selected_about, clicked_about = imgui.menu_item( "About", "", False, True ) if clicked_about: if self.showAbout: self.showAbout = False else: self.showAbout = True if selected_about: pass imgui.end_menu() imgui.end_main_menu_bar() imgui.end_frame()
class Application: def __init__(self): self.window = pyglet.window.Window(800, 600) imgui.create_context() self.renderer = PygletRenderer(self.window) self.impl = PygletRenderer(self.window) def clear(self): glClearColor(1, 1, 1, 1) def dispatch(self): self.clear() @self.window.event def on_draw(): self.window.clear() glClear(GL_COLOR_BUFFER_BIT) self.update(1 / 60.0) imgui.render() self.impl.render(imgui.get_draw_data()) pyglet.app.run() def crosshair(self): y = 300 for x in range(390, 410): pyglet.graphics.draw(1, pyglet.gl.GL_POINTS, ('v2i', (x, y)), ('c3B', (255, 0, 0))) x = 400 for y in range(290, 310): pyglet.graphics.draw(1, pyglet.gl.GL_POINTS, ('v2i', (x, y)), ('c3B', (255, 0, 0))) showDrawTools = True showLayers = True showTestWindow = False def update(self, dt): imgui.new_frame() self.crosshair() if self.showTestWindow: self.testWindow() if self.showDrawTools: # show Drawing Tools window self.drawTools() if self.showLayers: self.layers() if imgui.begin_main_menu_bar(): # stat menu bar (top bar) if imgui.begin_menu("File", True): # start menu bar entry: File clicked_quit, selected_quit = imgui.menu_item( # start File menu entry: Quit "Quit", 'Cmd+Q', False, True # Name label, Shortcut label, Check bool, Enabled bool ) if clicked_quit: # event: if entry quit is clicked exit(1) if selected_quit: pass imgui.end_menu() # end File menu if imgui.begin_menu("Draw", True): clicked_draw, selected_draw = imgui.menu_item( "Draw Tools", "", self.showDrawTools, True) if clicked_draw: if self.showDrawTools: self.showDrawTools = False else: self.showDrawTools = True clicked_layers, selected_layers = imgui.menu_item( "Layers", "", self.showLayers, True) if clicked_layers: if self.showLayers: self.showLayers = False else: self.showLayers = True imgui.end_menu() # Example of a window, check line 59 if imgui.begin_menu("Test", True): # start menu bar entry: Test clicked_test, selected_test = imgui.menu_item( "Test", "Ctrl+Alt+Del", self.showTestWindow, True) if clicked_test: if self.showTestWindow: self.showTestWindow = False else: self.showTestWindow = True imgui.end_menu() # end Test menu imgui.end_main_menu_bar() # imgui.show_test_window() # Built in test thing def shutdown(self): self.impl.shutdown() def testWindow(self): imgui.begin("Custom window", False) # start new window: Custom Window imgui.text("Bar") # text label imgui.text_colored("Eggs", 0.2, 1., 0.) # colored text label (text, r, g , b) imgui.button("Test Button", 100, 20) imgui.end() # End window def: Custom Window # consider moving these to global scope color = .0, .0, .0 # used for drawing color, set data type for pyglet.graphics.draw to c3f drawMode = "" # used to specify what to draw vrad = 0 # store vertical radius for ellipse, radius for circle hrad = 0 # stores horizontal radius for ellipse, unused for circle x_center = 400 # see x_center in cga_lib.py y_center = 300 # see y_center in cga_lib.py def drawTools(self): imgui.begin("Drawing Tools") if imgui.button("Reset", 207, 20): self.color = .0, .0, .0 self.drawMode = "" self.vrad = 0 self.hrad = 0 self.x_center = 400 self.y_center = 300 if imgui.button( "Circle", 100, 20 ): # imgui.core.button, https://github.com/ocornut/imgui/issues/2481 self.drawMode = "c" imgui.same_line(115) if imgui.button("Ellipse", 100, 20): self.drawMode = "e" imgui.new_line() if self.drawMode == "c": changed, self.vrad = imgui.input_int("Radius", self.vrad, 1, 100) # imgui.core.input_int changed, self.x_center = imgui.slider_int( "X-axis center", self.x_center, 0, 800) # imgui.core.slider_int, set max to window size changed, self.y_center = imgui.slider_int("Y-axis center", self.y_center, 0, 600) changed, self.color = imgui.color_edit3( "Set Color", *self.color) # asterisk used for tuple, I think... elif self.drawMode == "e": changed, self.vrad = imgui.input_int("Vertical Radius", self.vrad, 1, 100) # imgui.core.input_int # changed, self.vrad = imgui.slider_int("", self.vrad, 0, 1000) changed, self.hrad = imgui.input_int("Horizontal Radius", self.hrad, 1, 100) # changed, self.hrad = imgui.slider_int("Horizontal Radius", self.hrad, 0, 1000) changed, self.x_center = imgui.slider_int( "X-axis center", self.x_center, 0, 800) # imgui.core.slider_int, set max to window size changed, self.y_center = imgui.slider_int("Y-axis center", self.y_center, 0, 600) changed, self.color = imgui.color_edit3( "Set Color", *self.color) # asterisk used for tuple, I think... imgui.new_line imgui.begin_child("Current Settings", border=True) # imgui.core.begin_child imgui.text("Currently Drawing: ") # imgui.core.text if self.drawMode == "c": imgui.same_line(200), imgui.text_colored( "Circle", 0, 1, 0) # imgui.core.same_line, imgui.core.text_colored imgui.text("Radius:"), imgui.same_line(200), imgui.text_colored( str(self.vrad), 0, 1, 0) imgui.text("X Position:"), imgui.same_line( 200), imgui.text_colored(str(self.x_center), 0, 1, 0) imgui.text("Y Position:"), imgui.same_line( 200), imgui.text_colored(str(self.y_center), 0, 1, 0) elif self.drawMode == "e": imgui.same_line(200), imgui.text_colored("Ellipse", 0, 1, 0) imgui.text("V. Radius:"), imgui.same_line(200), imgui.text_colored( str(self.vrad), 0, 1, 0) imgui.text("H. Radius:"), imgui.same_line(200), imgui.text_colored( str(self.hrad), 0, 1, 0) imgui.text("X Position:"), imgui.same_line( 200), imgui.text_colored(str(self.x_center), 0, 1, 0) imgui.text("Y Position:"), imgui.same_line( 200), imgui.text_colored(str(self.y_center), 0, 1, 0) else: imgui.text("Nothing Selected") imgui.end_child() imgui.end() def layers(self): imgui.begin("Layers") # display layers here... imgui.end()