Hi all
Outliner window is able to show active object with the ‘KEYPAD .’ key.
How is it achievabale in python please ?
Happy blending !
Hi all
Outliner window is able to show active object with the ‘KEYPAD .’ key.
How is it achievabale in python please ?
Happy blending !
I believe you are looking for:
bpy.ops.view3d.localview(frame_selected=True)
Thanks for your answer. Am not sure what does
bpy.ops.view3d.localview(frame_selected=True)
as it raises an error in the python console:
Failed, context is incorrect.
The point is that i was not talking about the 3D view but about the outliner window…
well…
I found the
bpy.ops.outliner.show_active()
that should seem to do what i want but it raises an error ( again, context is incorrect )
EDIT: what i understand from the errors is that what i want to do cannot be done in the draw function of a panel…
EDIT2: what i need to do is to show the active object in the outliner window…
Sounds pretty simple to do bu appears to be hell to code^^
Anybody could help please ?
These operators need to be called from within the context of a particular editor (the 3D viewport for bpy.ops.view3d.localview
and the outliner for bpy.ops.outliner.show_active
). It means you want to draw a button linking to this operator in the interface of one of these editors. If you call it from an alternative context (or via code), it will throw an incorrect context error. It is annoying, but it is what it is…
You can override the operator by passing it the correct context, though, but it means getting access to it by other means. If you use these keywords in a search engine you should find some examples.
However by design you shouldn’t call operators or modify any data in a draw
method, this method is only supposed to be used to display data. It is called dozens of time per second, and every time the UI needs refreshing. Most of the data structures of blender objects are locked for edition when you are in the scope of this method.
Could you add a bit of information about your current script so we can try to see how your desired behaviour can fit in it ?
Hi @Gorgious and thanks for your answer.
I slowly understand things in python/blender and this makes sense that the draw function is not intended for doing anything but UI draw.
I then had a look at handlers and found that bpy.app.handlers.depsgraph_update_post would suit my needs.
I then set up a handler on depsgraph_update_post and tried to find some info on context switching.
In my handler func, i wrote this:
def oldshow_active():
override = None
for area in bpy.context.screen.areas:
if 'OUTLINER' in area.type:
for region in area.regions:
if 'WINDOW' in region.type:
override = {'area': area, 'region': region}
break
break
if override is not None:
bpy.ops.outliner.show_active(override)
This works pretty fine with a flag for preventing useless recursion but am told that this method is deprecated. Instead i should use Context.temp_override(…).
Then i tried to replace the func with:
def newshow_active():
areaOverride=bpy.context.area
if bpy.context.area is not None:
if bpy.context.area.type!='OUTLINER':
#If needed find the outliner area
for area in bpy.context.screen.areas:
if area.type == 'OUTLINER':
areaOverride=area
with bpy.context.temp_override(area=areaOverride):
bpy.ops.outliner.show_active(areaOverride)
wich raises errors in the console. I probably don’t know how to use this temp_override function…
Could you please help ?
Thanks and happy blending !
well
I got no idea why this works, but it works:
def show_active():
override = None
for area in bpy.context.screen.areas:
if area.type == 'OUTLINER':
for region in area.regions:
if 'WINDOW' in region.type:
override = {'area': area, 'region': region}
break
break
with bpy.context.temp_override(area=bpy.context.area):
bpy.ops.outliner.show_active(override)
temp_override param is nonsense and as there’s no doc nor info on this i can tell nothing.
If anyone got consistent info on how this works i’d be pleased to read !
Happy blending !
So here’s the full piece of code:
alreadyHere = False
def show_active(scene):
global alreadyHere
if(bpy.context.object.mode == 'EDIT'):
return
if(alreadyHere==False):
alreadyHere=True
override = None
for area in bpy.context.screen.areas:
if area.type == 'OUTLINER':
for region in area.regions:
if 'WINDOW' in region.type:
override = {'area': area, 'region': region}
break
break
with bpy.context.temp_override(area=bpy.context.area):
bpy.ops.outliner.show_active(override)
alreadyHere=False
#==========================================================================================
def add_handler(handlers, func):
c = 0
r = False
for i in handlers:
if i.__name__ == func.__name__:
handlers.remove(handlers[c])
r = True
c += 1
handlers.append(func)
print(("Added" if r == False else "Replaced")+" Handler:", i.__name__)
#==========================================================================================
def register():
add_handler(bpy.app.handlers.depsgraph_update_post, show_active)
f __name__ == "__main__":
register()
The purpose is pretty simple: always center the outliner on the active object ( a feature blender SHOULD have IMHO )
Don’t ask me how and why it works, i got absolutely no idea
Happy blending !
Sounds useful, I’m going to have to try this out
be carefull @joseph !
my script fux-up the loop cut & slide function when in edit mode…
For this problem not to happen you have to check for edit mode in handler and return immediately when edit mode is on
if(bpy.context.object.mode == 'EDIT'):
return
Happy blending !
Hi there back to this lil script that worked perfectly in B3.5 but don’t work anymore in B4.1…
Could anyone please tell me why ?
What changed in 4.1 that generates an error ?
Thanks for your help
wooops got it
It appears ( tho am not sure ) that i used things unproperly
this one:
alreadyHere = False # flag preventing recursion...
def ShowActive(scene):
global alreadyHere
if(bpy.context.object.mode == 'EDIT'):
return
if(alreadyHere==False):
alreadyHere=True
override = None
for foundArea in bpy.context.screen.areas:
if foundArea.type == 'OUTLINER':
for reg in foundArea.regions:
if 'WINDOW' in reg.type:
override = {'area': foundArea, 'region': reg}
break
break
with bpy.context.temp_override(area=foundArea,region=reg):
bpy.ops.outliner.show_active()
alreadyHere=False
works fin in B4.1
Happy blending !