diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-02-28 12:36:02 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-02-28 12:36:02 +0300 |
commit | 5369bd9c216243c4122d03896a3f7982631a4abf (patch) | |
tree | 46d920fdd4d44071d4e9e64b1759d9203fed2f6e | |
parent | 67af290bd125c181a1a851286da0677c7d5a1dbd (diff) |
- template with an example of a modal operator drawing with opengl (draw a line on the screen)
- access to event.mouse_region_x/y
- basic type checking to callback functions (use PyCapsule names)
-rw-r--r-- | release/scripts/templates/operator_modal_draw.py | 69 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/unit.c | 3 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_wm.c | 10 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna_callback.c | 30 |
4 files changed, 100 insertions, 12 deletions
diff --git a/release/scripts/templates/operator_modal_draw.py b/release/scripts/templates/operator_modal_draw.py new file mode 100644 index 00000000000..d830a380250 --- /dev/null +++ b/release/scripts/templates/operator_modal_draw.py @@ -0,0 +1,69 @@ +import BGL + +def draw_callback_px(self, context): + print("mouse points", len(self.mouse_path)) + + # 50% alpha, 2 pixel width line + BGL.glEnable(BGL.GL_BLEND) + BGL.glColor4f(0.0, 0.0, 0.0, 0.5) + BGL.glLineWidth(2) + + BGL.glBegin(BGL.GL_LINE_STRIP) + for x, y in self.mouse_path: + BGL.glVertex2i(x, y) + + BGL.glEnd() + + # restore opengl defaults + BGL.glLineWidth(1) + BGL.glDisable(BGL.GL_BLEND) + BGL.glColor4f(0.0, 0.0, 0.0, 1.0) + + +class ModalDrawOperator(bpy.types.Operator): + '''Draw a line with the mouse''' + bl_idname = "object.modal_operator" + bl_label = "Simple Modal Operator" + + def modal(self, context, event): + context.area.tag_redraw() + + if event.type == 'MOUSEMOVE': + self.mouse_path.append((event.mouse_region_x, event.mouse_region_y)) + + elif event.type == 'LEFTMOUSE': + context.region.callback_remove(self._handle) + return {'FINISHED'} + + elif event.type in ('RIGHTMOUSE', 'ESC'): + context.region.callback_remove(self._handle) + return {'CANCELLED'} + + return {'RUNNING_MODAL'} + + def invoke(self, context, event): + if context.area.type == 'VIEW_3D': + context.manager.add_modal_handler(self) + + # Add the region OpenGL drawing callback + # draw in view space with 'POST_VIEW' and 'PRE_VIEW' + self._handle = context.region.callback_add(draw_callback_px, (self, context), 'POST_PIXEL') + + self.mouse_path = [] + + return {'RUNNING_MODAL'} + else: + self.report({'WARNING'}, "View3D not found, cannot run operator") + return {'CANCELLED'} + + +def register(): + bpy.types.register(ModalDrawOperator) + + +def unregister(): + bpy.types.unregister(ModalDrawOperator) + + +if __name__ == "__main__": + register() diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index a16c1956cc4..87424dda04d 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -170,8 +170,7 @@ static void unit_dual_convert(double value, bUnitCollection *usys, { bUnitDef *unit= unit_best_fit(value, usys, NULL, 1); - if(value < 0.0) *value_a= -floor(-value/unit->scalar) * unit->scalar; - else *value_a= floor( value/unit->scalar) * unit->scalar; + *value_a= (value < 0.0 ? ceil:floor)(value/unit->scalar) * unit->scalar; *value_b= value - (*value_a); *unit_a= unit; diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 9b2a49b6ee5..a76030d9960 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -1088,6 +1088,16 @@ static void rna_def_event(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "y"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Mouse Y Position", "The window relative horizontal location of the mouse"); + + prop= RNA_def_property(srna, "mouse_region_x", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "mval[0]"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Mouse X Position", "The region relative vertical location of the mouse"); + + prop= RNA_def_property(srna, "mouse_region_y", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "mval[1]"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Mouse Y Position", "The region relative horizontal location of the mouse"); prop= RNA_def_property(srna, "mouse_prev_x", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "prevx"); diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c index ee0c5cb143b..ab97d7c3446 100644 --- a/source/blender/python/intern/bpy_rna_callback.c +++ b/source/blender/python/intern/bpy_rna_callback.c @@ -32,12 +32,9 @@ #include "BKE_context.h" #include "ED_space_api.h" -EnumPropertyItem region_draw_mode_items[] = { - {REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Pose View", ""}, - {REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""}, - {REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""}, - {0, NULL, 0, NULL, NULL}}; - +/* use this to stop other capsules from being mis-used */ +#define RNA_CAPSULE_ID "RNA_HANDLE" +#define RNA_CAPSULE_ID_INVALID "RNA_HANDLE_REMOVED" void cb_region_draw(const bContext *C, ARegion *ar, void *customdata) { @@ -74,6 +71,12 @@ PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args) if(RNA_struct_is_a(self->ptr.type, &RNA_Region)) { + EnumPropertyItem region_draw_mode_items[] = { + {REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Pose View", ""}, + {REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""}, + {REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""}, + {0, NULL, 0, NULL, NULL}}; + if(pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") < 0) return NULL; @@ -81,24 +84,28 @@ PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args) Py_INCREF(args); } else { - PyErr_SetString(PyExc_TypeError, "callbcak_add(): type does not suppport cllbacks"); + PyErr_SetString(PyExc_TypeError, "callback_add(): type does not suppport callbacks"); return NULL; } - return PyCapsule_New((void *)handle, NULL, NULL); + return PyCapsule_New((void *)handle, RNA_CAPSULE_ID, NULL); } PyObject *pyrna_callback_remove(BPy_StructRNA *self, PyObject *args) { PyObject *py_handle; - PyObject *py_args; void *handle; void *customdata; if (!PyArg_ParseTuple(args, "O!:callback_remove", &PyCapsule_Type, &py_handle)) return NULL; - handle= PyCapsule_GetPointer(py_handle, NULL); + handle= PyCapsule_GetPointer(py_handle, RNA_CAPSULE_ID); + + if(handle==NULL) { + PyErr_SetString(PyExc_ValueError, "callback_remove(handle): NULL handle given, invalid or already removed."); + return NULL; + } if(RNA_struct_is_a(self->ptr.type, &RNA_Region)) { customdata= ED_region_draw_cb_customdata(handle); @@ -107,5 +114,8 @@ PyObject *pyrna_callback_remove(BPy_StructRNA *self, PyObject *args) ED_region_draw_cb_exit(((ARegion *)self->ptr.data)->type, handle); } + /* dont allow reuse */ + PyCapsule_SetName(py_handle, RNA_CAPSULE_ID_INVALID); + Py_RETURN_NONE; } |