2
$\begingroup$

I have scripted materials on some objects, now I want to make a simple if/else-comparison like this for only (1,1,1)-white material:

if (mat1.diffuse_color == (1,1,1)):
  # do something
else:
  # do something other

printing the color to the console gives me:

<Color (r=0.0000, g=0.0000, b=2.5000)>

I tried several ways but nothing worked, as you can see in my screenshot I must detect the white cubes by comparison their material-colour to white.

Thanks for any help on this!

Edit: I read the API screenshot of Blender with my python script to the left

$\endgroup$
4
  • 1
    $\begingroup$ So did any print actually return an array of (1,1,1)? Also note that the documentation states that the values can be in the range [0,inf]. And floating point numbers have numerical inaccuracies, so comparison for equality is usually problematic. You could try something along the lines of if(mat2.diffuse_color >= (0.9,0.9,0.9)): $\endgroup$ Commented Feb 17, 2017 at 8:48
  • $\begingroup$ Thanks! That doesn't work ;-( Actually I compare like this: ´if (mat2.diffuse_color[0] == 1.0 ):´ This works because the blue cubes don't have any red in their rgb-values. But this ist not the best solution, there must be other ways for a in-array comparison. $\endgroup$
    – Atari800XL
    Commented Feb 17, 2017 at 8:57
  • $\begingroup$ Sorry, I forget to mention, that the blue cubes have randomed color. But only in the blue-rgb-value. When I printed out the color of a blue cube r and g were allways 0.0. $\endgroup$
    – Atari800XL
    Commented Feb 17, 2017 at 9:00
  • $\begingroup$ Suggest keeping your blue random color range to [0, 1]. Even if you are using randoms (r) ranging from 0 to 2.5 can set with with max(r, 1) $\endgroup$
    – batFINGER
    Commented Feb 18, 2017 at 6:26

2 Answers 2

4
$\begingroup$

Basically it's only possible to compare equal data types. By using python's built-in type() method on Material.diffuse_color the console yields it's an instance of the class Color:

>>> type(bpy.data.materials.get("Red-Material").diffuse_color)
>>> <class 'Color'>

Probably the simplest way is to access its 'components' by class attribute Material.diffuse_color.r or index operator Material.diffuse_color[0] and compare the values:

# Check if the red component is 1.0 via equal operator
>>> bpy.data.materials.get("Red-Material").diffuse_color.r == 1 
>>> True 
>>> bpy.data.materials.get("Red-Material").diffuse_color[0] == 1 
>>> True

However, you can also compare two class instances:

>>> mat1_diff = bpy.data.materials.get("Red-Material-I").diffuse_color
>>> mat2_diff = bpy.data.materials.get("Red-Material-II").diffuse_color
>>> mat1_diff == mat2_diff
>>> True

Means that you can create a custom color (class instance) via mathutils module to compare with:

>>> import mathutils
>>> my_red_color = mathutils.Color((1.0, 0.0, 0.0))
>>> type (my_red_color)
>>> <class 'Color'>
>>> isinstance(my_red_color, Color)
>>> True
# Compare color instance with diffuse color
>>> bpy.data.materials.get("Red-Material").diffuse_color == my_red_color
>>> True
$\endgroup$
0
4
$\begingroup$

Can treat Color values akin to Vector.
enter image description here The following example, subtracts two colors, normalized to [0, 1], from each other. The result is converted to a vector. If the length of the resultant vector is less than some tolerance then the colors "match".

import bpy
from mathutils import Vector, Color

def color_match(col1, col2, tol=0.001):
    ''' 
    Return true if vector col1 is within tol of vector col2
    '''
    def vector(col):
        # sanitize range (-2, 3, 5) = (0, 1, 1)
        return Vector([max(0, min(1, c)) for c in col])

    d = vector(col1) - vector(col2)
    return d.length <= tol

# test code
white = Color((1, 1, 1))

# comparing instances 
Color((1, 1, 0.999999)) == white
# False

# same again using color_match no tol
color_match(Color((1, 1, 0.999999)), white, tol=0)
# False

# with default tol
color_match(Color((1, 1, 0.999)), white)
# True

color_match(Color((1, 1, 0.995)), white)
# False

# shorthand
color_match((1, 1, 1), white)
# True

Suggest always use some tolerance test (fabs(x - y) < tol) when Comparing Floating Point Values . An example in test code above is

Color((1, 1, 0.999999))

which is NOT equal to

Color((1, 1, 1))

when it may be more desirable that they are treated as equal (or close enough).

$\endgroup$
0

You must log in to answer this question.

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