02 Oct, 2025

Skydimo Script Development Complete Guide

Welcome to the world of Skydimo script development! This guide will help you learn how to create your own RGB lighting effects using Lua scripts, whether you’re a beginner or an advanced user. This feature is available in the Skydimo beta version.

Table of Contents

Open Table of Contents


Features Overview

  • Creative Freedom: Write unique lighting effects with Lua code
  • AI Assistant: Generate custom effects with a single sentence, AI helps you write and optimize code
  • Audio Response: Make lights dance to music, supports real-time FFT spectrum analysis
  • Multi-tab Management: Edit multiple scripts simultaneously, easy switching and organization
  • Hot Reload: Changes take effect immediately, no need to restart software
  • Import/Export: Share your creations or use community scripts
  • Full Control: Speed, brightness, color temperature, and hue all at your fingertips

Quick Start

Your First Script: Rainbow Gradient

In Skydimo → “Scripts” page, create a new script and enter:

function get_color(x, y, width, height, env)
    -- Generate rainbow colors based on position and time
    local hue = (x / width * 360 + env.time * 60) % 360
    return hsv(hue, 255, 255)
end

Steps:

  1. Click “Register Mode” button in the top right (buttons from left to right: Register/Update Mode, Restore, Unregister, Export, Import)
  2. Find the newly registered script in the mode list
  3. Click to enable, device will display flowing rainbow gradient effect

Code Explanation:

  • get_color: Function called for each pixel
  • x / width: Generate 0–1 position ratio
  • env.time: Continuously growing time value, makes colors flow
  • hsv(): Convert hue, saturation, brightness to RGB color

Lua Script Basics

What is Lua?

Lua is a lightweight, easy-to-learn programming language. Skydimo uses Lua 5.4.

Basic Syntax Quick Reference

-- Single line comment

--[[
  Multi-line comment
  Can write multiple lines
]]

-- Variable definition (no type declaration needed)
local speed = 100
local name = "Rainbow"
local enabled = true

-- Math operations
local result = (10 + 5) * 2 / 3

-- Conditional statements
if x > 10 then
    -- Execute code
elseif x == 5 then
    -- Another case
else
    -- Default case
end

-- Loops
for i = 1, 10 do
    -- Repeat 10 times
end

-- Function definition
local function calculate(a, b)
    return a + b
end

Core API Specification

Required Function: get_color(x, y, width, height, env)

Purpose: Calculate color value for each LED (called multiple times per frame)

Parameters:

  • x, y: Current pixel coordinates (starting from 0)
  • width, height: Device total width/height
  • env: Environment variable object

Return Value: A 32-bit integer, format 0x00BBGGRR (Blue-Green-Red order, each channel 0–255)

Example:

function get_color(x, y, width, height, env)
    return rgb(255, 0, 0)  -- Pure red
end

Optional Function: begin_frame(env)

Purpose: Executed once at the beginning of each frame, for pre-computation or initializing frame-level variables.

-- Global variable stores pre-computed results
local wave_offset = 0

function begin_frame(env)
    -- Calculate wave offset once per frame
    wave_offset = math.sin(env.time) * 50
end

function get_color(x, y, width, height, env)
    -- Use pre-computed value directly
    local hue = (x / width * 360 + wave_offset) % 360
    return hsv(hue, 255, 255)
end

Environment Variables

Common fields in the env environment object:

  • env.time: Cumulative time since startup (seconds, float)
  • env.dt: Time step from previous frame to current frame (seconds)
  • env.fps: Current frame rate (frames/second)
  • env.random: Random number seed 0–1 (changes per frame)
  • env.bpm: Beat Per Minute, for rhythm-driven effects (optional)
  • env.audio: Audio data object (optional)
    • env.audio.level: Overall volume envelope 0–1
    • env.audio.fft: Spectrum array, low to high frequency
    • env.audio.sampleRate: Audio sample rate
    • env.audio.enabled: Whether audio input is enabled

Built-in Function Library

Color construction and transformation:

  • rgb(r, g, b): Return 32-bit color
  • hsv(h, s, v): HSV to RGB, h: 0–360, s/v: 0–255
  • saturate(v): Clamp value to 0–1
  • clamp(v, min, max): Range clipping
  • mix(a, b, t) / lerp(a, b, t): Linear blending
  • smoothstep(edge0, edge1, x): Smooth step
  • map(x, inMin, inMax, outMin, outMax): Range mapping

Noise and random:

  • random(): 0–1 random
  • noise1(x) / noise2(x, y): Smooth noise

Audio Visualization

Example spectrum visualization:

local spectrum = {}

function begin_frame(env)
    if env.audio and env.audio.fft then
        spectrum = env.audio.fft
    end
end

function get_color(x, y, width, height, env)
    if not spectrum or #spectrum == 0 then
        return rgb(10, 10, 10)
    end
    local band = math.max(1, math.floor((x / width) * #spectrum))
    local amp = spectrum[band] or 0
    local h = (band / #spectrum) * 360
    local v = math.floor(math.min(255, amp * 255 * 1.5))
    return hsv(h, 255, v)
end

Runtime Mechanism

Rendering loop sequence:

  1. Call begin_frame(env) at frame start (if implemented)
  2. Then call get_color(x, y, width, height, env) for each pixel
  3. Submit frame color buffer to device

Performance tips:

  • Do complex calculations in begin_frame and cache results
  • Avoid creating many temporary tables
  • Use pre-computed lookup tables when possible

AI-Assisted Development

Describe your desired effect in the script editor (e.g., “low frequency drives warm color bars, beat pulse enhances brightness”), and AI will generate initial code. Continue suggesting modifications to iterate quickly.


Practical Examples

1) Spectrum Bar Chart (Horizontal)

local smoothed = {}

function begin_frame(env)
    if not (env.audio and env.audio.fft) then return end
    local fft = env.audio.fft
    for i = 1, #fft do
        local v = fft[i]
        smoothed[i] = smoothed[i] and (smoothed[i] * 0.6 + v * 0.4) or v
    end
end

function get_color(x, y, width, height, env)
    if not smoothed or #smoothed == 0 then return rgb(0,0,0) end
    local band = math.max(1, math.floor((x / width) * #smoothed))
    local level = smoothed[band] or 0
    local barH = math.floor(level * height)
    if (height - 1 - y) <= barH then
        local hue = (band / #smoothed) * 360
        return hsv(hue, 255, 255)
    else
        return rgb(0, 0, 0)
    end
end

Best Practices

  • Prioritize heavy computation in begin_frame and data preprocessing
  • Cache frequently accessed global objects with local variables
  • Carefully create temporary tables, avoid table.insert expansion overhead in loops
  • Protect parameters and return values with boundary checks
  • Keep color and brightness ranges consistent (0–255), clip if exceeding

FAQ

Q1: What is the return format of get_color?
A: Returns a 32-bit integer, format 0x00BBGGRR.

Q2: Why doesn’t audio visualization respond?
A: Check env.audio.enabled and input device; also confirm if runtime environment has granted microphone permission.

Q3: How to improve frame rate?
A: Reduce complex calculations in get_color; put reusable values in begin_frame; avoid creating temporary tables.

Q4: Does it support running multiple scripts simultaneously?
A: Depends on host implementation; recommend activating one script per device for debugging and performance assurance.


Questions or suggestions? Click here for quick feedback.

Technical Support | Contact Us