diff options
Diffstat (limited to 'tools/shader_editor/index.html')
| -rw-r--r-- | tools/shader_editor/index.html | 90 |
1 files changed, 86 insertions, 4 deletions
diff --git a/tools/shader_editor/index.html b/tools/shader_editor/index.html index 122c15e..5db06de 100644 --- a/tools/shader_editor/index.html +++ b/tools/shader_editor/index.html @@ -166,11 +166,21 @@ body { background: #1177bb; } -#code-editor { +.editor-container { flex: 1; + position: relative; + overflow: hidden; +} + +#code-editor { + position: absolute; + top: 0; + left: 0; width: 100%; - background: #1e1e1e; - color: #d4d4d4; + height: 100%; + background: transparent; + color: transparent; + caret-color: #d4d4d4; border: none; padding: 15px; font-family: 'Courier New', monospace; @@ -178,8 +188,36 @@ body { line-height: 1.5; resize: none; outline: none; + z-index: 2; } +#syntax-highlight { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: #1e1e1e; + color: #d4d4d4; + padding: 15px; + font-family: 'Courier New', monospace; + font-size: 13px; + line-height: 1.5; + white-space: pre-wrap; + word-wrap: break-word; + overflow: auto; + pointer-events: none; + z-index: 1; +} + +.hl-keyword { color: #569cd6; } +.hl-type { color: #4ec9b0; } +.hl-attribute { color: #9cdcfe; } +.hl-function { color: #dcdcaa; } +.hl-number { color: #b5cea8; } +.hl-comment { color: #6a9955; } +.hl-string { color: #ce9178; } + .snippets-panel { background: #252526; border-top: 1px solid #3e3e42; @@ -256,7 +294,10 @@ body { <button id="snippets-btn">📚 Snippets</button> </div> - <textarea id="code-editor" spellcheck="false"></textarea> + <div class="editor-container"> + <div id="syntax-highlight"></div> + <textarea id="code-editor" spellcheck="false"></textarea> + </div> <div id="snippets-panel" class="snippets-panel hidden"> <h3>Available Snippets</h3> @@ -636,9 +677,42 @@ const loopTimeValue = document.getElementById('loop-time-value'); const loopTimeBar = document.getElementById('loop-time-bar'); const snippetsPanel = document.getElementById('snippets-panel'); const snippetsList = document.getElementById('snippets-list'); +const syntaxHighlight = document.getElementById('syntax-highlight'); let composeTimeout = null; +function highlightWGSL(code) { + const keywords = /\b(fn|var|let|const|struct|if|else|for|while|return|break|continue|switch|case|default|loop|continuing)\b/g; + const types = /\b(f32|i32|u32|bool|vec2|vec3|vec4|mat2x2|mat3x3|mat4x4|sampler|texture_2d|array)\b/g; + const attributes = /(@\w+)/g; + const functions = /\b([a-z_]\w*)\s*(?=\()/g; + const numbers = /\b(\d+\.?\d*)\b/g; + const comments = /(\/\/.*$)/gm; + const strings = /"([^"\\]|\\.)*"/g; + + let highlighted = code + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>'); + + highlighted = highlighted + .replace(comments, '<span class="hl-comment">$1</span>') + .replace(strings, '<span class="hl-string">$&</span>') + .replace(attributes, '<span class="hl-attribute">$1</span>') + .replace(keywords, '<span class="hl-keyword">$1</span>') + .replace(types, '<span class="hl-type">$1</span>') + .replace(functions, '<span class="hl-function">$1</span>') + .replace(numbers, '<span class="hl-number">$1</span>'); + + return highlighted; +} + +function updateHighlight() { + syntaxHighlight.innerHTML = highlightWGSL(editor.value); + syntaxHighlight.scrollTop = editor.scrollTop; + syntaxHighlight.scrollLeft = editor.scrollLeft; +} + async function init() { try { await preview.init(); @@ -654,6 +728,7 @@ async function init() { updateResolution(); editor.value = preview.getDefaultShader(); + updateHighlight(); preview.play(); playPauseBtn.textContent = '⏸ Pause'; renderLoop(); @@ -698,10 +773,16 @@ function updateResolution() { } editor.addEventListener('input', () => { + updateHighlight(); clearTimeout(composeTimeout); composeTimeout = setTimeout(composeAndLoad, 300); }); +editor.addEventListener('scroll', () => { + syntaxHighlight.scrollTop = editor.scrollTop; + syntaxHighlight.scrollLeft = editor.scrollLeft; +}); + editor.addEventListener('keydown', (e) => { if (e.key === 'Tab') { e.preventDefault(); @@ -731,6 +812,7 @@ fileInput.addEventListener('change', (e) => { const reader = new FileReader(); reader.onload = (event) => { editor.value = event.target.result; + updateHighlight(); composeAndLoad(); }; reader.readAsText(file); |
