Skip to content

Commit

Permalink
Refactor initialization and re-order methods (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
almarklein authored Nov 11, 2024
1 parent 6107796 commit 95bb8f4
Show file tree
Hide file tree
Showing 12 changed files with 649 additions and 599 deletions.
2 changes: 1 addition & 1 deletion examples/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from rendercanvas.auto import RenderCanvas, loop

from cube import setup_drawing_sync
from rendercanvas.utils.cube import setup_drawing_sync


canvas = RenderCanvas(
Expand Down
2 changes: 1 addition & 1 deletion examples/qt_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def __init__(self):
splitter = QtWidgets.QSplitter()

self.button = QtWidgets.QPushButton("Hello world", self)
self.canvas = QRenderWidget(splitter)
self.canvas = QRenderWidget(splitter, update_mode="continuous")
self.output = QtWidgets.QTextEdit(splitter)

self.button.clicked.connect(self.whenButtonClicked)
Expand Down
2 changes: 1 addition & 1 deletion examples/qt_app_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def __init__(self):

# todo: use update_mode = 'continuous' when that feature has arrived
self.button = QtWidgets.QPushButton("Hello world", self)
self.canvas = QRenderWidget(splitter)
self.canvas = QRenderWidget(splitter, update_mode="continuous")
self.output = QtWidgets.QTextEdit(splitter)

# self.button.clicked.connect(self.whenButtonClicked) # see above :(
Expand Down
33 changes: 20 additions & 13 deletions examples/wx_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
An example demonstrating a wx app with a wgpu viz inside.
"""

import time

import wx
from rendercanvas.wx import RenderWidget

Expand All @@ -13,30 +15,35 @@ def __init__(self):
super().__init__(None, title="wgpu triangle embedded in a wx app")
self.SetSize(640, 480)

splitter = wx.SplitterWindow(self)

# Using present_method 'image' because it reports "The surface texture is suboptimal"
self.canvas = RenderWidget(
self, update_mode="continuous", present_method="image"
)
self.button = wx.Button(self, -1, "Hello world")
self.canvas1 = RenderWidget(splitter)
self.canvas2 = RenderWidget(splitter)

splitter.SplitVertically(self.canvas1, self.canvas2)
splitter.SetSashGravity(0.5)
self.output = wx.StaticText(self)

sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.button, 0, wx.EXPAND)
sizer.Add(splitter, 1, wx.EXPAND)
sizer.Add(self.canvas, 1, wx.EXPAND)
sizer.Add(self.output, 1, wx.EXPAND)
self.SetSizer(sizer)

self.button.Bind(wx.EVT_BUTTON, self.OnClicked)

# Force the canvas to be shown, so that it gets a valid handle.
# Otherwise GetHandle() is initially 0, and getting a surface will fail.
self.Show()

def OnClicked(self, event): # noqa: N802
t = self.output.GetLabel()
t += f"\nClicked at {time.time():0.1f}"
self.output.SetLabel(t)


app = wx.App()
example = Example()

draw_frame1 = setup_drawing_sync(example.canvas1)
draw_frame2 = setup_drawing_sync(example.canvas2)

example.canvas1.request_draw(draw_frame1)
example.canvas2.request_draw(draw_frame2)
draw_frame = setup_drawing_sync(example.canvas)
example.canvas.request_draw(draw_frame)

app.MainLoop()
16 changes: 8 additions & 8 deletions rendercanvas/_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,12 +307,14 @@ class Scheduler:
# Note that any extra draws, e.g. via force_draw() or due to window resizes,
# don't affect the scheduling loop; they are just extra draws.

def __init__(self, canvas, loop, *, mode="ondemand", min_fps=1, max_fps=30):
def __init__(self, canvas, events, loop, *, mode="ondemand", min_fps=1, max_fps=30):
assert loop is not None

# We don't keep a ref to the canvas to help gc. This scheduler object can be
# referenced via a callback in an event loop, but it won't prevent the canvas
# from being deleted!
self._canvas_ref = weakref.ref(canvas)
self._events = canvas._events
self._events = events
# ... = canvas.get_context() -> No, context creation should be lazy!

# Scheduling variables
Expand All @@ -329,8 +331,6 @@ def __init__(self, canvas, loop, *, mode="ondemand", min_fps=1, max_fps=30):
# Keep track of fps
self._draw_stats = 0, time.perf_counter()

assert loop is not None

# Initialise the timer that runs our scheduling loop.
# Note that the backend may do a first draw earlier, starting the loop, and that's fine.
self._last_tick_time = -0.1
Expand Down Expand Up @@ -390,22 +390,22 @@ def _tick(self):

if self._mode == "fastest":
# fastest: draw continuously as fast as possible, ignoring fps settings.
canvas._request_draw()
canvas._rc_request_draw()

elif self._mode == "continuous":
# continuous: draw continuously, aiming for a steady max framerate.
canvas._request_draw()
canvas._rc_request_draw()

elif self._mode == "ondemand":
# ondemand: draw when needed (detected by calls to request_draw).
# Aim for max_fps when drawing is needed, otherwise min_fps.
if self._draw_requested:
canvas._request_draw()
canvas._rc_request_draw()
elif (
self._min_fps > 0
and time.perf_counter() - self._last_draw_time > 1 / self._min_fps
):
canvas._request_draw()
canvas._rc_request_draw()
else:
self._schedule_next_tick()

Expand Down
Loading

0 comments on commit 95bb8f4

Please sign in to comment.