Sfoglia il codice sorgente

web example build tool

Karl Zylinski 2 mesi fa
parent
commit
4370b8279e

+ 2 - 1
.gitignore

@@ -4,4 +4,5 @@ raylib/
 *.pdb
 *.exe
 *.rdi
-!/.sublime/karl2d.sublime-project
+!/.sublime/karl2d.sublime-project
+examples/*/web

+ 2 - 2
.sublime/karl2d.sublime-project

@@ -18,8 +18,8 @@
 				},
 				{
 					"name": "web example",
-					"shell_cmd": "odin build . -out:build/main.wasm -vet -strict-style -keep-executable -debug -target:js_wasm32",
-					"working_dir": "$project_path/../examples/web"
+					"shell_cmd": "odin run build_web_example -- minimal",
+					"working_dir": "$project_path/../examples"
 				},
 				{
 					"name": "fonts",

+ 77 - 0
examples/build_web_example/build_web_example.odin

@@ -0,0 +1,77 @@
+package karl2d_build_web_example
+
+import "core:os"
+import "core:fmt"
+import "core:path/filepath"
+import "core:os/os2"
+
+main :: proc() {
+	if len(os.args) != 2 {
+		fmt.eprintfln("Usage: 'odin run build_web_example -- example_directory_name'\nExample: 'odin run build_web_example -- minimal'")
+		return
+	}
+
+	WEB_ENTRY_TEMPLATE :: #load("web_entry_templates/web_entry_template.odin")
+	WEB_ENTRY_INDEX :: #load("web_entry_templates/index_template.html")
+
+	dir := os.args[1]
+	dir_handle, dir_handle_err := os.open(dir)
+
+	fmt.ensuref(dir_handle_err == nil, "Failed finding directory %v. Error: %v", dir, dir_handle_err)
+
+	dir_stat, dir_stat_err := os.fstat(dir_handle)
+
+	fmt.ensuref(dir_stat_err == nil, "Failed checking status of directory %v. Error: %v", dir, dir_stat_err)
+		
+	fmt.ensuref(dir_stat.is_dir, "%v is not a directory!", dir)
+
+	web_dir := filepath.join({dir, "web"})
+	os.make_directory(web_dir, 0o644)
+
+	web_build_dir := filepath.join({web_dir, "build"})
+
+	os.write_entire_file(
+		filepath.join(
+			{web_dir, fmt.tprintf("%v_web_entry.odin", dir)},
+		),
+		WEB_ENTRY_TEMPLATE,
+	)
+	os.write_entire_file(filepath.join({web_build_dir, "index.html"}), WEB_ENTRY_INDEX)
+
+	_, odin_root_stdout, _, odin_root_err := os2.process_exec({
+		command = { "odin", "root" },
+	}, allocator = context.allocator)
+
+	ensure(odin_root_err == nil, "Failed fetching 'odin root' (Odin in PATH needed!)")
+
+	odin_root := string(odin_root_stdout)
+	
+
+	js_runtime_path := filepath.join({odin_root, "core", "sys", "wasm", "js", "odin.js"})
+	fmt.ensuref(os2.exists(js_runtime_path), "File does not exist: %v -- It is the Odin Javascript runtime that this program needs to copy to the web build output folder!", js_runtime_path)
+
+	os2.copy_file(filepath.join({web_build_dir, "odin.js"}), js_runtime_path)
+
+	wasm_out_path := filepath.join({web_build_dir, "main.wasm"})
+
+	build_status, build_std_out, build_std_err, build_err := os2.process_exec({
+		command = {
+			"odin",
+			"build",
+			web_dir,
+			fmt.tprintf("-out:%v", wasm_out_path),
+			"-target:js_wasm32",
+			"-debug",
+			"-vet",
+			"-strict-style",
+		},
+	}, allocator = context.allocator)
+	
+	if len(build_std_out) > 0 {
+		fmt.println(string(build_std_out))
+	}
+
+	if len(build_std_err) > 0 {
+		fmt.println(string(build_std_err))
+	}
+}

+ 0 - 0
examples/web/build/index.html → examples/build_web_example/web_entry_templates/index_template.html


+ 22 - 0
examples/build_web_example/web_entry_templates/web_entry_template.odin

@@ -0,0 +1,22 @@
+// This file is a just a wrapper that takes care of context setup and provides an entry for the
+// javascript Odin runtime to call into. `main` will run on start and then `step` will run for each
+// frame.
+package karl2d_web_entry
+
+import ex ".."
+import "base:runtime"
+import "core:log"
+
+ctx: runtime.Context
+
+main :: proc() {
+	context.logger = log.create_console_logger()
+	ctx = context
+	ex.init()
+}
+
+@export
+step :: proc(dt: f64) -> bool {
+	context = ctx
+	return ex.step(f32(dt))
+}

+ 56 - 31
examples/minimal/minimal.odin

@@ -4,47 +4,72 @@ import k2 "../.."
 import "core:mem"
 import "core:log"
 import "core:fmt"
+import "core:math"
+import "core:time"
 
 _ :: fmt
 _ :: mem
 
+tex: k2.Texture
+
+init :: proc() {
+	k2.init(1080, 1080, "Karl2D Minimal Program", { .Resizable })
+	k2.set_window_position(300, 100)
+	tex = k2.load_texture_from_bytes(#load("sixten.jpg"))
+}
+
+t: f32
+
+step :: proc(dt: f32) -> bool {
+	k2.process_events()
+	k2.clear(k2.BLUE)
+
+	t += dt
+
+	pos := math.sin(t*10)*10
+	rot := t*50
+	k2.draw_texture_ex(tex, {0, 0, f32(tex.width), f32(tex.height)}, {pos + 400, 450, 900, 500}, {450, 250}, rot)
+
+	k2.draw_rect({10, 10, 60, 60}, k2.GREEN)
+	k2.draw_rect({20, 20, 40, 40}, k2.BLACK)
+	k2.draw_circle({120, 40}, 30, k2.BLACK)
+	k2.draw_circle({120, 40}, 20, k2.GREEN)
+	k2.draw_text("Hellöpe!", {10, 100}, 64, k2.WHITE)
+
+	k2.present()
+	free_all(context.temp_allocator)
+
+	res := true
+
+	if k2.key_went_down(.Escape) {
+		res = false
+	}
+
+	return res
+}
+
+shutdown :: proc() {
+	k2.destroy_texture(tex)
+	k2.shutdown()
+}
+
 main :: proc() {
 	context.logger = log.create_console_logger()
 
-	when ODIN_DEBUG {
-		track: mem.Tracking_Allocator
-		mem.tracking_allocator_init(&track, context.allocator)
-		context.allocator = mem.tracking_allocator(&track)
-
-		defer {
-			if len(track.allocation_map) > 0 {
-				for _, entry in track.allocation_map {
-					fmt.eprintf("%v leaked: %v bytes\n", entry.location, entry.size)
-				}
-			}
-			mem.tracking_allocator_destroy(&track)
-		}
-	}
+	init()
 
-	k2.init(1080, 1080, "Karl2D Minimal Program")
-	k2.set_window_position(300, 100)
-	tex := k2.load_texture_from_file("sixten.jpg")
+	prev_time := time.now()
 
 	for !k2.shutdown_wanted() {
-		k2.process_events()
-		k2.clear(k2.BLUE)
-
-		k2.draw_rect({10, 10, 60, 60}, k2.GREEN)
-		k2.draw_rect({20, 20, 40, 40}, k2.BLACK)
-		k2.draw_circle({120, 40}, 30, k2.BLACK)
-		k2.draw_circle({120, 40}, 20, k2.GREEN)
-		k2.draw_text("Hellöpe!", {10, 100}, 64, k2.WHITE)
-		k2.draw_texture_ex(tex, {0, 0, f32(tex.width), f32(tex.height)}, {10, 200, 900, 500}, {}, 0)
-
-		k2.present()
-		free_all(context.temp_allocator)
+		now := time.now()
+		since := time.diff(prev_time, now)
+		dt := f32(time.duration_seconds(since))
+		prev_time = now
+		
+		if !step(dt) {
+			break
+		}
 	}
 
-	k2.destroy_texture(tex)
-	k2.shutdown()
+	shutdown()
 }

+ 0 - 2
examples/web/.gitignore

@@ -1,2 +0,0 @@
-build/main.wasm
-build/odin.js

+ 0 - 62
examples/web/minimal.odin

@@ -1,62 +0,0 @@
-package karl2d_minimal_example
-
-import k2 "../.."
-import "core:mem"
-import "core:log"
-import "core:fmt"
-import "base:runtime"
-
-_ :: fmt
-_ :: mem
-tex: k2.Texture
-default_context: runtime.Context
-track: mem.Tracking_Allocator
-
-main :: proc() {
-	when ODIN_DEBUG {
-		mem.tracking_allocator_init(&track, context.allocator)
-		context.allocator = mem.tracking_allocator(&track)
-	}
-
-	context.logger = log.create_console_logger()
-	default_context = context
-
-	k2.init(1080, 1080, "Karl2D Minimal Program", {.Resizable})
-	tex = k2.load_texture_from_bytes(#load("sixten.jpg"),)
-
-	when ODIN_OS != .JS {
-		for !k2.shutdown_wanted() {
-			step(0)
-		}
-			
-		k2.destroy_texture(tex)
-		k2.shutdown()
-	}
-}
-
-shutdown :: proc() {
-	if len(track.allocation_map) > 0 {
-		for _, entry in track.allocation_map {
-			fmt.eprintf("%v leaked: %v bytes\n", entry.location, entry.size)
-		}
-	}
-	mem.tracking_allocator_destroy(&track)
-}
-
-@export
-step :: proc(dt: f64) -> bool {
-	context = default_context
-	k2.process_events()
-	k2.clear(k2.BLUE)
-
-	k2.draw_rect({10, 10, 60, 60}, k2.GREEN)
-	k2.draw_rect({20, 20, 40, 40}, k2.BLACK)
-	k2.draw_circle({120, 40}, 30, k2.BLACK)
-	k2.draw_circle({120, 40}, 20, k2.GREEN)
-	k2.draw_text("Hellöpe!", {10, 100}, 64, k2.WHITE)
-	k2.draw_texture_ex(tex, {0, 0, f32(tex.width), f32(tex.height)}, {10, 200, 900, 500}, {}, 0)
-
-	k2.present()
-	free_all(context.temp_allocator)
-	return true
-}

BIN
examples/web/minimal.wasm


BIN
examples/web/sixten.jpg