#!/usr/bin/env python3 from random import randint, shuffle, uniform import nanogui from nanogui import BoxLayout, Color, Label, Orientation, Screen, Widget, Window, glfw from nanogui.nanovg import RGB from knob import Knob class KnobsApp(Screen): def __init__(self, size=(450, 250)): super().__init__(size, "NanoGUI Knobs") self.set_background(Color(96, 96, 96, 255)) self.win = Window(self, "Envelope") self.win.set_layout(BoxLayout(Orientation.Horizontal, margin=20, spacing=20)) self.resize_event(size) knobs = ( ("Attack", 0.0, 0.0, 5.0, "s", 0.01), ("Decay", 0.0, 0.0, 5.0, "s", 0.01), ("Sustain", 0.0, 0.0, 100.0, "%", 0.01), ("Release", 0.0, 0.0, 5.0, "s", 0.01), ) self.knobs = [] self.entries = [] self.labels = [] for i, knobspec in enumerate(knobs): box = Widget(self.win) box.set_layout(BoxLayout(Orientation.Vertical, spacing=10)) rgb = [128 + randint(0, 127), randint(0, 127), 64] shuffle(rgb) knob = Knob(box, *knobspec) knob.color = RGB(*rgb) knob.value = round(uniform(knob.min_val, knob.max_val), 2) self.knobs.append(knob) self.entries.append(knob.create_value_entry(box)) self.labels.append(Label(box, knob.label, font="sans", font_size=20)) self.draw_all() self.set_visible(True) self.perform_layout() def resize_event(self, size): self.win.set_fixed_size(size) self.win.set_size(size) self.win.center() self.win.perform_layout(self.nvg_context()) super().resize_event(size) return True def keyboard_event(self, key, scancode, action, modifiers): if super().keyboard_event(key, scancode, action, modifiers): return True if key == glfw.KEY_ESCAPE and action == glfw.PRESS: self.set_visible(False) return True return True def __del__(self): # callbacks referencing other widgets cause memory leakage at cleanup for entry in self.entries: entry.set_callback(lambda x: True) for entry in self.knobs: entry.set_callback(lambda x: True) if __name__ == "__main__": import gc nanogui.init() app = KnobsApp() nanogui.mainloop(refresh=1 / 60.0 * 1000) del app gc.collect() nanogui.shutdown()