Skip to content

Commit

Permalink
Merge pull request #1030 from campagnola/scenegraph-update
Browse files Browse the repository at this point in the history
Scenegraph update - review
  • Loading branch information
larsoner committed Jul 30, 2015
2 parents bd39033 + 0491812 commit 588d107
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 41 deletions.
25 changes: 16 additions & 9 deletions examples/basics/scene/line_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,26 @@
color[:, 1] = color[::-1, 0]

canvas = scene.SceneCanvas(keys='interactive', show=True)
viewbox = canvas.central_widget.add_view()
grid = canvas.central_widget.add_grid(spacing=0)

# add some axes
domains = np.array([x_lim, y_lim])
pos_ax = [np.array([domains[0], [domains[1][0]] * 2]).T,
np.array([[domains[0][0]] * 2, domains[1]]).T]
x_axis = scene.Axis(pos_ax[0], domains[0], (0, -1), parent=viewbox.scene)
y_axis = scene.Axis(pos_ax[1], domains[1], (-1, 0), parent=viewbox.scene)

viewbox.camera = 'panzoom' # set after adding axes to auto-zoom
viewbox = grid.add_view(row=0, col=1, camera='panzoom')

# add some axes
x_axis = scene.AxisWidget(orientation='bottom')
x_axis.stretch = (1, 0.1)
grid.add_widget(x_axis, row=1, col=1)
x_axis.link_view(viewbox)
y_axis = scene.AxisWidget(orientation='left')
y_axis.stretch = (0.1, 1)
grid.add_widget(y_axis, row=0, col=0)
y_axis.link_view(viewbox)

# add a line plot inside the viewbox
line = scene.Line(pos, color, parent=viewbox.scene)

# auto-scale to see the whole line.
viewbox.camera.set_range()


def update(ev):
global pos, color, line
Expand Down
4 changes: 2 additions & 2 deletions examples/basics/scene/nested_viewbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
vb1.camera.interactive = False

# bottom-left (+y down)
vb11 = scene.widgets.ViewBox(parent=vb1.scene, name='vb11',
vb11 = scene.widgets.ViewBox(parent=vb1.scene, name='vb11', border_width=2e-3,
margin=0.02, border_color='green')
vb11.pos = 0, 0
vb11.size = 1, 0.5
Expand All @@ -97,7 +97,7 @@
parent=vb11.scene)

