Desenhado pelo hive.ui, em uma janelatype Msg { Tick }
func view(model: Int): hive.ui.View {
shapes := [
hive.ui.ground([hive.ui.paint(hive.ui.Tone.HEX("#2d5c34"))], 20.0, 20.0),
hive.ui.box(
[
hive.ui.at(0.0, 0.5, -3.0),
hive.ui.paint(hive.ui.Tone.HEX("#b5651d")),
hive.ui.surface(hive.ui.Surface.Planks()),
],
1.0, 1.0, 1.0,
),
hive.ui.sphere([hive.ui.at(2.0, 1.0, -4.0), hive.ui.paint(hive.ui.Tone.HEX("#e0c341"))], 1.0),
// Um cone recebe os dois raios: zero no topo é o pontudo.
hive.ui.cone(
[
hive.ui.at(-2.0, 0.4, -3.0),
hive.ui.paint(hive.ui.Tone.HEX("#ff5a1f")),
hive.ui.surface(hive.ui.Surface.Gloss()),
],
0.0, 0.4, 0.8,
),
// E uma cor com alpha é desenhada translúcida.
hive.ui.box(
[hive.ui.at(0.0, 1.2, -1.5), hive.ui.paint(hive.ui.Tone.RGBA(120, 200, 255, 96))],
3.0, 2.0, 0.2,
),
]
return hive.ui.scene(
[hive.ui.grow(1), hive.ui.eye(0.0, 1.6, 4.0), hive.ui.aim(0.0, 0.0), hive.ui.lens(70), hive.ui.fog(60)],
shapes,
)
}
proc update(model: mut Int, msg: Msg): Msg {
return msg
}
proc main(): void {
spawn(hive.ui.window("Uma cena 3D", view, update), 0)
}hive.ui.scene(attrs, shapes) é o único widget que só uma janela consegue desenhar: uma câmera, um céu e um vetor de formas, reconstruído a partir do estado por um func comum a cada quadro. Nada é um handle — nenhuma malha para guardar, nenhum material para alocar — então um programa diz o que existe agora, nunca o que mudou. Suas formas são chamadas hive.ui como qualquer outro widget, e é a única parte da biblioteca que carrega um download: um three.js fixado, buscado na primeira build que desenha uma cena e guardado em cache depois disso.
As formas recebem as dimensões como carga, em metros, porque uma esfera sem raio não é uma esfera com um raio padrão:
box(attrs, width, height, depth), sphere(attrs, radius), cylinder(attrs, radius, height), e cone(attrs, top, bottom, height) — um topo 0 é o pontudo, e um topo igual à base, um cilindro.roof(attrs, wide, tall, long), uma cumeeira ao longo do comprimento e uma empena em cada ponta; ground(attrs, width, depth), já deitado.label(attrs, words), sempre de frente para quem olha; sprite(attrs, image, wide, tall), uma imagem dos assets/ do programa que faz o mesmo, fica de pé sobre a base e não pelo meio, é desenhada sem filtro, e fica sem tingir a menos que pintada.line(attrs, fromX, fromY, fromZ, toX, toY, toZ), que não tem posição própria.at(x, y, z) é onde fica o meio de uma forma. turn(x, y, z) é a rotação dela em radianos como um rumo: a guinada, y, primeiro, depois a inclinação, x, em torno do eixo lateral da própria forma, depois a rolagem, z, em torno do próprio comprimento — então uma coisa virada para algum lugar e depois inclinada levanta o nariz na direção em que olha. paint(Tone) é a cor dela, e uma cor com alfa — Tone.RGBA, ou um Tone.HEX de quatro ou oito dígitos — é translúcida.
surface(Surface) é do que uma forma é feita, desenhado sobre a cor dela, do chão para cima: Turf, Gravel, Tarmac, Kerb; Concrete, Brick, Panes, Planks, Staves; Bark, Leaves, Crowd; Mesh; e Speckle, Metal, Carbon, Rubber, Glass, Gloss. Um acabamento se repete a cada dois metros mais ou menos, uma caixa face a face; todos têm relevo exceto Gloss, Glass e Mesh, que tem furos de verdade e aparece dos dois lados; e Panes pinta o próprio vidro. Onde uma forma não diz nada, o tipo dela decide — um chão é Turf, um cilindro ou cone Staves, uma esfera Speckle, qualquer outra coisa Planks. Uma fotografia em assets/textures/<surface>.jpg substitui o desenho de um acabamento, com -normal.jpg ao lado como relevo; ela deve ter média cinza, já que é aplicada sobre a cor, e uma que falta volta ao desenho.