Skip to main content
edited title
Link
Claas Kuhnen
  • 1.8k
  • 4
  • 18
  • 41

Creating empty, translating, snapping 3D cursor How to it, and then deleting empty script issuestructure modal operator correctly with macro like step by step execution?

added 245 characters in body
Source Link
Claas Kuhnen
  • 1.8k
  • 4
  • 18
  • 41

The screencast explains what I try to do very wellstruggle with understanding the modal operator concept. https://drive.google.com/file/d/0Byzv_NlyKp_2Sk5NZEREcE5YZG8/view

Below is my code:

Idea is press a button empty is created user jumps right into translation mode with CTRL you can snap to an object vertex with LMB user places new empty 3D cursor will be set to newly positioned empty empty will be deleted

Everything works right besides the lastchain of commands I would like to steps

It seemsstep by step to me that after I start the transformationexecute, while still being in transformation, Blender already executedduring translate the following steps should wait till translate is done. So I think I need some sort of a break/pause after the transformation and when I LBM the script execution continuesmodal operator structure is needed here.

bl_info = {
    "name": "Fullscreen Modelingbpy.ops.object.select_all(action='DESELECT') Toolbox",
    "author": "Claas Kuhnen",
    "version": (1, 0  bpy.ops.object.empty_add(),
    "blender": (2, 75, 0),
    "location": "View3D > Tools Shelfbpy.ops.transform.translate('INVOKE_DEFAULT')
 > Modeling Toolbox",
    "description": "Fullscreenbpy.ops.view3d.snap_cursor_to_selected()
 Modeling with Access to Object Properties",
  bpy.ops.object.delete()

This is the template I found and understand. I select one object, execute the command which will then get the location and the modal takes over. But I failed to implement my commands into this structure. How can I make the modal aware of that I added the empty and jump into translate.

I understand the confirm and cancel being the states where I can execute the rest after transform or even undo the initial empty generation if need needed.

import bpy


class "warning"ModalOperator(bpy.types.Operator): 
 "Beta - Concepy Study",
bl_idname = "object.modal_operator"
  "category": "User Interface",
}bl_label = "Simple Modal Operator"

import bpy
from bpy.types import Menu,def Panel,__init__(self):
 Operator, UIList
from rna_prop_ui import PropertyPanel
from bl_ui.properties_data_modifier import DATA_PT_modifiersprint("Start")
from 
 bpy.props import *

######################## def __del__(self):
# Operator Definitions #
########################

# Command Snap Origin  print("End")

    
classdef SnapOriginObjectexecute(bpy.types.Operatorself, context):
    bl_idname = "snap.originobject"
 # bpy.ops.object.empty_new()
  bl_label = "Snap Object Origin"
  context.object.location.x = bl_optionsself.value =/ {'REGISTER'}1000.0
        return {'FINISHED'}

    def executemodal(self, context, event):
       
  if event.type == 'MOUSEMOVE':  # Apply
     bpy.ops.object.select_all(action='DESELECT')       self.value = event.mouse_x
        bpy.ops.object    self.empty_addexecute(context)
        elif event.type == 'LEFTMOUSE':  # Confirm
            bpy.ops.transformview3d.translatesnap_cursor_to_selected('INVOKE_DEFAULT')
           x bpy.ops.view3dobject.snap_cursor_to_selecteddelete()
            return {'FINISHED'}
        elif event.type in {'RIGHTMOUSE', 'ESC'}:  # Cancel
            bpy.ops.object.delete(use_global=False)
            return {'CANCELLED'}

        return {'FINISHED''RUNNING_MODAL'} 

    def invoke(self, context, event):
        self.init_loc_x = context.object.location.x
########################        self.value = event.mouse_x
# Interface Definition #     self.execute(context)
########################
        context.window_manager.modal_handler_add(self)
# DATA       return {'RUNNING_MODAL'}


class ObjectData(bpy.types.Panel):
    bl_label = "Object + Mesh Data"
    bl_idname = "ObjectData"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Modeling Toolbox"

    def draw(self, context):
        layout = self.layout

        obj = context.object
  
        row = layout.row()
        self.layout.operator("snap"object.originobject"modal_operator") 



    
def register(): bpy.utils.register_module(__name__)
def unregister(): bpy.utils.unregister_module(__name__)

 
if __name__ == "__main__":
    register()

The screencast explains what I try to do very well. https://drive.google.com/file/d/0Byzv_NlyKp_2Sk5NZEREcE5YZG8/view

Below is my code:

Idea is press a button empty is created user jumps right into translation mode with CTRL you can snap to an object vertex with LMB user places new empty 3D cursor will be set to newly positioned empty empty will be deleted

Everything works right besides the last to steps

It seems to me that after I start the transformation, while still being in transformation, Blender already executed the following steps. So I think I need some sort of a break/pause after the transformation and when I LBM the script execution continues.

bl_info = {
    "name": "Fullscreen Modeling Toolbox",
    "author": "Claas Kuhnen",
    "version": (1, 0),
    "blender": (2, 75, 0),
    "location": "View3D > Tools Shelf > Modeling Toolbox",
    "description": "Fullscreen Modeling with Access to Object Properties",
    "warning": "Beta - Concepy Study",
    "category": "User Interface",
}    

import bpy
from bpy.types import Menu, Panel, Operator, UIList
from rna_prop_ui import PropertyPanel
from bl_ui.properties_data_modifier import DATA_PT_modifiers
from bpy.props import *

########################
# Operator Definitions #
########################

# Command Snap Origin 
    
class SnapOriginObject(bpy.types.Operator):
    bl_idname = "snap.originobject"
    bl_label = "Snap Object Origin"
    bl_options = {'REGISTER'}
        
    def execute(self, context):
       
         bpy.ops.object.select_all(action='DESELECT')       
        bpy.ops.object.empty_add()       
        bpy.ops.transform.translate('INVOKE_DEFAULT')
        bpy.ops.view3d.snap_cursor_to_selected()
        bpy.ops.object.delete()

        return{'FINISHED'}
   

########################
# Interface Definition #
########################

# DATA 
class ObjectData(bpy.types.Panel):
    bl_label = "Object + Mesh Data"
    bl_idname = "ObjectData"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Modeling Toolbox"

    def draw(self, context):
        layout = self.layout

        obj = context.object
  
        row = layout.row()
        self.layout.operator("snap.originobject")

def register(): bpy.utils.register_module(__name__)
def unregister(): bpy.utils.unregister_module(__name__)

 
if __name__ == "__main__":
    register()

I struggle with understanding the modal operator concept. Below is a chain of commands I would like to step by step to execute, while during translate the following steps should wait till translate is done. So a modal operator structure is needed here.

        bpy.ops.object.select_all(action='DESELECT')       
        bpy.ops.object.empty_add()       
        bpy.ops.transform.translate('INVOKE_DEFAULT')
        bpy.ops.view3d.snap_cursor_to_selected()
        bpy.ops.object.delete()

This is the template I found and understand. I select one object, execute the command which will then get the location and the modal takes over. But I failed to implement my commands into this structure. How can I make the modal aware of that I added the empty and jump into translate.

I understand the confirm and cancel being the states where I can execute the rest after transform or even undo the initial empty generation if need needed.

import bpy


class ModalOperator(bpy.types.Operator): 
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"

    def __init__(self):
        print("Start")
 
    def __del__(self):
        print("End")

    def execute(self, context):
       # bpy.ops.object.empty_new()
        context.object.location.x = self.value / 1000.0
        return {'FINISHED'}

    def modal(self, context, event):
        if event.type == 'MOUSEMOVE':  # Apply
            self.value = event.mouse_x
            self.execute(context)
        elif event.type == 'LEFTMOUSE':  # Confirm
            bpy.ops.view3d.snap_cursor_to_selected()
           x bpy.ops.object.delete()
            return {'FINISHED'}
        elif event.type in {'RIGHTMOUSE', 'ESC'}:  # Cancel
            bpy.ops.object.delete(use_global=False)
            return {'CANCELLED'}

        return {'RUNNING_MODAL'} 

    def invoke(self, context, event):
        self.init_loc_x = context.object.location.x
        self.value = event.mouse_x
        self.execute(context)

        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}


