python interface revision
[convexer.git] / __init__.py
index 544d770b19433a22b846762c0bf2ac2afe7ca5ba..fc20f056977ebaa93d2d186f258cf311167a64ca 100644 (file)
@@ -105,7 +105,7 @@ class cxr_vmf_context(Structure):
 
 # Public API
 libcxr_decompose = extern( "cxr_decompose", \
-      [POINTER(cxr_static_mesh)], c_void_p )
+      [POINTER(cxr_static_mesh), POINTER(c_int32)], c_void_p )
 
 libcxr_free_world = extern( "cxr_free_world", [c_void_p], None )
 libcxr_write_test_data = extern( "cxr_write_test_data", \
@@ -250,15 +250,16 @@ def cxr_draw():
 
    debug_gpu_shader.bind()
 
-   gpu.state.depth_test_set('LESS_EQUAL')
    gpu.state.depth_mask_set(False)
    gpu.state.line_width_set(1.5)
    gpu.state.face_culling_set('BACK')
 
+   gpu.state.depth_test_set('NONE')
    gpu.state.blend_set('ALPHA')
    if debug_gpu_lines != None:
       debug_gpu_lines.draw(debug_gpu_shader)
 
+   gpu.state.depth_test_set('LESS_EQUAL')
    gpu.state.blend_set('ADDITIVE')
    if debug_gpu_mesh != None:
       debug_gpu_mesh.draw(debug_gpu_shader)
@@ -813,6 +814,10 @@ def material_info(mat):
    return info
 
 def mesh_cxr_format(obj):
+   orig_state = obj.mode
+   if orig_state != 'OBJECT':
+      bpy.ops.object.mode_set(mode='OBJECT')
+
    dgraph = bpy.context.evaluated_depsgraph_get()
    data = obj.evaluated_get(dgraph).data
    
@@ -885,6 +890,7 @@ def mesh_cxr_format(obj):
    mesh.loop_count =  len(data.loops)
    mesh.material_count = len(obj.material_slots)
 
+   bpy.ops.object.mode_set(mode=orig_state)
    return mesh
 
 class CXR_WRITE_VMF(bpy.types.Operator):
@@ -909,8 +915,8 @@ class CXR_WRITE_VMF(bpy.types.Operator):
       os.makedirs( model_dir, exist_ok=True )
       
       # States
+      libcxr_reset_debug_lines()
       material_info.references = set()
-      
       output_vmf = F"{directory}/{settings.project_name}.vmf"
 
       with vdf_structure(output_vmf) as m:
@@ -995,7 +1001,7 @@ class CXR_WRITE_VMF(bpy.types.Operator):
             nonlocal m
 
             baked = mesh_cxr_format( brush[0] )
-            world = libcxr_decompose.call( baked )
+            world = libcxr_decompose.call( baked, None )
             
             if world == None:
                return False
@@ -1013,7 +1019,8 @@ class CXR_WRITE_VMF(bpy.types.Operator):
          # World geometry
          for brush in _collect.geo:
             if not _buildsolid( brush[0], brush[1] ):
-               print( "error" )
+               libcxr_batch_debug_lines()
+               scene_redraw()
                return {'CANCELLED'}
 
          m.edon()
@@ -1034,6 +1041,8 @@ class CXR_WRITE_VMF(bpy.types.Operator):
                else: m.kv( kv[0], str(kv[2]) )
 
             if not _buildsolid( obj, ctx ):
+               libcxr_batch_debug_lines()
+               scene_redraw()
                return {'CANCELLED'}
 
             m.edon()
@@ -1069,22 +1078,61 @@ class CXR_DEV_OPERATOR(bpy.types.Operator):
 
 class CXR_PREVIEW_OPERATOR(bpy.types.Operator):
    bl_idname="convexer.preview"
-   bl_label="Preview"
+   bl_label="Preview Brushes"
+
+   LASTERR = None
+   RUNNING = False
 
    def execute(_,context):
-      libcxr_use()
+      return {'FINISHED'}
+
+   def modal(_,context,event):
+      global debug_gpu_mesh
+      static = _.__class__
+
+      if event.type == 'ESC':
+         libcxr_reset_debug_lines()
+         libcxr_batch_debug_lines()
+         debug_gpu_mesh = None
+         scene_redraw()
+         
+         static.RUNNING = False
+         return {'FINISHED'}
 
+      return {'PASS_THROUGH'}
+
+   def invoke(_,context,event):
+      global debug_gpu_shader, debug_gpu_mesh
+      static = _.__class__
+      static.LASTERR = None
+
+      libcxr_use()
       libcxr_reset_debug_lines()
 
       mesh_src = mesh_cxr_format(context.active_object)
-      world = libcxr_decompose.call( mesh_src )
-      
-      global debug_gpu_shader, debug_gpu_mesh
+
+      err = c_int32(0)
+      world = libcxr_decompose.call( mesh_src, pointer(err) )
 
       if world == None:
          debug_gpu_mesh = None
          libcxr_batch_debug_lines()
-         return {'CANCELLED'}
+         scene_redraw()
+
+         static.LASTERR = ["There is no error", \
+               "Non-Manifold",\
+               "Bad-Manifold",\
+               "No-Candidate",\
+               "Internal-Fail",\
+               "Non-Coplanar",\
+               "Non-Convex Polygon"]\
+               [err.value]
+
+         if static.RUNNING:
+            return {'CANCELLED'}
+         else:
+            context.window_manager.modal_handler_add(_)
+            return {'RUNNING_MODAL'}
       
       ptrpreview = libcxr_world_preview.call( world )
       preview = ptrpreview[0]
@@ -1107,10 +1155,36 @@ class CXR_PREVIEW_OPERATOR(bpy.types.Operator):
 
       libcxr_free_tri_mesh.call( ptrpreview )
       libcxr_free_world.call( world )
-      
       libcxr_batch_debug_lines()
       scene_redraw()
-      return {'FINISHED'}
+
+      if static.RUNNING:
+         return {'CANCELLED'}
+      if not static.RUNNING:
+         static.RUNNING = True
+         context.window_manager.modal_handler_add(_)
+         return {'RUNNING_MODAL'}
+
+class CXR_VIEW3D( bpy.types.Panel ):
+   bl_idname = "VIEW3D_PT_convexer"
+   bl_label = "Convexer"
+   bl_space_type = 'VIEW_3D'
+   bl_region_type = 'UI'
+   bl_category = "Convexer"
+
+   @classmethod
+   def poll(cls, context):
+      return (context.object is not None)
+
+   def draw(_, context):
+      layout = _.layout
+      row = layout.row()
+      row.scale_y = 2
+      row.operator("convexer.preview")
+
+      if CXR_PREVIEW_OPERATOR.LASTERR != None:
+         box = layout.box()
+         box.label(text=CXR_PREVIEW_OPERATOR.LASTERR, icon='ERROR')
 
 class CXR_INTERFACE(bpy.types.Panel):
    bl_label="Convexer"
@@ -1587,7 +1661,8 @@ classes = [ CXR_RELOAD, CXR_DEV_OPERATOR, CXR_INTERFACE, \
             CXR_WRITE_VMF, CXR_MATERIAL_PANEL, CXR_IMAGE_SETTINGS,\
             CXR_MODEL_SETTINGS, CXR_ENTITY_SETTINGS, CXR_CUBEMAP_SETTINGS,\
             CXR_LIGHT_SETTINGS, CXR_SCENE_SETTINGS, CXR_DETECT_COMPILERS,\
-            CXR_ENTITY_PANEL, CXR_LIGHT_PANEL, CXR_PREVIEW_OPERATOR ]
+            CXR_ENTITY_PANEL, CXR_LIGHT_PANEL, CXR_PREVIEW_OPERATOR,\
+            CXR_VIEW3D ]
 
 def register():
    global debug_draw_handler, vmt_param_dynamic_class