How to use alternate user inputs and automation

I watched the modal operators templates, other modal add-ons too, but I couldn’t reach what I want.
I would like my script to do the following easy 4 steps :
Automation : Create an empty
User input : move it with snapping on (user choose the new location)
Automation : when the empty is placed (left-click from user), execute an operator and change some parameter (like snaping mode, etc…)
User Input : then move the originally selected object (user define new location again)

If it’s too long to describe how to really do it, at least some explanation on how to alternate between automation and user input, then automation, then user input, etc…

i can’t see the actual purpose of your desired script, isn’t that basically moving objects with snapping activated?

@CodemanX I simplified my goal to make it clearer. If I explained everithing I want in my plug-in, I could write many pages. Solution is nearly done here : http://blender.stackexchange.com/questions/3032/alternate-between-user-input-and-automation-in-one-step-script

Often times we even wear bracelets without even thinking about it. An easy example of this is a for medical and identification purposes,www.vincentgallo.com/writing/TheAnthony.html, such as name tags, and health conditions in a hospital. One of the first major fads of braclets to move through was in the 1980’s, with ‘snap bracelets’. Though most of us had collections when we were young,http://www.red-raspberry.org/procession.asp, a Scientific American article says that children might “reveal a proclivity to hoarding in their emotions.” Attachments can manifest in a few ways. Dr. Perot names a few examples: "Someone might feel guilty about discarding an old toy for fear that he is hurting the toy’s feelings. College presidents will meet a worse fate. Led to believe that they are summoned to an Important Meeting with Administration Officials to have a rational discussion of the proposed new rating system, they will be herded into the subterranean ballroom of the Hyatt Regency on Capitol Hill where they will be subjected to hours of powerpoint presentations by Education Consultants. They will run out screaming that they are late for drinks with donors at the Hay Adams. 3, 2013,nike air max tn, in New York. Open tennis tournament, Tuesday, Sept. 3, 2013,isabel marant sneakers, in New York. Its as if they were still six to eight years old and never grew up. Why do you have people who not only wear their pants that are falling so far down they are almost at their knees? Is it to show off their small buts? Their small private parts? To let you know their wearing underclothing? Why do guys wear sports jerseys to non sporting events? Is it to highlight how far they are from actually playing that sport,air max 1 pas cher, or any other sport for that matter? Not to forget the ladies now. How low are you going to wear “hiphuggers” with the bare midriff? Will it end when the tops are below the hip area and to the thighs,jeremy scott bear pas cher, somewhere between the knee and the crotch? Bad taste is all around us. A very sweet,nike air max 1 pas cher, and a good girl. Shortly after,nike air max, knowing her for 3 weeks, she goes back home overseas. Her and her best friend were crying when they left at the airport. While many highprofile women admonish them (ahem,www.vincentgallo.com/intro_links.html, Sarah Jessica Parker, Arianna Huffington),new balance homme, some stars like Kate Upton are adept at multitasking in perilous pumps. We’ll admit that high heels offer an enviable boost to height, glamour and confidence so much so that it often seems celebs don’t want to take their magic footwear off. Bicycle race? Beach trip? Some of our favorite ladies sport the shoes through it all. Mathieu was dismissed from the LSU team on Aug. 10 for repeated positive drug tests for marijuana. He was in a drug rehabilitation facility in Houston for nearly three weeks before returning to LSU. I believe the debate is more nuanced but everyone is lined up at opposite sides of the room.June 13, 2013 at 5:48 pm Report abuse Your right,nike blazer vintage pas cher, what the lady did to save her and her husband is why we have guns. But I want you to put this on a grant view now. The USA has been attack, they are here,nike air jordan pas cher, they have beat our military back, and the cops are fighting for there lives. ???: beautyful of course who are freezing cold a new creation. A child of God teddy bears

I second this question!
I too had problems to make a script activate the translate operator and then give the control of using it to the user. What it always did is perform the translation by itself or doing nothing. I ve noticed that it is possible to activate it in such a way from a menu, when a button pressed activates the transform.translate, but when I try to make a script do that after lets say, adding an empty, it doesn’t work…
Any help?

@CoDEmanX Could you check the stackexchange link above ? Lukas is not checking it’s answer anymore I think. He nearly solved the problem I suppose, but the script is buggy. Maybe you could find a fix for it ?

@CoDEmanX Thanks for the fast reply. I tried your script and it was almost what I need :slight_smile: The good thing is that it uses the border select in the way I mentioned, but the event ignoring is a problem. I don’t believe that hack would be possible in case of all modal operators… We really have to learn how to use them properly…
I also took a second look at matali’s link, and the ansver he received really seams to adress the matter, except I didn’t manage to get the thing moving in Blender… I pasted the script to the text editor and hit run script but nothing happened. I must be missing something obvious… :frowning: 2.68, Linux Mint

Posted a modified script:

Okavango: run script, then go to View 3D, hit spacebar an find the “Translate Cursor” macro!

Guys, you made my day :slight_smile:

Lukas’ script does handover an eror ‘previous object not found’, but his macro system is a breakthrough!
CoDEmanX, thanx for the instructions, your script is running flawlessly, and your snapping system is better managed. Also thanks for the two sript-editing addons from yesterday, i’ll be on your tail :slight_smile:

I am a bit rusty with coding, but hopefully I will have something to present in few days…

Ok, i gave it a shot… trying to understand the way macros work i made a minimal script that gives no errors (first attachment). The second one is the operator i was going for, and it works. The only problem is that i am not sure how to make it an installable addon, the user preferences/addon dialog is giving me errors. I add the standard bl_info, but it complains about storage class and other stuff. It works from the text editor… If someone can help, that would be great…

Attachments

macros_UserNonUser_minimal.py.zip (632 Bytes)NP_Anchor_Translate_002.zip (899 Bytes)

I’m happy to hear, that I’m not alone having this error “previous object not found” ! My report was refused on the tracker, I made a copy paste error on the report, but I tried it again and with everything copied, it works on windows but not linux. Maybe you could report as well Okavango ?
For the macro as addon, I couldn’t find a solution, sorry, but yes, would be interesting.

Okavango: there’s no bl_info block in your scripts, and what you provided works from text editor. What’s the exact error message you get?

Sorry CoDEmanX, here is the anchor_tranlate script with the bl-info block, exactly as i tried to install it. It would be nice if this script would be registered as an operator automaticly, so it could have it’s own shortcut.

What this script is supposed to do is to let user translate selected objects in CAD style, with start and end points (i called them anchor and target). You select the objects, start the anchor_translate operator, choose the anchor point holding ctrl for snap and move the objects in regard to the anchor point, again with snap. This was a feature i was missing from the Grab function, and saves a step or two in the modelling process…

In this version i added a small improvement, the anchor point appears directly under the mouse pointer, which is helpful when choosing an arbitrary point in 3d space. I used the 3Dcursor operator. Although, i didn’t manage to retrieve the 3Dcursor to its original location…

@matali: yes, on linux i was getting that “previous object not found” error when using lukas’ script, but CoDEmanX fixed it, and now i can use the macros fine. Why exactly do you insist on that glitch, do you intend to use that specific code?

Attachments

NP_anchor_translate_003.py.zip (1.13 KB)

Error msg is:

snap_element = bpy.context.tool_settings.snap_element

AttributeError: ‘_RestrictContext’ object has no attribute ‘tool_settings’

As I use that class with static members only, it definately tries to access bpy.context instantly when script is executed. If that happens during addon registration, it will fail of course. See: http://wiki.blender.org/index.php/Extensions:2.6/Py/API_Changes#Restricted_Context

Corrected (also registeration):

bl_info={
  "name":"NP_Anchor_Translate",
  "author":"Okavango with help of Lukas, CoDEmanX, matali",
  "version":(0,0,3),
  "blender":(2,68,0),
  "location":"View3D",
  "description":"Translate objects with anchor and target points - install, assign shortcut, save user settings",
  "category":"3D View"}

import bpy

class AnchorTranslate(bpy.types.Macro):
    bl_idname = "object.add_empty_and_translate"
    bl_label = "Anchor Translate"
    bl_options = {'REGISTER', 'UNDO'}

class Storage:
    ob = None
    anchor = None
    
    # Can't access bpy.context during addon registration, use some default values
    snap_element = 'INCREMENT' #bpy.context.tool_settings.snap_element
    snap_target = 'CLOSEST' #bpy.context.tool_settings.snap_target
    
    cl = None
    print('first',cl)
    
