Skip to content

Commit 00e3d0a

Browse files
committed
fast fix
1 parent 1b0d1d3 commit 00e3d0a

10 files changed

Lines changed: 390 additions & 25 deletions

.github/workflows/webversion.yml

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,24 @@ name: Web Version with Emscripten
33
on: [push, pull_request, workflow_dispatch]
44

55
jobs:
6+
7+
build-documentation:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- name: checkout
11+
uses: actions/checkout@v4
12+
- name: apt-update
13+
run: sudo apt-get update -qq
14+
- name: apt-get doxygen
15+
run: sudo apt-get install -y doxygen
16+
- name: build doc
17+
run: make docs
18+
- name: Upload docs artifact
19+
uses: actions/upload-artifact@v4
20+
with:
21+
name: doc
22+
path: doc/html
23+
624
build-web:
725
runs-on: ubuntu-latest
826

@@ -28,54 +46,38 @@ jobs:
2846
run: embuilder build sdl3
2947

3048
- name: Build web demo
31-
working-directory: demo/sdl3_renderer
32-
run: make webver WEBVER_OUT="web"
49+
#working-directory: demo/sdl3_renderer
50+
run: make webver
3351

3452
- name: Upload webversion artifact
3553
uses: actions/upload-artifact@v4
3654
with:
3755
name: web
38-
path: web
56+
path: doc/html
3957

40-
build-documentation:
41-
runs-on: ubuntu-latest
42-
steps:
43-
- name: checkout
44-
uses: actions/checkout@v4
45-
- name: apt-update
46-
run: sudo apt-get update -qq
47-
- name: apt-get doxygen
48-
run: sudo apt-get install -y doxygen
49-
- name: build doc
50-
run: make docs DOCS_OUT="doc"
51-
- name: Upload docs artifact
52-
uses: actions/upload-artifact@v4
53-
with:
54-
name: doc
55-
path: doc
5658

5759
deploy:
58-
needs: [build-web, build-documentation]
60+
needs: [build-documentation, build-web]
5961
runs-on: ubuntu-latest
6062
steps:
6163

62-
- name: Download docs artifact
64+
- name: Download doc artifact
6365
uses: actions/download-artifact@v4
6466
with:
6567
name: doc
66-
path: doc
68+
path: .
6769

6870
- name: Download web artifact
6971
uses: actions/download-artifact@v4
7072
with:
7173
name: web
72-
path: doc/webver
73-
74+
path: .
75+
#/doc/html
7476
- name: Deploy to GitHub Pages
7577
uses: peaceiris/actions-gh-pages@v4
7678
with:
7779
github_token: ${{ secrets.GITHUB_TOKEN }}
78-
publish_dir: ./doc
80+
publish_dir: .
7981
enable_jekyll: false
8082
allow_empty_commit: false
8183
force_orphan: true

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
## path stuff
77
DOCS_PATH:=./doc
8+
# The output folder for docs is set in the Doxyfile. This variable are defined for convenience access only.
89
DOCS_OUT:=$(DOCS_PATH)/html
910

1011
DEMO_PATH=demo

web_del/demo_sdl3_renderer.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web_del/demo_sdl3_renderer.wasm

1.13 MB
Binary file not shown.

web_del/emscripten_logo.png

24.3 KB
Loading

web_del/favicon.ico

1.12 KB
Binary file not shown.

