summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Kobert <d-kobert@web.de>2019-05-31 04:18:45 +0200
committerDennis Kobert <d-kobert@web.de>2019-05-31 04:18:45 +0200
commit15ebdb46e906aceef5cea09e2db63650e66369d1 (patch)
tree7fd5a716b10b835ebcc961142130a3bdba6bf2f1
parent3f539662518609390964c60acf2f38d9a08aee6d (diff)
parenta6d2d62fae44b6d8c96e51055f7222bc679efc48 (diff)
Merge branch 'wasm' of github.com:TrueDoctor/DiscoBot into wasm
-rw-r--r--WebInterface/wasm/asm-paint/Cargo.toml21
-rwxr-xr-xWebInterface/wasm/asm-paint/build.sh3
-rwxr-xr-xWebInterface/wasm/asm-paint/deploy4
-rwxr-xr-xWebInterface/wasm/asm-paint/deploy.py102
-rw-r--r--WebInterface/wasm/asm-paint/index.html14
-rw-r--r--WebInterface/wasm/asm-paint/lighttpd.config29
-rw-r--r--WebInterface/wasm/asm-paint/loader.js4
-rwxr-xr-xWebInterface/wasm/asm-paint/run3
-rw-r--r--WebInterface/wasm/asm-paint/src/app.rs19
-rw-r--r--WebInterface/wasm/asm-paint/src/canvas.rs39
-rw-r--r--WebInterface/wasm/asm-paint/src/client_logger.rs46
-rw-r--r--WebInterface/wasm/asm-paint/src/lib.rs31
-rw-r--r--WebInterface/wasm/asm-paint/src/shader.rs97
-rw-r--r--WebInterface/wasm/asm-paint/src/site.rs28
14 files changed, 309 insertions, 131 deletions
diff --git a/WebInterface/wasm/asm-paint/Cargo.toml b/WebInterface/wasm/asm-paint/Cargo.toml
index 5713415..ceb1866 100644
--- a/WebInterface/wasm/asm-paint/Cargo.toml
+++ b/WebInterface/wasm/asm-paint/Cargo.toml
@@ -1,7 +1,10 @@
[package]
name = "asm-paint-rs"
version = "0.1.0"
-authors = ["Dennis Kobert <d-kobert@web.de>"]
+authors = [
+ "natrixaeria",
+ "TrueDoctor"
+]
edition = "2018"
[lib]
@@ -9,4 +12,18 @@ crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
-web-sys = {version="0.3.22", features=["Window", "Document", "HtmlElement", "Node", "Element"]}
+log = "0.4"
+fern = "0.5"
+
+[dependencies.web-sys]
+version = "0.3.22"
+features = [
+ 'Document',
+ 'Element',
+ 'HtmlCanvasElement',
+ 'WebGl2RenderingContext',
+ 'WebGlShader',
+ 'WebGlProgram',
+ 'WebGlBuffer',
+ 'Window'
+]
diff --git a/WebInterface/wasm/asm-paint/build.sh b/WebInterface/wasm/asm-paint/build.sh
deleted file mode 100755
index 61c1997..0000000
--- a/WebInterface/wasm/asm-paint/build.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-wasm-pack build --target web
diff --git a/WebInterface/wasm/asm-paint/deploy b/WebInterface/wasm/asm-paint/deploy
index 9f7f823..13d1d0a 100755
--- a/WebInterface/wasm/asm-paint/deploy
+++ b/WebInterface/wasm/asm-paint/deploy
@@ -1,4 +1,2 @@
#!/bin/sh
-
-./build.sh
-./deploy.py
+lighttpd -f ./lighttpd.config
diff --git a/WebInterface/wasm/asm-paint/deploy.py b/WebInterface/wasm/asm-paint/deploy.py
deleted file mode 100755
index b64c322..0000000
--- a/WebInterface/wasm/asm-paint/deploy.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/usr/bin/env python3
-
-from socket import (socket, AF_INET, SOCK_STREAM, IPPROTO_TCP,
- SOL_SOCKET, SO_REUSEADDR)
-from threading import Thread
-
-WASM_MIME = 'application/wasm'
-JS_MIME = 'application/javascript'
-PLAIN_MIME = 'text/plain'
-HTML_MIME = 'text/html'
-
-REQUESTS = {
- '/': ('index.html', HTML_MIME),
- '/loader.js': ('loader.js', JS_MIME),
- '/asm_paint_rs.js': ('pkg/asm_paint_rs.js', JS_MIME),
- '/asm_paint_rs_bg.wasm': ('pkg/asm_paint_rs_bg.wasm', WASM_MIME),
-}
-
-PAGE_404 = '''<!doctype html><html><head></head>
-<body>
- <marquee><h1>Request '404 Not Found'</h1></marquee>
- <span>resource <address>'<strong>{}</strong>'</address> not found</span>
-</body>
-</html>'''
-
-def header_line_to_entry(line):
- key, value = line.decode('utf-8').split(': ')
- return key, value
-
-
-class Server:
- def __init__(self):
- self.s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
- self.s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
- self.threads = []
-
- def rec_http(self, client):
- headers = b''
- while not headers.endswith(b'\r\n' * 2):
- headers += client.recv(1)
- headers = headers.split(b'\r\n')
- head, headers = headers[0], headers[1:]
- method, url, _ = head.split(b' ')
- url = url.decode('utf-8')
- headers = dict(header_line_to_entry(v) for v in headers if v)
- if 'Content-Length' in headers:
- client.recv(int(headers['Content-Length']))
- return method, url, headers
-
- def sen_http(self, client, status='200 OK', payload=b'', mime=PLAIN_MIME):
- print('sende...')
- client.send((f'HTTP/1.1 {status}\r\n'
- f'Content-Length: {len(payload)}\r\n'
- f'Content-Type: {mime}\r\n\r\n').encode('utf-8')
- + payload)
- print('gesendet')
-
- def run_client(self, client, addr):
- while True:
- print('wait for receive')
- method, url, headers = self.rec_http(client)
- print('got receive')
- if method == b'GET':
- if not url.startswith('/'):
- url += '/'
- print(f'got request for "{url}"')
- if url in REQUESTS:
- path, mime = REQUESTS[url]
- f = open(path, 'rb')
- payload = f.read()
- f.close()
- self.sen_http(client, '200 OK', payload, mime)
- elif url == '/close':
- client.close()
- self.kill()
- exit()
- else:
- self.sen_http(client, '404 Not Found',
- PAGE_404.format(url).encode('utf-8'),
- HTML_MIME)
- else:
- self.sen_http(client, '400 Bad Request', b'only supporting GET')
-
- def deploy(self, host='localhost', port=8080):
- self.s.bind((host, port))
- self.s.listen(1)
- while True:
- client, addr = self.s.accept()
- thread = Thread(target=self.run_client, args=(client,addr))
- self.threads.append(thread)
- thread.run()
-
- def kill(self):
- self.s.close()
-
-
-if __name__ == '__main__':
- try:
- server = Server()
- server.deploy()
- finally:
- server.kill()
diff --git a/WebInterface/wasm/asm-paint/index.html b/WebInterface/wasm/asm-paint/index.html
index 46be213..c4f3734 100644
--- a/WebInterface/wasm/asm-paint/index.html
+++ b/WebInterface/wasm/asm-paint/index.html
@@ -4,7 +4,21 @@
<meta charset="UTF-8">
<title> Scribblio </title>
<script src='loader.js' type='module'></script>
+ <style>
+ body {
+ margin: 0;
+ background: black;
+ }
+ #canvas {
+ width: 100%;
+ height: 100%;
+ }
+ img {
+ background: violet;
+ }
+ </style>
</head>
<body>
+ <canvas id='canvas'></canvas>
</body>
</html>
diff --git a/WebInterface/wasm/asm-paint/lighttpd.config b/WebInterface/wasm/asm-paint/lighttpd.config
new file mode 100644
index 0000000..5fae32d
--- /dev/null
+++ b/WebInterface/wasm/asm-paint/lighttpd.config
@@ -0,0 +1,29 @@
+server.http-parseopts = (
+ "header-strict" => "enable",
+ "host-strict" => "enable",
+ "host-normalize" => "enable",
+ "url-normalize" => "enable",
+ "url-normalize-unreserved" => "enable",
+ "url-normalize-required" => "enable",
+ "url-ctrls-reject" => "enable",
+ "url-path-2f-decode" => "enable",
+ "url-path-dotseg-remove" => "enable",
+ "url-query-20-plus" => "enable"
+)
+
+server.document-root = "/home/jan/projects/DiscoBot/WebInterface/wasm/asm-paint"
+server.port = 8080
+dir-listing.activate = "enable"
+index-file.names = ( "index.html" )
+mimetype.assign = (
+ ".html" => "text/html",
+ ".txt" => "text/plain",
+ ".css" => "text/css",
+ ".js" => "application/x-javascript",
+ ".jpg" => "image/jpeg",
+ ".jpeg" => "image/jpeg",
+ ".gif" => "image/gif",
+ ".png" => "image/png",
+ ".wasm" => "application/wasm",
+ "" => "application/octet-stream"
+)
diff --git a/WebInterface/wasm/asm-paint/loader.js b/WebInterface/wasm/asm-paint/loader.js
index f1d15ef..4566ee1 100644
--- a/WebInterface/wasm/asm-paint/loader.js
+++ b/WebInterface/wasm/asm-paint/loader.js
@@ -1,2 +1,2 @@
-import {default as init} from './asm_paint_rs.js'
-init('asm_paint_rs_bg.wasm');
+import {default as init} from './pkg/asm_paint_rs.js'
+init('./pkg/asm_paint_rs_bg.wasm');
diff --git a/WebInterface/wasm/asm-paint/run b/WebInterface/wasm/asm-paint/run
new file mode 100755
index 0000000..1da1e35
--- /dev/null
+++ b/WebInterface/wasm/asm-paint/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+wasm-pack build --release --target web
diff --git a/WebInterface/wasm/asm-paint/src/app.rs b/WebInterface/wasm/asm-paint/src/app.rs
new file mode 100644
index 0000000..005764d
--- /dev/null
+++ b/WebInterface/wasm/asm-paint/src/app.rs
@@ -0,0 +1,19 @@
+use crate::site::Site;
+
+pub struct App {
+ site: Site,
+}
+
+impl App {
+ pub fn new() -> Option<Self> {
+ Some(Self {
+ site: Site::from_current()?,
+ })
+ }
+
+ pub fn run(&mut self) {
+ let mut canvas = self.site.create_canvas().unwrap();
+ canvas.init().unwrap();
+ info!("canvas initialisation was succuessfull");
+ }
+}
diff --git a/WebInterface/wasm/asm-paint/src/canvas.rs b/WebInterface/wasm/asm-paint/src/canvas.rs
new file mode 100644
index 0000000..400e258
--- /dev/null
+++ b/WebInterface/wasm/asm-paint/src/canvas.rs
@@ -0,0 +1,39 @@
+use web_sys;
+use web_sys::{WebGl2RenderingContext};
+use wasm_bindgen::JsCast;
+use crate::shader::Shaders;
+
+pub struct Canvas {
+ element: web_sys::HtmlCanvasElement,
+ ctx: WebGl2RenderingContext,
+ shaders: Shaders,
+}
+
+impl Canvas {
+ pub fn new(element: web_sys::Element) -> Option<Self> {
+ let element: web_sys::HtmlCanvasElement =
+ element.dyn_into::<web_sys::HtmlCanvasElement>()
+ .ok()?;
+ debug!("create webgl2 context");
+ let ctx = element.get_context("webgl2").ok()??
+ .dyn_into::<WebGl2RenderingContext>().ok()?;
+ info!("created webgl2 context successfully");
+ Some(Self {
+ element, ctx,
+ shaders: Shaders::new(),
+ })
+ }
+
+ pub fn init(&mut self) -> Result<(), ()> {
+ self.shaders.init(&self.ctx).map_err(|_|())?;
+ self.ctx.clear_color(1.0, 0.2, 1.0, 1.0);
+ self.ctx.clear(WebGl2RenderingContext::COLOR_BUFFER_BIT);
+ Ok(())
+ }
+}
+
+impl Drop for Canvas {
+ fn drop(&mut self) {
+ self.shaders.remove(&self.ctx);
+ }
+}
diff --git a/WebInterface/wasm/asm-paint/src/client_logger.rs b/WebInterface/wasm/asm-paint/src/client_logger.rs
new file mode 100644
index 0000000..f71918f
--- /dev/null
+++ b/WebInterface/wasm/asm-paint/src/client_logger.rs
@@ -0,0 +1,46 @@
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+extern "C" {
+ #[wasm_bindgen(js_namespace=console, js_name=debug)]
+ fn __console_debug_colored2(f: &str, c1: &str, c2: &str);
+ #[wasm_bindgen(js_namespace=console, js_name=info)]
+ fn __console_info_colored2(f: &str, c1: &str, c2: &str);
+ #[wasm_bindgen(js_namespace=console, js_name=warn)]
+ fn __console_warn_colored2(f: &str, c1: &str, c2: &str);
+ #[wasm_bindgen(js_namespace=console, js_name=error)]
+ fn __console_error_colored2(f: &str, c1: &str, c2: &str);
+}
+
+fn log(rec: &log::Record) {
+ let log_fn = match rec.level() {
+ log::Level::Trace | log::Level::Debug => __console_debug_colored2,
+ log::Level::Info => __console_info_colored2,
+ log::Level::Warn => __console_warn_colored2,
+ log::Level::Error => __console_error_colored2,
+ };
+ log_fn(&format!("{}", rec.args()),
+ &format!("color: {}", match rec.level() {
+ log::Level::Trace => "violet",
+ log::Level::Debug => "blue",
+ log::Level::Info => "green",
+ log::Level::Warn => "orange",
+ log::Level::Error => "red"
+ }), "");
+}
+
+pub fn init_logger() {
+ fern::Dispatch::new().format(|out, message, record|{
+ out.finish(format_args!(
+ "%c{}%c {} > {}",
+ record.level(),
+ record.target(),
+ message
+ )
+ )
+ })
+ .level(log::LevelFilter::Debug)
+ .chain(fern::Output::call(log))
+ .apply().unwrap();
+}
+
diff --git a/WebInterface/wasm/asm-paint/src/lib.rs b/WebInterface/wasm/asm-paint/src/lib.rs
index 462a89d..6c773c5 100644
--- a/WebInterface/wasm/asm-paint/src/lib.rs
+++ b/WebInterface/wasm/asm-paint/src/lib.rs
@@ -1,27 +1,20 @@
-use wasm_bindgen::prelude::*;
+mod client_logger;
+mod shader;
+mod canvas;
+mod site;
+mod app;
-macro_rules! console_log {
- ($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
-}
+use wasm_bindgen::prelude::*;
-#[wasm_bindgen]
-extern "C" {
- #[wasm_bindgen(js_namespace = console)]
- fn log(s: &str);
-}
+#[macro_use]
+extern crate log;
#[wasm_bindgen(start)]
pub fn entry() {
- use web_sys;
- console_log!("hello {} wasm", 42);
-
- let window = web_sys::window().unwrap();
-
- let document = window.document().unwrap();
-
- let body = document.body().unwrap();
+ client_logger::init_logger();
- //body.set_inner_html("<marquee><h1 style='font-size: 100px'>Hello from WASM</h1></marquee>");
+ info!("begin running wasm application");
- body.set_inner_html("oho");
+ let mut app = app::App::new().unwrap();
+ app.run();
}
diff --git a/WebInterface/wasm/asm-paint/src/shader.rs b/WebInterface/wasm/asm-paint/src/shader.rs
new file mode 100644
index 0000000..3352bcf
--- /dev/null
+++ b/WebInterface/wasm/asm-paint/src/shader.rs
@@ -0,0 +1,97 @@
+use web_sys::{WebGlProgram, WebGl2RenderingContext};
+
+const VERTEX_SHADER: &str =
+r#"#version 300 es
+in vec4 pos;
+void main() {
+ gl_Position = pos;
+}
+"#;
+
+const FRAGMENT_SHADER: &str =
+r#"#version 300 es
+precision mediump float;
+out vec4 color;
+
+void main() {
+ color = vec4(1, 0, 0, 1);
+}
+"#;
+
+pub struct Shaders {
+ program: Option<WebGlProgram>,
+ pos_loc: i32,
+}
+
+impl Shaders {
+ pub fn new() -> Self {
+ Self {
+ program: None,
+ pos_loc: -1
+ }
+ }
+
+ fn create_program(&mut self, ctx: &WebGl2RenderingContext) -> Result<(), String> {
+ self.program = Some(ctx.create_program().ok_or("could not create program id")?);
+ Ok(())
+ }
+
+ fn create_shader(&mut self, ctx: &WebGl2RenderingContext,
+ shader_type: u32, source: &str) -> Result<(), String> {
+ let program = self.program.as_ref().ok_or("could not find created program")?;
+ let shader = ctx.create_shader(shader_type)
+ .ok_or("could not create shader")?;
+ ctx.shader_source(&shader, source);
+ ctx.compile_shader(&shader);
+ let status = ctx.get_shader_parameter(&shader, WebGl2RenderingContext::COMPILE_STATUS);
+ if status == wasm_bindgen::JsValue::TRUE {
+ ctx.attach_shader(program, &shader);
+ Ok(())
+ } else {
+ Err(format!("\n{}", ctx.get_shader_info_log(&shader).unwrap_or_default()))
+ }
+ }
+
+ fn create_vertex_shader(&mut self, ctx: &WebGl2RenderingContext) -> Result<(), String> {
+ self.create_shader(ctx, WebGl2RenderingContext::VERTEX_SHADER, VERTEX_SHADER)
+ }
+
+ fn create_fragment_shader(&mut self, ctx: &WebGl2RenderingContext) -> Result<(), String> {
+ self.create_shader(ctx, WebGl2RenderingContext::FRAGMENT_SHADER, FRAGMENT_SHADER)
+ }
+
+ fn compile(&mut self, ctx: &WebGl2RenderingContext) -> Result<(), String> {
+ let program = self.program.as_ref().ok_or("could not find created program")?;
+ ctx.link_program(program);
+ let status = ctx.get_program_parameter(program, WebGl2RenderingContext::LINK_STATUS);
+ if status == wasm_bindgen::JsValue::TRUE {
+ Ok(())
+ } else {
+ Err(format!("\n{}", ctx.get_program_info_log(program).unwrap_or_default()))
+ }
+ }
+
+ pub fn init(&mut self, ctx: &WebGl2RenderingContext) -> Result<(), String> {
+ debug!("create program");
+ self.create_program(ctx)
+ .map_err(|e| { error!("webgl2 create program: {}", e); e})?;
+ debug!("create vertex shader");
+ self.create_vertex_shader(ctx)
+ .map_err(|e| { error!("webgl2 create vertex shader: {}", e); e})?;
+ debug!("create fragment shader");
+ self.create_fragment_shader(ctx)
+ .map_err(|e| { error!("webgl2 create fragment shader: {}", e); e})?;
+ debug!("compile shader program");
+ self.compile(ctx)
+ .map_err(|e| { error!("webgl2 shader: {}", e); e})?;
+ let program = self.program.as_ref().ok_or("could not find created program")?;
+ self.pos_loc = ctx.get_attrib_location(program, "pos");
+ trace!("got attrib location 'pos'({})", self.pos_loc);
+ info!("initialised shader program");
+ Ok(())
+ }
+
+ pub fn remove(&mut self, ctx: &WebGl2RenderingContext) {
+ ctx.delete_program(self.program.as_ref())
+ }
+}
diff --git a/WebInterface/wasm/asm-paint/src/site.rs b/WebInterface/wasm/asm-paint/src/site.rs
new file mode 100644
index 0000000..4ae0237
--- /dev/null
+++ b/WebInterface/wasm/asm-paint/src/site.rs
@@ -0,0 +1,28 @@
+use web_sys;
+use crate::canvas::Canvas;
+
+pub struct Site {
+ window: web_sys::Window,
+ document: web_sys::Document,
+}
+
+impl Site {
+ pub fn from_current() -> Option<Self> {
+ let window = web_sys::window()
+ .or_else(|| {error!("unable to query window"); None})?;
+ let document = window.document()
+ .or_else(|| {error!("unable to query document"); None})?;
+ Some(Self {
+ window, document
+ })
+ }
+
+ pub fn create_canvas(&self) -> Option<Canvas> {
+ debug!("gain canvas element");
+ let element = self.document.get_element_by_id("canvas")
+ .or_else(|| {error!("could not gain canvas element"); None})?;
+ Canvas::new(element)
+ .or_else(|| {error!("could not create a webgl2 canvas.
+ Your browser doesn't seem to support webgl2"); None})
+ }
+}