0
$\begingroup$

I am currently trying to use my code to add objects that are selected by a pointer to one of the two global dictionaries. It used to add the associated object name alone to its corresponding dictionary, however, now it seems to have switched to returning the "unrepresented" form of the string (ex. <bpy_struct, Object("Camera") at 0x0000023695E1EB08>).

As far as I'm aware I didn't change anything that would have caused this to suddenly switch, but now I can't seem to get it back to only adding the object's name. I currently have variables "camera_pointer_status" and "light_pointer_status" representing the object names of each item selected in the form of a string.

Can anybody help me out?

My Code:

import bpy

# Global dictinaries for appending objects selected in corresponding pointers.

global active_camera
active_camera = {}

global light_source_list
light_source_list = {}

# Object Sorting:

def poll_is_camera(self, obj):
    return obj.type == 'CAMERA'
def poll_is_light(self, obj):
    return obj.type == 'LIGHT'

class ADDON_pointers(bpy.types.PropertyGroup):
    
    # Camera Pointer:

    camera_pointer : bpy.props.PointerProperty(
        name= "", 
        description= "None", 
        type= bpy.types.Object,
        poll= poll_is_camera,
    )
    
    # Light Source Pointer:
    
    light_pointer : bpy.props.PointerProperty(
        name= "", 
        description= "None", 
        type= bpy.types.Object,
        poll= poll_is_light,
    )

# Main UI Panel:
 
class ADDON_PT_main_panel(bpy.types.Panel):
    bl_label = "ADDON"
    bl_idname = "ADDON_PT_main_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "ADDON"

    def draw(self, context):
        layout = self.layout
        scene = context.scene
        mytool = scene.my_tool
        
        # Camera Pointer UI:
        
        layout.label(text= "Camera:")
        layout.prop(mytool, "camera_pointer")
        
        # Get string name of object selected in the corresponding pointer.
        
        camera_pointer_status = str(bpy.context.scene.my_tool.camera_pointer)
        
        camera_count = 0
        
        # If an object is selected, then increase number of cameras by 1 and append
        # object name to its corresponding global dictionary.
        
        if camera_pointer_status != 'None':
            camera_count += 1
            active_camera.update({camera_pointer_status: camera_count})
            
        # If camera_pointer is cleared, then decrease number of cameras by 1 and
        # reset the corresponding global dictionary.
            
        if camera_pointer_status == 'None':
            camera_count -= 1
            active_camera.clear()
            
        # Print list of cameras.
        
        print('Active Camera List: ' + str(active_camera))
        
        # Light Source Pointer UI:
        
        light_source_count = 0
        
        layout.label(text= "Light Source(s):")
        layout.prop(mytool, "light_pointer")
        
        # Get string name of object selected in the corresponding pointer.
        
        light_pointer_status = str(bpy.context.scene.my_tool.light_pointer)
        
        # If an object is selected, then increase number of light sources by 1 and
        # append object name to its corresponding global dictionary.
        
        if light_pointer_status != 'None':
            light_source_count += 1
            light_source_list.update({light_pointer_status: light_source_count})
            
        # If light_pointer is cleared, then decrease number of light sources by 1 and
        # reset the corresponding global dictionary.
            
        if light_pointer_status == 'None':
            light_source_count -= 1
            light_source_list.clear()
            
        # Print list of light sources.
            
        print('Light Source List: ' + str(light_source_list))
        
    
classes = [ADDON_pointers,  
           ADDON_PT_main_panel]
 
def register():
    for cls in classes:
        bpy.utils.register_class(cls)
        bpy.types.Scene.my_tool = bpy.props.PointerProperty(type= ADDON_pointers)
  
def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
        del bpy.types.Scene.my_tool
 
if __name__ == "__main__":
    register()
