Skip to content

Instantly share code, notes, and snippets.

@skinnyjames
Created June 1, 2026 14:14
Show Gist options
  • Select an option

  • Save skinnyjames/fd06d079ee64e422ce54e778673cfefc to your computer and use it in GitHub Desktop.

Select an option

Save skinnyjames/fd06d079ee64e422ce54e778673cfefc to your computer and use it in GitHub Desktop.
launcher code
module HackOS
class MovingIcon < Hokusai::Block
template <<~EOF
[template]
virtual
EOF
computed! :moving
computed! :name
computed! :width
computed! :height
computed :padding, default: Hokusai::Padding.new(0.0, 0.0, 0.0, 0.0), convert: Hokusai::Padding
def vertex
<<-EOF
#version 100
attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord;
attribute vec4 vertexColor;
uniform mat4 mvp;
uniform float uTime;
uniform int uIsHeld;
varying vec2 fragTexCoord;
varying vec4 fragColor;
void main() {
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
vec3 pos = vertexPosition;
if (uIsHeld == 1) {
// Warp the X and Y bounds slightly based on time to simulate jiggliness
pos.x += sin(pos.y * 0.1 + uTime * 15.0) * 4.0;
pos.y += cos(pos.x * 0.1 + uTime * 12.0) * 2.0;
}
gl_Position = mvp * vec4(pos, 1.0);
}
EOF
end
def fragment
<<-EOF
#version 100
precision mediump float;
varying vec2 fragTexCoord;
varying vec4 fragColor;
uniform sampler2D texture0;
void main() {
gl_FragColor = texture2D(texture0, fragTexCoord) * fragColor;
}
EOF
end
def glitch
<<-EOF
#version 100
precision mediump float;
varying vec2 fragTexCoord;
varying vec4 fragColor;
uniform sampler2D texture0;
uniform float uTime;
uniform int uIsHeld;
// Simple pseudo-random generator
float rand(vec2 co) {
return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
}
void main() {
if (uIsHeld == 1) {
// Create an intermittent horizontal slicing glitch triggered by time
float glitchThreshold = step(0.85, sin(uTime * 10.0));
float sliceY = floor(fragTexCoord.y * 10.0); // Split button into 10 bands
vec2 uvOffset = vec2(0.0);
if (glitchThreshold > 0.0) {
// Apply unique horizontal displacement per vertical slice band
uvOffset.x = (rand(vec2(sliceY, uTime)) - 0.5) * 0.08;
}
// Sample separate channels with offsets to create Chromatic Aberration splits
float r = texture2D(texture0, fragTexCoord + uvOffset).r;
float g = texture2D(texture0, fragTexCoord).g;
float b = texture2D(texture0, fragTexCoord - uvOffset).b;
float a = texture2D(texture0, fragTexCoord + uvOffset).a;
// Inject subtle matrix lines
float scanline = sin(fragTexCoord.y * 120.0) * 0.15 + 0.85;
gl_FragColor = vec4(vec3(r, g, b) * scanline, a) * fragColor;
} else {
gl_FragColor = texture2D(texture0, fragTexCoord) * fragColor;
}
}
EOF
end
def render(canvas)
@time = Hokusai.monotonic - @start
draw do
if img = Hokusai.images.get(name)
draw do
if moving == "t"
uniforms = {
"uIsHeld" => [1, HP_SHADER_UNIFORM_INT],
"uTime" => [@time, HP_SHADER_UNIFORM_FLOAT]
}
shader_begin do |command|
# command.vertex_shader = vertex
command.fragment_shader = glitch
command.uniforms = uniforms
end
end
image(img, canvas.x + padding.left, canvas.y + padding.top, (width&.to_f || canvas.width) - padding.right, (height&.to_f || canvas.height) - padding.bottom)
shader_end if moving
end
end
end
yield canvas
end
def initialize(**args)
@start = Hokusai.monotonic
super
end
end
class Homescreen < Hokusai::Block
style <<-EOF
[style]
appIcon {
width: 228.0;
height: 228.0;
padding: padding(50.0, 50.0, 50.0, 50.0);
}
container {
padding: padding(80.0, 0.0, 0.0, 80.0);
}
EOF
template do
child(Hokusai::Blocks::Vblock) do
on :taprelease do
if pressing
self.pressing = nil
control.theme.save
end
end
child(Hokusai::Blocks::Vblock) do
static :height, "300.0"
child(Hokusai::Blocks::Empty) do
end
end
child(Hokusai::Blocks::Hblock) do
static :wrap, "true"
static :width, "684.0"
each_child(MovingIcon, :apps) do |app|
merge_styles "appIcon"
prop :key do
"app-#{app.value["name"]}"
end
prop :name do
"icon-#{app.value["name"]}"
end
prop :moving do
pressing && pressing["name"] == app.value["name"] ? "t" : "f"
end
prop :width do
pressing && pressing["name"] == app.value["name"] ? 240.0 : 228.0
end
prop :height do
pressing && pressing["name"] == app.value["name"] ? 240.0 : 228.0
end
# on :tap do
# emit("open", app.value["name"])
# end
on :taphold do |event|
if event.duration > 0.3
p "taphold"
control.dbus.feedback.button(1)
self.pressing = app.value
end
end
on :tapdown do |event|
if pressing
move(pressing["name"], app.value["name"])
end
end
end
end
end
end
inject :theme
inject :control
attr_accessor :pressing
def initialize(**args)
@pressing = nil
super
end
def move(from, to)
return if from == to
targetidx = apps.index { |app| app["name"] == to }
app = apps.find{ |app| app["name"] == from }
apps.delete(app)
apps.insert(targetidx, app)
end
def apps
theme.apps
end
def render(canvas)
image(Hokusai.images.get("wallpaper"), canvas.x, canvas.y, canvas.width, canvas.height) do |command|
end
yield canvas
end
end
class Launcher < Hokusai::Block
template <<-EOF
[template]
vblock
[if="active"]
variable {
:klass="active"
@close="remove"
@swipe="handle_swipe"
}
[else]
homescreen { @open="launch" }
EOF
uses(
vblock: Hokusai::Blocks::Vblock,
variable: Variable,
homescreen: Homescreen
)
inject :control
inject :theme
inject :dbus
attr_reader :currents
attr_accessor :active
def handle_swipe(event)
if event.swipe_direction == :up
self.active = nil
end
end
def launch(app)
if current = currents[app]
self.active = current
else
# mount and setup events
self.active = begin
config = control.theme.apps.find do |config|
config["name"] == app
end
klass = eval config["class"]
klass.provides.merge!(@injections)
obj = klass.mount("root", node)
obj
end
currents[app] = active
end
end
def initialize(**args)
@currents = {}
@active = nil
super
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment