@@ -3,11 +3,14 @@ import { installAutomaginariumPacked } from "./generated/automate_packed_runtime
33await installAutomaginariumPacked ( ) ;
44
55const PRESETS = [
6- { id : "wolfram-30" , label : "Wolfram 30" } ,
7- { id : "wolfram-90" , label : "Wolfram 90" } ,
8- { id : "binaire-5-sillage" , label : "Binaire 5 - Sillage" } ,
9- { id : "ternaire-totalistique" , label : "Ternaire totalistique" } ,
10- { id : "multi-canal-aurore" , label : "Multi-canal Aurore" } ,
6+ { id : "wolfram-30" , label : "Wolfram 30" , family : "elementaire" } ,
7+ { id : "wolfram-90" , label : "Wolfram 90" , family : "elementaire" } ,
8+ { id : "wolfram-110" , label : "Wolfram 110" , family : "elementaire" } ,
9+ { id : "binaire-5-sillage" , label : "Binaire 5 - Sillage" , family : "voisinage 5" } ,
10+ { id : "ternaire-totalistique" , label : "Ternaire totalistique" , family : "ternaire" } ,
11+ { id : "quaternaire-cristal" , label : "Quaternaire cristal" , family : "quaternaire" } ,
12+ { id : "multi-canal-aurore" , label : "Multi-canal Aurore" , family : "multi-canal" } ,
13+ { id : "symboles-jardin" , label : "Symboles jardin" , family : "custom" } ,
1114] ;
1215
1316const state = { config : null , universe : null , lastValidConfig : null } ;
@@ -18,6 +21,7 @@ const title = document.querySelector("#config-title");
1821const meta = document . querySelector ( "#config-meta" ) ;
1922const statusBox = document . querySelector ( "#validation-status" ) ;
2023const tableView = document . querySelector ( "#rule-table" ) ;
24+ const gallery = document . querySelector ( "#preset-gallery" ) ;
2125const controls = {
2226 name : document . querySelector ( "#config-name" ) ,
2327 alphabetInput : document . querySelector ( "#alphabet-input" ) ,
@@ -37,6 +41,7 @@ const controls = {
3741 json : document . querySelector ( "#config-json" ) ,
3842 importJson : document . querySelector ( "#import-json" ) ,
3943} ;
44+ const presetCache = new Map ( ) ;
4045
4146function parseSymbol ( raw ) {
4247 const trimmed = raw . trim ( ) ;
@@ -175,6 +180,23 @@ function colorFor(value, config, rowIndex, colIndex, channels) {
175180 return palette [ ( index + drift ) % palette . length ] || palette [ 0 ] ;
176181}
177182
183+ function drawUniverseToCanvas ( targetCanvas , universe , maxWidth = 240 , maxHeight = 132 ) {
184+ const { configuration, lignes, sorties } = universe ;
185+ const context = targetCanvas . getContext ( "2d" ) ;
186+ const cell = Math . max ( 1 , Math . floor ( Math . min ( maxWidth / configuration . largeur , maxHeight / configuration . hauteur ) ) ) ;
187+ targetCanvas . width = configuration . largeur * cell ;
188+ targetCanvas . height = configuration . hauteur * cell ;
189+ context . fillStyle = configuration . rendu . fond || "#05070d" ;
190+ context . fillRect ( 0 , 0 , targetCanvas . width , targetCanvas . height ) ;
191+ lignes . forEach ( ( ligne , y ) => {
192+ ligne . forEach ( ( value , x ) => {
193+ if ( String ( value ) === String ( configuration . alphabet_entree [ 0 ] ) && ! configuration . rendu . afficher_zero ) return ;
194+ context . fillStyle = colorFor ( value , configuration , y , x , sorties ?. [ y ] ?. [ x ] ) ;
195+ context . fillRect ( x * cell , y * cell , cell , cell ) ;
196+ } ) ;
197+ } ) ;
198+ }
199+
178200function resizeCanvas ( config ) {
179201 const cell = Number ( config . rendu . taille_cellule || 5 ) ;
180202 canvas . width = config . largeur * cell ;
@@ -222,9 +244,17 @@ function applyConfig(config, { updateJson = true, updateControls = true } = {})
222244}
223245
224246async function loadPreset ( id ) {
247+ const config = await fetchPreset ( id ) ;
248+ applyConfig ( config ) ;
249+ }
250+
251+ async function fetchPreset ( id ) {
252+ if ( presetCache . has ( id ) ) return structuredClone ( presetCache . get ( id ) ) ;
225253 const response = await fetch ( `../examples/${ id } .json` ) ;
254+ if ( ! response . ok ) throw new Error ( `Preset introuvable: ${ id } ` ) ;
226255 const config = await response . json ( ) ;
227- applyConfig ( config ) ;
256+ presetCache . set ( id , config ) ;
257+ return structuredClone ( config ) ;
228258}
229259
230260function applyGeneratedRule ( ) {
@@ -260,6 +290,41 @@ function downloadText(filename, text) {
260290 URL . revokeObjectURL ( url ) ;
261291}
262292
293+ async function renderGallery ( ) {
294+ gallery . innerHTML = "" ;
295+ for ( const preset of PRESETS ) {
296+ const config = await fetchPreset ( preset . id ) ;
297+ const previewConfig = {
298+ ...config ,
299+ largeur : Math . min ( config . largeur || 140 , 140 ) ,
300+ hauteur : Math . min ( config . hauteur || 80 , 80 ) ,
301+ rendu : { ...( config . rendu || { } ) , taille_cellule : 2 } ,
302+ } ;
303+ const universe = window . AutomaginariumCore . genererUnivers ( previewConfig ) ;
304+ const button = document . createElement ( "button" ) ;
305+ button . type = "button" ;
306+ button . className = "preset-card" ;
307+ button . dataset . preset = preset . id ;
308+
309+ const thumbnail = document . createElement ( "canvas" ) ;
310+ thumbnail . className = "preset-thumb" ;
311+ drawUniverseToCanvas ( thumbnail , universe ) ;
312+
313+ const name = document . createElement ( "strong" ) ;
314+ name . textContent = preset . label ;
315+
316+ const family = document . createElement ( "span" ) ;
317+ family . textContent = preset . family ;
318+
319+ button . append ( thumbnail , name , family ) ;
320+ button . addEventListener ( "click" , ( ) => {
321+ presetSelect . value = preset . id ;
322+ loadPreset ( preset . id ) ;
323+ } ) ;
324+ gallery . appendChild ( button ) ;
325+ }
326+ }
327+
263328PRESETS . forEach ( ( preset ) => {
264329 const option = document . createElement ( "option" ) ;
265330 option . value = preset . id ;
@@ -298,5 +363,7 @@ document.querySelector("#export-png").addEventListener("click", () => {
298363 link . href = canvas . toDataURL ( "image/png" ) ;
299364 link . click ( ) ;
300365} ) ;
366+ document . querySelector ( "#refresh-gallery" ) . addEventListener ( "click" , renderGallery ) ;
301367
368+ await renderGallery ( ) ;
302369loadPreset ( "wolfram-90" ) ;
0 commit comments