0

if I want these classes to be called by other plugins, like Pie Menu Editor addon, What code should I add?

enter image description here

import bpy

class Cam_Base(bpy.types.Operator): bl_idname = "cam.base" bl_label = "Cam Base" cam_name = "C_"

def execute(self, context):
    C = bpy.context

    # lock cam
    bpy.context.object.lock_scale = (True, True, True)
    bpy.context.object.lock_rotation = (True, True, True)
    bpy.context.object.lock_location = (True, True, True)

    # select cam
    bpy.context.space_data.camera = bpy.data.objects[self.cam_name]

    # Select Active Cam
    for area in C.screen.areas:
        if area.type == 'VIEW_3D':
            A = C.area.spaces.active.camera

    bpy.context.scene.camera = bpy.data.objects[A.name]

    bpy.context.space_data.shading.color_type = 'OBJECT'
    bpy.context.space_data.region_3d.view_perspective = 'CAMERA'

#############Supplementary Code################ #Modify camera attributes bpy.data.objects[A.name].lock_scale[0] = True bpy.data.objects[A.name].lock_scale[1] = True bpy.data.objects[A.name].lock_scale[2] = True bpy.data.objects[A.name].lock_location[0] = True bpy.data.objects[A.name].lock_location[1] = True bpy.data.objects[A.name].lock_location[2] = True bpy.data.objects[A.name].lock_rotation[0] = True bpy.data.objects[A.name].lock_rotation[1] = True bpy.data.objects[A.name].lock_rotation[2] = True bpy.data.objects[A.name].scale[0] = 1 bpy.data.objects[A.name].scale[1] = 1 bpy.data.objects[A.name].scale[2] = 1 bpy.data.cameras[A.name].display_size = 0.05 bpy.data.cameras[A.name].background_images[0].alpha = 0 bpy.data.cameras[A.name].dof.use_dof = False bpy.data.cameras[A.name].clip_start = 25 bpy.data.cameras[A.name].clip_end = 100000 bpy.data.cameras[A.name].background_images[0].scale = 1 bpy.data.cameras[A.name].background_images[1].scale = 1 bpy.data.cameras[A.name].background_images[2].scale = 1

    bpy.ops.view3d.view_center_camera()
    bpy.ops.image.reload()

    #select camera as active objcet in object mode
    if bpy.context.object.mode == 'OBJECT':
        bpy.ops.object.select_all(action='DESELECT')
        objectToSelect = bpy.data.objects[A.name]
        objectToSelect.select_set(True)
        bpy.context.view_layer.objects.active = objectToSelect

#############Supplementary Code################ return {'FINISHED'}

class Cam_0V0(Cam_Base): bl_idname = "cam.0v0" bl_label = "Cam_0V0" cam_name = "C_0V0"

class Cam_0V1(Cam_Base): bl_idname = "cam.0v1" bl_label = "Cam_0V1" cam_name = "C_0V1"

class Cam_0V2(Cam_Base): bl_idname = "cam.0v2" bl_label = "Cam_0V2" cam_name = "C_0V2"

addon_keymaps = []

def register(): bpy.utils.register_class(Cam_Base) bpy.utils.register_class(Cam_0V0) bpy.utils.register_class(Cam_0V1) bpy.utils.register_class(Cam_0V2)

def unregister(): bpy.utils.unregister_class(Cam_Base) bpy.utils.unregister_class(Cam_0V0) bpy.utils.unregister_class(Cam_0V1) bpy.utils.unregister_class(Cam_0V2)

if name == "main": register()

lee blues
  • 121
  • 7
  • AFAIK it won't work if you use inheritance in that way. An operator class must inherit directly from bpy.types.Operator to correctly register. It's a quirk of the API. You can use composition though, and inherit from Operator and another class – Gorgious Apr 20 '23 at 06:22
  • So how do I change the code? – lee blues Apr 20 '23 at 07:34
  • make Cam_Base a base class (no inheritance) and define your child classes with Cam_0V0(Cam_Base, bpy.types.Operator):. Note that you won't be able to register Cam_Base – Gorgious Apr 20 '23 at 07:37

1 Answers1

0

You need to use context overrides. In this example, I added your operator buttons into the header of the Python Console:

import bpy

class Cam_Base(): bl_idname = "cam.base" bl_label = "Cam Base" cam_name = "C_"

