Can't get alpha to work when setting color to shapes

Moho allows users to write new tools and plugins. Discuss scripting ideas and problems here.

Moderators: Víctor Paredes, Belgarath, slowtiger

Post Reply
LunarRunner
Posts: 3
Joined: Tue Sep 28, 2004 6:44 am

Can't get alpha to work when setting color to shapes

Post by LunarRunner »

I am trying to create a cluster of grass on a separate layer using only 2 colors of green. I've cut-n-pasted from several scripts but I cannot get the alpha on any color to be 100%. I've tried using values from .0 to 1.0 and from 0 to 255. In neither case does it set the alpha to 100%

Here is a snippet of the script that assigns the color to a blade of grass:

local color = LM.ColorVector:new_local()
color.r = 0
color.g = .5
color.b = 0
color.a = 1.0
shape.fMyStyle.fLineCol:SetValue(0, color:AsColorStruct())

color = LM.ColorVector:new_local()
color.r = 0
color.g = 1.0
color.b = 0
color.a = 1.0
shape.fMyStyle.fFillCol:SetValue(0, color:AsColorStruct())

I'm assuming that color.a is the alpha, but when I set it to 1.0, it doesn't obscure the blade of grass behind it.

What am I doing wrong?

- Bob
myles
Posts: 821
Joined: Sat Aug 21, 2004 3:32 am
Location: Australia, Victoria, Morwell
Contact:

Re: Can't get alpha to work when setting color to shapes

Post by myles »

LunarRunner wrote:I'm assuming that color.a is the alpha, but when I set it to 1.0, it doesn't obscure the blade of grass behind it.
Hello Bob,

wouldn't alpha 1.0 be fully transparent ? Don't you want alpha to be 0 to obscure the grass behind it ?

What results are you getting ?
Are you welding your grass shapes closed so that they can be filled ?
And then creating a shape ?

How about stealing the example from Lost Marble's Sparkles particle script, which apparently leaves alpha set to the default (I'm guessing opaque) ?

Set up the colours first:

Code: Select all

YourScript.greenA = LM.ColorVector:new_local()
YourScript.greenA:Set(0, 0.5, 0)
YourScript.greenB = LM.ColorVector:new_local()
YourScript.greenB:Set(0, 1.0, 0)
Then create your shapes and use your preset colours:

Code: Select all

-- ** Create all your points here **
-- then weld the last to the first.
mesh:WeldPoints(n, 0, 0)
-- Now add a shape and set its color and style properties
mesh:SelectConnected()
local id = moho:CreateShape(true, 0, false)
if (id >= 0) then
	local shape = mesh:Shape(id)
	shape.fHasOutline = false
	shape:RemoveStyles()
	shape.fMyStyle.fFillCol:SetValue(0, self.greenA:AsColorStruct())
end
In the usual tradition, I haven't even tried this, so I may be missing something (being careful about which points to weld, for starters)

Let us know how you get on!

Regards, Myles.
User avatar
Lost Marble
Site Admin
Posts: 2347
Joined: Tue Aug 03, 2004 6:02 pm
Location: Scotts Valley, California, USA
Contact:

Post by Lost Marble »

LunarRunner, you're doing the right thing regarding the alpha value. 0 makes a color fully transparent, and 1 makes it opaque. I just tested a little script, and setting the color.a value should work just fine.

Your statement about obscuring the blade of grass behind leaves some room for interpretation. After you run your script, did you check the colors of the grass? Use the select shape tool to select a blade of grass. Then, in the style window, click on the fill color - there you can confirm whether or not the alpha value is 255. (The 1.0 value you set in the script will translate to 255 in the Moho color picker.)

If the color is totally opaque, then there are other possibilities. Myles hinted at making sure the shape was closed - if the grass blade isn't a closed shape, it can't be filled. For a really small object like grass, it might be hard to realize that it isn't filled - if it only has an outline, the missing fill might look similar to a semi-transparent fill.
myles
Posts: 821
Joined: Sat Aug 21, 2004 3:32 am
Location: Australia, Victoria, Morwell
Contact:

Post by myles »

Lost Marble wrote:LunarRunner, you're doing the right thing regarding the alpha value. 0 makes a color fully transparent, and 1 makes it opaque.
Oops! That'll teach me to guess without testing it! :oops:

