diff options
Diffstat (limited to 'lib/gui/simulator')
| -rw-r--r-- | lib/gui/simulator/control_panel.py | 6 | ||||
| -rw-r--r-- | lib/gui/simulator/drawing_panel.py | 42 | ||||
| -rw-r--r-- | lib/gui/simulator/split_simulator_window.py | 7 |
3 files changed, 39 insertions, 16 deletions
diff --git a/lib/gui/simulator/control_panel.py b/lib/gui/simulator/control_panel.py index 9226d5de..99d1f92b 100644 --- a/lib/gui/simulator/control_panel.py +++ b/lib/gui/simulator/control_panel.py @@ -208,7 +208,11 @@ class ControlPanel(wx.Panel): self.set_speed(global_settings['simulator_speed']) return if self.target_duration: - self.set_speed(int(self.num_stitches / float(self.target_duration))) + stitches_per_second = round(self.num_stitches / float(self.target_duration)) + if stitches_per_second < 10: + # otherwise it just looks weirdly slow + stitches_per_second = 10 + self.set_speed(stitches_per_second) else: self.set_speed(self.target_stitches_per_second) diff --git a/lib/gui/simulator/drawing_panel.py b/lib/gui/simulator/drawing_panel.py index ced11f00..1587ecfa 100644 --- a/lib/gui/simulator/drawing_panel.py +++ b/lib/gui/simulator/drawing_panel.py @@ -52,8 +52,9 @@ class DrawingPanel(wx.Panel): self.SetDoubleBuffered(True) self.animating = False + self.timer = wx.Timer(self) + self.last_frame_start = 0 self.target_frame_period = 1.0 / self.TARGET_FPS - self.last_frame_duration = 0 self.direction = 1 self.current_stitch = 0 self.black_pen = wx.Pen((128, 128, 128)) @@ -72,6 +73,7 @@ class DrawingPanel(wx.Panel): self.Bind(wx.EVT_LEFT_DOWN, self.on_left_mouse_button_down) self.Bind(wx.EVT_MOUSEWHEEL, self.on_mouse_wheel) self.Bind(wx.EVT_SIZE, self.on_resize) + self.Bind(wx.EVT_TIMER, self.animate) # wait for layouts so that panel size is set if self.stitch_plan: @@ -99,20 +101,30 @@ class DrawingPanel(wx.Panel): elif self.direction == 1 and self.current_stitch < self.num_stitches: self.go() - def animate(self): + def animate(self, event=None): if not self.animating: return - frame_time = max(self.target_frame_period, self.last_frame_duration) - - # No sense in rendering more frames per second than our desired stitches - # per second. - frame_time = max(frame_time, 1.0 / self.speed) + # Each frame, we need to advance forward some number of stitches to + # match the speed setting. The tricky thing is that with bigger + # designs, it may take a long time to render a frame. That might + # mean that we'll fall behind. Even if we set our Timer to 30 FPS, + # we may only actually manage to render 20 FPS or fewer, and the + # duration of each frame may vary. + # + # To deal with that, we'll figure out how many stitches to advance + # based on how long it took to render the last frame. We'll always + # be behind by one frame, but it should work out fine. - stitch_increment = int(self.speed * frame_time) + now = time.time() + if self.last_frame_start: + frame_time = now - self.last_frame_start + else: + frame_time = self.target_frame_period + self.last_frame_start = now + stitch_increment = self.speed * frame_time self.set_current_stitch(self.current_stitch + self.direction * stitch_increment) - wx.CallLater(int(1000 * frame_time), self.animate) def OnPaint(self, e): dc = wx.PaintDC(self) @@ -167,7 +179,6 @@ class DrawingPanel(wx.Panel): stitch = 0 last_stitch = None - start = time.time() for pen, stitches, jumps in zip(self.pens, self.stitch_blocks, self.jumps): canvas.SetPen(pen) if stitch + len(stitches) < self.current_stitch: @@ -177,13 +188,12 @@ class DrawingPanel(wx.Panel): self.draw_needle_penetration_points(canvas, pen, stitches) last_stitch = stitches[-1] else: - stitches = stitches[:self.current_stitch - stitch] + stitches = stitches[:int(self.current_stitch) - stitch] if len(stitches) > 1: self.draw_stitch_lines(canvas, pen, stitches, jumps) self.draw_needle_penetration_points(canvas, pen, stitches) last_stitch = stitches[-1] break - self.last_frame_duration = time.time() - start if last_stitch: self.draw_crosshair(last_stitch[0], last_stitch[1], canvas, transform) @@ -260,7 +270,6 @@ class DrawingPanel(wx.Panel): def load(self, stitch_plan): self.current_stitch = 1 self.direction = 1 - self.last_frame_duration = 0 self.minx, self.miny, self.maxx, self.maxy = stitch_plan.bounding_box self.width = self.maxx - self.minx self.height = self.maxy - self.miny @@ -326,6 +335,7 @@ class DrawingPanel(wx.Panel): def stop(self): self.animating = False + self.timer.Stop() self.control_panel.on_stop() def go(self): @@ -335,6 +345,8 @@ class DrawingPanel(wx.Panel): if not self.animating: try: self.animating = True + self.last_frame_start = 0 + self.timer.Start(int(self.target_frame_period * 1000)) self.animate() self.control_panel.on_start() except RuntimeError: @@ -412,8 +424,8 @@ class DrawingPanel(wx.Panel): def set_current_stitch(self, stitch): self.current_stitch = stitch self.clamp_current_stitch() - command = self.commands[self.current_stitch] - self.control_panel.on_current_stitch(self.current_stitch, command) + command = self.commands[int(self.current_stitch)] + self.control_panel.on_current_stitch(int(self.current_stitch), command) statusbar = self.GetTopLevelParent().statusbar statusbar.SetStatusText(_("Command: %s") % COMMAND_NAMES[command], 2) self.stop_if_at_end() diff --git a/lib/gui/simulator/split_simulator_window.py b/lib/gui/simulator/split_simulator_window.py index 72fd1143..e4b2803e 100644 --- a/lib/gui/simulator/split_simulator_window.py +++ b/lib/gui/simulator/split_simulator_window.py @@ -67,6 +67,13 @@ class SplitSimulatorWindow(wx.Frame): def cancel(self, event=None): if self.cancel_hook: self.cancel_hook() + try: + if not self.settings_panel.confirm_close(): + event.Veto() + return + except AttributeError: + pass + self.close(None) def close(self, event=None): |
