Hello,
I’m starting to understand how to use the internal C functions within the Blender API in Python.
And to begin, I decided to import a function that I find very useful. It’s the “snapObjectsex”, referenced in the header: c:\BlenderDEV\blender\source\blender\editors\include\ED_transform.h
This function is used by the operator ruler for example.
And I got, Look:
But as you can see, I’m having trouble with the snap mode: face.
WHYYY???
The Cython function that I used was this:
from libc.stdint cimport intptr_t
#C:\BlenderDEV\blender\source\blender\blenkernel\BKE_bvhutils.h
#cdef extern from "BKE_bvhutils.h":
# ctypedef struct BVHTreeFromMesh:
# pass
# ctypedef struct BVHTreeNearest:
# pass
#C:\BlenderDEV\blender\source\blender\makesdna\DNA_space_types.h
#cdef extern from "DNA_space_types.h":
# pass
#C:\BlenderDEV\blender\source\blender\makesdna\DNA_scene_types.h
cdef extern from "DNA_scene_types.h":
cdef short SCE_SNAP_MODE_VERTEX
cdef short SCE_SNAP_MODE_EDGE
cdef short SCE_SNAP_MODE_FACE
ctypedef struct Base:
pass
ctypedef struct Scene:
float cursor[3]
#C:\BlenderDEV\blender\source\blender\makesdna\DNA_view3d_types.h
cdef extern from "DNA_view3d_types.h":
ctypedef struct RegionView3D:
pass
ctypedef struct View3D:
float viewquat[4]
#C:\BlenderDEV\blender\source\blender\makesdna\DNA_screen_types.h
cdef extern from "DNA_screen_types.h":
ctypedef struct ScrArea:
pass
ctypedef struct ARegion:
short winx, winy
#C:\BlenderDEV\blender\source\blender\makesdna\DNA_object_types.h
cdef extern from "DNA_object_types.h":
ctypedef struct BoundBox:
pass
ctypedef struct Object:
pass
#C:\BlenderDEV\blender\source\blender\blenkernel\BKE_context.h
cdef extern from "BKE_context.h":
ctypedef struct bContext:
pass
ScrArea *CTX_wm_area(const bContext *C)
ARegion *CTX_wm_region(const bContext *C)
View3D *CTX_wm_view3d(const bContext *C)
Scene *CTX_data_scene(const bContext *C)
Object *CTX_data_edit_object(const bContext *C)
#C:\BlenderDEV\blender\source\blender\editors\include\ED_transform.h
cdef extern from "ED_transform.h":
ctypedef enum SnapMode:
SNAP_ALL = 0,
SNAP_NOT_SELECTED = 1,
SNAP_NOT_OBEDIT = 2
bint snapObjectsEx(
Scene *scene,
Base *base_act,
View3D *v3d,
ARegion *ar,
Object *obedit,
short snap_mode,
const float mval[2],
float *r_dist_px,
float r_loc[3],
float r_no[3],
float *r_ray_dist,
SnapMode mode)
#C:\BlenderDEV\blender\source\blender\python\intern\bpy_util.h
#cdef extern from "bpy_util.h":
# bContext *BPy_GetContext()
def test_snap(PyCtx, const float mval_x, const float mval_y, bint use_vert, bint use_edge, bint use_face, bint use_depth = True):
#cdef intptr_t pointer = PyCtx.as_pointer()
#cdef bContext *C = (<bContext*>pointer)
cdef intptr_t scenePointer = PyCtx.scene.as_pointer()
cdef Scene *scene = (<Scene*>scenePointer)
cdef intptr_t v3dPointer = PyCtx.space_data.as_pointer()
cdef View3D *v3d = (<View3D*>v3dPointer)
cdef intptr_t arPointer = PyCtx.region.as_pointer()
cdef ARegion *ar = (<ARegion*>arPointer)
#cdef bContext *C = <bContext *>BPy_GetContext()
#if C == NULL:
# print("Context is None, cant poll any operators")
# return
#cdef Scene *scene = CTX_data_scene(C)
#cdef View3D *v3d = CTX_wm_view3d(C)
#cdef ARegion *ar = CTX_wm_region(C)
#cdef Object *obedit = CTX_data_edit_object(C)
cdef float r_co[3]
r_co = 0.0,0.0,0.0
cdef float co_ss[2]
co_ss = mval_x, mval_y
cdef float dist_px = 12.0 # snap dist #
cdef float r_no_dummy[3]
cdef float ray_dist = 1.701411733e+38
cdef bint ret = False
cdef float *r_no_ptr = r_no_dummy
cdef short elem = -1
if use_vert:
if snapObjectsEx(scene, NULL, v3d, ar, NULL, SCE_SNAP_MODE_VERTEX,
co_ss, &dist_px, r_co, r_no_ptr, &ray_dist, SNAP_ALL):
elem = 0
ret = True
if use_edge and (not ret or use_depth):
if not use_depth: ray_dist = 1.701411733e+38
if snapObjectsEx(scene, NULL, v3d, ar, NULL, SCE_SNAP_MODE_EDGE,
co_ss, &dist_px, r_co, r_no_ptr, &ray_dist, SNAP_ALL):
elem = 1
ret = True
if use_face and (not ret or use_depth):
if not use_depth: ray_dist = 1.701411733e+38
if snapObjectsEx(scene, NULL, v3d, ar, NULL, SCE_SNAP_MODE_FACE,
co_ss, &dist_px, r_co, r_no_ptr, &ray_dist, SNAP_ALL):
elem = 2
ret = True
print(scene.cursor)
print(v3d.viewquat)
print(ar.winx, ar.winy)
return elem, r_co
Here is the compiled module for 64-bit Windows:
And here’s a script that uses the module:
import bpy, bgl
from get_context import test_snap
class ModalOperator(bpy.types.Operator):
"""Move an object with the mouse, example"""
bl_idname = "object.snap_operator"
bl_label = "SNAP"
bl_options = {'REGISTER', 'UNDO'}
def draw_callback_px(self, context):
if self.elem != -1:
bgl.glEnable(bgl.GL_BLEND)
if self.elem == 0:
bgl.glColor4f(1.0,0.0,0.0,0.5)
if self.elem == 1:
bgl.glColor4f(0.0,1.0,0.0,0.5)
if self.elem == 2:
bgl.glColor4f(0.0,0.0,1.0,0.5)
bgl.glDepthRange(0,0)
bgl.glPointSize(12)
bgl.glBegin(bgl.GL_POINTS)
bgl.glVertex3f(*self.co)
bgl.glEnd()
# restore opengl defaults
bgl.glDepthRange(0,1)
bgl.glPointSize(1)
bgl.glDisable(bgl.GL_BLEND)
bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
def modal(self, context, event):
if event.type == 'MOUSEMOVE':
context.area.tag_redraw()
self.elem, self.co = test_snap(context, event.mouse_region_x, event.mouse_region_y,
self.use_vert, self.use_edge, self.use_face, self.use_depth)
print(self.elem, self.co)
elif event.type in {'RIGHTMOUSE', 'ESC'}:
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
return {'FINISHED'}
return {'PASS_THROUGH'}
def invoke(self, context, event):
if context.area.type == 'VIEW_3D':
self.use_vert = True
self.use_edge = True
self.use_face = False
self.use_depth = False
self.elem = -1
self.ret = False
self._handle = bpy.types.SpaceView3D.draw_handler_add(self.draw_callback_px, (context,), 'WINDOW', 'POST_VIEW')
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
self.report({'WARNING'}, "View3D not found, cannot run operator")
return {'CANCELLED'}
def register():
bpy.utils.register_class(ModalOperator)
def unregister():
bpy.utils.unregister_class(ModalOperator)
if __name__ == "__main__":
register()
Any other information, just ask me.
Thank you