class ObjectData(bpy.types.Panel):
    bl_label = "Object + Mesh Data"
    bl_idname = "ObjectData"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Modeling Toolbox"

    def draw(self, context):
        layout = self.layout

        obj = context.object
  
        row = layout.row()
        self.layout.operator("object.modal_operator") 



    
def register(): bpy.utils.register_module(__name__)
def unregister(): bpy.utils.unregister_module(__name__)

 
if __name__ == "__main__":
    register()
deleted 156 characters in body
Source Link
zeffii
  • 39.9k
  • 9
  • 106
  • 189
bl_info = {
    "name": "Fullscreen Modeling Toolbox",
    "author": "Claas Kuhnen",
    "version": (1, 0),
    "blender": (2, 75, 0),
    "location": "View3D > Tools Shelf > Modeling Toolbox",
    "description": "Fullscreen Modeling with Access to Object Properties",
    "warning": "Beta - Concepy Study",
    "category": "User Interface",
}    

import bpy
 
from bpy.types import (
        Panel,
        Menu,
        Operator,
        )
from bpy.types import MenuPanel, PanelOperator, UIList
from rna_prop_ui import PropertyPanel
from bl_ui.properties_data_modifier import DATA_PT_modifiers
from bpy.props import *

########################
# Operator Definitions #
########################

# Command Snap Origin 




 
    
class SnapOriginObject(bpy.types.Operator):
    bl_idname = "snap.originobject"
    bl_label = "Snap Object Origin"
    bl_options = {'REGISTER'}
        
    def execute(self, context):
       
        bpy.ops.object.select_all(action='DESELECT')       
        bpy.ops.object.empty_add()       
        bpy.ops.transform.translate('INVOKE_DEFAULT')
        bpy.ops.view3d.snap_cursor_to_selected()
        bpy.ops.object.delete()

        return{'FINISHED'}
   

########################
# Interface Definition #
########################

# DATA 
class ObjectData(bpy.types.Panel):
    bl_label = "Object + Mesh Data"
    bl_idname = "ObjectData"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Modeling Toolbox"

    def draw(self, context):
        layout = self.layout

        obj = context.object
  
        row = layout.row()
        self.layout.operator("snap.originobject")


 
# END     
def register(): bpy.utils.register_module(__name__)
def unregister(): bpy.utils.unregister_module(__name__)

 
if __name__ == "__main__":
    register()
bl_info = {
    "name": "Fullscreen Modeling Toolbox",
    "author": "Claas Kuhnen",
    "version": (1, 0),
    "blender": (2, 75, 0),
    "location": "View3D > Tools Shelf > Modeling Toolbox",
    "description": "Fullscreen Modeling with Access to Object Properties",
    "warning": "Beta - Concepy Study",
    "category": "User Interface",
}    

import bpy
 
from bpy.types import (
        Panel,
        Menu,
        Operator,
        )
from bpy.types import Menu, Panel, UIList
from rna_prop_ui import PropertyPanel
from bl_ui.properties_data_modifier import DATA_PT_modifiers
from bpy.props import *

########################
# Operator Definitions #
########################

# Command Snap Origin 




 

class SnapOriginObject(bpy.types.Operator):
    bl_idname = "snap.originobject"
    bl_label = "Snap Object Origin"
    bl_options = {'REGISTER'}
        
    def execute(self, context):
       
        bpy.ops.object.select_all(action='DESELECT')       
        bpy.ops.object.empty_add()       
        bpy.ops.transform.translate('INVOKE_DEFAULT')
        bpy.ops.view3d.snap_cursor_to_selected()
        bpy.ops.object.delete()

        return{'FINISHED'}
   

########################
# Interface Definition #
########################

# DATA 
class ObjectData(bpy.types.Panel):
    bl_label = "Object + Mesh Data"
    bl_idname = "ObjectData"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Modeling Toolbox"

    def draw(self, context):
        layout = self.layout

        obj = context.object
  
        row = layout.row()
        self.layout.operator("snap.originobject")


 
# END     
def register(): bpy.utils.register_module(__name__)
def unregister(): bpy.utils.unregister_module(__name__)

 
if __name__ == "__main__":
    register()
bl_info = {
    "name": "Fullscreen Modeling Toolbox",
    "author": "Claas Kuhnen",
    "version": (1, 0),
    "blender": (2, 75, 0),
    "location": "View3D > Tools Shelf > Modeling Toolbox",
    "description": "Fullscreen Modeling with Access to Object Properties",
    "warning": "Beta - Concepy Study",
    "category": "User Interface",
}    

import bpy
from bpy.types import Menu, Panel, Operator, UIList
from rna_prop_ui import PropertyPanel
from bl_ui.properties_data_modifier import DATA_PT_modifiers
from bpy.props import *

########################
# Operator Definitions #
########################

# Command Snap Origin 
    
class SnapOriginObject(bpy.types.Operator):
    bl_idname = "snap.originobject"
    bl_label = "Snap Object Origin"
    bl_options = {'REGISTER'}
        
    def execute(self, context):
       
        bpy.ops.object.select_all(action='DESELECT')       
        bpy.ops.object.empty_add()       
        bpy.ops.transform.translate('INVOKE_DEFAULT')
        bpy.ops.view3d.snap_cursor_to_selected()
        bpy.ops.object.delete()

        return{'FINISHED'}
   

########################
# Interface Definition #
########################

# DATA 
class ObjectData(bpy.types.Panel):
    bl_label = "Object + Mesh Data"
    bl_idname = "ObjectData"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Modeling Toolbox"

    def draw(self, context):
        layout = self.layout

        obj = context.object
  
        row = layout.row()
        self.layout.operator("snap.originobject")

def register(): bpy.utils.register_module(__name__)
def unregister(): bpy.utils.unregister_module(__name__)

 
if __name__ == "__main__":
    register()
added 259 characters in body
Source Link
Claas Kuhnen
  • 1.8k
  • 4
  • 18
  • 41
Loading
added 331 characters in body; edited title
Source Link
Claas Kuhnen
  • 1.8k
  • 4
  • 18
  • 41
Loading
Source Link
Claas Kuhnen
  • 1.8k
  • 4
  • 18
  • 41
Loading