2

In Blender when I select an object and I change any setting, the other objects are not affected, but when I create a panel with properties from bpy.props, changing an intProperty on one changes it on the others

Look at this example: I made a custom panel with 2 properties

enter image description here

I create 2 object A and B with property "Resolution" = 12, then on object A I change resolution to 20

enter image description here

when clicking on object B I see that resolution is 20 as well, but I want it to be still 12.

I understand that this is because I have only registered one set of properties, that are all the same, so is there a way to register different properties for each object, and create a panel that shows only the properties of the active one?

(custom ID props could be a workaround, but I would prefer to use a custom panel because it's cleaner and drivers are way worse to trigger update functions)


here there is the part of the code related to properties:

class MyProperties(bpy.types.PropertyGroup):
sphere_resolution: IntProperty(
    name="Resolution",
    description="resolution of the sphere",
    default=8,
    min=3,
    update=updateResolution #function that changes the subdivisions of the sphere
)

sphere_transform: FloatProperty(
    name="Transformation",
    description="curvature of the Radial Sphere: = 0 is a plane, 1 is a sphere",
    default=1.0,
    min=0.0,
    max=1.0
)


operator to create the objects. Each object should have its own properties

class MESH_OT_CreateRadialSphere(bpy.types.Operator): bl_idname = "mesh.create_radial_sphere" bl_label = "Radial Sphere"

def execute(self, context):
    # stuff
    return {'FINISHED'}

create panel. Here there should be the properties of the active object, if the active object was created by the create operator, and changing a value should only affect the active object

class MESH_PT_sphere_topologies(bpy.types.Panel): bl_idname = "MESH_PT_sphere_topologies" bl_label = "Sphere Topologies" bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "data"

@classmethod
def poll(self, context):
    # stuff

def draw(self, context):
    layout = self.layout
    mytool = context.scene.SphereTopology

    layout.prop(mytool, "sphere_resolution")
    layout.prop(mytool, "sphere_transform")


classes = ( MESH_OT_CreateRadialSphere, MESH_PT_sphere_topologies, MyProperties )

def register(): for cls in classes: bpy.utils.register_class(cls) bpy.types.Scene.SphereTopology = PointerProperty(type=MyProperties)

def unregister(): for cls in classes: bpy.utils.unregister_class(cls) del bpy.types.Scene.SphereTopology

Tareyes
  • 1,794
  • 6
  • 18
  • Hello, could you post your code ? What is "Resolution" related to ? – Gorgious Nov 23 '20 at 15:05
  • @Gorgious I added a schematic version of the code (the entire code is too long). "Resolution" is just a intProperty I created. Each sphere is created with an operator and has a certain resolution: when I select a sphere I want to see the current Resolution value for that sphere and edit it (which through the update function modifies the mesh as needed). In the update function I can tell it to only modify the mesh of the active object, so it's not a problem, the problem is just that the "Resolution" in the panel doesn't reflects the true resolution of the selected sphere – Tareyes Nov 23 '20 at 16:09
  • 1
    Thanks ! I think you need to add your SphereTopology class to bpy.types.Objectrather than to bpy.types.Scene else you only have one instance of your MyProperty group (per Scene), and only one shared value – Gorgious Nov 23 '20 at 16:16
  • Thanks, you were right – Tareyes Nov 23 '20 at 16:31

1 Answers1

3

Easy. You would have to assign the PointerProperty to bpy.types.Object. Use context.object to get a reference. Demo based on the template from How to create a custom UI?

import bpy

from bpy.props import (StringProperty, BoolProperty, IntProperty, FloatProperty, FloatVectorProperty, EnumProperty, PointerProperty, ) from bpy.types import (Panel, Menu, Operator, PropertyGroup, )

------------------------------------------------------------------------

Object Properties

------------------------------------------------------------------------

class MyProperties(PropertyGroup):

my_bool: BoolProperty(
    name="Enable or Disable",
    description="A bool property",
    default = False
    )

my_int: IntProperty(
    name = "Int Value",
    description="A integer property",
    default = 23,
    min = 10,
    max = 100
    )

my_float: FloatProperty(
    name = "Float Value",
    description = "A float property",
    default = 23.7,
    min = 0.01,
    max = 30.0
    )

------------------------------------------------------------------------

Panel in Object Mode

------------------------------------------------------------------------

class OBJECT_PT_CustomPanel(Panel): bl_label = "My Panel" bl_idname = "OBJECT_PT_custom_panel" bl_space_type = "VIEW_3D"
bl_region_type = "UI" bl_category = "Tools" bl_context = "objectmode"

@classmethod
def poll(self,context):
    return context.object is not None

def draw(self, context):
    layout = self.layout
    #scene = context.scene
    mytool = context.object.my_tool

    layout.prop(mytool, "my_bool")
    layout.prop(mytool, "my_int")
    layout.prop(mytool, "my_float")
    layout.separator()

------------------------------------------------------------------------

Registration

------------------------------------------------------------------------

classes = ( MyProperties, OBJECT_PT_CustomPanel )

def register(): from bpy.utils import register_class for cls in classes: register_class(cls)

bpy.types.Object.my_tool = PointerProperty(type=MyProperties)

def unregister(): from bpy.utils import unregister_class for cls in reversed(classes): unregister_class(cls) del bpy.types.Object.my_tool

if name == "main": register()

brockmann
  • 12,613
  • 4
  • 50
  • 93