4
$\begingroup$

With objects, there you can add Custom Properties to an object, though it only seems to let you specify numeric values.

Is there any way that I can add a color value as a custom property, such as through Blender's python API?

EDIT: To clarify what I am doing: I am making a set of character models for use in a web comic I am making. The character models will be "generic" ones for ordinary characters (ie: bystanders, pedestrians, etc.). What I want to do is put some color field properties onto the armature (which is the parent of all the model pieces and clothing), and then use drivers in the model pieces so that they can pull the color data for the clothing, eyes, and skin.

I wish to use this method because I want to use models in a linked fashion, where I import one or more generic models and set the colors in the scene they are used in after importing, so that I don't fill up my hard drive (or my cloud drive) with dozens of .blend files for every color variation I use.

EDIT 2: To clarify further, I wish for a solution that can be applied on a per-model basis, rather than needing to create an addon that adds the same set of properties to all models.

$\endgroup$
  • $\begingroup$ This should help: wiki.blender.org/index.php/Doc:2.6/Manual/Extensions/Python/… $\endgroup$ – Mike Pan Feb 12 '14 at 5:16
  • 1
    $\begingroup$ Does it need to appear in the Custom Properties panel? I would use a FloatVectorProperty() instead, which wouldn't show in tha panel, but can be added to any panel with a custom draw function. It would give you a color field, click to open color picker. $\endgroup$ – CoDEmanX Feb 12 '14 at 8:56
  • $\begingroup$ CoDEmanX: Yes, that's pretty much what I want. How do I set that up? $\endgroup$ – Zauber Paracelsus Feb 12 '14 at 14:04
5
$\begingroup$

Here is condensed heavily edited sample add-on an artist requested t use blender as the middleman to mass convert vertex colors data from custom data source, the latter being removed as its not related to the question.

The color value was selected using FloatVectorProperty, specifically with subtype COLOR. This also has the advantage that if exposed through the UI is visualised by the nice UI Color wheel/hex-widget.

The code is split into properties.py and ui.py as this is done for ease of maintainance and separation of concerns, ie storage and display. You can store the custom property anywhere you want I choose object as per the question, the same applies for where the ui appears.

You can also combine it into one script, just need to change registration from module to class and supply each class name.

I generally use a properties group when working with multiple properties, but you can just define a single custom property to attach. properties.py

import bpy
from bpy.props import FloatVectorProperty, StringProperty, PointerProperty

class ObjectProperties(bpy.types.PropertyGroup):
    @classmethod
    def register(cls):

        bpy.types.Object.custom = PointerProperty(
            name="Custom properties",
            description="Custom Properties for Objects",
            type=cls,
            )

        #Add in the properties you want      
        cls.hexwidget = FloatVectorProperty(name="Hex Value", 
                                        subtype='COLOR', 
                                        default=[0.0,0.0,0.0])

        cls.test_string = StringProperty(name="Test String",
                                        default="I am a string")

    @classmethod
    def unregister(cls):
        del bpy.types.Object.custom

def register():
    bpy.utils.register_class(ObjectProperties)

def unregister():
    bpy.utils.unregister_class(ObjectProperties)

This module has specific registration handling as we prefer to get rid of custom info if the addon is not install, design decision.

Here is the UI which will display the value stored in the defined property ui.py

import bpy

class UtilityPanel(bpy.types.Panel):
    bl_label = "Utilites Panel"
    bl_idname = "OBJECT_PT_utilities"

    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"

    def draw(self, context):
        layout = self.layout       

        box = layout.box()
        row = box.row()
        row.prop(context.active_object.custom, "hexwidget")
        row = box.row()
        row.prop(context.active_object.custom, "test_string")

__init__.py for completeness

#--- ### Header
bl_info = {
    "name": "Custom Property: Color",
    "category": "Object",
}

import bpy
import bpy.props

from <folder_name> import ui, properties

def register():
    properties.register()
    bpy.utils.register_module(__name__)


def unregister():
    properties.unregister()
    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()

When enabled the add-on adds a custom propertygroup to each Object, which can be altered or expanded as you need.

Custom Panel Object Tab

$\endgroup$
  • $\begingroup$ Okay, going to try this out. Will ask if I have any trouble. $\endgroup$ – Zauber Paracelsus Feb 12 '14 at 18:58
  • $\begingroup$ Okay, I have all three scripts copied into the text editor and registered. How do I hook them up to an object, though? $\endgroup$ – Zauber Paracelsus Feb 12 '14 at 19:03
  • $\begingroup$ This is the bare bones of an addon. Create a new folder in your addon directory and enable the new add-on. $\endgroup$ – neomonkeus Feb 12 '14 at 19:11
  • $\begingroup$ Okay, and after that, how do I use it? Also, I am going to edit the original question to put my use case down so that it fits into the context. $\endgroup$ – Zauber Paracelsus Feb 12 '14 at 19:12
  • $\begingroup$ You need to edit the <folder_name> of init to whatever you called the folder you created. Some slight corrections, works and displays in the Properties -> Object tab. See screenshot $\endgroup$ – neomonkeus Feb 12 '14 at 20:10
2
$\begingroup$

I don't know whether this would be the intended way, but at least it works:

You could add a string representation of other datatypes than integer from the edit dialog, there you could paste a color value Ctrl-V copied from e.g. material settings, this would add a list with 4 floats.

enter image description here

To access your custom properties attached to your object e.g.

o=bpy.data.objects["Cube"]
c = Color( o["customColor"][:3] )
print( c )
>>> <Color (r=0.8000, g=0.2236, b=0.2440)>

To set a color programmatically:

c = Color((1,2,3))
o["customColor"]=c

c2=o["customColor"]
print(c2)
>>> <bpy id property array [3]>

print(Color(c2))
>>> <Color (r=1.0000, g=2.0000, b=3.0000)>

See also:

$\endgroup$
1
$\begingroup$

Just want do add:

Similar to python properties, the properties from bpy.props basically provide setter/getter methods for custom properties which actually are items of an ID dictionary.

Creating such a property

bpy.types.Object.test = bpy.props.IntProperty()

has no effect on an object until you assign a value to its test attribute

obj.test = 4
#calls the default setter if not specified which sets the custom property
obj["test"] = 4

The getter method returns the default value if nothing has been set for this attribute

obj.test
#calls the default setter if not specified which either returns the custom property,
#if it exists, or the default value
if "test" in obj:
    return obj["test"]
else:
    return default_value

Custom properties will be saved to the .blend file.

Correct me if i am wrong.

In this case:

#addon bl_info to be inserted here - see Templates -> Addon Add Object
import bpy

def hndl_draw(self, context):
    row = self.layout.row()
    #if "myColor" in context.object.data:
    row.prop(context.object.data, "myColor")

def register():   
    bpy.types.Armature.myColor = bpy.props.FloatVectorProperty(
                                     name = "myColor",
                                     subtype = "COLOR",
                                     size = 4,
                                     min = 0.0,
                                     max = 1.0,
                                     default = (0.75,0.0,0.8,1.0)
                                     )
    bpy.types.DATA_PT_display.append(hndl_draw)

def unregister():
    bpy.types.DATA_PT_display.remove(hndl_draw)
    del bpy.types.Armature.myColor

if __name__ == "__main__":
    register()

For all armatures the specified default color will be displayed in Properties Area -> Armature -> Display
ColorPicker

If you don't change the color no data will be added to the armature.

You can hide this color picker for objects without the custom property "myColor" by uncommenting the if-line. However you will have to set obj.data["myColor"] = (0.0,0.0,0.0,1.0) manually then (via console, script or UI).

$\endgroup$
  • $\begingroup$ How would I apply this to a specific object? $\endgroup$ – Zauber Paracelsus Feb 13 '14 at 18:25
  • $\begingroup$ You can simply assign a custom property. obj["myColor"] = (100, 255, 0). If you create a bpy.props.IntVectorProperty the end result will be the same when saved to the .blend file. $\endgroup$ – pink vertex Feb 13 '14 at 18:51
  • $\begingroup$ My problem is I'm trying to get it to show up with a color picker. $\endgroup$ – Zauber Paracelsus Feb 13 '14 at 18:59
  • $\begingroup$ Added an example. $\endgroup$ – pink vertex Feb 13 '14 at 19:32
  • $\begingroup$ Tried that, and it appears to work. However, it appears that if the code is run more than once, the MyColor fields get added multiple times. $\endgroup$ – Zauber Paracelsus Feb 13 '14 at 19:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.