setColor not working

Hi, tried to write a Conway life in 3D
everything worked so far, but now I wanted to implement a edit feature. I implemented it so that there is a small cube at each grid position. When clicked, it should add or remove a cell. This is not fully implemented yet, but the collission detection works already. (line 186, the hide() function in 187 works)
For that the actual cube under the mouse should be highlighted. But setColor doesn’t work for some reason.
After I encountered that problem I added another setColor when the objects are created, but even there it doesn’t work (lines 132 and 140)
Later there will be a button to show/hide those editmarkers

Please ignore other details, the thing isn’t finished yet, but I need the highlighting functionality

To make the thing run you would need two simple models. a cube (cube.egg) and a smaller cube simple_cube.egg)
I created both with blender + chicken

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Import section
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import *
from direct.gui.DirectGui import *
from direct.task.Task import Task
from direct.interval.IntervalGlobal import *
import sys

class World(DirectObject):
    # ruleset
    rule_set = {"new_min" : 3, "new_max" : 6,  "survive_min" : 4, "survive_max" : 6}
    wrap_walls = 0
    # grid size
    size_x = 11
    size_y = 11
    size_z = 11
    size_plane = size_x * size_y
    size_total = size_x * size_y * size_z
    # data array
    models = [[[0]*size_z for x in xrange(size_y)] for y in xrange(size_x)]
    edit_markers = [[[0]*size_z for x in xrange(size_y)] for y in xrange(size_x)]
    collider_spheres = [[[0]*size_z for x in xrange(size_y)] for y in xrange(size_x)]
    collider_nodes = [[[0]*size_z for x in xrange(size_y)] for y in xrange(size_x)]
    # some constants
    MARKER_BASE = Vec4(1, 1, 1, 1)
    MARKER_HIGH = Vec4(0, 0, 0, 1)
    # currently highlighted marker
    marker_high = False

    def __init__(self):
        self.accept('escape', sys.exit)              # Escape quits