Regards, Myles.
LunarRunner
Posts: 3
Joined: Tue Sep 28, 2004 6:44 am

Post by LunarRunner »

I am closing the shape using the welding method described. However, when I edit select the blade of grass, and edit the colors, they are not set to the color of green I use, but are in fact set to black (line) and white (fill) -- for both colors, the alpha is set to 255.

When I render the image, it does show the blade of grass in green with the border of the blade in dark green.

Code: Select all

-- **************************************************
-- Provide Moho with the name of this script object
-- **************************************************

ScriptName = "LM_Grass"

-- **************************************************
-- General information about this script
-- **************************************************

LM_Grass = {}

function LM_Grass:Name()
	return "Grass"
end

function LM_Grass:Version()
	return "5.0"
end

function LM_Grass:Description()
	return "Creates a Grass cluster in a new layer."
end

function LM_Grass:Creator()
	return "Bob Tryon"
end

function LM_Grass:UILabel()
	return("Grass")
end

-- **************************************************
-- The guts of this script
-- **************************************************

function LM_Grass:IsEnabled(moho)
	if (moho.layer:CurrentAction() ~= "") then
		return false -- creating new objects in the middle of an action can lead to unexpected results
	end
	return true
end

function LM_Grass:Run(moho)

	math.randomseed(os.time())

	moho.document:PrepUndo(moho.layer)
	moho.document:SetDirty()
	
	local y = MOHO.RandomRange (0, 1)
	
	local layer = moho:CreateNewLayer(MOHO.LT_VECTOR)
	layer:SetName("Grass field")

	local v3 = LM.Vector3:new_local()
	v3:Set(.8, .8, .8)
	layer.fScale:SetValue(0, v3)

	moho:SetSelLayer(layer)

	local mesh = moho:Mesh()
	if (mesh == nil) then
		return
	end


	LM_Grass:CreateCluster (moho, mesh, y)
	LM_Grass:CreateCluster (moho, mesh, y - MOHO.RandomRange (.2, .5))
	LM_Grass:CreateCluster (moho, mesh, y - MOHO.RandomRange (.2, .5))
end

function LM_Grass:CreateCluster (moho, mesh, y)

    DrawReferenceLine (moho, mesh, y)

    -- Create a cluster
    local c = MOHO.RandomRange (10, 25)
    
    for i = 1, c do
        local inc = MOHO.RandomRange (0, .03)
        y = y - inc

        local c1 = MOHO.RandomRange (1, 3)
        for x = 1, c1 do
            local x = MOHO.RandomRange (-.5, .5)
    	    LM_Grass:CreateBlade(moho, mesh, x, y)
        end
    end
end

function LM_Grass:CreateBlade(moho, mesh, x, by)

    -- calculate a lean
	local lean = MOHO.RandomRange (-.01, .01)
	local bx = x + MOHO.RandomRange (-.5, .5)
    
	local n = mesh:CountPoints()
	local v = LM.Vector2:new_local()
	local h = MOHO.RandomRange(0.15, 0.20)
	local w = MOHO.RandomRange(0.01, 0.02)
	
    -- Bottom of blade
	v.x = bx - w
	v.y = by
	mesh:AddLonePoint(v, 0)

	v.x = bx - w + lean
	v.y = by + h
	mesh:AppendPoint(v, 0)

	v.x = bx - w + (lean * 2)
	v.y = by + (h * 2)
	mesh:AppendPoint(v, 0)

    -- Peak Point (top of blade)
	v.x = bx + (lean * 3)
	v.y = by + (h * 3)
	mesh:AppendPoint(v, 0)

	v.x = bx + w + (lean * 2)
	v.y = by + (h * 2)
	mesh:AppendPoint(v, 0)

	v.x = bx + w + lean
	v.y = by + h
	mesh:AppendPoint(v, 0)

	v.x = bx + w
	v.y = by
	mesh:AppendPoint(v, 0)

	v.x = bx - w
	v.y = by
	mesh:AppendPoint(v, 0)
	
	mesh:WeldPoints(n, n + 7, 0)

	mesh:Point(n + 2):SetCurvature(MOHO.PEAKED, 0)
	mesh:Point(n + 5):SetCurvature(MOHO.PEAKED, 0)
	mesh:Point(n + 6):SetCurvature(MOHO.PEAKED, 0)

	mesh:SelectConnected()
	local blade = moho:CreateShape(true)    
    
	if (blade >= 0) then
		local shape = mesh:Shape(blade)
		shape.fHasOutline = true
		shape:RemoveStyles()

		local color = LM.ColorVector:new_local()		
		color.r = 0  -- color.r * MOHO.RandomRange(0.95, 1.05)
		color.g = .5 -- color.g * MOHO.RandomRange(0.95, 1.05)
		color.b = 0  -- color.b * MOHO.RandomRange(0.95, 1.05)
		color.a = 1.0
		shape.fMyStyle.fLineCol:SetValue(0, color:AsColorStruct())
		
		color = LM.ColorVector:new_local()
		color.r = 0 -- color.r * MOHO.RandomRange(0.95, 1.05)
		color.g = 1  -- color.g * MOHO.RandomRange(0.95, 1.05)
		color.b = 0 -- color.b * MOHO.RandomRange(0.95, 1.05)
		color.a = 1.0
		shape.fMyStyle.fFillCol:SetValue(0, color:AsColorStruct())
	end    