```
$\endgroup$
2
  • 2
    $\begingroup$ The camera name is scene.my_tool.camera_pointer.name If the pointer is set, ie not None Btw use draw method to layout data only. Consider using an update method to fire when the pointer is set. $\endgroup$
    – batFINGER
    Nov 12, 2021 at 5:26
  • $\begingroup$ @batFINGER When I include ".name" at the end of either one it returns an error that states there is no attribute called 'name' that is associated with the object. And thanks for the tip! $\endgroup$
    – leoprd
    Nov 12, 2021 at 16:43

1 Answer 1

0
$\begingroup$

I'm not sure what made the name pop up before and now it doesn't, but the text it gives you ('<bpy_struct...'>) is a string representation of the whole object, not just the name. The definition to return that string is defined in bpy.types.Object class. As the comment said, camera_pointer.name is what you want. If the pointer currently has no object, ie is None, then it will return an error when you try to access its name property.

A few things I saw in your code to keep in mind, which is probably why that alone didn't work for you:

  1. Blender wants you to use its property library for storing variables. global variables cannot be referenced in panels as far as I know.
  2. The panel is not the ideal place to check when the variable is updated and use it (what if it's updated outside the panel, or perhaps in your script?). From the property documentation, you can use the update parameter when declaring your prop to set a function for each update (such as, adding to your list).
  3. You add and delete your my_tool var multiple times during (un)register. You only need to do it once, so unindent the line to be out of the loop :)

My solution mainly involves adding a new PropertyGroup Name_List that just holds a string for your object name. Then I made two collection properties within your ADDON_pointers (added Name_List to the list of classes to register, before the ADDON_pointers), and then added update functions for whenever the pointers change (I just did the add functionality - I'll let you figure out the removal, use Blender docs and stack exchange for examples). For visual reference, I had the panel loop through the camera and light lists and print the name of each one.

Panel with list of cameras and lights

import bpy

def poll_is_camera(self, obj):
    return obj.type == 'CAMERA'
def poll_is_light(self, obj):
    return obj.type == 'LIGHT'

class Name_List(bpy.types.PropertyGroup):
    name: bpy.props.StringProperty()


class ADDON_pointers(bpy.types.PropertyGroup):
    
    def update_camera(self, context):
        if self.camera_pointer is None:
            return
        o = self.camera_coll.add()
        o.name = self.camera_pointer.name
        
    def update_light(self, context):
        if self.camera_pointer is None:
            return
        o = self.light_coll.add()
        o.name = self.light_pointer.name
    
    # Camera Pointer:

    camera_pointer : bpy.props.PointerProperty(
        type=bpy.types.Object,
        poll=poll_is_camera,
        update=update_camera
    )
    
    camera_coll : bpy.props.CollectionProperty(type=Name_List)
    
    # Light Source Pointer:
    
    light_pointer : bpy.props.PointerProperty(
        type= bpy.types.Object,
        poll=poll_is_light,
        update=update_light
    )
    
    light_coll : bpy.props.CollectionProperty(type=Name_List)

# Main UI Panel:
 
class ADDON_PT_main_panel(bpy.types.Panel):
    bl_label = "ADDON"
    bl_idname = "ADDON_PT_main_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "ADDON"

    def draw(self, context):
        layout = self.layout
        scene = context.scene
        mytool = scene.my_tool
        
        # Camera Pointer UI:
        layout.prop(mytool, "camera_pointer", text='Selected Camera:')
        layout.prop(mytool, 'camera_coll')
        for c in mytool.camera_coll:
            layout.label(text=c.name)
        
        
        layout.prop(mytool, "light_pointer", text='Selected light:')
        
        layout.prop(mytool, 'light_coll')
        for l in mytool.light_coll:
            layout.label(text=l.name)
        
    
classes = [Name_List, ADDON_pointers,  
           ADDON_PT_main_panel]
 
def register():
    for cls in classes:
        bpy.utils.register_class(cls)
    bpy.types.Scene.my_tool = bpy.props.PointerProperty(type= ADDON_pointers)
  
def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
        del bpy.types.Scene.my_tool
 
if __name__ == "__main__":
    register()
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .