[Bf-blender-cvs] [e5d1e6350b6] temp-wm-event-api: Add cursor motion utility function

Campbell Barton noreply at git.blender.org
Wed Jan 30 13:16:00 CET 2019


Commit: e5d1e6350b61424d89b20dfac4c200ca30c12c03
Author: Campbell Barton
Date:   Wed Jan 30 23:09:06 2019 +1100
Branches: temp-wm-event-api
https://developer.blender.org/rBe5d1e6350b61424d89b20dfac4c200ca30c12c03

Add cursor motion utility function

===================================================================

M	tests/python/event_simulate/modules/easy_keys.py
A	tests/python/event_simulate/sculpt_undo_editmode.py

===================================================================

diff --git a/tests/python/event_simulate/modules/easy_keys.py b/tests/python/event_simulate/modules/easy_keys.py
index 0b35a922e74..1155e77fe3c 100644
--- a/tests/python/event_simulate/modules/easy_keys.py
+++ b/tests/python/event_simulate/modules/easy_keys.py
@@ -40,6 +40,9 @@ event_types_text = (
     ('EIGHT', "*", True),
     ('NINE', "-", True),
 
+    ('ACCENT_GRAVE', "`", False),
+    ('ACCENT_GRAVE', "~", True),
+
     ('SEMI_COLON', ";", False),
     ('SEMI_COLON', ":", True),
 
@@ -79,13 +82,11 @@ class _EventBuilder:
         "_event_gen",
         "_ty",
         "_parent",
-        "_event_simulate_kw",
     )
-    def __init__(self, event_gen, ty, kw):
+    def __init__(self, event_gen, ty):
         self._event_gen = event_gen
         self._ty = ty
         self._parent = None
-        self._event_simulate_kw = kw.copy()
 
     def __call__(self, count=1):
         for _ in range(count):
@@ -102,6 +103,7 @@ class _EventBuilder:
         build_keys.reverse()
 
         ty_pressed = set()
+        events = [None, None]
         for i, value in enumerate(('PRESS', 'RELEASE')):
             if value == 'RELEASE':
                 build_keys.reverse()
@@ -130,7 +132,7 @@ class _EventBuilder:
                             # Some keys don't care about shift
                             unicode = event_types_text_from_event.get((ty, False))
 
