Reply
Logi Guru
bystander
Posts: 1,122
Registered: ‎06-04-2010
0

Color Fading Script

[ Edited ]

I see a lot of people looking for a color fading script a lot around here.  So many just can't get them to work, most often because they are using older scripts that do not work on the new software.  They may also have troubles with it locking up their system due to not releasing OnEvent, or simply not allowing them to program other key scripts.

 

This is my script.  To make it work, you must copy this script into your scripting editor and save it.  There is one modification needed on line 2.  To use this on a keyboard, you need line 2 to read like this:

DEVICE = "kb"

 

If you want it to work on the G13 or any other left handed controller that supports backlighting, it should read this:

DEVICE = "lhc"

 

You will also find that pressing G1 will toggle the script to pause.  G2 will speed up the speed it changes color, and G3 slows it down and G4 and G5 will increase or decrease the color change difference.

 

EDIT: I added a little more control

Logi Guru
bystander
Posts: 1,122
Registered: ‎06-04-2010

Re: Color Fading Script

[ Edited ]
-- Code update by Bystander on  5/13/2012
DEVICE = "lhc"	-- "kb" for keyboard, "lhc" for left handed controller, such as the G13
------------------------------------------------------------------------------------------------------------
POLL_DELAY = 16     -- Sleep time after each poll (beware of number below 16)
POLL_FAMILY = DEVICE  -- The device polling will take place on.  Prefered to not be on macroed device.
------------------------------------------------------------------------------------------------------------

speed = POLL_DELAY  -- this should alwasy be equal or larger than POLL_DELAY
inc = 1

lcd = OutputLCDMessage

function _onActivation(event, arg, family)
--
-- ADD ANY START UP ROUTINES HERE
--

	ctDiscoColors = CoThread:new(discoColors)
	ctDiscoColors:start()
	Toggle = true
end

function _OnEvent(event, arg, family)
--
-- ADD EVENT FUNCTIONALITY HERE
-- 

	if event == "G_PRESSED" and arg == 1 then
		Toggle = not Toggle
		if Toggle then
			lcd("Fade resumed.", 3000)
		else
			lcd("Fade paused.", 3000)
		end
	end
	if event == "G_PRESSED" and arg == 2 then
		speed = speed-POLL_DELAY
		if speed < POLL_DELAY 	then	-- if speed is 0 or less, the program will not reliquish control
			speed = POLL_DELAY
		end
		lcd(speed .. "ms between updates")
	end
	if event == "G_PRESSED" and arg == 3 then
		speed = speed+POLL_DELAY
		lcd(speed .. "ms between updates")
	end

	if event == "G_PRESSED" and arg == 4 then
		inc = inc + 1
		lcd(inc.." color increment(s)")
	end
	if event == "G_PRESSED" and arg == 5 then
		if inc > 1 then
			inc = inc - 1
		end
		lcd(inc.." color increment(s)")
	end

	if Toggle then
		ctDiscoColors:run()
	end
end
 
function discoColors(ct)
	while true do
		for i = 0, 255, inc do
			SetBacklightColor(i,0,255,DEVICE)
--			OutputLogMessage("Red: %i, Green: %i, Blue: %i\n", i, 0, 255)
			ct:sleep(speed)
		end

	-- now to red
		for i = 255, 0, -inc do
			SetBacklightColor(255,0,i,DEVICE)
--			OutputLogMessage("Red: %i, Green: %i, Blue: %i\n", 255, 0, i)
			ct:sleep(speed)
		end

	-- now to green-red
		for i = 0, 255, inc do
			SetBacklightColor(255,i,0,DEVICE)
--			OutputLogMessage("Red: %i, Green: %i, Blue: %i\n", 255, i, 0)
			ct:sleep(speed)
		end

	-- now to green
		for i = 255, 0, -inc do
			SetBacklightColor(i,255,0,DEVICE)
--			OutputLogMessage("Red: %i, Green: %i, Blue: %i\n", i, 255, 0)
			ct:sleep(speed)
		end

	-- now to green-blue
		for i = 0, 255, inc do
			SetBacklightColor(0,255,i,DEVICE)