#        base.disableMouse()                          # Disble mouse camera control

        self.init_empty_grid()
        self.init_grid()
        # Lights
        self.init_light()
        # Camera
        self.init_camera()
        self.init_gui()

    def init_empty_grid(self):
        self.live_grid = [[[0]*(self.size_z+1) for x in xrange(self.size_y+1)] for y in xrange(self.size_x+1)]

    def count_neighbours(self, x, y, z):
        sum = 0
        mod_x = self.size_x + self.wrap_walls
        mod_y = self.size_y + self.wrap_walls
        mod_z = self.size_z + self.wrap_walls
        for dx in range (-1, 2):
            for dy in range (-1, 2):
                for dz in range (-1, 2):
                    sum += self.live_grid[(x + dx) % mod_x][(y + dy) % mod_y][(z + dz) % mod_z]
        sum -= self.live_grid[x][y][z] # remove the cell itself
        return sum

    def calculate_grid(self):
        new_grid = [[[0]*(self.size_z+1) for x in xrange(self.size_y+1)] for y in xrange(self.size_x+1)]
        for x in range (0, self.size_x):
            for y in range (0, self.size_y):
                for z in range (0, self.size_z):
                    n = self.count_neighbours(x, y, z)
                    if(self.live_grid[x][y][z]):
                        if(n <= self.rule_set["survive_max"] and n >= self.rule_set["survive_min"]): new_grid[x][y][z] = 1
                        else:	new_grid[x][y][z] = 0
                    else:
                        if(n <= self.rule_set["new_max"] and n >= self.rule_set["new_min"]): new_grid[x][y][z] = 1
                        else:	new_grid[x][y][z] = 0

                    if(new_grid[x][y][z]): self.models[x][y][z].show()
                    else: self.models[x][y][z].hide()
        self.live_grid = new_grid

    def init_cross(self, x, y, z):
        # cross
        self.live_grid[x][y-1][z] = 1
        self.live_grid[x][y][z] = 1
        self.live_grid[x][y+1][z] = 1

        self.live_grid[x-1][y][z] = 1
        self.live_grid[x+1][y][z] = 1

        self.live_grid[x][y][z-1] = 1
        self.live_grid[x][y][z+1] = 1

    def init_grid(self):
        self.init_cross(self.size_x/2, self.size_y/2, self.size_z/2)

        #Since we are using collision detection to do picking, we set it up like
        #any other collision detection system with a traverser and a handler
        self.picker = CollisionTraverser()            #Make a traverser
        self.pq     = CollisionHandlerQueue()         #Make a handler
        #Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        #Attach that node to the camera since the ray will need to be positioned
        #relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        #Everything to be picked will use bit 1. This way if we were doing other
        #collision we could seperate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()               #Make our ray
        self.pickerNode.addSolid(self.pickerRay)      #Add it to the collision node
        #Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        #self.picker.showCollisions(render)

        # create the basic cube (only once)
        self.cube = loader.loadModel('models/cube.egg')
        self.cube.reparentTo(hidden)

        self.edit_marker = loader.loadModel('models/simple_cube.egg')
        self.edit_marker.reparentTo(hidden)
        self.edit_marker_group = render.attachNewNode("edit_markers")
        #self.edit_marker_group.hide()

        for x in xrange (self.size_x):
            for y in xrange (self.size_y):
                for z in xrange (self.size_z):
                    # built instances of cube and move into the grid
                    self.models[x][y][z] = render.attachNewNode("cube_" + str(x) + "_" + str(y) + "_" + str(z))
                    self.cube.instanceTo(self.models[x][y][z])
                    self.models[x][y][z].setPos(x*2 - self.size_x+1, y*2 - self.size_y+1, z*2 - self.size_z+1)
                    # add some info
                    self.models[x][y][z].setTag("cell", str(1))
                    self.models[x][y][z].setTag("x", str(x))
                    self.models[x][y][z].setTag("y", str(y))
                    self.models[x][y][z].setTag("z", str(z))
                    self.models[x][y][z].setColor(1.0, 0.0, 0.0, 0.0)
                    if(not self.live_grid[x][y][z]): self.models[x][y][z].hide()

                    # and the edit_markers
                    self.edit_markers[x][y][z] = render.attachNewNode("edit_marker_" + str(x) + "_" + str(y) + "_" + str(z))
                    self.edit_markers[x][y][z].setPos(x*2 - self.size_x+1, y*2 - self.size_y+1, z*2 - self.size_z+1)
                    self.edit_marker.instanceTo(self.edit_markers[x][y][z])
                    self.edit_markers[x][y][z].reparentTo(self.edit_marker_group)
                    self.edit_markers[x][y][z].setColor(1.0, 0.0, 0.0, 0.0)
                    self.edit_markers[x][y][z].setTag("edit", str(1))
                    self.edit_markers[x][y][z].setTag("x", str(x))
                    self.edit_markers[x][y][z].setTag("y", str(y))
                    self.edit_markers[x][y][z].setTag("z", str(z))

                    self.collider_spheres[x][y][z] = CollisionSphere(0, 0, 0, .25)
                    self.collider_nodes[x][y][z] = self.edit_markers[x][y][z].attachNewNode(CollisionNode('cnode'))
                    self.collider_nodes[x][y][z].node().addSolid(self.collider_spheres[x][y][z])
                    #self.collider_nodes[x][y][z].show()
                    self.collider_nodes[x][y][z].setTag("x", str(x))
                    self.collider_nodes[x][y][z].setTag("y", str(y))
                    self.collider_nodes[x][y][z].setTag("z", str(z))
                    #self.edit_markers[x][y][z].node().setIntoCollideMask(BitMask32.bit(1))
                    #self.edit_markers[x][y][z].find("**/polygon").node().setIntoCollideMask(BitMask32.bit(1))
                    #Set a tag on the square's node so we can look up what square this is
                    #self.edit_markers[x][y][z].find("**/polygon").node().setTag('square', str(i))

        base.setBackgroundColor(0.35, 0.25, 0.0)

        # built sequence to calculate grid
        self.calculator = Sequence(Wait(0.75),	Func(self.calculate_grid))

        #Start the task that handles the picking
        self.mouse_task = taskMgr.add(self.mouse_task, 'mouseTask')
        self.accept("mouse1", self.click)
