code wiki / _hdl_build / nx_gen_explorer.nx
nx_gen_explorer.nx source
↩ module page · 116 lines · 9551 B
1// nx_gen_explorer.nx -- ★R10: a PUBLIC interactive generate front-end over the unified nx_gen surface. Renders a
2// matrix of assets across the parameter space (tree species x seed, creature plan x seed, figures, faces) via
3// nx_gen, bakes each into a self-contained page with an interactive picker (kind tabs + param buttons + seed
4// thumbnails + a big preview + a real per-asset DOWNLOAD) -- this is Infinigen's "downloadable pre-generated data"
5// offering, made interactive, on OUR generator. Worlds are excluded here (heavy ray-march; covered by /world).
6// license_tier: ORIGINAL expect_exit: 0
7import "nx_syscalls.nx"
8import "nx_png.nx"
9import "nx_base64.nx"
10import "nx_gen.nx"
11const K_MAGIC_2026: i64 = 2026
12
13func hw(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd, s, n); return 0 }
14func hn(fd: i64, v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} sys_write(fd,(b as i64+i+1) as *u8,31-i); return 0 }
15
16// render asset (kind,seed,p0) via nx_gen, downsample to a <=360px tile, write PNG, read back, base64, emit a JS
17// object {k,p,pl,s,src} to fd. plabel = param name string (or "").
18func emit_asset(fd: i64, kind: i64, seed: i64, p0: i64, plabel: *u8, tile: *i64, scratch: *u8) -> i64 {
19 let spec: *i64 = sys_mmap(8*8) as *i64
20 let res: *i64 = sys_mmap(8*8) as *i64
21 spec[0]=kind; spec[1]=seed; spec[2]=p0; spec[3]=0
22 nx_gen(spec, res)
23 if res[0] != 1 { return 0 }
24 let sw: i64 = res[1]; let sh: i64 = res[2]; let sfb: *i64 = res[4] as *i64
25 var mx: i64 = sw
26 if sh > mx { mx = sh }
27 let tw: i64 = sw*360/mx
28 let th: i64 = sh*360/mx
29 var y: i64 = 0
30 while y < th {
31 var x: i64 = 0
32 while x < tw { tile[y*tw+x] = sfb[(y*sh/th)*sw + (x*sw/tw)]; x = x + 1 }
33 y = y + 1
34 }
35 write_png(tile, tw, th, scratch)
36 let lenp: *i64 = sys_mmap(16) as *i64
37 let png: *u8 = sys_read_file(scratch, lenp)
38 if (png as i64) == 0 { return 0 }
39 let b64: *u8 = sys_mmap(lenp[0]*2+64) as *u8
40 let blen: i64 = b64_encode(png, lenp[0], b64)
41 hw(fd, "{k:" as *u8); hn(fd, kind); hw(fd, ",p:" as *u8); hn(fd, p0)
42 hw(fd, ",pl:'" as *u8); hw(fd, plabel); hw(fd, "',s:" as *u8); hn(fd, seed)
43 hw(fd, ",src:'data:image/png;base64," as *u8)
44 sys_write(fd, b64, blen)
45 hw(fd, "'},\n" as *u8)
46 return 1
47}
48
49func main() -> i64 {
50 let fd: i64 = sys_openat_wr("knowledge/generate.html\x00" as *u8, 0x1a4)
51 if fd < 0 { hw(2, "gen_explorer: open failed\n" as *u8); return 1 }
52 let tile: *i64 = sys_mmap(360*360*8) as *i64
53 let scr: *u8 = "knowledge/_gxtile.png\x00" as *u8
54
55 hw(fd, "<!doctype html><html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>Nishi Generator -- nx_gen(spec)</title><style>\n" as *u8)
56 hw(fd, "html,body{margin:0;background:#0a0d13;color:#cde;font-family:system-ui,sans-serif}.wrap{max-width:1000px;margin:0 auto;padding:16px}h1{font-size:22px;text-align:center}h1 .k{color:#8ef}p.intro{color:#9ab;font-size:14px;line-height:1.55;text-align:center;max-width:720px;margin:0 auto 18px}\n" as *u8)
57 hw(fd, "#tabs{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin:12px 0}.tab{background:#16222c;color:#cde;border:1px solid #223;border-radius:8px;padding:8px 16px;font-size:14px;cursor:pointer}.tab.on{background:#3fd0b0;color:#0a0d13;border-color:#3fd0b0;font-weight:600}\n" as *u8)
58 hw(fd, "#params{display:flex;gap:6px;justify-content:center;flex-wrap:wrap;margin:8px 0;align-items:center}.plab{color:#7f9;font-size:13px;font-family:ui-monospace,monospace}.pv{background:#111a22;color:#9ab;border:1px solid #223;border-radius:6px;padding:5px 11px;font-size:13px;cursor:pointer}.pv.on{background:#234;color:#8ef;border-color:#3fd0b0}\n" as *u8)
59 hw(fd, "#seeds{display:flex;gap:6px;justify-content:center;flex-wrap:wrap;margin:12px 0}.th{width:72px;height:72px;object-fit:cover;border-radius:7px;border:2px solid #223;cursor:pointer;background:#16222c}.th.on{border-color:#3fd0b0}\n" as *u8)
60 hw(fd, "#stage{text-align:center}#preview{max-width:100%;width:520px;border:1px solid #223;border-radius:9px;box-shadow:0 6px 24px #0009;background:#111a22}#meta{color:#7f9;font-size:14px;margin:8px 0}#dl{display:inline-block;background:#3fd0b0;color:#0a0d13;font-weight:600;text-decoration:none;padding:9px 20px;border-radius:8px;font-size:14px}#call{color:#8ef;font-family:ui-monospace,monospace;font-size:13px;background:#0e1420;border:1px solid #223;border-radius:7px;padding:10px;max-width:420px;margin:14px auto;text-align:center}\n" as *u8)
61 hw(fd, "</style></head><body><div class='wrap'>\n" as *u8)
62 hw(fd, "<h1>Nishi <span class='k'>Generator</span> — one API, every asset</h1>\n" as *u8)
63 hw(fd, "<p class='intro'>Every asset below is produced by a single sovereign call — <code style='color:#8ef'>nx_gen([kind, seed, params])</code> — the unified function-oriented generator surface (Infinigen's ProcFunc, ours). Pick a kind, choose a variant, browse seeds, and <b>download</b> any result. No ML, no libraries: integer procedural generation on our own stack. (Worlds live on <a href='/world' style='color:#8ef'>/world</a>.)</p>\n" as *u8)
64 hw(fd, "<div id='tabs'></div><div id='params'></div><div id='seeds'></div>\n" as *u8)
65 hw(fd, "<div id='stage'><img id='preview' alt='generated asset'><div id='meta'></div><a id='dl'>⇩ Download PNG</a><pre id='call'></pre></div>\n" as *u8)
66 hw(fd, "</div>\n<script>\nvar A=[\n" as *u8)
67
68 // ---- TREES: 5 species x 4 seeds ----
69 let tsp: *i64 = sys_mmap(8*8) as *i64
70 let tspn: *i64 = sys_mmap(8*8) as *i64
71 tspn[0]="broadleaf" as *u8 as i64; tspn[1]="conifer" as *u8 as i64; tspn[2]="birch" as *u8 as i64; tspn[3]="palm" as *u8 as i64; tspn[4]="dead" as *u8 as i64
72 let tseed: *i64 = sys_mmap(8*8) as *i64
73 tseed[0]=3; tseed[1]=9; tseed[2]=17; tseed[3]=42
74 var sp: i64 = 0
75 while sp < 5 {
76 var si: i64 = 0
77 while si < 4 { emit_asset(fd, GEN_TREE, tseed[si], sp, tspn[sp] as *u8, tile, scr); si = si + 1 }
78 sp = sp + 1
79 }
80 // ---- CREATURES: 3 plans x 3 seeds ----
81 let cpn: *i64 = sys_mmap(8*8) as *i64
82 cpn[0]="quadruped" as *u8 as i64; cpn[1]="bird" as *u8 as i64; cpn[2]="fish" as *u8 as i64
83 let cseed: *i64 = sys_mmap(8*8) as *i64
84 cseed[0]=4; cseed[1]=11; cseed[2]=29
85 var pl: i64 = 0
86 while pl < 3 {
87 var ci: i64 = 0
88 while ci < 3 { emit_asset(fd, GEN_CREATURE, cseed[ci], pl, cpn[pl] as *u8, tile, scr); ci = ci + 1 }
89 pl = pl + 1
90 }
91 // ---- FIGURES: 6 seeds ----
92 let fseed: *i64 = sys_mmap(8*8) as *i64
93 fseed[0]=7; fseed[1]=42; fseed[2]=57; fseed[3]=88; fseed[4]=101; fseed[5]=150
94 var fi: i64 = 0
95 while fi < 6 { emit_asset(fd, GEN_FIGURE, fseed[fi], 0, "" as *u8, tile, scr); fi = fi + 1 }
96 // ---- FACES: 6 seeds ----
97 let xseed: *i64 = sys_mmap(8*8) as *i64
98 xseed[0]=7; xseed[1]=42; xseed[2]=99; xseed[3]=256; xseed[4]=777; xseed[5]=K_MAGIC_2026
99 var xi: i64 = 0
100 while xi < 6 { emit_asset(fd, GEN_FACE, xseed[xi], 0, "" as *u8, tile, scr); xi = xi + 1 }
101
102 hw(fd, "];\n" as *u8)
103 // ---- the picker (no '!' anywhere -- NishiLang literal trap) ----
104 hw(fd, "var K=[{k:1,nm:'Trees',pn:'species',op:['broadleaf','conifer','birch','palm','dead']},{k:2,nm:'Creatures',pn:'plan',op:['quadruped','bird','fish']},{k:3,nm:'People',pn:'',op:[]},{k:4,nm:'Faces',pn:'',op:[]}];\n" as *u8)
105 hw(fd, "var ki=0,pp=0,ss=0;\nfunction cur(){return K[ki];}\n" as *u8)
106 hw(fd, "function matches(){var c=cur();return A.filter(function(a){return a.k===c.k&&(c.pn===''?true:a.p===pp);});}\n" as *u8)
107 hw(fd, "function draw(){var c=cur();var tb=document.getElementById('tabs').children;for(var i=0;i<tb.length;i++){tb[i].className=(i===ki?'tab on':'tab');}\n" as *u8)
108 hw(fd, "var pr=document.getElementById('params');pr.innerHTML='';if(c.pn.length>0){var lab=document.createElement('span');lab.className='plab';lab.textContent=c.pn+': ';pr.appendChild(lab);for(var j=0;j<c.op.length;j++){var b=document.createElement('button');b.className=(j===pp?'pv on':'pv');b.textContent=c.op[j];(function(jj){b.onclick=function(){pp=jj;ss=0;draw();};})(j);pr.appendChild(b);}}\n" as *u8)
109 hw(fd, "var lst=matches();if(ss>=lst.length){ss=0;}var sr=document.getElementById('seeds');sr.innerHTML='';for(var s=0;s<lst.length;s++){var im=document.createElement('img');im.className=(s===ss?'th on':'th');im.src=lst[s].src;(function(si){im.onclick=function(){ss=si;draw();};})(s);sr.appendChild(im);}\n" as *u8)
110 hw(fd, "var sel=lst[ss];if(sel){document.getElementById('preview').src=sel.src;var dl=document.getElementById('dl');dl.href=sel.src;dl.download='nishi_'+c.nm+'_'+(sel.pl||'')+'_seed'+sel.s+'.png';document.getElementById('meta').textContent=c.nm+(sel.pl?(' / '+sel.pl):'')+' / seed '+sel.s;document.getElementById('call').textContent='nx_gen(['+c.k+', '+sel.s+(c.pn.length>0?', '+pp:'')+'])';}}\n" as *u8)
111 hw(fd, "var tabs=document.getElementById('tabs');for(var i=0;i<K.length;i++){var t=document.createElement('button');t.className='tab';t.textContent=K[i].nm;(function(ii){t.onclick=function(){ki=ii;pp=0;ss=0;draw();};})(i);tabs.appendChild(t);}draw();\n" as *u8)
112 hw(fd, "</script></body></html>\n" as *u8)
113 sys_close(fd)
114 hw(1, "nx_gen_explorer: wrote knowledge/generate.html (interactive nx_gen catalog: 20 trees + 9 creatures + 6 figures + 6 faces)\n" as *u8)
115 return 0
116}