class StoreSelectedObjects(bpy.types.Operator):
    bl_idname = "object.store_selected"
    bl_label = "Store Selected Objects"
    
    def execute(self, context):
        Storage.ob=bpy.context.selected_objects
        ob=bpy.context.selected_objects
        for o in ob:
            o.select = False
        Storage.cl=bpy.context.scene.cursor_location
        cl=Storage.cl
        print('second',cl)
        return {'FINISHED'}
    
class AddAnchor(bpy.types.Operator):
    bl_idname = "object.add_anchor"
    bl_label = "Add Anchor"
    
    def execute(self, context):
        bpy.ops.mesh.primitive_cube_add(enter_editmode = True)
        bpy.ops.mesh.select_all
        bpy.ops.mesh.delete(type ='VERT')
        bpy.ops.object.mode_set(mode='OBJECT')
        
        Storage.anchor = bpy.context.object
        
        ts = bpy.context.tool_settings
        Storage.snap_element = ts.snap_element
        Storage.snap_target = ts.snap_target
        
        ts.snap_element = 'VERTEX'
        ts.snap_target = 'ACTIVE'
        return {'FINISHED'}
    
class ReselectStoredObjects(bpy.types.Operator):
    bl_idname = "object.reselect_stored"
    bl_label = "Reselect Stored Objects"
    
    def execute(self, context):
        ob=Storage.ob
        for o in ob:
            o.select = True
        return {'FINISHED'}
    
class DeselectReselectAnchor(bpy.types.Operator):
    bl_idname = "object.deselect_reselect_anchor"
    bl_label = "Deselect Reselect Anchor"
    
    def execute(self, context):
        anchor=Storage.anchor
        anchor.select = False # what is this for?
        anchor.select = True
        return {'FINISHED'}
    
class DeselectStoredObjects(bpy.types.Operator):
    bl_idname = "object.deselect_stored"
    bl_label = "Deselect Stored Objects"
    
    def execute(self, context):
        ob=Storage.ob
        for o in ob:
            o.select = False
        return {'FINISHED'}
    
class DeleteAnchor(bpy.types.Operator):
    bl_idname = "object.delete_anchor"
    bl_label = "Delete Anchor"

    def execute(self, context):
        bpy.ops.object.delete('EXEC_DEFAULT')
        
        ts = bpy.context.tool_settings
        ts.snap_element = Storage.snap_element
        ts.snap_target = Storage.snap_target
        cl=Storage.cl
        print('third',cl)
        return {'FINISHED'}

def register():
    bpy.utils.register_module(__name__)
    
    AnchorTranslate.define("OBJECT_OT_store_selected")
    AnchorTranslate.define("VIEW3D_OT_cursor3d")
    AnchorTranslate.define("OBJECT_OT_add_anchor")
    AnchorTranslate.define("TRANSFORM_OT_translate")
    AnchorTranslate.define("OBJECT_OT_reselect_stored")
    AnchorTranslate.define("OBJECT_OT_deselect_reselect_anchor")
    AnchorTranslate.define("TRANSFORM_OT_translate")
    AnchorTranslate.define("OBJECT_OT_deselect_stored")
    AnchorTranslate.define("OBJECT_OT_delete_anchor")
    AnchorTranslate.define("OBJECT_OT_reselect_stored")

def unregister():
    bpy.utils.unregister_module(__name__)
    
if __name__ == "__main__":
    register()


I extended the script to work like how you described (or what I understood), hope you don’t mind :slight_smile:

http://www.pasteall.org/46022/python

Of course I don’t mind CoDEmanX, you are always welcome :slight_smile:

Hahaha, Elevator Translate! Great! Not exactly what I had in mind, but it is great to see what you made of it! You just gave me a research homework to do :smiley:
Although I am not quite sure yet what this one could be used for, it definitely has potential and it’s packed with some new things for me.
Thanks for the inline explanations and links, it is very helpful! The addon is working like a charm.

You had a good hunch that there will be a 005 version - in order to try to resolve my cursor problems while waiting, I too made a shot with dummy objects, but yours is much more elegant :slight_smile: I even succeded, but now i am embarased to present it :smiley:

