icondumper2/input.htm

532 lines
23 KiB
HTML
Raw Normal View History

2023-10-12 02:49:07 -04:00
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="initial-scale=1.5"></meta>
2023-10-12 02:49:07 -04:00
<meta name="description" content="A HTML client for icondumper2"></meta>
<title>icondumper2 - HTML reference client</title>
2023-10-12 02:49:07 -04:00
<script src="icon.js"></script>
<style>
html {color: #ccc; background: black; font-family: sans-serif}
#title1, #title2 {
color: yellow;
text-align: right;
line-height: 0.50em;
2023-10-12 02:49:07 -04:00
}
#version {position: fixed;bottom:4px;right:4px}
#advanced {display: none}
#iconcanvas {position: absolute; left: 8px}
#titlebox {width: 99%;position: absolute;}
input[type="file"] {line-height: 2em;}
#version {text-shadow: 1px 1px 2px black;}
2023-10-12 02:49:07 -04:00
</style>
<meta data-comment="WebGL Shader: Icon">
<script type="text/plain" id="shader-icon-v">
attribute vec3 a_position;
attribute vec3 a_normal;
attribute vec2 a_textureCoords;
attribute vec4 a_color;
uniform float u_rotation;
uniform highp vec3 u_ambientLight;
//uniform highp vec3 u_lightColorA;
//uniform highp vec3 u_lightColorB;
//uniform highp vec3 u_lightColorC;
varying lowp vec4 v_color;
varying lowp vec2 v_textureCoords;
void main() {
float angle = radians(360.0) * u_rotation;
vec2 pos = vec2(cos(angle), sin(angle));
// x, y, z, scale (w)
gl_Position = vec4(
(a_position.x * pos.x) + (a_position.z * pos.y), //transform the x position
(0.0 - a_position.y) - 2.75, // invert the y position and move down -2.75, which will center the model
(a_position.x * -pos.y) + (a_position.z * pos.x), //transform the z position
3.5
);
// flip it, scale it
v_textureCoords = a_textureCoords;
v_color = a_color;
}
</script>
<script type="text/plain" id="shader-icon-f">
varying lowp vec4 v_color;
uniform highp vec3 u_ambientLight;
void main() {
highp vec3 ambientColor = (u_ambientLight * vec3(v_color));
gl_FragColor = vec4(ambientColor, v_color.a);
}
</script>
<script type="text/plain" id="shader-icon-f2">
varying lowp vec2 v_textureCoords;
varying lowp vec4 v_color;
uniform sampler2D u_sampler;
uniform highp vec3 u_ambientLight;
void main() {
mediump vec4 texture_c = texture2D(u_sampler, v_textureCoords);
highp vec3 ambientColorT = (u_ambientLight * vec3(texture_c));
highp vec3 ambientColorV = (u_ambientLight * vec3(v_color));
//This has issues with oversaturation, but it means blended icons work.
if(v_color == vec4(1.0,1.0,1.0,1.0)) {
gl_FragColor = vec4((ambientColorT * ambientColorV), texture_c.a);
} else {
gl_FragColor = vec4((ambientColorT * ambientColorV) * 2.0, texture_c.a);
}
}
</script>
<meta data-comment="WebGL Shader: Background">
<script type="text/plain" id="shader-bg-v">
attribute vec2 a_position;
2023-10-12 02:49:07 -04:00
attribute vec4 a_color;
varying lowp vec4 vColor;
void main() {
// x, y, z, scale (w)
gl_Position = vec4(a_position, 0.99, 1.0);
2023-10-12 02:49:07 -04:00
vColor = a_color;
}
</script>
<script type="text/plain" id="shader-bg-f">
precision lowp float;
2023-10-12 02:49:07 -04:00
varying lowp vec4 vColor;
void main() {
gl_FragColor = vColor;
}
</script>
</head>
<body>
<label for="strictnessOption">enable strict mode</label>
<input id="strictnessOption" type="checkbox" checked></input>
<span>(enables console-accurate title parsing) | </span>
<label for="showExtractedInputOption">show other import options</label>
<input id="showExtractedInputOption" type="checkbox"></input>
2023-10-12 02:49:07 -04:00
<hr>
<div id="titlebox">
<h1 id="title1">&#xFF2E;&#xFF4F;&#x3000;&#xFF26;&#xFF49;&#xFF4C;&#xFF45;</h1>
<h1 id="title2">&#xFF2C;&#xFF4F;&#xFF41;&#xFF44;&#xFF45;&#xFF44;</h1>
</div>
<span>Background/icon preview (rotate: &larr;/&rarr; keys):</span><br>
<canvas id="bgcanvas" width="360" height="360"></canvas>
<canvas id="iconcanvas" width="360" height="360"></canvas>
2023-10-12 02:49:07 -04:00
<hr>
<p>Normal: <kbd id="iconn">(no&nbsp;file)<wbr></kbd> Copying: <kbd id="iconc">(no&nbsp;file)<wbr></kbd> Deleting: <kbd id="icond">(no&nbsp;file)</kbd></p>
<div id="advanced">
<hr>
<label for="input">icon.sys goes here:</label>
<input type="file" id="input" name="input" accept=".sys" />
<br>
<label for="icon">.ic(n|o) goes here:</label>
<input type="file" id="icon" name="icon" accept=".icn, .ico" />
<br>
</div>
2023-10-12 02:49:07 -04:00
<hr>
<label for="psuinput">EMS Memory Adapter export file (.psu) goes here:</label>
2023-10-12 02:49:07 -04:00
<input type="file" id="psuinput" name="psuinput" accept=".psu" />
<br>
<label for="psvinput">PS3 export file (.psv) goes here:</label>
<input type="file" id="psvinput" name="psvinput" accept=".psv" />
<br>
<label for="spsinput">SharkPort/X-Port export file (.sps, .xps) goes here:</label>
<input type="file" id="spsinput" name="spsinput" accept=".sps, .xps" />
<br>
2023-10-12 02:49:07 -04:00
<p>
<span>Date&nbsp;created: </span><span id="dateCreated">--:--:--&nbsp;--/--/----</span><span> UTC+09:00</span>
<wbr><span>&ndash;</span>
<span>Date&nbsp;modified: </span><span id="dateModified">--:--:--&nbsp;--/--/----</span><span> UTC+09:00</span>
2023-10-12 02:49:07 -04:00
</p>
<p>
<span>File comments: </span><span id="fileCommentGame">(no title)</span></span><span> - </span><span id="fileCommentName">(no description)</span>
</p>
2023-10-12 02:49:07 -04:00
<script>
const rotationDensity = 60;
rotations = 2;
document.body.onkeydown = function(ev) {
if(glBgContext === null) {return;}
if(typeof URotation !== "undefined") {
switch(ev.code) {
case "ArrowLeft": {
rotations--;
if(rotations < -rotationDensity) {rotations = -1;}
break;
}
case "ArrowRight": {
rotations++;
if(rotations > rotationDensity) {rotations = 1;}
break;
}
};
glFgContext.uniform1f(URotation, (rotations/rotationDensity));
glFgContext.drawArrays(glFgContext.TRIANGLES, 0, ULength);
} else {return;}
}
// I usually don't do in-body <script>'s, but I didn't want to do an await onload again
2023-10-12 02:49:07 -04:00
function updateDisplay(input) {
document.getElementById("title1").textContent = input.title[0];
document.getElementById("title2").textContent = input.title[1];
document.getElementById("iconn").textContent = input.filenames.n;
document.getElementById("iconc").textContent = input.filenames.c;
document.getElementById("icond").textContent = input.filenames.d;
let colours = input.background;
if(glBgContext !== null) {
2023-10-12 02:49:07 -04:00
colors = [
colours.colors[0].r/255,
colours.colors[0].g/255,
colours.colors[0].b/255,
(colours.alpha*2)/255,
colours.colors[1].r/255,
colours.colors[1].g/255,
colours.colors[1].b/255,
(colours.alpha*2)/255,
colours.colors[2].r/255,
colours.colors[2].g/255,
colours.colors[2].b/255,
(colours.alpha*2)/255,
colours.colors[3].r/255,
colours.colors[3].g/255,
colours.colors[3].b/255,
(colours.alpha*2)/255
2023-10-12 02:49:07 -04:00
];
drawBackground(colors);
2023-10-12 02:49:07 -04:00
}
}
function resetDisplay() {
document.getElementById("title1").textContent = "\uff0d";
document.getElementById("title2").textContent = "\uff0d";
document.getElementById("iconn").textContent = "?";
document.getElementById("iconc").textContent = "?";
document.getElementById("icond").textContent = "?";
document.getElementById("dateCreated").textContent = "--:--:-- --/--/----";
document.getElementById("dateModified").textContent = "--:--:-- --/--/----";
document.getElementById("fileCommentGame").textContent = "(no title)";
document.getElementById("fileCommentName").textContent = "(no description)";
}
function renderIcon(iconData, fileMetadata = null) {
if(fileMetadata === null) {
fileMetadata = {
"lighting": {
"points": [{x:0,y:0,z:0},{x:0,y:0,z:0},{x:0,y:0,z:0}],
"colors": [
{r:1,g:1,b:1,a:1}, //ambient
{r:1,g:0,b:0,a:1}, //p[0]
{r:0,g:1,b:0,a:1}, //p[1]
{r:0,g:0,b:1,a:1} //p[2]
]
}
};
}
if(glFgContext === null) {return -1;} else {
const texture = glFgContext.createTexture();
glFgContext.bindTexture(glFgContext.TEXTURE_2D, texture);
if (iconData.textureFormat !== "N") {
let rgb5a1_converted;
if (iconData.textureFormat === "C") {
let uncompressed = uncompressTexture(iconData.texture.data);
2023-10-18 03:25:42 -04:00
rgb5a1_converted = convertBGR5A1toRGB5A1(uncompressed);
} else {
2023-10-18 03:25:42 -04:00
rgb5a1_converted = convertBGR5A1toRGB5A1(iconData.texture);
}
glFgContext.texImage2D(glFgContext.TEXTURE_2D, 0, glFgContext.RGBA, 128, 128, 0, glFgContext.RGBA, glFgContext.UNSIGNED_SHORT_5_5_5_1, rgb5a1_converted);
glFgContext.generateMipmap(glFgContext.TEXTURE_2D);
}
//.section PROGRAM.icon
if(iconData.textureFormat !== "N") {
var iconVertexShader = createShader(glFgContext, glFgContext.VERTEX_SHADER, document.getElementById("shader-icon-v").text);
var iconFragmentShader = createShader(glFgContext, glFgContext.FRAGMENT_SHADER, document.getElementById("shader-icon-f2").text);
} else {
var iconVertexShader = createShader(glFgContext, glFgContext.VERTEX_SHADER, document.getElementById("shader-icon-v").text);
var iconFragmentShader = createShader(glFgContext, glFgContext.FRAGMENT_SHADER, document.getElementById("shader-icon-f").text);
}
let iconProgram = createProgram(glFgContext, iconVertexShader, iconFragmentShader);
glFgContext.useProgram(iconProgram);
if(iconData.textureFormat !== "N") {
var attributes = {
position: glFgContext.getAttribLocation(iconProgram, "a_position"),
textureCoords: glFgContext.getAttribLocation(iconProgram, "a_textureCoords"),
color: glFgContext.getAttribLocation(iconProgram, "a_color"),
};
var uniforms = {
rotation: glFgContext.getUniformLocation(iconProgram, "u_rotation"),
ambientLighting: glFgContext.getUniformLocation(iconProgram, "u_ambientLight")
}
} else {
var attributes = {
position: glFgContext.getAttribLocation(iconProgram, "a_position"),
color: glFgContext.getAttribLocation(iconProgram, "a_color"),
};
var uniforms = {
sampler: glFgContext.getUniformLocation(iconProgram, "u_sampler"),
rotation: glFgContext.getUniformLocation(iconProgram, "u_rotation"),
ambientLighting: glFgContext.getUniformLocation(iconProgram, "u_ambientLight")
}
}
//.section SETUP
let verticesArray = new Array();
let colourArray = new Array();
let uvArray = new Array();
iconData.vertices.forEach(function(vertexObject){
verticesArray.push(vertexObject.shapes[0].x);
verticesArray.push(vertexObject.shapes[0].y);
verticesArray.push(vertexObject.shapes[0].z);
colourArray.push(vertexObject.color.r/255);
colourArray.push(vertexObject.color.g/255);
colourArray.push(vertexObject.color.b/255);
colourArray.push((vertexObject.color.a > 1) ? (vertexObject.color.a/255): 1);
uvArray.push(vertexObject.uv.u);
uvArray.push(vertexObject.uv.v);
});
//.section VERTICES
const positionBuffer = glFgContext.createBuffer();
glFgContext.bindBuffer(glFgContext.ARRAY_BUFFER, positionBuffer);
glFgContext.enableVertexAttribArray(attributes.position);
glFgContext.bufferData(glFgContext.ARRAY_BUFFER, new Float32Array(verticesArray), glFgContext.STATIC_DRAW);
glFgContext.vertexAttribPointer(attributes.position, 3, glFgContext.FLOAT, false, 0, 0);
//.section COLOURS
const colorBuffer = glFgContext.createBuffer();
glFgContext.bindBuffer(glFgContext.ARRAY_BUFFER, colorBuffer);
glFgContext.enableVertexAttribArray(attributes.color);
glFgContext.bufferData(glFgContext.ARRAY_BUFFER, new Float32Array(colourArray), glFgContext.STATIC_DRAW);
glFgContext.vertexAttribPointer(attributes.color, 4, glFgContext.FLOAT, false, 0, 0);
if(iconData.textureFormat !== "N") {
//.section UV
const uvBuffer = glFgContext.createBuffer();
glFgContext.bindBuffer(glFgContext.ARRAY_BUFFER, uvBuffer);
glFgContext.enableVertexAttribArray(attributes.textureCoords);
glFgContext.bufferData(glFgContext.ARRAY_BUFFER, new Float32Array(uvArray), glFgContext.STATIC_DRAW);
glFgContext.vertexAttribPointer(attributes.textureCoords, 2, glFgContext.FLOAT, false, 0, 0);
//.section TEXTURE
glFgContext.activeTexture(glFgContext.TEXTURE0);
glFgContext.bindTexture(glFgContext.TEXTURE_2D, texture);
glFgContext.uniform1i(uniforms.sampler, 0);
}
//.section ROTATE
// sets the angle uniform to 2/rotationDensity, this puts the icon at an angle.
// globalize uniform rotation
URotation = uniforms.rotation;
rotations = 2;
glFgContext.uniform1f(URotation, rotations/rotationDensity);
//.section LIGHTING
let colours = fileMetadata.lighting.colors[0];
//glFgContext.uniform3f(uniforms.ambientLighting, colours.r, colours.g, colours.b);
glFgContext.uniform3f(uniforms.ambientLighting, 1, 1, 1);
//.section WRITE
//globalize count of triangles, as well
ULength = (verticesArray.length/3);
glFgContext.drawArrays(glFgContext.TRIANGLES, 0, ULength);
}
}
2023-10-12 02:49:07 -04:00
document.getElementById("strictnessOption").onchange = function(e) {
setStrictness(e.target.checked);
if(!!filebox.files.length) {filebox.onchange();}
if(!!iconbox.files.length) {iconbox.onchange();}
if(!!psubox.files.length) {psubox.onchange();}
if(!!psvbox.files.length) {psvbox.onchange();}
if(!!spsbox.files.length) {spsbox.onchange();}
2023-10-12 02:49:07 -04:00
}
filebox = document.getElementById("input");
filebox.onchange = function(e) {
resetDisplay();
2023-10-12 02:49:07 -04:00
if(filebox.files.length === 0) {
return;
}
filebox.files[0].arrayBuffer().then(function(d){
try {
let output = readPS2D(d);
console.log("icon.sys", output);
updateDisplay(output);
} catch(e) {
if(glBgContext!==null){glBgContext.clear(glBgContext.COLOR_BUFFER_BIT);}
2023-10-12 02:49:07 -04:00
alert(e);
}
});
}
iconbox = document.getElementById("icon");
iconbox.onchange = function(e) {
if(iconbox.files.length === 0) {
return;
}
iconbox.files[0].arrayBuffer().then(function(d){
try {
let output = readIconFile(d);
renderIcon(output);
2023-10-12 02:49:07 -04:00
console.log("model data",output);
} catch(e) {
if(glFgContext!==null){glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);}
2023-10-12 02:49:07 -04:00
alert(e);
}
});
}
psubox = document.getElementById("psuinput");
psubox.onchange = function(e) {
resetDisplay();
2023-10-12 02:49:07 -04:00
if(psubox.files.length === 0) {
return;
}
psubox.files[0].arrayBuffer().then(function(d){
try {
let vFilesystem = readEmsPsuFile(d);
let output = readPS2D(vFilesystem[vFilesystem.rootDirectory]["icon.sys"].data);
updateDisplay(output);
let output2 = new Object();
Object.keys(output.filenames).forEach(function(file) {
output2[file] = readIconFile(vFilesystem[vFilesystem.rootDirectory][output.filenames[file]].data);
});
renderIcon(output2.n, output);
2023-10-12 02:49:07 -04:00
let cTime = vFilesystem.timestamps.created;
let mTime = vFilesystem.timestamps.modified;
//TODO: use Time() to align JST times to user-local timezone
document.getElementById("dateCreated").textContent = `${cTime.hours.toString().padStart("2","0")}:${cTime.minutes.toString().padStart("2","0")}:${cTime.seconds.toString().padStart("2","0")} ${cTime.day.toString().padStart("2","0")}/${cTime.month.toString().padStart("2","0")}/${cTime.year}`;
document.getElementById("dateModified").textContent = `${mTime.hours.toString().padStart("2","0")}:${mTime.minutes.toString().padStart("2","0")}:${mTime.seconds.toString().padStart("2","0")} ${mTime.day.toString().padStart("2","0")}/${mTime.month.toString().padStart("2","0")}/${mTime.year}`;
console.log("model files", output2);
} catch(e) {
if(glBgContext!==null){glBgContext.clear(glBgContext.COLOR_BUFFER_BIT);}
if(glFgContext!==null){glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);}
2023-10-12 02:49:07 -04:00
alert(e);
}
});
}
psvbox = document.getElementById("psvinput");
psvbox.onchange = function(e) {
resetDisplay();
if(psvbox.files.length === 0) {
return;
}
psvbox.files[0].arrayBuffer().then(function(d){
try {
let inputData = readPsvFile(d);
let output = readPS2D(inputData["icon.sys"]);
updateDisplay(output);
renderIcon(readIconFile(inputData.icons.n), output);
console.log(readIconFile(inputData.icons.n));
let cTime = inputData.timestamps.created;
let mTime = inputData.timestamps.modified;
//TODO: use Time() to align JST times to user-local timezone
document.getElementById("dateCreated").textContent = `${cTime.hours.toString().padStart("2","0")}:${cTime.minutes.toString().padStart("2","0")}:${cTime.seconds.toString().padStart("2","0")} ${cTime.day.toString().padStart("2","0")}/${cTime.month.toString().padStart("2","0")}/${cTime.year}`;
document.getElementById("dateModified").textContent = `${mTime.hours.toString().padStart("2","0")}:${mTime.minutes.toString().padStart("2","0")}:${mTime.seconds.toString().padStart("2","0")} ${mTime.day.toString().padStart("2","0")}/${mTime.month.toString().padStart("2","0")}/${mTime.year}`;
} catch(e) {
if(glBgContext!==null){glBgContext.clear(glBgContext.COLOR_BUFFER_BIT);}
if(glFgContext!==null){glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);}
alert(e);
}
});
}
spsbox = document.getElementById("spsinput");
spsbox.onchange = function(e) {
resetDisplay();
if(spsbox.files.length === 0) {
return;
}
spsbox.files[0].arrayBuffer().then(function(d){
try {
let vFilesystem = readSharkXPortSxpsFile(d);
let output = readPS2D(vFilesystem[vFilesystem.rootDirectory]["icon.sys"].data);
updateDisplay(output);
let output2 = new Object();
Object.keys(output.filenames).forEach(function(file) {
output2[file] = readIconFile(vFilesystem[vFilesystem.rootDirectory][output.filenames[file]].data);
});
renderIcon(output2.n, output);
let cTime = vFilesystem.timestamps.created;
let mTime = vFilesystem.timestamps.modified;
//TODO: use Time() to align JST times to user-local timezone
document.getElementById("dateCreated").textContent = `${cTime.hours.toString().padStart("2","0")}:${cTime.minutes.toString().padStart("2","0")}:${cTime.seconds.toString().padStart("2","0")} ${cTime.day.toString().padStart("2","0")}/${cTime.month.toString().padStart("2","0")}/${cTime.year}`;
document.getElementById("dateModified").textContent = `${mTime.hours.toString().padStart("2","0")}:${mTime.minutes.toString().padStart("2","0")}:${mTime.seconds.toString().padStart("2","0")} ${mTime.day.toString().padStart("2","0")}/${mTime.month.toString().padStart("2","0")}/${mTime.year}`;
document.getElementById("fileCommentGame").textContent = vFilesystem.comments.game;
document.getElementById("fileCommentName").textContent = vFilesystem.comments.name;
console.log("model files", output2);
} catch(e) {
if(glBgContext!==null){glBgContext.clear(glBgContext.COLOR_BUFFER_BIT);}
if(glFgContext!==null){glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);}
alert(e);
}
});
}
2023-10-12 02:49:07 -04:00
function createShader(gl, type, source) {
let shader = gl.createShader(type);
2023-10-12 02:49:07 -04:00
gl.shaderSource(shader, source);
gl.compileShader(shader);
let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
2023-10-12 02:49:07 -04:00
if (success) {
return shader;
}
console.log(gl.getShaderInfoLog(shader), source);
2023-10-12 02:49:07 -04:00
gl.deleteShader(shader);
}
function createProgram(gl, vertexShader, fragmentShader) {
let program = gl.createProgram();
2023-10-12 02:49:07 -04:00
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
let success = gl.getProgramParameter(program, gl.LINK_STATUS);
2023-10-12 02:49:07 -04:00
if (success) {
return program;
}
console.log(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
}
const bgCanvas = document.getElementById("bgcanvas");
const glBgContext = bgCanvas.getContext("webgl");
const fgCanvas = document.getElementById("iconcanvas");
const glFgContext = fgCanvas.getContext("webgl");
function drawBackground(colorInput) {
//.section PROGRAM.background
let backgroundVertexShader = createShader(glBgContext, glBgContext.VERTEX_SHADER, document.getElementById("shader-bg-v").text);
let backgroundFragmentShader = createShader(glBgContext, glBgContext.FRAGMENT_SHADER, document.getElementById("shader-bg-f").text);
let backgroundProgram = createProgram(glBgContext, backgroundVertexShader, backgroundFragmentShader);
glBgContext.useProgram(backgroundProgram);
let attributes = {
position: glBgContext.getAttribLocation(backgroundProgram, "a_position"),
color: glBgContext.getAttribLocation(backgroundProgram, "a_color")
2023-10-12 02:49:07 -04:00
};
//.section POSITION
const positions = [-1,1, 1,1, -1,-1, 1,-1];
const positionBuffer = glBgContext.createBuffer();
glBgContext.bindBuffer(glBgContext.ARRAY_BUFFER, positionBuffer);
glBgContext.enableVertexAttribArray(attributes.position);
glBgContext.bufferData(glBgContext.ARRAY_BUFFER, new Float32Array(positions), glBgContext.STATIC_DRAW);
glBgContext.vertexAttribPointer(attributes.position, 2, glBgContext.FLOAT, false, 0, 0);
2023-10-12 02:49:07 -04:00
//.section COLOR
const colors = (Array.isArray(colorInput)) ? colorInput : [1,0,0,1, 0,1,0,1, 0,0,1,1, 1,1,1,1];
const colorBuffer = glBgContext.createBuffer();
glBgContext.bindBuffer(glBgContext.ARRAY_BUFFER, colorBuffer);
glBgContext.enableVertexAttribArray(attributes.color);
glBgContext.bufferData(glBgContext.ARRAY_BUFFER, new Float32Array(colors), glBgContext.STATIC_DRAW);
glBgContext.vertexAttribPointer(attributes.color, 4, glBgContext.FLOAT, false, 0, 0);
2023-10-12 02:49:07 -04:00
//.section WRITE
glBgContext.drawArrays(glBgContext.TRIANGLE_STRIP, 0, 4);
}
if(glBgContext !== null) {
//.section CONFIGURATION
glBgContext.enable(glBgContext.DEPTH_TEST);
glFgContext.enable(glFgContext.DEPTH_TEST);
//.section CLEAR
glBgContext.clearColor(0.1,0.1,0.4,1);
glBgContext.clear(glBgContext.COLOR_BUFFER_BIT | glBgContext.DEPTH_BUFFER_BIT);
glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);
drawBackground();
2023-10-12 02:49:07 -04:00
} else {
bgCanvas.style.display = "none";
fgCanvas.style.display = "none";
2023-10-12 02:49:07 -04:00
}
document.getElementById("showExtractedInputOption").onchange = function(e) {
document.getElementById("advanced").style.display = ((e.target.checked) ? "block" : "none");
}
//todo: Animation parsing, animation tweening
2023-10-12 02:49:07 -04:00
</script>
<span id="version">icondumper2 <span id="iconjsVersion">(unknown icon.js version)</span> [C: <span id="clientVersion">Loading...</span>] &mdash; &copy; 2023 yellows111</span>
<script>document.getElementById("iconjsVersion").textContent = ICONJS_VERSION;</script>
<script>document.getElementById("clientVersion").textContent = "0.6.2";</script>
2023-10-12 02:49:07 -04:00
</body>
</html>