end

function DrawReferenceLine (moho, mesh, y)

    -- reference line
	local v = LM.Vector2:new_local() 
	v.x = -1
	v.y = y
	mesh:AddLonePoint(v, 0)
    
	v.x = 1
	v.y = y
	mesh:AppendPoint(v, 0)

	mesh:SelectNone()
	mesh:SelectConnected()
	moho:CreateShape(true)       
end

User avatar
Lost Marble
Site Admin
Posts: 2347
Joined: Tue Aug 03, 2004 6:02 pm
Location: Scotts Valley, California, USA
Contact:

Post by Lost Marble »

OK, I spotted a few problems with this script:

1. Each time the CreateBlade function is called, it selects all the blades of grass and fills them. This causes hundreds of overlapping redundant fills to be created. That's why the script takes so long and Moho runs slowly after it's done. Add this line to the beginning of the CreateBlade function - that way, only the newly created blade of grass will be selected and filled.

mesh:SelectNone()

2. Please name your script something different. Our plan is to reserve the LM_* names for Lost Marble-created scripts. If we someday create a grass script, they would conflict. Since you're LunarRunner, you might choose to name it LR_Grass instead. Or BT_Grass for Bob Tryon.

3. In DrawReferenceLine, you call SelectNone followed by SelectConnected - the result is that nothing will be selected. SelectConnected selects all points that are connected to the currently selected ones. You should probably call SelectNone at the beginning of the function - the new points you create will be selected, and SelectConnected will then select the whole shape.

4. Your original problem was about blades of grass not obscuring the ones behind them. This is caused because of the order you draw the grass. In a 2D layer, Moho can't know which blades are in back and which are in front unless you draw them in that order. As you watch the script run, you can see that some blades that are further back appear after the front ones - this means they will draw on top of them. Your script needs to draw back-to-front.

As far as black line and white fill, I'm not seeing that - the grass all appears to be green - in editing mode, when I select one, and when I render it - always green.

The other thing I have to add is that this seems like a perfect application of particle layers. Have you looked at Tutorials 19 in the old manual? It shows how to create grass using particle layers - you might want to create a script that would automate this process.
LunarRunner
Posts: 3
Joined: Tue Sep 28, 2004 6:44 am

Post by LunarRunner »

I stumbled across the SelectNone by accident when I was trying to manipulate one blade of grass by selecting it as usual, but moho selected the last blade created. At first, I thought I didn't close the shape properly (weld) but then I realized all the points in the layer were still selected after creating the grass cluster. After searching other scripts, I found the SelectNone, applied it to my code (at the end of the CreateBlade method) and all is well -- it even sped up the rendering as well.

As far as the black and white issue, I must have been smoking something. It works just fine.

That brings me to particle layers. I am drawing the grass back to front. I don't know why you saw a blade of grass draw in front of another that should've been behind it. The way you can know for sure is the base of the grass. I always subtract an increment of Y for each blade group. I first considered using a particle layer for the grass, but couldn't gleen enough knowledge from the sample scripts and without documentation, that seemed a little more difficult. Besides that, I wasn't sure that I could control the animation of each blade the way I wanted.

I might rewrite the code when the docs are published for the scripting interface.
Post Reply