web_del/index.html

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Nuklear Emscripten Demo</title>
7+
<link rel="icon" type="image/x-icon" href="favicon.ico">
8+
<meta name="description" content="Run Nuklear demos in the browser with Emscripten. Our homepage is https://github.com/Immediate-Mode-UI/Nuklear">
9+
<meta name="author" content="Initially created by PavelSharp(https://github.com/PavelSharp) (2026.02.11)">
10+
<!--This work is released under Public Domain-->
11+
<!--Inspired by Emscripten default shell, see https://github.com/emscripten-core/emscripten/blob/main/html/shell.html-->
12+
<!--The purpose of this shell is to provide a visually polished, production-quality presentation for Nuklear demos-->
13+
<style>
14+
/*================================
15+
BASIC SECTION
16+
==================================*/
17+
html, body {
18+
width: 100%;
19+
height: 100%;
20+
}
21+
22+
* {
23+
padding: 0;
24+
margin: 0;
25+
box-sizing: border-box;
26+
scrollbar-width: thin; /* Firefox */
27+
}
28+
29+
/*================================
30+
TAG SECTION
31+
==================================*/
32+
body {
33+
font-family: arial;
34+
background: #222;
35+
scrollbar-color: #555 #111;
36+
}
37+
38+
button {
39+
-webkit-tap-highlight-color: transparent;
40+
background: #444;
41+
color: white;
42+
border: 1px solid #666;
43+
padding: 6px 12px;
44+
cursor: pointer;
45+
}
46+
47+
@media (hover:hover) {
48+
button:hover {
49+
background: #555;
50+
}
51+
}
52+
53+
input[type="checkbox"] {
54+
display: none;
55+
}
56+
57+
input[type="checkbox"]:checked + button {
58+
background: #762F84; /*#256839*/
59+
border-color: #A245B2; /*#38935E*/
60+
}
61+
62+
#app {
63+
display: flex;
64+
flex-direction: column;
65+
height: 100%;
66+
}
67+
68+
/*================================
69+
HEADER SECTION
70+
==================================*/
71+
#header {
72+
display: flex;
73+
justify-content: flex-start;
74+
align-items: center;
75+
flex-wrap: wrap;
76+
padding: 4px 7px;
77+
gap: 5px;
78+
background: #333;
79+
color: white;
80+
}
81+
82+
.header-clickable-logo {
83+
display: flex;
84+
align-items: center;
85+
height: 70px;
86+
}
87+
88+
.header-clickable-logo img {
89+
object-fit: contain;
90+
display: block;
91+
height: 100%;
92+
width: auto;
93+
max-width: 300px;
94+
}
95+
96+
.header-spacer {
97+
flex: 1;
98+
}
99+
100+
/*================================
101+
MAIN SECTION
102+
==================================*/
103+
main {
104+
flex: 1;
105+
background: #222;
106+
overflow: auto;
107+
display: flex;
108+
}
109+
110+
#main-canvas-block {
111+
display: flex;
112+
border: 1px solid #555;
113+
}
114+
115+
#main-canvas-block:not(.fixed) {
116+
flex: 1 1 auto;
117+
}
118+
119+
#main-canvas-block.fixed {
120+
flex: 0 0 auto;
121+
width: var(--canvas-fixed-width);
122+
height: var(--canvas-fixed-height);
123+
}
124+
125+
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
126+
#main-canvas-block canvas {
127+
width: 100%;
128+
height: 100%;
129+
border: 0;
130+
}
131+
132+
#app:has(#consoleshow-toggle:not(:checked)) #footer-console {
133+
display: none;
134+
}
135+
136+
/*================================
137+
FOOTER SECTION
138+
==================================*/
139+
#footer-console {
140+
padding: 3px;
141+
width: 100%;
142+
height: 3.5lh;
143+
font-family: 'Lucida Console', Monaco, monospace;
144+
font-size: 12px;
145+
line-height: 1.4;
146+
overflow-y: auto;
147+
white-space: pre-wrap;
148+
overflow-wrap: break-word;
149+
}
150+
151+
#footer-console > .line {
152+
display: block;
153+
margin: 0;
154+
padding: 0;
155+
}
156+
157+
#footer-console > .line.ok {
158+
color: #ddd;
159+
}
160+
161+
#footer-console > .line.error {
162+
color: #ff5555;
163+
}
164+
</style>
165+
<script>
166+
class UIConsole {
167+
constructor(container, toggle) {
168+
this.container = container;
169+
this.toggle = toggle;
170+
this.line_style = "line";
171+
this.ok_style = "ok";
172+
this.error_style = "error";
173+
}
174+
#append(text, style) {
175+
this.toggle.checked = true;
176+
const line = document.createElement('div');
177+
line.textContent = String(text);//textContent protects from XSS attacks
178+
line.classList.add(this.line_style, style);
179+
this.container.appendChild(line);
180+
line.scrollIntoView({ behavior: 'smooth', block: 'end' });
181+
}
182+
print(text) { this.#append(text, this.ok_style); }
183+
print_error(text) { this.#append(text, this.error_style); }
184+
}
185+
186+
class EmscriptenLogMonitor {
187+
constructor(uiconsole) {
188+
this.uiconsole = uiconsole;
189+
this.total_depends = 0;
190+
}
191+
report_dependencies(left) {
192+
if (!this.total_depends) this.total_depends = left;
193+
const msg = left ? 'Preparing... (' + (this.total_depends - left) + '/' + this.total_depends + ')' : 'All downloads complete.';
194+
console.log(`[dependencies] ${msg}`);
195+
if (!left) this.total_depends = 0;
196+
}
197+
report_status(text) {
198+
if (!text) return;
199+
console.log(`[status] ${text}`);
200+
}
201+
report_glcontext_lost() {
202+
alert('WebGL context lost. You will need to reload the page.');
203+
}
204+
report_runtime_initialized() {
205+
this.report_status("WASM runtime initialized!")
206+
}
207+
report_window_error(e) {
208+
this.uiconsole.print_error('Exception thrown, see JavaScript console');
209+
}
210+
}
211+
212+
document.addEventListener('DOMContentLoaded', function () {
213+
const ui = {
214+
canvas: document.getElementById('canvas'),
215+
console: new UIConsole(document.getElementById('footer-console'), document.getElementById('consoleshow-toggle')),
216+
init: function () {
217+
this.ems_monitor = new EmscriptenLogMonitor(this.console);
218+
return this;
219+
}
220+
}.init();
221+
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
222+
// application robust, you may want to override this behavior before shipping!
223+
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
224+
ui.canvas.addEventListener('webglcontextlost', e => { ui.ems_monitor.report_glcontext_lost(); e.preventDefault(); }, false);
225+
window.addEventListener('error', e => {
226+
// TODO: do not warn on ok events like simulating an infinite loop or exitStatus
227+
ui.ems_monitor.report_window_error(e);
228+
});
229+
const onresize_observe = () => { requestAnimationFrame(() => { window.dispatchEvent(new Event('resize')); }); }
230+
const size_observer = new ResizeObserver(onresize_observe);
231+
size_observer.observe(ui.canvas);
232+
//TODO[Future]: use MODULARIZE or even EXPORT_ES6
233+
window.Module = {
234+
canvas: ui.canvas,
235+
onRuntimeInitialized: () => { ui.ems_monitor.report_runtime_initialized(); onresize_observe(); },
236+
print: text => { ui.console.print(text); console.log(text); },
237+
printErr: text => { ui.console.print_error(text); console.error(text); },
238+
monitorRunDependencies: left => { ui.ems_monitor.report_dependencies(left); },
239+
setStatus: text => { ui.ems_monitor.report_status(text); }
240+
};
241+
const script = document.createElement('script');
242+
script.async = true;
243+
script.src = 'demo_sdl3_renderer.js';
244+
document.body.appendChild(script);
245+
});
246+
247+
function liveresize_changed(enabled) {
248+
const canvas = document.getElementById('main-canvas-block');
249+
if (enabled) {
250+
canvas.classList.remove('fixed');
251+
} else {
252+
canvas.style.setProperty('--canvas-fixed-width', canvas.offsetWidth + 'px');
253+
canvas.style.setProperty('--canvas-fixed-height', canvas.offsetHeight + 'px');
254+
canvas.classList.add('fixed');
255+
}
256+
}
257+
258+
function fullscreen_click() {
259+
const LOCK_POINTER = false;
260+
const RESIZE_CANVAS = true;
261+
window.Module.requestFullscreen(LOCK_POINTER, RESIZE_CANVAS);
262+
}
263+
</script>
264+
</head>
265+
<body>
266+
<div id="app">
267+
<header id="header">
268+
<a class="header-clickable-logo" href="https://github.com/Immediate-Mode-UI/Nuklear" target="_blank">
269+
<img src="nuklear_logo.png" alt="Nuklear Homepage">
270+
</a>
271+
<a class="header-clickable-logo" href="http://emscripten.org" target="_blank">
272+
<img src="emscripten_logo.png" alt="Powered by Emscripten">
273+
</a>
274+
<div class="header-spacer"></div>
275+
<!--NOTE[Future]: This is a good place to add a combobox for select backend/renderer-->
276+
<input type="checkbox" id="liveresize-toggle" checked onchange="liveresize_changed(this.checked)" />
277+
<button onclick="this.previousElementSibling.click();">Live resize</button>
278+
<input type="checkbox" id="consoleshow-toggle" />
279+
<button onclick="this.previousElementSibling.click();">Show console</button>
280+
<button onclick="fullscreen_click()">Fullscreen</button>
281+
</header>
282+
<main>
283+
<div id="main-canvas-block">
284+
<canvas id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
285+
</div>
286+
</main>
287+
<footer>
288+
<div id="footer-console"></div>
289+
</footer>
290+
</div>
291+
</body>
292+
</html>
293+

0 commit comments

Comments
 (0)