I’m writing an add-on that uses sliders in the tool panel to control the values of variables that in turn control the positions of objects in the scene.
Generally, each variable has a specific ‘step’ value that is added or subtracted as the slider is dragged to the left or right:
The problem is, if I zoom out, I want that step value to be larger, so I can move the object farther with a smaller mouse drag. While if I zoom very far in, I want that step value to be very small, so I can move the object with a fine degree of control.
3dbi, thanks for the code! Could you elaborate a little? How could I use the viewport location to alter the step value of a given variable?
The problem is that when I’m zoomed out, having a very tiny step value is inconvenient because the target object moves incredibly slowly across the screen. If I use a larger step value in the code, then the object will move faster across the screen when I drag its slider. But the problem then becomes what happens when I’m zoomed in all the way. At that point, with a super large step value, the object will zip right past me, and I will have no fine-grained control over its position.
Oh hell I think I might have misunderstood you! I just assumed when you said ‘zooming’ you actually meant translating the viewport camera around in 3d space, but now I think you may be taking about changing it’s focal length i.e. it’s lens property. If that’s the case I don’t really know the answer other that to map that one range of values to another (see below) but if on the other hand you do just mean translating the viewport camera around then it’s just basic vector maths.
All you need to do is subtract one vector location from the other and the resulting vector’s magnitude/length will equal the distance between the two objects. If you know the distance from the camera to the object you can then decide what range of distances to map to your step values and then just clamp any distance that exceed this range.
It’s possible that all I need is the value of the “viewport lens angle”. But when I hover over the ‘lens’ slider in the ‘View’ tab of the N-Key panel, blender pops up a helper window with incomplete information.
It says:
“Python: SpaceView3D.lens
bpy.data.screens[“Default”] … lens”
That information doesn’t lead anywhere. If I go to the python console, I get this:
>>> SpaceView3D.lens
Traceback (most recent call last):
File “<blender_console>”, line 1, in <module>
NameError: name ‘SpaceView3D’ is not defined
If I go back to the View tab and rightclick on the ‘lens’ slider, the “Copy Data Path” option is greyed out so I can’t copy the data path.
Right there it says that ‘lens’ is the value I want, but it doesn’t give me any way to access it. At the top of the page it says:
“bpy.types.SpaceView3D(Space)”
So I click on the link to “Space” and it suggests using a value of “VIEW_3D”. Looks right to me, since that’s where I am in blender when I want to use it.
I go back to the python console in blender and try it:
>>> bpy.types.SpaceView3D(VIEW_3D).lens
Traceback (most recent call last):
File “<blender_console>”, line 1, in <module>
NameError: name ‘VIEW_3D’ is not defined
So I’m left with the same frustrating question. After all my research, I still don’t know how to access the lens variable of the viewport.
‘’’
bpy.types contains a list of class types not actually instances of those classes for example :
>>> type(bpy.context.scene)
will print:
<class ‘bpy.types.Scene’>
So bpy.context.scene holds a reference to an instance of the Scene class. In fact it holds a reference to the currently selected/active scene.
If we wanted to get a reference to another scene we would have to use
bpy.data.scenes
Something you may want to try:
In the python console type:
>>> bpy.
and press ctrl+spacebar then type
>>> bpy.data.scree
and press ctrl+spacebar then press ctrl+spacebar again and so on…
You may also want to try, if you haven’t already, Visual Studio Code with Python extension or Eclipse with PyDev. Either one of these free IDE’s will allow you to set breakpoints in your Python scripts then enter debug mode, then when you execute your script in Blender, and the program hits a breakpoint, all the properties and their values within the scope of your executing code will be visible to you.
Although personal I usually just end up using Sublime Text most of the time along with the Blender Python console.
import bpy
class TestExample(bpy.types.Operator):
bl_idname = "view3d.test_example"
bl_label = "Test Example"
@classmethod
def poll(cls, context):
return context.space_data.type == 'VIEW_3D'
def execute(self, context):
space_data = context.space_data
print(dir(space_data))
print(type(space_data))
print('Lens: %s' % space_data.lens)
return{'FINISHED'}
class TestExample2(bpy.types.Operator):
bl_idname = "view3d.test_example2"
bl_label = "Test Example 2"
def execute(self, context):
screen = context.screen
areas = screen.areas
#find all view 3d spaces in the current active screen
spaces_3d = [area.spaces[0] for area in areas if area.type == 'VIEW_3D']
print("
==== %i View 3D Space(s) Found =====" % len(spaces_3d))
for s in spaces_3d:
print("%s.lens = %f
" % (s, s.lens))
#Get the active view 3d space if there is one
active_3d_space = context.area.spaces[0] if context.area.type == 'VIEW_3D' else None
print("active_3d_space: %s" % active_3d_space)
return{'FINISHED'}
def register():
bpy.utils.register_module(__name__)
def unregister():
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
register()