-                self._event_gen._window.event_simulate(
+                event = self._event_gen._window.event_simulate(
                     type=ty,
                     value=value,
                     unicode=unicode,
@@ -139,22 +141,56 @@ class _EventBuilder:
                     alt=alt,
                     oskey=oskey,
                     # typically mouse coords.
-                    **self._event_simulate_kw,
+                    **self._event_gen._event_simulate_kw,
                 )
+                events[i] = event
+        return tuple(events)
 
     def tap(self):
         self._key_press_release(do_press=True, do_release=True)
 
     def press(self):
-        self._key_press_release(do_press=True)
+        return self._key_press_release(do_press=True)[0]
 
     def release(self):
-        self._key_press_release(do_release=True)
+        return self._key_press_release(do_release=True)[1]
+
+    def cursor_motion(self, coords):
+        coords = list(coords)
+        self._event_gen.cursor_position_set(*coords[0], move=True)
+        yield True
+
+        event = self.press()
+        yield True
+
+        shift = event.shift
+        ctrl = event.ctrl
+        shift = event.shift
+        alt = event.alt
+        oskey = event.oskey
+
+        for x, y in coords:
+            event = self._event_gen._window.event_simulate(
+                type='MOUSEMOVE',
+                value='NOTHING',
+                unicode=None,
+                shift=shift,
+                ctrl=ctrl,
+                alt=alt,
+                oskey=oskey,
+                x=x,
+                y=y
+            )
+            print(x, y)
+            yield True
+        self._event_gen.cursor_position_set(x, y, move=False)
+        self.release()
+        yield True
 
     def __getattr__(self, attr):
         attr = event_types_alias.get(attr, attr)
         if attr in event_types:
-            e = _EventBuilder(self._event_gen, attr, self._event_simulate_kw)
+            e = _EventBuilder(self._event_gen, attr)
             e._parent = self
             return e
         raise Exception(f"{attr!r} not found in {event_types!r}")
@@ -171,9 +207,16 @@ class EventGenerate:
 
         self.cursor_position_set(window.width // 2, window.height // 2)
 
-    def cursor_position_set(self, x, y):
+    def cursor_position_set(self, x, y, move=False):
         self._event_simulate_kw["x"] = x
         self._event_simulate_kw["y"] = y
+        if move:
+            self._window.event_simulate(
+                type='MOUSEMOVE',
+                value='NOTHING',
+                x=x,
+                y=y,
+            )
 
     def text(self, text):
         """ Type in entire phrases. """
@@ -181,26 +224,23 @@ class EventGenerate:
             ty, shift = event_types_text_from_char[ch]
             ty = ty.lower()
             if shift:
-                eb = getattr(_EventBuilder(self, 'left_shift', self._event_simulate_kw), ty)
+                eb = getattr(_EventBuilder(self, 'left_shift'), ty)
             else:
-                eb = _EventBuilder(self, ty, self._event_simulate_kw)
+                eb = _EventBuilder(self, ty)
             eb.tap()
         return self
 
     def __getattr__(self, attr):
         attr = event_types_alias.get(attr, attr)
         if attr in event_types:
-            return _EventBuilder(self, attr, self._event_simulate_kw)
+            return _EventBuilder(self, attr)
         raise Exception(f"{attr!r} not found in {event_types!r}")
 
 
 def run(event_iter):
     import bpy
-
-    # 3 works, 4  to be on the safe side.
-    TICKS = 4
-
-    def event_step(*args):
+    TICKS = 4  # 3 works, 4  to be on the safe side.
+    def event_step():
         # Run once 'TICKS' is reached.
         if event_step._ticks < TICKS:
             event_step._ticks += 1
@@ -210,8 +250,8 @@ def run(event_iter):
         val = next(event_step.run_events, False)
         if val is not False:
             return 0.0
-        print("Success!")
 
     event_step.run_events = iter(event_iter)
     event_step._ticks = 0
+
     bpy.app.timers.register(event_step, first_interval=0.0)
diff --git a/tests/python/event_simulate/sculpt_undo_editmode.py b/tests/python/event_simulate/sculpt_undo_editmode.py
new file mode 100644
index 00000000000..76bd6942551
--- /dev/null
+++ b/tests/python/event_simulate/sculpt_undo_editmode.py
@@ -0,0 +1,46 @@
+# Apache License, Version 2.0
+# ./blender.bin --debug-events-simulate --python tests/python/event_simulate/sculpt_undo_editmode.py
+
+import os
+import sys
+sys.path.append(os.path.join(os.path.dirname(__file__), "modules"))
+
+import easy_keys
+
+# Callback doesn't have context.
+import bpy
+from bpy import context
+window = context.window
+
+def play_keys():
+
+    e = easy_keys.EventGenerate(window)
+    yield e.esc()                     # Kick splash screen away
+
+    size = window.width, window.height
+
+    yield e.shift.f5()                # 3D View
+    yield e.ctrl.space()              # Full-screen.
+    yield e.a().x().ret()             # Delete all.
+    yield e.shift.a().m().t()         # Add torus.
+    yield e.f3()                      # Remove UV's via search.
+    yield e.text("Remove UV Map").ret()
+    yield e.ctrl.tab().s()            # Sculpt via pie menu.
+    yield e.ctrl.d().ret()            # Dynamic topology.
+    yield e.f3()                      # Symmetrize via search.
+    yield e.text("Symmetrize").ret()  # ...
+    # Some painting (demo it works, not needed for the crash)
+    yield from e.leftmouse.cursor_motion(
+        (x, size[1] // 2) for x in
+        range(int(size[0] * 0.2), int(size[0] * 0.8), 20)
+    )
+    yield e.tab()                     # Edit mode.
+    yield e.tab()                     # Object mode.
+    yield e.ctrl.z(3)                 # Undo
+    yield e.ctrl.z()              # Undo crash
+
+    # Allow human interaction.
+    bpy.app.debug_events_simulate = False
+    yield False
+
+easy_keys.run(play_keys())



More information about the Bf-blender-cvs mailing list