3

If I move an object or rotate an object and press Enter to confirm, I would like to trigger a function. Is this possible?

I did research on app handlers and msgbus to no avail. Is msgbus deprecated in Blender 3.4? Because the documentation's sample code is not working for me.

I would like this. For example, pseudocode I'm trying to make:

def on_transform_complete(event):
    print("transform complete/confirmed")

my_object.addEventListener("TRANSFORM_COMPLETE", on_transform_complete)

Here's a similar post using scene_update_post, but it's outdated now and does not work anymore.

I did experiment on bpy.app.handlers.depsgraph_update_post, but the problem is that it keeps updating while dragging object, but I need my update to trigger only exactly once after the drag is confirmed with a final position or rotation or scale. There must be some "complete" event that gets dispatched which I can listen or subscribe to.

Harry McKenzie
  • 10,995
  • 8
  • 23
  • 51

2 Answers2

4

Here is a script that will trigger when I move an object in the 3d View

import bpy

def transformEvent(obj, scene): print('transformEvent')

def on_depsgraph_update(scene): depsgraph = bpy.context.evaluated_depsgraph_get() for update in depsgraph.updates: if update.is_updated_transform: obj= bpy.context.active_object transformEvent(obj, scene)

Make blender call on_depsgraph_update after each

update of Blender's internal dependency graph

bpy.app.handlers.depsgraph_update_post.append(on_depsgraph_update)

james_t
  • 5,446
  • 8
  • 29
  • Hey cool thanks for the new answer. I'll have to check it tomorrow. Does it only trigger once? – Harry McKenzie Jan 08 '23 at 18:51
  • 1
    @HarryMcKenzie -- no it still suffers from being "invoked too often". Might have to set a timer event to then do whatever... ugh! perhaps there's some way to see if LMB is up. – james_t Jan 08 '23 at 18:51
  • oh no :( but it looks like the solution is very close! – Harry McKenzie Jan 08 '23 at 18:53
  • you can get the current operator with bpy.context.active_operator. It's possible the last callback happens when the operator is finished so it will return None otherwise it will point to the transform operator. wild guess :) – Gorgious Jan 08 '23 at 21:41
  • @Gorgious thanks! i think it is impossible since it probably was never implemented by the developers because I've been searching for the answer for several months now. Well at least nobody knows how to do this. I feel that the last resort is to write a bug report in order to reach out to the developers since there is no other way to get this type of information? What do you think? I think that "operation complete" handlers are pretty basic functionality that should have been shipped with the blender python API. – Harry McKenzie Jan 09 '23 at 01:05
  • 2
    I think I found something. Looks hacky though. I'll post an answer – Gorgious Jan 09 '23 at 07:39
  • by the way +1 to both of you for getting me to a "solution" hahaha – Harry McKenzie Jan 09 '23 at 08:05
3

enter image description here

I noticed bpy.context.active_operator returns a pointer to a different location on the last callback to depsgraph_update_post when moving an object with the mouse. It means the test for equality between the two will likely yield False. I don't know how or why but we can leverage that "feature".

enter image description here

I'll piggyback on james_t's answer on this same Q&A.

import bpy

def transformEvent(obj, scene): print('transformEvent')

def on_depsgraph_update(scene): depsgraph = bpy.context.evaluated_depsgraph_get() if on_depsgraph_update.operator is None: on_depsgraph_update.operator = bpy.context.active_operator for update in depsgraph.updates: if not update.is_updated_transform: continue if on_depsgraph_update.operator == bpy.context.active_operator: continue obj = bpy.context.active_object transformEvent(obj, scene) on_depsgraph_update.operator = None

on_depsgraph_update.operator = None

bpy.app.handlers.depsgraph_update_post.append(on_depsgraph_update)

Gorgious
  • 30,723
  • 2
  • 44
  • 101
  • 1
    Hey! i took a look at the pointer as well and didn't notice they were different! i should've paid closer attention haha awesome! – Harry McKenzie Jan 09 '23 at 07:55
  • 1
    wow this hack is the correct solution since there is no other solution thank you sooo much! XD – Harry McKenzie Jan 09 '23 at 07:58
  • 2
    @HarryMcKenzie hehe glad it helped :) – Gorgious Jan 09 '23 at 09:02
  • Something like this should be added to the scripting Templates. I suggest this in rightclickselect https://blender.community/c/rightclickselect/KQ6G -- perhaps vote or comment on this? – james_t Jan 09 '23 at 17:00
  • @james_t agreed ! although it's a bit hacky so I think the devs will say they prefer waiting for an officially designed and supported feature, which may or may not come in our lifetime >< – Gorgious Jan 09 '23 at 17:23
  • @james_t thank you, i've upvoted and my friend as well. – Harry McKenzie Jan 11 '23 at 06:29