def execute(self, context):
    area_type = 'VIEW_3D'
    areas = [area for area in bpy.context.window.screen.areas if area.type == area_type]

    if len(areas) <= 0:
        raise Exception(f"Make sure an Area of type {area_type} is open or visible in your screen!")

    with bpy.context.temp_override(area=areas[0]):        
        c = bpy.context
        c.object.lock_scale = (True, True, True)
        c.object.lock_rotation = (True, True, True)
        c.object.lock_location = (True, True, True)
        c.space_data.camera = bpy.data.objects[self.cam_name]
        c.scene.camera = bpy.data.objects[self.cam_name]

    return {'FINISHED'}


class Cam_0V0(bpy.types.Operator, Cam_Base): bl_idname = "cam.cam0" bl_label = "Cam_0V0" cam_name = "C_0V0"

class Cam_0V1(bpy.types.Operator, Cam_Base): bl_idname = "cam.cam1" bl_label = "Cam_0V1" cam_name = "C_0V1"

class Cam_0V2(bpy.types.Operator, Cam_Base): bl_idname = "cam.cam2" bl_label = "Cam_0V2" cam_name = "C_0V2"

class Info_Head(bpy.types.Header): bl_space_type = 'INFO'

def draw(self, context):
    self.layout.operator("cam.cam0")
    self.layout.operator("cam.cam1")
    self.layout.operator("cam.cam2")

bpy.types.CONSOLE_HT_header.prepend(draw)


addon_keymaps = []

def register(): bpy.utils.register_class(Cam_0V0) bpy.utils.register_class(Cam_0V1) bpy.utils.register_class(Cam_0V2)

def unregister(): bpy.utils.unregister_class(Cam_0V0) bpy.utils.unregister_class(Cam_0V1) bpy.utils.unregister_class(Cam_0V2)

if name == "main": register()

Harry McKenzie
  • 10,995
  • 8
  • 23
  • 51
  • 1
    You are wonderful! But I missed a piece of code before, how to add this piece of code to the new code, can you help me to simplify and standardize this code, the new code is in between #Supplementary Code# and #Supplementary Code# I tried it myself to add but it reported an error, so I'll have to ask you – lee blues Apr 20 '23 at 09:59
  • ah just nest the supplementary code after with bpy.context.temp_override similar to my answer – Harry McKenzie Apr 20 '23 at 10:22
  • All other code is normal, but this is the only one that reports an error ”bpy.ops.view3d.view_center_camera()” ----RuntimeError:Operator bpy.ops.view3d.view center camera.poll()failed,context is incorrect . How do I go about modifying it? – lee blues Apr 20 '23 at 10:52
  • bpy.ops.view3d.view_center_camera() should also work within the VIEW_3D context. can u edit your question and add an updated version of your code – Harry McKenzie Apr 20 '23 at 11:24
  • I was thinking the same thing, but there was an error. Here is the full code of the error. Python:Traceback (most recent call last): File "C:\Users\blues\AppData\RoamingBlender Foundation\Blender3.3\scripts\addons\CamS3.py",line 49,in execute bpy.ops.view3d.view_center_camera() File "C:\Programs\blender-3.3.0-windows-x6413.3\scripts\modules\bpyops.py".line 113,in call ret op call(self.idname_py(),None,kw) RuntimeError:Operator bpy.ops.view3d.view_center_camera.poll()failed,context is incorrect – lee blues Apr 20 '23 at 12:02
  • Just this line, correct the code, it would to be perfection, I will rename author of this plugin by you name – lee blues Apr 20 '23 at 12:05
  • yeah i tried as well, i could not figure it out. i will try again tomorrow https://blender.stackexchange.com/questions/95793/how-to-use-view-center-camera-for-fitting-camera-to-3d-view – Harry McKenzie Apr 20 '23 at 15:50
  • hi,You rewrite the code there is a little problem, before my code ca switch the area‘s camera in the current area where the mouse is located,it is this paragraph code: “bpy.context.space_data.camera = bpy.data.objects["C_0V0"]” change to “c.space_data.camera = bpy.data.objects[self.cam_name]” It doesn't work anymore.,But the new code can only switch the camera in one area now when there ara many areas in windows, how can I modify it? – – lee blues Apr 21 '23 at 09:08