--			OutputLogMessage("Red: %i, Green: %i, Blue: %i\n", 0, 255, i)
			ct:sleep(speed)
		end

	-- back to blue
		for i = 255, 0, -inc do
			SetBacklightColor(0,i,255,DEVICE)
--			OutputLogMessage("Red: %i, Green: %i, Blue: %i\n", 0, i, 255)
			ct:sleep(speed)
		end
	end
end

--------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------
--
--                             NOTHING BELOW HERE NEEDS TO BE ALTERED
--
--------------------------------------------------------------------------------------------------------

function OnEvent(event, arg, family)
-- POLLING INITIATED HERE
    _GetRunningTime = GetRunningTime()
    if event == "PROFILE_ACTIVATED" then
        ClearLog()
        POLL = Poll:new(POLL_FAMILY, POLL_DELAY)
        POLL:start()
        if KB_EVENTS then
            kb = EventHandler:new("kb")
            kb:ProcessEvent(event, arg, family)
        end
        if LHC_EVENTS then
            lhc = EventHandler:new("lhc")
            lhc:ProcessEvent(event, arg, family)
        end
        _onActivation(event, arg, family)
    else
-- POLLING ROUTINES BELOW
        POLL:run(event,arg,family)
        if KB_EVENTS then kb:ProcessEvent(event, arg, family) end
        if LHC_EVENTS then lhc:ProcessEvent(event, arg, family) end
	    _GetRunningTime = GetRunningTime()
        _OnEvent(event, arg, family)  -- Runs myOnEvent to compartmentalize
    end
    if KB_EVENTS then kb:CleanupAfterEvent() end
    if LHC_EVENTS then lhc:CleanupAfterEvent() end
end

log = OutputLogMessage

function Type(v)
    if type(v) == "table" then
        if v.Type ~= nil then
            return v.Type
        elseif v.type ~= nil then
            return v.type
        end
    end
    return type(v)
end

Poll = {}
Poll.__index = Poll
Poll.__newindex = function(table, key, value)
    for k,v in pairs(table) do
        if k == key then
            rawset(table,key,value) return
        end
    end
    error("'" .. key .. "' is not a member of Poll.", 2)
end

function Poll:new(family, delay)
    local self = {}

    self.delay = delay or 50
    if family ~= "kb" and family ~= "lhc" then
        error("Poll:new() - 'pFamily' must be 'kb' or 'lhc'", 2)
    end
    self.pFamily = family
    self.presses = 0
    self.running = false
    self.runMKeyModifier = false
    self.MKeyModifier = { nil, nil, nil }   -- "default" or Modifiers. i.e. "lshift", "ctrl"
    self.modFamily = ""
    self.Type = "Poll"

    setmetatable(self, Poll)

    return self
end

function Poll:setMKeyModifier( m1, m2, m3, family )
    self.runMKeyModifier = true
    self.MKeyModifier[1] = m1
    self.MKeyModifier[2] = m2
    self.MKeyModifier[3] = m3
    if family ~= "kb" and family ~= "lhc" then  error("Poll:setMKeyModifier() family - needs to be 'kb' or 'lhc'",2) end
    self.modFamily = family
end

function Poll:start()
    self.running = true
    self:setMKeyState()
end

function Poll:stop()
    self.running = false
end

function Poll:_press()
    if self.running then
        self.presses = self.presses + 1
    end
end

function Poll:release()
    if self.running then
        self.presses = self.presses - 1
    end
end

function Poll:setMKeyState()
    if self.runMKeyModifier then
        local default = nil
        local i = 1
        local modMKeyState = nil

        for i = 1, 3, 1 do
            if self.MKeyModifier[i] == "default" then
                default = i
            elseif self.MKeyModifier[i] == "" then
                -- do nothing
            elseif string.find(self.MKeyModifier[i],"mb%d") then
                local iMB = tonumber(string.sub(self.MKeyModifier[i],3))
                if IsMouseButtonPressed(iMB) then
                    modMKeyState = i
                end
            elseif IsModifierPressed(self.MKeyModifier[i]) then
                modMKeyState = i
            end
        end
        if modMKeyState == nil then
            modMKeyState = default
        end
        if modMKeyState ~= nil then
            if self.pFamily == self.modFamily then
                SetMKeyState(modMKeyState, self.pFamily)
                return
            elseif GetMKeyState(self.modFamily) ~= modMKeyState then
                SetMKeyState(modMKeyState, self.modFamily)
            end
        end
    end
    SetMKeyState( GetMKeyState(self.pFamily), self.pFamily )
