Color Chooser

using GLVisualize, Colors, GeometryTypes, Reactive

window = glscreen()

color_s = Signal(RGBA{Float32}(1,0,0,1))
color_s, color_v = vizzedit(color_s, window)

view(color_v, window, camera=:fixed_pixel)

view(visualize(rand(Point2f0, 50_000) * 1000f0, scale=Vec2f0(5), color=color_s))

renderloop(window)

Graph Editing

using GeometryTypes, GLVisualize, GLAbstraction, Reactive, GLWindow, GLFW

window = glscreen()

n = 50
n_connections = 100
a = rand(Point2f0, n)*1000f0
indices = Signal(rand(1:n, n_connections))
# for the points, we only need unique indices!
unique_indices = map(unique, indices)
points = visualize((Circle(Point2f0(0), 15f0), a), indices=unique_indices)

const point_robj = points.children[] # temporary way of getting the render object. Shouldn't stay like this
 # best way to get the gpu object. One could also start by creating a gpu array oneself.
 # this is a bit tricky, since not there are three different types.
 # for points and lines you need a GLBuffer. e.g gpu_position = GLBuffer(rand(Point2f0, 50)*1000f0)
const gpu_position = point_robj[:position]
# GPUVector adds functionality like push! and splice!
# now the lines and points share the same gpu object
# for linesegments, you can pass indices, which needs to be of some 32bit int type
lines  = visualize(gpu_position, :linesegment, indices=indices)

# current tuple of renderobject id and index into the gpu array
const m2id = GLWindow.mouse2id(window)
isoverpoint = const_lift(is_same_id, m2id, point_robj)

# inputs are a dict, materialize gets the keys out of it (equivalent to mouseposition = window.inputs[:mouseposition])
@materialize mouse_buttons_pressed, mouseposition = window.inputs

# single left mousekey pressed (while no other mouse key is pressed)
key_pressed = const_lift(GLAbstraction.singlepressed, mouse_buttons_pressed, GLFW.MOUSE_BUTTON_LEFT)
# righ
right_pressed = const_lift(GLAbstraction.singlepressed, mouse_buttons_pressed, GLFW.MOUSE_BUTTON_RIGHT)
# dragg while key_pressed. Drag only starts if isoverpoint is true
mousedragg  = GLAbstraction.dragged(mouseposition, key_pressed, isoverpoint)

# use mousedrag and mouseid + index to actually change the gpu array with the positions
preserve(foldp((value(m2id)..., Point2f0(0)), mousedragg) do v0, dragg
    if dragg == Vec2f0(0) # if drag just started. Not the best way, maybe dragged should return a tuple of (draggvalue, started)
        id, index = value(m2id)
        if id==point_robj.id && length(gpu_position) >= index
            p0 = gpu_position[index]
        else
            p0 = v0[3]
        end
    else
        id, index, p0 = v0
        if id==point_robj.id && length(gpu_position) >= index
            gpu_position[index] = Point2f0(p0) + Point2f0(dragg)
        end

    end
    return id, index, p0
end)
# On right click remove nodes!
preserve(map(right_pressed) do rp
    id, index = value(m2id)
    if rp && id==point_robj.id && length(gpu_position) >= index
        new_indices = Int[]
        indice_val = value(indices)
        for i=1:2:length(indice_val) #filter out indices
            a, b = indice_val[i], indice_val[i+1]
            if a != index && b != index
                push!(new_indices, a, b)
            end
        end
        push!(indices, new_indices) # update indices!
    end
end)
# view it!
view(lines, window, camera=:fixed_pixel)
view(points, window, camera=:fixed_pixel)

renderloop(window)

Image Processing

using Images, Colors, GeometryTypes
using Reactive, FileIO, GLVisualize
using GLAbstraction, GeometryTypes, GLWindow

window = glscreen()

# loadasset loads data from the GLVisualize asset folder and is defined as
# FileIO.load(assetpath(name))
doge = loadasset("doge.png")
# Convert to RGBA{Float32}. Float for filtering and 32 because it fits the GPU better
img = map(RGBA{Float32}, doge)
# create a slider that goes from 1-20 in 0.1 steps
slider_s, slider = vizzedit(Signal(1f0), range=1f0:0.1f0:20f0, window)

# performant conversion to RGBAU8, implemted with a functor
# in 0.5 anonymous functions offer the same speed, so this wouldn't be needed
immutable ClampRGBAU8 end
call(::ClampRGBAU8, x) = RGBA{U8}(clamp(comp1(x), 0,1), clamp(comp2(x), 0,1), clamp(comp3(x), 0,1), clamp(alpha(x), 0,1))