Anyway, i attached it as 005, with your addon code incorporated, just so you could see the general idea (it is way simpler than you anticipated :slight_smile: In order to apreciate it, try moving yor selection and just snapping it to something else… I will try to make the 007 combine the best of them, I think i have enough info now to make the next step. Thank you very much for your effort!

p.s. hehe, 007…

Attachments

NP_anchor_translate_005_pluged_in.py.zip (1.19 KB)

xD oh well, yours seems to be much more useful. Mine could use another snapping with empty object instead of placing 3d cursor at mouse position in the beginning, then both would be useful for their purpose - yours for relative translate, mine for parallel shift on the initially set-up axis.

Something similar could be done for rotation, just like in Google SketchUp!

BTW: if you abort while in modal translation, macro will terminate and leave behind the helper objects. Asked Campbell and he says there’s no way to detect that “event”. And that’s true, i can detect the init by wrapping the translate operator, but it doesn’t work for the esc/end (those events seem to occur on run script).

bl_info={
  "name":"NP Anchor Translate 005",
  "author":"Okavango with CoDEmanX, Lukas, matali",
  "version":(0,0,5),
  "blender":(2,68,0),
  "location":"View3D",
  "description":"Translate objects with anchor and target points - install, assign shortcut, save user settings",
  "category":"3D View"}

import bpy
print("-"*30)
class AnchorTranslate(bpy.types.Macro):
    bl_idname = "object.add_empty_and_translate"
    bl_label = "Anchor Translate"
    bl_options = {'REGISTER', 'UNDO'}
    
    def __init__(self, *args, **kwargs):
        print("INIT MACRO")
    def __del__(self, *args, **kwargs):
        print("DEL MACRO")
        
    __delattr__ = __del__
    __delitem__ = __del__
    __new__ = __init__

class Storage:
    snap_element = None
    snap_target = None
    
class StoreSelectedObjects(bpy.types.Operator):
    bl_idname = "object.store_selected"
    bl_label = "Store Selected Objects"
    bl_options = {'REGISTER', 'UNDO'}    
    def execute(self, context):
        Storage.ob=bpy.context.selected_objects
        ob=bpy.context.selected_objects
        for o in ob:
            o.select = False
        Storage.snap_element = bpy.context.tool_settings.snap_element
        Storage.snap_target = bpy.context.tool_settings.snap_target
        return {'FINISHED'}

class AddCursorDummy(bpy.types.Operator):
    bl_idname = "object.add_cursor_dummy"
    bl_label = "Add Cursor Dummy"
    bl_options = {'REGISTER', 'UNDO'}    
    def execute(self, context):
        bpy.ops.mesh.primitive_cube_add()
        Storage.dummy = bpy.context.object
        return {'FINISHED'}
    
class AddAnchor(bpy.types.Operator):
    bl_idname = "object.add_anchor"
    bl_label = "Add Anchor"
    bl_options = {'REGISTER', 'UNDO'}    
    def execute(self, context):
        bpy.ops.mesh.primitive_cube_add(enter_editmode = True)
        bpy.ops.mesh.select_all
        bpy.ops.mesh.delete(type ='VERT')
        bpy.ops.object.mode_set(mode='OBJECT')
        Storage.anchor = bpy.context.object
        bpy.context.tool_settings.snap_element = 'VERTEX'
        bpy.context.tool_settings.snap_target = 'ACTIVE'
        return {'FINISHED'}
    
class ActivateDummy(bpy.types.Operator):
    bl_idname = "object.activate_dummy"
    bl_label = "Activate Dummy"
    bl_options = {'REGISTER', 'UNDO'}
    def execute(self, context):
        obdm=Storage.dummy
        bpy.context.scene.objects.active = obdm
        return {'FINISHED'}
class ActivateAnchor(bpy.types.Operator):
    bl_idname = "object.activate_anchor"
    bl_label = "Activate Anchor"
    bl_options = {'REGISTER', 'UNDO'}    
    
    def execute(self, context):
        oban=Storage.anchor
        bpy.context.scene.objects.active = oban
        oban.select = False
        obdm=Storage.dummy
        obdm.select = True
        bpy.ops.object.delete('EXEC_DEFAULT')
        oban.select = True
        return {'FINISHED'}
    
class ReselectStoredObjects(bpy.types.Operator):
    bl_idname = "object.reselect_stored"
    bl_label = "Reselect Stored Objects"
    bl_options = {'REGISTER', 'UNDO'}    
    
    def execute(self, context):
        ob=Storage.ob
        for o in ob:
            o.select = True
        return {'FINISHED'}
    
class DeselectStoredObjects(bpy.types.Operator):
    bl_idname = "object.deselect_stored"
    bl_label = "Deselect Stored Objects"
    bl_options = {'REGISTER', 'UNDO'}    
    def execute(self, context):
        ob=Storage.ob
        for o in ob:
            o.select = False
        return {'FINISHED'}
    
class DeleteAnchor(bpy.types.Operator):
    bl_idname = "object.delete_anchor"
    bl_label = "Delete Anchor"
    bl_options = {'REGISTER', 'UNDO'}
    def execute(self, context):
        bpy.ops.object.delete('EXEC_DEFAULT')
        bpy.context.tool_settings.snap_element = Storage.snap_element
        bpy.context.tool_settings.snap_target = Storage.snap_target
        return {'FINISHED'}

class TT(bpy.types.Operator):
    bl_idname = "object.tt"
    bl_label = "tt wrap"
    bl_options = {'REGISTER', 'UNDO'}
    
    def __init__(self):
        print("INIT TT")
        
    def __del__(self):
        print("DEL TT")
        
    __delattr__ = __del__
    __delitem__ = __del__
    __new__ = __init__
        
    def invoke(self, context, event):
        bpy.ops.transform.translate('INVOKE_DEFAULT')
        return {'FINISHED'}


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

  AnchorTranslate.define("OBJECT_OT_store_selected")
  AnchorTranslate.define("OBJECT_OT_add_cursor_dummy")
  AnchorTranslate.define("VIEW3D_OT_cursor3d")
  AnchorTranslate.define("OBJECT_OT_add_anchor")
  AnchorTranslate.define("OBJECT_OT_activate_dummy")
  AnchorTranslate.define("VIEW3D_OT_snap_cursor_to_active")
  AnchorTranslate.define("OBJECT_OT_activate_anchor")
  AnchorTranslate.define("TRANSFORM_OT_translate")
  AnchorTranslate.define("OBJECT_OT_reselect_stored")
  AnchorTranslate.define("OBJECT_OT_tt")
  #AnchorTranslate.define("TRANSFORM_OT_translate")
  AnchorTranslate.define("OBJECT_OT_deselect_stored")
  AnchorTranslate.define("OBJECT_OT_delete_anchor")
  AnchorTranslate.define("OBJECT_OT_reselect_stored")

def unregister():
  bpy.utils.unregister_module(__name__)
       
if __name__ == "__main__":
  register()

Hi CoDEmanX, i checked your Elevator Translate, as i call it, and it’s atcually brilliant in rotating/tracking the helper :slight_smile: I will have to spend some more time on studying it…

Yeah, you are right about the helper object dumping, it’s is something i expected to be the case, thanks for trying to get the hang of it. I guess that i will just have to introduce another operator that would go after the standard ones and sweep the leftovers :slight_smile: Or something like that…

Anyway, i come from the architecture design business, and i really rely on speed in my work. Blender is not quite optimised for cubelike-object manipulation, as some 3D apps that you’ ve mentioned. That is what i would like my NP-series to address. You are totally right about the rotation operator, i was thinking of upgrading it too. However, that will require some coding-skill upgrade on my side, which i am doing right now :slight_smile:

Here is a nifty challenge… CAGE SCALE :slight_smile: Imagine you scale objects vith some kind of bgl cage that appears around the selection when you activate the operator. A cage with some handles and with posibbility of rotating around the selection for better fit. I am planning of giving it a shot sometime, and I am relying on you guys for the supervision :slight_smile:

As there are many ideas for operator upgrades, another important thing comes to my mind. What about copyright?
Is it legal to actualy emulate the functions we saw in another applications? I know there is for example, the pie menu system that people emulate here… Let’s say there are some comercial applications (as there are :slight_smile: that have good manipulators and commands and you want to replicate their efficiency in Blender. Is it legal? Is only the code behind them coprighted or could there be problems using actual CONCEPTS, like their UI procedures/elements or shorcut systems? For example, the basepoint/destinationpoint procedure is from AutoCAD and i find it to be very useful for precision displacing. Do you have any information or know who could i talk to about this?

@Okavango Please report that Luka’s version also crash on your computer. The report is here : https://projects.blender.org/tracker/index.php?func=detail&aid=36857&group_id=9&atid=498 . What Distrib do you use ?

Cage scale - isn’t that like a 2x2 lattice deformation?

Or should the sides of the cage stay axis-aligned?

I’m not a lawyer, but AFAIK you can’t copyrigt concepts in general.

Here’s an exception however: