def __init__(self, size, position=(0, 0, 0, 1), cs=(0, 1, 0, 1), style=DEFAULT_STYLE, axes_unit=None): super().__init__() # state self.cs = cs self.size = size self.position = position if axes_unit is not None: self.axes_unit = axes_unit #self.axes_unit = (0.1, 0.1) self._style = Style( { 'border': parse_4f1_1c4, 'background-color': parse_1c4, 'grid-color': parse_1c4, 'grid-sub-color': parse_1c4, 'plot-background-color': parse_1c4, 'plot-padding': parse_4f1, 'min-size': parse_2f1, 'plot-scaling': float, }, style) self.background_color = self._style['background-color'] self.plot_background_color = self._style['plot-background-color'] self.plot_padding = self._style['plot-padding'] self.ubo = None self.on_plot = Event() self._plot_margin = vec4((0, 0, 0, 0)) self.grid = None self.layer = None self._graphs = [] self._graphs_initialized = False self._init() self.a = False self.last_fr = False self.on_plot.once(self.init_graphs) self.cmc = [ [1, 0, 0, 1], [1, 1, 0, 1], [1, 0, 1, 1], [0, 1, 0, 1], [0, 0, 1, 1], [1, 1, 1, 1], ]
def __init__(self): self.gl_buffer_base_register = {} self._next_free_gl_buffer_base_index = 0 self.on_ready = Event() self.on_cycle = Event() self.on_resize = Event() self.on_close = Event() self.active_keys = set()
def _transform_observables(context, mutator, transformation, *observable): # the dispatcher arguments will be the observable values. dspargs = [None] * len(observable) # an context having a on_change attribute implies that # it is itself mutable (otherwise one could not append event listeners). # => mutator must be callable if hasattr(context, 'on_change'): if not hasattr(mutator, '__call__'): raise ValueError('mutator') on_change = context.on_change __dispatch = mutator else: # a context without on_change attribute can either be mutable # or immutable. Here it is mutable if a mutator exists. on_change = Event() if hasattr(mutator, '__call__'): def __dispatch(val): mutator(val) # context is mutable, so pass context itself as # the first event argument. on_change(context) else: # it just does not make sense to use a context here, since it will be overwritten # directly when the initial valaue is transformed. if context is not None: raise ValueError( 'context must be None since it is implicitly given by transformation if mutator is None.' ) def __dispatch(val): # the context is immutable so pass the value # from the transformation as the event argument. on_change(val) # dispatch if the i-th observable has changes def _callback(i, context): dspargs[i] = context __dispatch(transformation(*dspargs)) # initialize dispatching args and assign # event handlers to observables. for i, s in enumerate(observable): dspargs[i] = bind(s, partial(_callback, i)) # transform the initial value and dispatch val = transformation(*dspargs) __dispatch(val) # object is mutable and is an observable if hasattr(context, 'on_change'): return context else: if hasattr(mutator, '__call__'): return (context, on_change) # mutable, no observable else: return (val, on_change) # immutable, no observable
def __init__(self): self.on_ready = Event() self.on_init = Event() self.on_cycle = Event() self.on_close = Event()
def __init__(self): self.on_tick = Event() self._ = ObservablesAccessor(self)
def __init__(self): super().__init__() self.on_pre_render = Event() self.on_post_render = Event()
class Plotter2d(Widget): UBO_DTYPE = np.dtype([('mat_cs', np.float32, (4, 4)), ('cs', np.float32, 4), ('cs_size', np.float32, 2)]) # widget configuration size = attributes.VectorAttribute(2) position = attributes.VectorAttribute(4, (0, 0, 0, 1)) # configuration space determines [minx, maxx, miny, maxy] cs = attributes.VectorAttribute(4, (0, 1, 0, 1)) # axes configuration # size of one unit (sx, sy) in configuration space axes_unit = attributes.VectorAttribute(2, (0.25, 0.25)) # division of one axes_unit into sub units minor_axes_n = attributes.VectorAttribute(2, (5, 5)) # the plot plane is implemented via framebuffer. this factor # allows to adjust the resolution of the framebuffer viewport. plot_resolution_factor = attributes.CastedAttribute(float, 1) background_color = attributes.VectorAttribute(4, (0, 0, 0, 1)) plot_background_color = attributes.VectorAttribute(4, (0, 0, 0, 1)) plot_padding = attributes.VectorAttribute(4, (0, 0, 0, 0)) # common precomputed properties cs_size = attributes.ComputedAttribute( cs, descriptor=attributes.VectorAttribute(2), transformation=cs_size) def __init__(self, size, position=(0, 0, 0, 1), cs=(0, 1, 0, 1), style=DEFAULT_STYLE, axes_unit=None): super().__init__() # state self.cs = cs self.size = size self.position = position if axes_unit is not None: self.axes_unit = axes_unit #self.axes_unit = (0.1, 0.1) self._style = Style( { 'border': parse_4f1_1c4, 'background-color': parse_1c4, 'grid-color': parse_1c4, 'grid-sub-color': parse_1c4, 'plot-background-color': parse_1c4, 'plot-padding': parse_4f1, 'min-size': parse_2f1, 'plot-scaling': float, }, style) self.background_color = self._style['background-color'] self.plot_background_color = self._style['plot-background-color'] self.plot_padding = self._style['plot-padding'] self.ubo = None self.on_plot = Event() self._plot_margin = vec4((0, 0, 0, 0)) self.grid = None self.layer = None self._graphs = [] self._graphs_initialized = False self._init() self.a = False self.last_fr = False self.on_plot.once(self.init_graphs) self.cmc = [ [1, 0, 0, 1], [1, 1, 0, 1], [1, 0, 1, 1], [0, 1, 0, 1], [0, 0, 1, 1], [1, 1, 1, 1], ] # -- graph api def init_graphs(self): for graph in self._graphs: graph.init() self._graphs_initialized = True def append(self, graph): self._graphs.append(graph) if self._graphs_initialized: graph.init() graph.resolution = self.plotframe.resulution graph.viewport = self.plotframe.resulution def __iadd__(self, graph): self.append(graph) return self # -- init def _init(self): self._initlayer() self._initplotcam() self._init_grid() self._init_ubo() # -- plot ubo def _init_ubo(self): """ initializes plotting ubo """ self.ubo = BufferObject.to_device(np.zeros(1, dtype=Plotter2d.UBO_DTYPE), target=GL_UNIFORM_BUFFER) buffer_base = GPUPY_GL.CONTEXT.buffer_base('gpupy.plot.plotter2d') self.ubo.bind_buffer_base(buffer_base) self.update_ubo() @cs.on_change def update_ubo(self, *e): self.ubo.host['mat_cs'] = mat_cs(self.cs, self.layer.content_size) self.ubo.host['cs'] = self.cs.values self.ubo.host['cs_size'] = cs_size(self.cs) self.ubo.sync_gpu() # -- grid def _init_grid(self): """ initializes grid component """ major_grid = observables.transform_observables( transformation=grid, observables=(self.axes_unit, self.cs)) self.grid = CartesianGrid( size=self.layer.content_size, position=self.layer.content_position, cs=self.cs, major_grid=major_grid, major_grid_color=self._style['grid-color'], minor_grid_color=self._style['grid-sub-color'], background_color=self.plot_background_color, resolution=self.layer.content_size, minor_grid_n=self.minor_axes_n) #.dev() # -- camera def _initplotcam(self): """ creates a plot camera which is connected to the configuration space """ pos = observables.transform_observables( lambda s: (s[0] * 0.5, s[1] * 0.5, 1), vecn((0, 0, 0)), (self.layer.content_size, )) self.plotcam = Camera2D(self.layer.content_size, pos) # -- container def _initlayer(self): """ initializes main plotcontainer. the plotcontainer manages border, margin padding and contains the main plot framebuffer """ layer = Container(size=self.size, position=self.position, margin=self._plot_margin, padding=self.plot_padding, border=self._style['border'][0], border_color=self._style['border'][1]) self.plotframe = FrameWidget(position=layer.content_position, size=layer.content_size, resulution=layer.content_size, clear_color=(0, 0, 0, 0)) self.layer = layer self.layer.content_size.on_change.append(self.update_ubo) def tick(self): self.on_tick() # -- tick the components self.plotcam.enable() self.layer.tick() self.grid.tick() self.plotframe.tick() # -- graph rendering self.plotframe.use() self.plotcam.enable() self.on_plot() self.ubo.bind_buffer_base( GPUPY_GL.CONTEXT.buffer_base('gpupy.plot.plotter2d')) for graph in self._graphs: graph.tick() graph.render() self.plotframe.unuse() def draw(self): self.grid.render() self.layer.render() self.plotframe.render()
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.on_change = Event()
def __create__(self, val): return val, Event()
def __create__(self, val): return (self._cast(val) if val is not None else None), Event()