Last active
April 2, 2023 20:26
-
-
Save jonasfrey/dab4d236bc505df6db8a9d5005b4ad0b to your computer and use it in GitHub Desktop.
monaco /vscode editor for shadertoy.com
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var f_display_editor = null; | |
class O_error{ | |
constructor( | |
n_idx_line, | |
s_text | |
){ | |
this.n_idx_line = n_idx_line | |
this.s_text = s_text | |
} | |
} | |
var f_implement_monaco_editor = function(){ | |
f_display_editor = function(s_selector){ | |
var a_o = Array.prototype.slice.apply(document.querySelectorAll('#editorManager .tab')); | |
for(var o of a_o){ | |
o.classList.remove("selected"); | |
} | |
window.event.target.classList.add("selected"); | |
var a_s_selector = [ | |
`#editor .CodeMirror`, | |
'#editor .monaco-editor' | |
]; | |
for(let s_selector of a_s_selector){ | |
document.querySelector(s_selector).style.display = "none"; | |
} | |
document.querySelector(s_selector).style.display = "block"; | |
} | |
var s_html_editor_choice = ` | |
<div id="editorManager"> | |
<div id="tab0" style='width: 45%;' onclick="f_display_editor('#editor .CodeMirror')" class="tab"><label>Shadertoy Editor</label></div> | |
<div id="tab1" style='width: 45%;' onclick="f_display_editor('#editor .monaco-editor')" class="tab"><label>VScode (Monaco) Editor</label></div> | |
</div> | |
` | |
var o_div_html_editor_choice = document.createElement("div"); | |
o_div_html_editor_choice.innerHTML = s_html_editor_choice; | |
document.querySelector(".block1").insertBefore( | |
o_div_html_editor_choice, | |
document.querySelector(".block1").firstChild, | |
); | |
var o_script = document.createElement('script'); | |
o_script.type = 'text/javascript'; | |
o_script.src = 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs/loader.min.js'; | |
document.head.appendChild(o_script); | |
window.o_editor_monaco = null; | |
o_script.onload = function(){ | |
require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs' }}); | |
require(["vs/editor/editor.main"], () => { | |
f_add_glsl_language_to_monaco_editor(monaco); | |
o_editor_monaco = monaco.editor.create(document.getElementById('editor'), { | |
value: gShaderToy.mPass[gShaderToy.mActiveDoc].mDocs.getValue(), | |
language: 'glsl', | |
theme: 'vs-dark', | |
// automaticLayout: true | |
}); | |
o_editor_monaco.a_n_view_zone_id = [] | |
o_editor_monaco.n_ms_checkerrors = 4200; | |
o_editor_monaco.n_id_timeout_checkerrors = 0; | |
window.onresize = function (){ | |
o_editor_monaco.layout(); | |
}; | |
o_editor_monaco.getModel().onDidChangeContent((event) => { | |
var s_code = o_editor_monaco.getModel().getValue(); | |
gShaderToy.mPass[gShaderToy.mActiveDoc].mDocs.setValue(s_code); | |
document.querySelector("#compileButton").click() | |
window.clearTimeout(o_editor_monaco.n_id_timeout_checkerrors); | |
o_editor_monaco.n_id_timeout_checkerrors = window.setTimeout(function(){ | |
var a_o_div_error = Array.prototype.slice.call(document.querySelectorAll(`.errorMessage`)); | |
var a_o_error = []; | |
for(var o_div_error of a_o_div_error){ | |
var o_error = new O_error( | |
Array.prototype.slice.call(document.querySelectorAll(".CodeMirror-code > div")).indexOf((o_div_error.parentElement.parentElement)), | |
o_div_error.innerText | |
); | |
a_o_error.push(o_error) | |
} | |
a_o_error = a_o_error.filter(o=>o.s_text.trim() != ''); | |
// remvoe all errors | |
o_editor_monaco.changeViewZones(function (changeAccessor) { | |
for(var n of o_editor_monaco.a_n_view_zone_id){ | |
changeAccessor.removeZone(n) | |
} | |
}); | |
console.log(a_o_error) | |
// add new errors if existing | |
for(var o_error of a_o_error){ | |
// Add a zone to make hit testing more interesting | |
// var o_error = {n_idx_line: 2, s_text: "test error"} | |
var a_n_view_zone_id = []; | |
o_editor_monaco.changeViewZones(function (changeAccessor) { | |
var o_div_error = document.createElement('div'); | |
o_div_error.style.background = '#FEE'; | |
o_div_error.style.border = '1px solid #EDD'; | |
o_div_error.style.color = '#A66'; | |
o_div_error.innerText = o_error.s_text; | |
o_editor_monaco.a_n_view_zone_id.push(changeAccessor.addZone({ | |
afterLineNumber: o_error.n_idx_line, | |
heightInLines: 'auto', | |
domNode: o_div_error, | |
})); | |
}); | |
} | |
},o_editor_monaco.n_ms_checkerrors) | |
}); | |
document.querySelector(".monaco-editor").addEventListener("keydown", function (e) { | |
if (e.key === 's' && (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey)) { | |
e.preventDefault(); | |
// o_self.f_run_o_program(); | |
document.querySelector("#saveButton").click(); | |
} | |
}, false); | |
}); | |
} | |
var f_ChangePass_old = ShaderToy.prototype.ChangePass; | |
ShaderToy.prototype.ChangePass = function(n_id){ | |
console.log("change Pass") | |
f_ChangePass_old.call(this, n_id) | |
var s_code = gShaderToy.mPass[gShaderToy.mActiveDoc].mDocs.getValue(); | |
o_editor_monaco.getModel().setValue(s_code); | |
} | |
var f_add_glsl_language_to_monaco_editor = function(monaco){ | |
monaco.languages.register({ id: 'glsl' }); | |
monaco.languages.setLanguageConfiguration('glsl', { | |
wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\#\$\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, | |
comments: { | |
lineComment: '//', | |
blockComment: ['/*', '*/'] | |
}, | |
brackets: [ | |
['{', '}'], | |
['[', ']'], | |
['(', ')'] | |
], | |
autoClosingPairs: [ | |
{ open: '[', close: ']' }, | |
{ open: '{', close: '}' }, | |
{ open: '(', close: ')' }, | |
{ open: "'", close: "'", notIn: ['string', 'comment'] }, | |
{ open: '"', close: '"', notIn: ['string'] } | |
] | |
}); | |
monaco.languages.setMonarchTokensProvider('glsl', { | |
defaultToken: '', | |
tokenPostfix: '.glsl', | |
types: [ 'bool', 'bvec2', 'bvec3', 'bvec4', 'float', 'int', 'ivec2', 'ivec3', 'ivec4', 'mat2', 'mat2x2', 'mat2x3', 'mat2x4', 'mat3', 'mat3x2', 'mat3x3', 'mat3x4', 'mat4', 'mat4x2', 'mat4x3', 'mat4x4', 'uint', 'uvec2', 'uvec3', 'uvec4', 'vec2', 'vec3', 'vec4', 'void' ], | |
keywords: [ 'attribute', 'break', 'case', 'centroid', 'const', 'continue', 'default', 'discard', 'do', 'else', 'false', 'flat', 'for', 'highp', 'if', 'in', 'inout', 'invariant', 'isampler2D', 'isampler2DArray', 'isampler3D', 'isamplerCube', 'layout', 'lowp', 'mediump', 'out', 'precision', 'return', 'sampler2D', 'sampler2DArray', 'sampler2DArrayShadow', 'sampler2DShadow', 'sampler3D', 'samplerCube', 'samplerCubeShadow', 'smooth', 'struct', 'switch', 'true', 'uniform', 'usampler2D', 'usampler2DArray', 'usampler3D', 'usamplerCube', 'varying', 'while' ], | |
functions: [ 'radians', 'degrees', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'sinh', 'cosh', 'tanh', 'asinh', 'acosh', 'atanh', 'pow', 'exp', 'log', 'exp2', 'log2', 'sqrt', 'inversesqrt', 'abs', 'sign', 'floor', 'trunc', 'round', 'roundEven', 'ceil', 'fract', 'mod', 'modf', 'min', 'max', 'clamp', 'mix', 'step', 'smoothstep', 'isnan', 'isinf', 'floatBitsToInt', 'floatBitsToUint', 'intBitsToFloat', 'uintBitsToFloat', 'packSnorm2x16', 'unpackSnorm2x16', 'packUnorm2x16', 'unpackUnorm2x16', 'packHalf2x16', 'unpackHalf2x16', 'length', 'distance', 'dot', 'cross', 'normalize', 'faceforward', 'reflect', 'refract', 'matrixCompMult', 'outerProduct', 'transpose', 'determinant', 'inverse', 'lessThan', 'lessThanEqual', 'greaterThan', 'greaterThanEqual', 'equal', 'notEqual', 'any', 'all', 'not', 'textureSize', 'texture', 'texture2D', 'textureCube', 'texture2DProj', 'texture2DLodEXT', 'texture2DProjLodEXT', 'textureCubeLodEXT', 'texture2DGradEXT', 'texture2DProjGradEXT', 'textureCubeGradEXT', 'textureProj', 'textureLod', 'textureOffset', 'texelFetch', 'texelFetchOffset', 'textureProjOffset', 'textureLodOffset', 'textureProjLod', 'textureProjLodOffset', 'textureGrad', 'textureGradOffset', 'textureProjGrad', 'textureProjGradOffset', 'dFdx', 'dFdy', 'fwidth' ], | |
operators: [ '++', '--', '+', '-', '~', '!', '*', '/', '%', '<<', '>>', '<', '>', '<=', '>=', '==', '!=', '&', '^', '|', '&&', '^^', '||', '?', ':', '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '&=', '^=', '|=', ',' ], | |
brackets: [ | |
{ token: 'delimiter.curly', open: '{', close: '}' }, | |
{ token: 'delimiter.parenthesis', open: '(', close: ')' }, | |
{ token: 'delimiter.square', open: '[', close: ']' }, | |
{ token: 'delimiter.angle', open: '<', close: '>' } | |
], | |
symbols: /[=><!~?:&|+\-*\/\^%]+/, | |
integersuffix: /[uU]?/, | |
floatsuffix: /[fF]?/, | |
func: /[a-zA-Z_0-9]+/, | |
tokenizer: { | |
root: [ | |
[/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/, 'number.float'], | |
[/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/, 'number.float'], | |
[/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/, 'number.hex'], | |
[/([+-]?)\d+(@integersuffix)/, 'number.integer'], | |
[/#(version|define|undef|ifdef|ifndef|else|elsif|endif)/, 'keyword.directive'], | |
[/\$[a-zA-Z0-9]*/, 'regexp'], | |
[/\s[A-Z_][A-Z_0-9]*/, 'constant'], | |
[/gl_[a-zA-Z_0-9]+/, 'keyword.gl'], | |
[ | |
/([a-zA-Z_][a-zA-Z_0-9]*)/, | |
{ | |
cases: { | |
'@types': { token: 'keyword.$0' }, | |
'@keywords': { token: 'keyword.$0' }, | |
'@functions': { token: 'keyword.builtins.$0' }, | |
'@default': 'identifier' | |
} | |
} | |
], | |
[/(\d+(\.\d+))/, 'number.float'], | |
[/\d+/, 'keyword'], | |
[/\/\/.+/, 'comment'], | |
[/\/\*.+?(\*\/)/, 'comment'], | |
[/[{}()\[\]]/, '@brackets'], | |
[ | |
/@symbols/, | |
{ | |
cases: { | |
'@operators': 'delimiter', | |
'@default': '' | |
} | |
} | |
], | |
[/[;,.]/, 'delimiter'], | |
], | |
} | |
}); | |
} | |
} | |
var f_b_shadertoy_loaded = async function(){ | |
window.setTimeout(function(){ | |
return window.gShaderToy != null; | |
},100) | |
} | |
if(window.location.href.includes("/view/")){ | |
var n_id = 0; | |
n_id = window.setInterval(function(){ | |
if(window.gShaderToy != null){ | |
window.clearInterval(n_id); | |
window.setTimeout(function(){ | |
f_implement_monaco_editor(); | |
},1000) | |
} | |
},100); | |
// var b_shadertoy_loaded = await f_b_shadertoy_loaded(); | |
// while(!b_shadertoy_loaded){ | |
// b_shadertoy_loaded = await f_b_shadertoy_loaded(); | |
// } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment