Blender Tutorial: Color Sliders
Many people wonder about this topic. Real functional color sliders in Blender.
Here is a tutorial on the Python aspect of it.
NOTE: This is my first tutorial so I am still working out some of the HTML bugs. Please use
the Contact Us page to report bugs. :)
Files:
Start Blend: ColorSliderExample_start.blend
Finished Blend: ColorSliderExample_finished.blend
You can download the full version of the script here: ColorSlider.py (Right-Click, "Save Target as..." or "Save Link as..." )
Inside the start blend you will see that we have a 3 very simple color sliders already
modeled. Each slider has a handle with a “handle” property. The handle it self is just a no collision object that
will simply tell the user where the slider’s value is at. This script is very 2D, if you need it to work at any
angle, you should use overlay scenes.
The first few lines of the script is just the basic, importing modules, getting objects, and
other stuff like that. There is also a function that we will use later on.
|
##
modules ##
#
import the GameLogic module
import GameLogic
#
define a function that gets a list of vertices
def
getVertexArray(mesh,numMaterials=1):
list = []
for material in range(numMaterials):
vertices = mesh.getVertexArrayLength(material)
for v in range(vertices):
vert = mesh.getVertex(material,v)
list.append(vert)
return list
##
important stuf ##
#
get the current controller
cont
= GameLogic.getCurrentController()
#
the owner of the controller is the object that it is attached to.
own
= cont.owner
##
Sensors ##
#
mouseover any sensor named "mouseover"
mouseover =
cont.sensors["mouseover"]
#
click sensor named "click" click =
cont.sensors["click"]
|
Then we get to the main code. The first thing you should see is the “object_list” variable.
That is simply a list of all the objects in the current scene, on the current layer.
You should notice that after that we have a line that says “if own['clicking'] == -2:” this is so that we can run some initializing code:
|
#
check to see if we have initialized yet.
if
own['clicking'] == -2:
# import module Rasterizer, and show the mouse.
import Rasterizer; Rasterizer.showMouse(1)
## find each slider then set its color to [0.0, 0.0, 0.0]
# find alist of objects
objects = [object_list["OB"+obj['object']] for obj in object_list if
obj.get('slider')]
# color all the verts
for ob in objects:
[vert.setRGBA([0,0,0,1]) for vert in getVertexArray(ob.meshes[0])]
# set 'clicking' to its default value
own['clicking'] = -1
|
First thing that we do is show the mouse. This is done through the
module Rasterizer
. A cool thing about that line is that there are two statements on one line. Python is
cool because we can have as many statements as we want as long as we separate them with semicolons ( ;
).
Next we get a list of all the target objects of the sliders, using a quite advanced topic
called “list
comprehensions“. The reason we get this list is so that we can set all the target object’s
colors to the default of black ( [0.0, 0.0, 0.0] ).
The last phase in our initialization is to change the value of the property “clicking” to
its default value, which is -1.
In the next few lines we start getting into the heart of the code. This is where it becomes
a bit more complicated and the explanations get longer.
|
# if
we are clicking
if
click.positive:
# if the object under the mouse is a slider.
if own['clicking'] >= -1 and (mouseover.hitObject and
mouseover.hitObject.get("slider")):
# notice how we used 'get' instead of
# has_key to do truth value testing.
# if its the first click
if own['clicking'] == -1:
slider = mouseover.hitObject
# for future reference, save the object
own['lastobj'] = slider
own['clicking'] = 0
else:
slider = own['lastobj']
|
In this first part of it, we see some simple stuff. The first part of this code is testing to
see, first if we are clicking, then if we are clicking on a slider. Notice how in the second part of the second if
statement, we are using the “get” function instead of the “has_key” function. This is so that if the user of the
script wanted to say, turn off a slider, he/she could do that simply by changing the value of that slider’s
“slider” property to True.
Next we check to see if this is the first time we are clicking, or not. Either way, we are
going to have to declare the variable slider anyway, that is why we use the else statement.
|
# get the slider's handle using list comprehensions
handle = [obj for obj in slider.children if obj.get("handle")][0]
if bool(handle):
# NOTE: This script assumes that the slider's center is in the middle of it.
# max x location
xmax = slider.worldPosition[0]+slider['length']/2
xmin = slider.worldPosition[0]-slider['length']/2
# using the min/max built in functions we can
# easily determine things.
x = max(xmin, min(mouseover.hitPosition[0], xmax))
# the y & z stay the same
y,z = handle.worldPosition[1:3]
# set the handle's position
handle.localPosition = [x,
y, z]
|
This next part of the script gets the handle object, then computes the new position of the
handle. Using the "length" property of the slider (basically the x dimension) we can determine, assuming that the
slider's center is actually in the center of the slider, what the maximum and minimum position that the handle can
go. You also see how the min and max built in functions are very useful. The y and z coordinates stay
the same.
|
# The target object
object = object_list['OB'+slider['object']]
# the number of materials to search
numMaterials = 1
# get a list of vertices
verts = getVertexArray(object.meshes[0], numMaterials)
index = {'red':0,'green':1,'blue':2}.get(slider['color'],slider['color'])
# the value of the slider
cvalue = slider['min'] + (x - slider.worldPosition[0] + slider['length']/2.0) / slider['length'] *
(slider['max']-slider['min'])
# we have to color each vert individually
color = vert.color
# now to change the color
vert.colour = color
|
In this part we actually have to do some calculations. First we get the target object. This is denoted by the "object" property in the slider. Next is the variable numMaterials, this is the number of materials you want the script to search when getting the vertices. "verts" is a list of vertices created by the function "getVertexArray" already declared on top. This function pretty much just runs through a loop and collects all the vertices. This next technique is very great because this way, we don't have to use multiple if statements. Instead we just use a dictionary. This next variable, which is the new value of the color for the vert, we can break down into 3 different variables, just to make it simple.Note: I added brackets to make it easier to isolate the steps.
-
x = x-slider.worldPosition[0] + (slider['length']/2.0)
-
interval = slider["max"]-slider["min"]
-
cvalue = slider["min"] + (x*interval)
The first variable is calculated by taking x, the variable determined above to be the value of the current mouse position, and subtract the slider's x position, which we already know to be half of the lenght, then because we only subtracted half of the length before, we have to add the rest. The second variable is simply the interval of between the maximum value and the minimum value that the slider can get. In this case interval will just equal 1.0 because our min value is 0.0 and our max value is 1.0 (1.0-0.0). The last variable is called "cvalue" because it stores the current value of the slider. "cvalue" takes the minimum value of the slider and adds it to x times the interval. This is important for smaller intervals.
else:
own['clicking'] = -1
This last piece of code is just to reset our clicking property. The entire purpose
of this property is to control and track mouse events.
|
Click to login
Click to login