# top-left (+y up)
vb12 = scene.widgets.ViewBox(parent=vb1.scene, name='vb12',
vb12 = scene.widgets.ViewBox(parent=vb1.scene, name='vb12', border_width=2e-3,
margin=0.02, border_color='blue')
vb12.pos = 0, 0.5
vb12.size = 1, 0.5
Expand Down
3 changes: 2 additions & 1 deletion examples/basics/scene/one_cam_two_scenes.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
vb1.camera.link(vb2.camera)

# Set the view bounds to show the entire image with some padding
#view.camera.rect = (-10, -10, image.size[0]+20, image.size[1]+20)
vb1.camera.set_range()


if __name__ == '__main__':
app.run()
27 changes: 26 additions & 1 deletion examples/demo/scene/oscilloscope.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
# Copyright (c) 2015, Vispy Development Team.
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
"""
Make a realtime oscilloscope
An oscilloscope, spectrum analyzer, and spectrogram.
This demo uses pyaudio to record data from the microphone. If pyaudio is not
available, then a signal will be generated instead.
"""

from __future__ import division
Expand Down Expand Up @@ -86,6 +89,28 @@ def start(self):


class Oscilloscope(scene.ScrollingLines):
"""A set of lines that are temporally aligned on a trigger.
Data is added in chunks to the oscilloscope, and each new chunk creates a
new line to draw. Older lines are slowly faded out until they are removed.
Parameters
----------
n_lines : int
The maximum number of lines to draw.
line_size : int
The number of samples in each line.
dx : float
The x spacing between adjacent samples in a line.
color : tuple
The base color to use when drawing lines. Older lines are faded by
decreasing their alpha value.
trigger : tuple
A set of parameters (level, height, width) that determine how triggers
are detected.
parent : Node
An optional parent scenegraph node.
"""
def __init__(self, n_lines=100, line_size=1024, dx=1e-4,
color=(20, 255, 50), trigger=(0, 0.002, 1e-4), parent=None):

Expand Down
3 changes: 3 additions & 0 deletions vispy/scene/cameras/fly.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,9 @@ def viewbox_mouse_event(self, event):
print('scale factor: %1.1f units/s' % self.scale_factor)
return

if event.type == 'mouse_press':
event.handled = True

if event.type == 'mouse_release':
# Reset
self._event_value = None
Expand Down
6 changes: 3 additions & 3 deletions vispy/scene/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,9 @@ def visual_at(self, pos):
fbpos = tr.map(pos)[:2]

try:
id_ = self._render_picking(region=(fbpos[0]-10, fbpos[1]-10,
20, 20))
vis = VisualNode._visual_ids.get(id_[10, 10], None)
id_ = self._render_picking(region=(fbpos[0], fbpos[1],
1, 1))
vis = VisualNode._visual_ids.get(id_[0, 0], None)
except RuntimeError:
# Don't have read_pixels() support for IPython. Fall back to
# bounds checking.
Expand Down
9 changes: 9 additions & 0 deletions vispy/scene/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,15 @@ def set_transform(self, type_, *args, **kwargs):
self.transform = create_transform(type_, *args, **kwargs)

def _update_trsys(self, event):
"""Called when has changed.
This allows the node and its children to react (notably, VisualNode
uses this to update its TransformSystem).
Note that this method is only called when one transform is replaced by
another; it is not called if an existing transform internally changes
its state.
"""
for ch in self.children:
ch._update_trsys(event)
self.events.transform_change()
Expand Down
3 changes: 3 additions & 0 deletions vispy/scene/visuals.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ def picking(self, p):
self.update_gl_state(blend=not p)

def _update_trsys(self, event):
"""Transform object(s) have changed for this Node; assign these to the
visual's TransformSystem.
"""
doc = self.document_node
scene = self.scene_node
root = self.root_node
Expand Down
40 changes: 15 additions & 25 deletions vispy/scene/widgets/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class Widget(Compound):
A 2-element tuple to spicify the size of the widget.
border_color : color
The color of the border.
border_width : float
The width of the border line in pixels.
bgcolor : color
The background color.
padding : int
Expand All @@ -40,7 +42,7 @@ class Widget(Compound):
"""

def __init__(self, pos=(0, 0), size=(10, 10), border_color=None,
bgcolor=None, padding=0, margin=0, **kwargs):
border_width=1, bgcolor=None, padding=0, margin=0, **kwargs):

# For drawing border.
# A mesh is required because GL lines cannot be drawn with predictable
Expand All @@ -54,12 +56,15 @@ def __init__(self, pos=(0, 0), size=(10, 10), border_color=None,

# reserved space inside border
self._padding = padding

self._border_width = border_width

# reserved space outside border
self._margin = margin
self._size = 100, 100

# layout interaction
# todo: use Cassowary; see #277
self._fixed_size = (None, None)
self._stretch = (None, None)

Expand Down Expand Up @@ -123,12 +128,12 @@ def rect(self, r):

@property
def inner_rect(self):
"""The rectangular area inside the margin, border and padding.
"""The rectangular area inside the margin, border, and padding.
Generally widgets should avoid drawing or placing widgets outside this
rectangle.
Generally widgets should avoid drawing or placing sub-widgets outside
this rectangle.
"""
m = self.margin + self.padding
m = self.margin + self._border_width + self.padding
if not self.border_color.is_blank:
m += 1
return Rect((m, m), (self.size[0]-2*m, self.size[1]-2*m))
Expand All @@ -146,22 +151,7 @@ def stretch(self):

@stretch.setter
def stretch(self, s):
self._stretch = s
self._update_layout()

@property
def fixed_size(self):
"""Fixed size (w, h) of the widget.
Specifying a fixed size for either axis forces the widget to have a
specific size in a layout. Setting either axis to None allows the
widget to be resized by the layout.
"""
return self._fixed_size

@fixed_size.setter
def fixed_size(self, s):
self._fixed_size = s
self._stretch = float(s[0]), float(s[1])
self._update_layout()

def _update_layout(self):
Expand Down Expand Up @@ -231,8 +221,8 @@ def padding(self, p):

def _update_line(self):
""" Update border line to match new shape """
w = 1 # XXX Eventually this can be a parameter
m = int(self.margin)
w = self._border_width
m = self.margin
# border is drawn within the boundaries of the widget:
#
# size = (8, 7) margin=2
Expand All @@ -246,8 +236,8 @@ def _update_line(self):
# ........
#
l = b = m
r = int(self.size[0]) - m
t = int(self.size[1]) - m
r = self.size[0] - m
t = self.size[1] - m
pos = np.array([
[l, b], [l+w, b+w],
[r, b], [r-w, b+w],
Expand Down

0 comments on commit 588d107

Please sign in to comment.