#        self.accept("mouse1-up", self.releasePiece) #releasing places it

    def click(self):
        print "click"

    def mouse_task(self, task):
        # print 'mouse'
        # First we check that the mouse is not outside the screen
        if base.mouseWatcherNode.hasMouse():
            # take screen coordinates and adjust picker ray
            mpos = base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
            # now traverse collission
            self.picker.traverse(render)
            # assume for simplicity's sake that myHandler is a CollisionHandlerQueue
            if(not self.marker_high is False): self.marker_high.setColor(self.MARKER_BASE)
            if self.pq.getNumEntries() > 0:
                self.pq.sortEntries() #this is so we get the closest object
                cm = self.pq.getEntry(0).getIntoNodePath()
                self.marker_high = self.edit_markers[int(cm.getTag('x'))][int(cm.getTag('y'))][int(cm.getTag('z'))]
                self.marker_high.setColor(self.MARKER_HIGH)
                #self.marker_high.hide()
                #print 'pick: {} / {} / {}', (pickedObj.getTag('x'), pickedObj.getTag('y'), pickedObj.getTag('z'))

        return Task.cont

    def init_light(self):
        plight = AmbientLight('my plight')
        plight.setColor(VBase4(0.20, 0.20, 0.20, 1))
        plnp = render.attachNewNode(plight)
        render.setLight(plnp)

        light2 = PointLight('pointlight')
        plnp2 = render.attachNewNode(light2)
        plnp2.setPos(-50, -10, 10)
        render.setLight(plnp2)

    def init_camera(self):
        # Camera
        base.camera.setPos(-50, -50, 10)
        base.camera.lookAt(self.cube)
        mat=Mat4(camera.getMat())
        mat.invertInPlace()
        base.mouseInterfaceNode.setMat(mat)

    def init_gui(self):
        self.first_frame = DirectFrame(frameColor=(0,0.5,0,1) , frameSize=(0, 0.75, 0, 0.5 ) , pos =(-1.3, 0, 0.45 ))
        self.step_button = DirectButton(pos = Vec3(0.125, 0.0, 0.35), text = ">",
                   scale = .1, pad = (.5, .5),
                   rolloverSound = None, clickSound = None,
                   command = self.calculate_grid)
        self.step_button.reparentTo(self.first_frame)
        self.start_button = DirectButton(pos = Vec3(0.35, 0.0, 0.35), text = ">>",
                   scale = .1, pad = (.5, .5),
                   rolloverSound = None, clickSound = None,
                   command = self.start_stop)
        self.start_button.reparentTo(self.first_frame)

        self.button_reset_random = DirectButton(pos = Vec3(0.15, 0.0, 0.1), text = "reset",
                   scale = .1, pad = (.25, .25),
                   rolloverSound = None, clickSound = None,
                   command = self.reset_random)
        self.button_reset_random.reparentTo(self.first_frame)
        self.slider_rnd = DirectSlider(pos = Vec3(0.5, 0.0, 0.1), text = "0.25", value = 0.25,
                   scale = .1, pad = (.25, .5),
                   command = self.set_random_base)
        self.slider_rnd.reparentTo(self.first_frame)

        self.button_reset_cross = DirectButton(pos = Vec3(0.15, 0.0, -0.1), text = "reset +",
                   scale = .1, pad = (.25, .25),
                   rolloverSound = None, clickSound = None,
                   command = self.reset_cross)
        self.button_reset_cross.reparentTo(self.first_frame)

        # rulesetter
        self.button_new_min_minus = DirectButton(pos = Vec3(-1.1, 0.0, 0.0), text = "<",
                   scale = .075, pad = (.3, .2), rolloverSound = None, clickSound = None,
                   command = self.set_rule, extraArgs = ("new_min", -1))
        self.button_new_min_plus = DirectButton(pos = Vec3(-0.9, 0.0, 0.0), text = ">",
                   scale = .075, pad = (.3, .2), rolloverSound = None, clickSound = None,
                   command = self.set_rule, extraArgs = ("new_min", 1))

        self.button_new_min_minus = DirectButton(pos = Vec3(-1.1, 0.0, -0.1), text = "<",
                   scale = .075, pad = (.3, .2), rolloverSound = None, clickSound = None,
                   command = self.set_rule, extraArgs = ("new_max", -1))
        self.button_new_min_plus = DirectButton(pos = Vec3(-0.9, 0.0, -0.1), text = ">",
                   scale = .075, pad = (.3, .2), rolloverSound = None, clickSound = None,
                   command = self.set_rule, extraArgs = ("new_max", 1))

        self.button_new_min_minus = DirectButton(pos = Vec3(-1.1, 0.0, -0.2), text = "<",
                   scale = .075, pad = (.3, .2), rolloverSound = None, clickSound = None,
                   command = self.set_rule, extraArgs = ("survive_min", -1))
        self.button_new_min_plus = DirectButton(pos = Vec3(-0.9, 0.0, -0.2), text = ">",
                   scale = .075, pad = (.3, .2), rolloverSound = None, clickSound = None,
                   command = self.set_rule, extraArgs = ("survive_min", 1))

        self.button_new_min_minus = DirectButton(pos = Vec3(-1.1, 0.0, -0.3), text = "<",
                   scale = .075, pad = (.3, .2), rolloverSound = None, clickSound = None,
                   command = self.set_rule, extraArgs = ("survive_max", -1))
        self.button_new_min_plus = DirectButton(pos = Vec3(-0.9, 0.0, -0.3), text = ">",
                   scale = .075, pad = (.3, .2), rolloverSound = None, clickSound = None,
                   command = self.set_rule, extraArgs = ("survive_max", 1))

        self.rule_set_labels = {
            "new_min" :
            DirectLabel(pos = Vec3(-1.0, 0.0, 0.0), text = str(self.rule_set["new_min"]),
                   scale = .075, pad = (.5, .2)),
            "new_max" :
            DirectLabel(pos = Vec3(-1.0, 0.0, -0.1), text = str(self.rule_set["new_max"]),
                   scale = .075, pad = (.5, .2)),
            "survive_min" :
            DirectLabel(pos = Vec3(-1.0, 0.0, -0.2), text = str(self.rule_set["survive_min"]),
                   scale = .075, pad = (.5, .2)),
            "survive_max" :
            DirectLabel(pos = Vec3(-1.0, 0.0, -0.3), text = str(self.rule_set["survive_max"]),
                   scale = .075, pad = (.5, .2))
            }
        self.button_check_wrap = DirectCheckButton(pos = Vec3(-1.0, 0.0, 0.65), text = "wrap walls",
                   scale = .075, pad = (.3, .2), rolloverSound = None, clickSound = None,
                   command = self.set_wrap, indicatorValue = not self.wrap_walls)
        self.button_check_wrap.reparentTo(self.first_frame)

    def set_rule(self, what, val = 0):
        if(self.rule_set[what] + val >= 0 and self.rule_set[what] + val <= 26):	self.rule_set[what] += val
        self.rule_set_labels[what]["text"] = str(self.rule_set[what])

    def set_wrap(self, status):
        self.wrap_walls = not status

    def reset_cross(self):
        self.init_empty_grid()
        self.init_cross(self.size_x/2, self.size_y/2, self.size_z/2)
        for x in xrange (self.size_x):
            for y in xrange (self.size_y):
                for z in xrange (self.size_z):
                    if(not self.live_grid[x][y][z]):	self.models[x][y][z].hide()
                    else:	self.models[x][y][z].show()

    def reset_random(self):
        import random
        self.init_empty_grid()
        for x in xrange (self.size_x):
            for y in xrange (self.size_y):
                for z in xrange (self.size_z):
                    self.live_grid[x][y][z] = (random.random() < self.slider_rnd["value"])
                    if(not self.live_grid[x][y][z]):	self.models[x][y][z].hide()
                    else:	self.models[x][y][z].show()

    def set_random_base(self):
        self.slider_rnd["text"] = '{0:.3f}.'.format(self.slider_rnd["value"])

    def start_stop(self):
        if(self.calculator.isStopped()): self.calculator.loop()
        else: self.calculator.finish()

# Application code
if __name__ == "__main__":
    w = World()
    run()

Replace:

self.marker_high.setColor(self.MARKER_HIGH)

with:

self.marker_high.setColor(self.MARKER_HIGH, 1)

Just as with setTexture(), if a model already has a color applied, you need to supply a second parameter to override that existing color.

David

hmm, didn’t work.
But I created a new cube with blender and deleted the material. That worked.

That second parameter you mentioned is named priority, maybe the priority in the egg file was already highest possible?
I didn’t find anything of the kind in the egg file.

But anyway, it works now with the new egg files.
Thanks a lot

Ah, another wrinkle is the use of materials–I didn’t know you were using them. If you have a material in effect, and that material specifies a color, then the color specified at the scene graph level no longer applies. (It is possible to define a material that does not replace the scene graph color, but allows it to show through instead; but if you have defined a material naively, it may completely shadow the scene graph color.)

David