"""
Applies a gaussian filter to `img` and converts it to RGBA{U8}
"""
function myfilter(img, sigma)
    img = Images.imfilter_gaussian(img, [sigma, sigma])
    map(ClampRGBAU8(), img).data
end


startvalue = myfilter(img, value(slider_s))
# Use Reactive.async_map, to filter the image without blocking the main process
task, imgsig = async_map(myfilter, startvalue, Signal(img), slider_s)
# visualize the image signal
image_renderable = visualize(imgsig, model=translationmatrix(Vec3f0(50,100,0)))
view(image_renderable)

vec2i(a,b,x...) = Vec{2,Int}(round(Int, a), round(Int, b))
vec2i(vec::Vec) = vec2i(vec...)
"""
creates a rectangle around `robj`
"""
function screen(robj)
    bb = value(boundingbox(robj))
    m  = vec2i(minimum(bb))
    area = SimpleRectangle{Float32}(0,0, ((vec2i(maximum(bb))-m)+30)...)

    view(visualize((area, [Point2f0(0)]),
        color=RGBA{Float32}(0,0,0,0), stroke_color=RGBA{Float32}(0,0,0,0.7),
        stroke_width=3f0),
        camera=:fixed_pixel
    )
    robj.children[][:model] = translationmatrix(Vec3f0(15,15,0)-minimum(bb))
    view(robj, camera=:fixed_pixel)
end
screen(slider)

renderloop(window)

Mario Game

using GeometryTypes, GLVisualize, GLAbstraction, ImageMagick
using FileIO, ColorTypes, Reactive

window = glscreen()

type Mario{T}
    x           ::T
    y           ::T
    vx          ::T
    vy          ::T
    direction   ::Symbol
end



gravity(dt, mario) = (mario.vy = (mario.y > 0.0 ? mario.vy - (dt/4.0) : 0.0); mario)

function physics(dt, mario)
    mario.x = mario.x + dt * mario.vx
    mario.y = max(0.0, mario.y + dt * mario.vy)
    mario
end

function walk(keys, mario)
    mario.vx = keys[1]
    mario.direction = keys[1] < 0.0 ? :left : keys[1] > 0.0 ? :right : mario.direction
    mario
end

function jump(keys, mario)
    if keys[2] > 0.0 && mario.vy == 0.0
        mario.vy = 6.0
    end
    mario
end

function update(dt, keys, mario)
    mario = gravity(dt, mario)
    mario = jump(keys,  mario)
    mario = walk(keys,  mario)
    mario = physics(dt, mario)
    mario
end



mario2model(mario) = translationmatrix(Vec3f0(mario.x, mario.y, 0f0))*scalematrix(Vec3f0(5f0))

const mario_images = Dict()


function play(x::Vector)
    const_lift(getindex, x, loop(1:length(x)))
end

function read_sequence(path)
    if isdir(path)
        return map(load, sort(map(x->joinpath(path, x), readdir(path))))
    else
        return fill(load(path), 1)
    end
end

for verb in ["jump", "walk", "stand"], dir in ["left", "right"]
    pic = dir
    if verb != "walk" # not a sequemce
        pic *= ".png"
    end
    path = assetpath("mario", verb, pic)
    sequence = read_sequence(path)
    gif = map(img->map(RGBA{U8}, img), sequence)
    mario_images[verb*dir] = play(gif)
end
function mario2image(mario, images=mario_images)
    verb = mario.y > 0.0 ? "jump" : mario.vx != 0.0 ? "walk" : "stand"
    mario_images[verb*string(mario.direction)].value # is a signal of pictures itself (animation), so .value samples the current image
end
function arrows2vec(direction)
    direction == :up    && return Vec2f0( 0.0,  1.0)
    direction == :down  && return Vec2f0( 0.0, -1.0)
    direction == :right && return Vec2f0( 3.0,  0.0)
    direction == :left  && return Vec2f0(-3.0,  0.0)
    Vec2f0(0.0)
end

# Put everything together
arrows          = sampleon(bounce(1:10), window.inputs[:arrow_navigation])
keys            = const_lift(arrows2vec, arrows)
mario_signal    = const_lift(update, 8.0, keys, Mario(0.0, 0.0, 0.0, 0.0, :right))
image_stream    = const_lift(mario2image, mario_signal)
modelmatrix     = const_lift(mario2model, mario_signal)

mario = visualize(image_stream, model=modelmatrix)

view(mario, window, camera=:fixed_pixel)

renderloop(window)