summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--client/main.ha29
-rw-r--r--client/paintui/paintui.ha39
-rw-r--r--drawing/drawing.ha27
-rw-r--r--drawing/op.ha28
-rw-r--r--server/main.ha4
-rw-r--r--todo3
7 files changed, 106 insertions, 25 deletions
diff --git a/.gitignore b/.gitignore
index 218cb60..5321b16 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.ppm
+e/*
diff --git a/client/main.ha b/client/main.ha
index 2a341c4..04e6854 100644
--- a/client/main.ha
+++ b/client/main.ha
@@ -47,8 +47,6 @@ export fn main() void = {
case let err: net::error =>
fmt::fatal("couldn't connect to server:",net::strerror(err));
};
-
-
const pollfd: [1]poll::pollfd = [ poll::pollfd {
fd = conn, events=poll::event::POLLIN, revents = 0
@@ -56,7 +54,7 @@ export fn main() void = {
const packet_reader = packet_reader::new();
// paintui state
- let pstate = paintui::state { ... };
+ let pstate = paintui::state { size_idx = 4, ... };
let camera_pos: pos = (25, 50);
let quit = false;
@@ -65,10 +63,14 @@ export fn main() void = {
let requested_chunks: []pos = [];
- // in WORLD coords
+ // in SCREEN coords
let mouse_pos: pos = (0,0);
let mouse_down = false;
request_visible_chunks(pictures, conn, camera_pos, &requested_chunks);
+
+
+ const win_pic = picture_from_surface(wsurf, (9,9));
+
for (!quit) {
const did_move = do_movement(&camera_pos);
@@ -86,20 +88,27 @@ export fn main() void = {
case sdl2::SDL_EventType::QUIT => quit = true;
case sdl2::SDL_EventType::KEYDOWN =>
const keysym = ev.key.keysym.sym;
- if (keysym == sdl2::SDL_Keycode::ESCAPE) quit = true;
+ if (keysym == sdl2::SDL_Keycode::ESCAPE) quit = true
+ else if (sdl2::SDL_Keycode::ZERO <= keysym
+ && keysym <= sdl2::SDL_Keycode::NINE)
+ paintui::key(&pstate, keysym - sdl2::SDL_Keycode::ZERO);
case sdl2::SDL_EventType::MOUSEBUTTONDOWN,
sdl2::SDL_EventType::MOUSEBUTTONUP =>
const edata = ev.button;
- mouse_pos = (edata.x + camera_pos.0, edata.y + camera_pos.1);
+ mouse_pos = (edata.x, edata.y);
if (edata.button == 1)
mouse_down = (edata.state == 1);
case sdl2::SDL_EventType::MOUSEMOTION =>
const edata = ev.motion;
- mouse_pos = (edata.x + camera_pos.0, edata.y + camera_pos.1);
+ mouse_pos = (edata.x, edata.y);
+ case sdl2::SDL_EventType::MOUSEWHEEL =>
+ const edata = ev.wheel;
+ paintui::mousewheel(&pstate, edata.y);
case => void;
};
- match (paintui::tick(&pstate, mouse_pos, mouse_down)) {
+ const mouse_pos_world = (mouse_pos.0 + camera_pos.0, mouse_pos.1 + camera_pos.1);
+ match (paintui::tick(&pstate, mouse_pos_world, mouse_down)) {
case void => yield;
case let op: drawing::op =>
drawing::perform(pictures, op);
@@ -140,7 +149,8 @@ export fn main() void = {
};
};
- drawing::clear_picture(&picture_from_surface(wsurf,(9,9)), 0xff0000);
+
+ drawing::clear_picture(&win_pic, 0xff0000);
for (let i = 0z; i < len(pictures); i += 1) {
const psurf = picture_surfaces[i];
@@ -148,6 +158,7 @@ export fn main() void = {
render_picture(pic, psurf, wsurf, camera_pos);
};
+ drawing::circle_hollow(&win_pic, mouse_pos, paintui::sizes[pstate.size_idx]: i32, pstate.color);
sdl2::SDL_UpdateWindowSurface(win)!;
n += 1;
diff --git a/client/paintui/paintui.ha b/client/paintui/paintui.ha
index ce55bb7..212e16b 100644
--- a/client/paintui/paintui.ha
+++ b/client/paintui/paintui.ha
@@ -10,12 +10,31 @@
use drawing;
use drawing::{pos};
+export const sizes: [_]u8 = [
+ 1, 2, 4, 8, 16, 32, 48, 64, 80, 96, 112, 128
+];
+
+const colors: [_]u32 = [
+ 0xffffff, // white
+ 0xff4040, // red
+ 0xff8000, // orange
+ 0xc0c040, // yellow
+ 0x00c000, // green
+ 0x00c0c0, // teal
+ 0x4040ff, // blue
+ 0xc000c0, // purple
+ 0x808080, // grey
+ 0x000000, // black
+];
+
export type state = struct {
// last known mouse position, in world coordinates
last_mouse_pos: pos,
// last known mouse pressed-ness
- last_mouse_pressed: bool
+ last_mouse_pressed: bool,
+ size_idx: size,
+ color: u32
};
export fn tick(
@@ -32,7 +51,23 @@ export fn tick(
&& (mouse_pos.0 != pstate.last_mouse_pos.0
|| mouse_pos.1 != pstate.last_mouse_pos.1
|| (!pstate.last_mouse_pressed)))
- mouse_pos: drawing::op_circle
+ drawing::op_circle {
+ pos = mouse_pos,
+ radius = sizes[pstate.size_idx],
+ color = pstate.color,
+ }
else void;
};
+export fn mousewheel(pstate: *state, amt: i32) void = {
+ if (amt < 0 && pstate.size_idx > 0)
+ pstate.size_idx -= 1
+ else if (amt > 0 && pstate.size_idx < len(sizes) - 1)
+ pstate.size_idx += 1;
+};
+
+export fn key(pstate: *state, key: uint) void = {
+ assert(key <= 9, "what what what what what");
+ pstate.color = colors[key];
+};
+
diff --git a/drawing/drawing.ha b/drawing/drawing.ha
index fc59e1b..54a877b 100644
--- a/drawing/drawing.ha
+++ b/drawing/drawing.ha
@@ -77,15 +77,38 @@ export fn circle(picture: *picture, c: pos, r: i32, color: u32) void = {
};
};
+export fn circle_hollow(picture: *picture, c: pos, r: i32, color: u32) void = {
+ const (cx,cy) = c;
+ const ymin = max(0, cy-r);
+ const ymax = min(picture.h:i32-1, cy+r);
+ const xmin = max(0, cx-r);
+ const xmax = min(picture.w:i32-1, cx+r);
+
+ const r2l = r*r - r;
+ const r2u = r*r + r;
+
+ for (let y = ymin; y<=ymax; y+=1) {
+ const yd = y-cy;
+ for (let x = xmin; x<=xmax; x+=1) {
+ const xd = x-cx;
+ const v = yd*yd + xd*xd;
+ if (r2l <= v && v <= r2u) {
+ pic_set(picture, (x,y), color);
+ };
+ };
+ };
+};
export fn perform(pictures: []picture, op: op) void = {
match (op) {
case op_other => abort("oopsy");
case let o: op_circle =>
- const x = o.0, y=o.1;
+ const x = o.pos.0, y=o.pos.1;
+ const r = o.radius;
+ const c = o.color & 0xffffff;
for (const pic &.. pictures) {
let pos_within_pic =
(x - pic.world_pos.0, y - pic.world_pos.1): pos;
- circle(pic, pos_within_pic, 20, 0xff0088);
+ circle(pic, pos_within_pic, r: i32, c);
};
};
};
diff --git a/drawing/op.ha b/drawing/op.ha
index acbca29..532fd75 100644
--- a/drawing/op.ha
+++ b/drawing/op.ha
@@ -1,25 +1,35 @@
use io;
use endian;
-export type op_circle = pos;
+export type op_circle = struct {
+ pos: pos,
+ radius: u8,
+ color: u32
+};
export type op_other = void;
export type op = (op_circle| op_other);
+def SER_LEN: size = 13;
+
// return value must be freed... for now. ehh
export fn ser_op(op: op) []u8 = {
const opc = op as op_circle;
- let buf: []u8 = alloc([0...],8);
- endian::leputu32(buf[0..4], opc.0: u32);
- endian::leputu32(buf[4..8], opc.1: u32);
+ let buf: []u8 = alloc([0...],SER_LEN);
+ endian::leputu32(buf[0..4], opc.pos.0: u32);
+ endian::leputu32(buf[4..8], opc.pos.1: u32);
+ endian::leputu32(buf[8..12], opc.color: u32);
+ buf[12] = opc.radius;
return buf;
};
export fn deser_op(bytes: []u8) op = {
- assert(len(bytes) == 8, "wrong length somehow");
- return (
- endian::legetu32(bytes[0..4]): i32,
- endian::legetu32(bytes[4..8]): i32,
- ) : op_circle;
+ assert(len(bytes) == SER_LEN, "wrong length somehow");
+ return op_circle {
+ pos = (endian::legetu32(bytes[0..4]): i32,
+ endian::legetu32(bytes[4..8]): i32),
+ color = endian::legetu32(bytes[8..12]),
+ radius = bytes[12],
+ };
};
diff --git a/server/main.ha b/server/main.ha
index 31cb6dc..71bb71b 100644
--- a/server/main.ha
+++ b/server/main.ha
@@ -195,8 +195,8 @@ fn handle_packet(
match (packet) {
case let op: packet_reader::packet_drawop =>
const opc = op as drawing::op_circle;
- fmt::printfln("#{}: drawop ({:+6},{:+6})",
- conn_idx,opc.0,opc.1)!;
+ fmt::printfln("#{}: drawop ({:+6},{:+6}) r{}",
+ conn_idx,opc.pos.0,opc.pos.1, opc.radius)!;
drawing::perform(state.pictures, opc);
for (let other_idx = 0z;
other_idx < len(state.connections);
diff --git a/todo b/todo
index 8b13789..111b85b 100644
--- a/todo
+++ b/todo
@@ -1 +1,2 @@
-
+smooth brush strokes
+rle compression