end

function Poll:run(event, arg, family)
    if self.running and self.pFamily == family then
        if event == "M_PRESSED" then
            self:_press()
            Sleep(self.delay)
        elseif event == "M_RELEASED" then
            if self.presses == 1 then
                self:setMKeyState()
                Sleep(self.delay)
            end
            self:release()
        end
    end
end

CoThread = {}
CoThread.__index = CoThread

function CoThread:new(f) -- f - function(MultiThread)
	local self = {}

	if type(f) ~= "function" then
		error("A function is needed",2)
	end
    self.func = f
    self.co = nil
    self.sleepUntilTimeStamp = nil
    self.Type = "CoThread"

	setmetatable(self, CoThread)
	return self
end

function CoThread:recreate()
    self:kill()
    self.co = coroutine.create(self.func)
end

function CoThread:create()
    self.co = coroutine.create(self.func)
end

function CoThread:isDead()
    if self.co == nil then
        return true
	elseif coroutine.status(self.co) == "dead" then
        self.co = nil
		return true
	else
        return false
    end
end

function CoThread:run(...)
	if self:isDead() then
        return
    end
    if self.sleepUntilTimeStamp ~= nil then
        if _GetRunningTime < self.sleepUntilTimeStamp then
            return
        else
            self.sleepUntilTimeStamp = nil
        end
    end
    coroutine.resume(self.co, self, ...)
end

function CoThread:kill()
    self.co = nil
    self.sleepUntilTimeStamp = nil
end

function CoThread:yield()
    coroutine.yield()
end

function CoThread:sleep(Milliseconds)
    self.sleepUntilTimeStamp = _GetRunningTime + Milliseconds

    coroutine.yield()
end

function CoThread:start()     
    self:recreate()
end

function CoThread:stop()
    self:kill()
end

function CoThread:isFinished()
    return self:isDead()
end

 

Logi Visitor
Jademalo
Posts: 26
Registered: ‎08-03-2011
0

Re: Color Fading Script

[ Edited ]

Wow, this script works flawlessly!

 

My only problem, but it's probably hardware - when I've got it set at a high polling rate to slow it down a bit, it starts to flicker. Is it possible to remove that flicker or not?

 

EDIT: Never mind, fixed it. Just had to change all the 15s in the colour changing bit to 1s, and it is slower and smoother

Logi Guru
bystander
Posts: 1,122
Registered: ‎06-04-2010
0

Re: Color Fading Script

I was considering making that adjustment variable as well, but never got around to it.

Logi Visitor
Jademalo
Posts: 26
Registered: ‎08-03-2011
0

Re: Color Fading Script

It would be good, having it cycle incredibly slowly here is nice. When its quick it catches your eye too much, but slow normally it is way too jittery

Logi Guru
bystander
Posts: 1,122
Registered: ‎06-04-2010
0

Re: Color Fading Script

[ Edited ]

I updated it to add the added control.  G4 and G5 will allow you to increase of decrease the color change difference.  You can also change the POLL_DELAY lower for more fine control.  This is done by altering the script near the top.

Logi Visitor
Jademalo
Posts: 26
Registered: ‎08-03-2011
0

Re: Color Fading Script

[ Edited ]

Awesome, thanks!

I've made a personal tweak so theres a config value to disable the buttons messing with it, Its bizzare when it starts changing when im playing something with my default setup (which I have that script on)

 

I'll post it if you want, it's nothing fancy. just an extra and on the button ifs.

Logi Guru
bystander
Posts: 1,122
Registered: ‎06-04-2010
0

Re: Color Fading Script


Jademalo wrote:

Awesome, thanks!

I've made a personal tweak so theres a config value to disable the buttons messing with it, Its bizzare when it starts changing when im playing something with my default setup (which I have that script on)

 

I'll post it if you want, it's nothing fancy. just an extra and on the button ifs.


Ya, I could definitely see that if you wanted to use this as a default script that can do a lot of other stuff, those keys would be annoying to have.  All the variables are at the top, so you could easily predefine everything and remove all the control keys.