Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 72 additions & 28 deletions dist/artimus.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ window.artimus = {
this.workspace = workspace;
this.name = name || `${artimus.translate("layer#", "layer").replace("#", this.layers.length + 1)}`;

//Do a thing, guarenteed to not exist (hopefully)
//Do a thing, guaranteed to not exist (hopefully)
if (this.workspace.layerExists(name)) {
let num = 1;
name = (`${artimus.translate("layer#", "layer").replace("#", num)}`);
Expand All @@ -405,6 +405,7 @@ window.artimus = {
num++;
name = (`${artimus.translate("layer#", "layer").replace("#", num)}`);
}
this.name = name
}


Expand Down Expand Up @@ -1975,6 +1976,16 @@ window.artimus = {
return layer;
}

duplicateLayer(name, noSwitch) {
const oldLayer = this.layers.find(layer => layer.name === name);
const newLayer = new artimus.layer(this.canvas.width, this.canvas.height, oldLayer.name + " copy", this, noSwitch);

newLayer.dataRaw.data.set(oldLayer.dataRaw.data); // Copy the image data between the layers
newLayer.alpha = oldLayer.alpha;
newLayer.visibility = oldLayer.visibility;
newLayer.blendMode = oldLayer.blendMode;
}

_createLayerElement(layerData) {
const element = document.createElement("div");
element.className = "artimus-layerWrapper";
Expand All @@ -1991,7 +2002,8 @@ window.artimus = {
label.CUGI_CONTEXT = () => {
return [
{ type: "button", text: "delete", onclick: () => this.removeLayer(element.targetLayer) },
{ type: "button", text: "properties", onclick: () => (artimus.layerPropertyMenu)(this, this.getLayer(element.targetLayer)) }
{ type: "button", text: "properties", onclick: () => (artimus.layerPropertyMenu)(this, this.getLayer(element.targetLayer)) },
{ type: "button", text: "duplicate", onclick: () => this.duplicateLayer(element.targetLayer, false)}
]
}

Expand Down Expand Up @@ -2691,7 +2703,9 @@ window.artimus = {
this.createLayer(name, true);

//Set layer data
this.layers[layer + 1].dataRaw = new ImageData(imageData, this.width, this.height);
this.layers[layer + 1].dataRaw = new ImageData(imageData,
(data[5] << 16) + (data[6] << 8) + (data[7]),
(data[8] << 16) + (data[9] << 8) + (data[10]));
this.layers[layer + 1].blendMode = blendMode;

this.updateLayer(layer + 1);
Expand Down Expand Up @@ -2723,7 +2737,9 @@ window.artimus = {
this.createLayer(name, true);

//Set layer data
this.layers[layer + 1].dataRaw = new ImageData(imageData, this.width, this.height);
this.layers[layer + 1].dataRaw = new ImageData(imageData
(data[5] << 16) + (data[6] << 8) + (data[7]),
(data[8] << 16) + (data[9] << 8) + (data[10]));
this.layers[layer + 1].blendMode = blendMode;

this.updateLayer(layer + 1);
Expand Down Expand Up @@ -2756,7 +2772,9 @@ window.artimus = {
this.createLayer(name, true);

//Set layer data
this.layers[layer + 1].dataRaw = new ImageData(imageData, this.width, this.height);
this.layers[layer + 1].dataRaw = new ImageData(imageData
(data[5] << 16) + (data[6] << 8) + (data[7]),
(data[8] << 16) + (data[9] << 8) + (data[10]));
this.layers[layer + 1].blendMode = blendMode;

this.updateLayer(layer + 1);
Expand Down Expand Up @@ -2792,7 +2810,9 @@ window.artimus = {
this.createLayer(name, true);

//Set layer data
this.layers[layer + 1].dataRaw = new ImageData(imageData, this.width, this.height);
this.layers[layer + 1].dataRaw = new ImageData(imageData,
(data[5] << 16) + (data[6] << 8) + (data[7]),
(data[8] << 16) + (data[9] << 8) + (data[10]));
this.layers[layer + 1].blendMode = blendMode;
this.layers[layer + 1].alpha = alpha;

Expand All @@ -2803,7 +2823,7 @@ window.artimus = {
},
];

importArtimus(input) {
importArtimus(input, replaceFile) {
const data = new Uint8Array(input);

//Make sure it is an artimus image
Expand All @@ -2813,12 +2833,14 @@ window.artimus = {
data[2] == this.magic[2] &&
data[3] == this.magic[3]
) {
this.new(
(data[5] << 16) + (data[6] << 8) + (data[7]),
(data[8] << 16) + (data[9] << 8) + (data[10]),
() => {
const handleImport = () => {
//Count bytes needed
const bytesPerLayer = this.width * this.height * 4;
if (replaceFile) {
this.width = (data[5] << 16) + (data[6] << 8) + (data[7])
this.height = (data[8] << 16) + (data[9] << 8) + (data[10])
}

const bytesPerLayer = ((data[5] << 16) + (data[6] << 8) + (data[7])) * ((data[8] << 16) + (data[9] << 8) + (data[10])) * 4;
const layerCount = (data[11] << 8) + data[12];
const format = (data[4]);

Expand All @@ -2827,7 +2849,7 @@ window.artimus = {
let idx = 12;

//layer 1 is set to NaN as to not confuse it with an actual layer
this.layers[0].name = NaN;
if (replaceFile) this.layers[0].name = NaN;

//Loop through layers, and read them with whatever format of reader is needed;
let layerReader = this.layerReaders[format];
Expand All @@ -2837,11 +2859,12 @@ window.artimus = {
return;
}

for (let layer = 0; layer < layerCount; layer++) {
const fileLayers = this.layers.length;
for (let layer = (replaceFile ? 0 : this.layers.length-1); layer < (replaceFile ? layerCount : layerCount+fileLayers-1); layer++) {
idx = layerReader(data, layer, bytesPerLayer, idx);
}

this.setLayer(1).then(() => {
if (replaceFile) this.setLayer(1).then(() => {
this.removeLayer(0)
this.setLayer(0);
});
Expand All @@ -2861,7 +2884,16 @@ window.artimus = {
console.error("Json header could possibly be corrupted :(");
}
}
});


}

if (replaceFile) this.new(
(data[5] << 16) + (data[6] << 8) + (data[7]),
(data[8] << 16) + (data[9] << 8) + (data[10]),
handleImport
);
else handleImport();
}
else console.error("Artimus File invalid!");
}
Expand Down Expand Up @@ -2964,17 +2996,17 @@ window.artimus = {
// Will be set upon file save/load
fileSystemHandle = null;

importFromImage(image) {
importFromImage(image, replaceFile) {
let extension = image.name.split(".");
extension = extension[extension.length - 1];

this.fileReader.onload = () => { this.onImageLoad(this.fileReader.result, extension); };
this.fileReader.onload = () => { this.onImageLoad(this.fileReader.result, extension, replaceFile); };
this.fileReader[this.importTypes[extension] || "readAsDataURL"](image);
}

importFromPC() {
importFromPC(replaceFile) {
// Not yet widely available, so we will need to check we can use the file system access API
if (window.showSaveFilePicker) window.showOpenFilePicker({
if (window.showSaveFilePicker) return window.showOpenFilePicker({
id: "artimus_file_location",
multiple: false,
startIn: "documents",
Expand All @@ -2985,37 +3017,49 @@ window.artimus = {
]
}).then(fsHandle => {
artimus.activeWorkspaces[0].fileSystemHandle = fsHandle[0];
fsHandle[0].getFile().then(file => artimus.activeWorkspaces[0].importFromImage(file));
fsHandle[0].getFile().then(file => artimus.activeWorkspaces[0].importFromImage(file, replaceFile));
});

else {
const fileInput = document.createElement("input");
fileInput.type = "file";
fileInput.accept = "image/*, .artimus";

fileInput.onchange = () => {
artimus.activeWorkspaces[0].importFromImage(fileInput.files[0]);
};
const filePromise = new Promise((resolve) => {
fileInput.onchange = () => {
artimus.activeWorkspaces[0].importFromImage(fileInput.files[0], replaceFile);
resolve();
};
fileInput.onError = () => { console.log('file load error wow'); }
});

fileInput.click();
fileInput.click();
return filePromise;
}
}

onImageLoad(data, extension) {
onImageLoad(data, extension, replaceFile) {
switch (extension) {
case "art":
case "artimus":
this.importArtimus(data);
this.importArtimus(data, replaceFile);
break;

default:
const image = new Image();
image.onload = () => {
this.new(image.width, image.height, () => {
if (replaceFile) this.new(image.width, image.height, () => {
this.setLayer(0, () => {
this.editGL.drawImage(image, 0, 0);
});
});

else {
this.createLayer(`Layer ${this.layers.length+1}`, false);
this.setLayer(this.layers.length-1, () => {
this.editGL.drawImage(image, 0, 0, image.width, image.height); // Todo: Maybe prompt about resizing the canvas?
});
}
}

image.src = data;
Expand Down
3 changes: 2 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
editor.exportMenu();
}}</cugi-option>
<cugi-option>{ type: "button", text: "Load", onclick: () => {
artimus.activeWorkspaces[0].importFromPC();
editor.loadFile(false);
}}</cugi-option>
</cugi-dropdown>
<cugi-dropdown>Edit
Expand Down Expand Up @@ -89,6 +89,7 @@
<script src="site/src/menus/resizeFile.js"></script>
<script src="site/src/menus/layerProperty.js"></script>
<script src="site/src/menus/exportFile.js"></script>
<script src="site/src/menus/loadFile.js"></script>
<script src="site/src/menus/settingsPage.js"></script>
<script src="site/src/extensions.js"></script>
</body>
Expand Down
17 changes: 15 additions & 2 deletions lang/english.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@

"artimus.layerDropdown.delete": "Delete",
"artimus.layerDropdown.properties": "Properties",
"artimus.layerDropdown.duplicate": "Duplicate",

"artimus.blendModes.source-over": "Source over",
"artimus.blendModes.source-in": "Source in",
Expand Down Expand Up @@ -81,7 +82,7 @@
"artimus.modal.welcome.info": [
"<img src=\"site/Logo_NoGraffiti.png\" class=\"LOGO\"></img>",

"<p>A web based art editor and library created by ObviousStudios and open sourced under the MIT liscense</p>",
"<p>A web based art editor and library created by ObviousStudios and open sourced under the MIT license</p>",
"<p>Originally created for <a href=\"https://coffee-engine.github.io/\">Coffee Engine</a></p>",

"<h3>Disclaimer</h3>",
Expand All @@ -90,7 +91,13 @@
"<p>Things may break or be unstable.</p>",
"<p>If you are fine with this and want to try this web demo click the \"I'm ready!\" button below!</p>",

"<button class=\"artimus-button\" onclick=\"editor.modals[editor.modals.length - 1].close(); editor.newFile(true);\">I'm ready!</button>"
"<button class=\"artimus-button\" onclick=\"editor.modals[editor.modals.length - 1].close(); new editor.modal(artimus.translate('ready.title', 'modal'), artimus.translate('ready.info', 'modal'), { height: 25, hasClose: false });\">I'm ready!</button>"
],
"artimus.modal.ready.title": "Load or create",
"artimus.modal.ready.info": [
"<p>Do you have an existing file you'd like to open?</p>",
"<button class=\"artimus-button\" onclick=\"editor.modals[editor.modals.length - 1].close(); editor.loadFile(true);\">Yes, load</button>",
"<button class=\"artimus-button\" onclick=\"editor.modals[editor.modals.length - 1].close(); editor.newFile(true);\">No, create new</button>"
],

"artimus.modal.layerProperty.title": "Editing \"[LAYER]\"",
Expand All @@ -100,6 +107,12 @@

"artimus.modal.newFile.title": "New File",
"artimus.modal.newFile.create": "Create!",
"artimus.modal.newFile.loadInstead": "Load a file instead",

"artimus.modal.loadFile.title": "Load file",
"artimus.modal.loadFile.loadAndReplace": "Load and replace",
"artimus.modal.loadFile.loadAndAdd": "Load and add as layer",
"artimus.modal.loadFile.createInstead": "Create a file instead",

"artimus.modal.resizeFile.title": "Resize",
"artimus.modal.resizeFile.resize": "Resize!",
Expand Down
39 changes: 39 additions & 0 deletions site/src/menus/loadFile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
editor.loadFile = (forced) => {
//Simple, easy.
new editor.modal(artimus.translate("title", "modal.loadFile"), (contents, modal) => {

const loadReplaceButton = document.createElement("button");
const loadAddButton = document.createElement("button");
const createButon = document.createElement("button");

loadReplaceButton.className = "artimus-button";
loadAddButton.className = "artimus-button";
createButon.className = "artimus-button";


createButon.innerText = artimus.translate("createInstead", "modal.loadFile");
loadReplaceButton.innerText = artimus.translate("loadAndReplace", "modal.loadFile");
loadAddButton.innerText = artimus.translate("loadAndAdd", "modal.loadFile");

createButon.onclick = () => {
modal.close();
editor.newFile(true);
}
loadReplaceButton.onclick = () => {
artimus.activeWorkspaces[0].importFromPC(true).then(() => {
modal.close();
});
};
loadAddButton.onclick = () => {
artimus.activeWorkspaces[0].importFromPC(false).then(() => {
modal.close();
});
};

contents.appendChild(loadReplaceButton); // don't give the option to add as a layer if this is probably an empty file
if (!forced) contents.appendChild(loadAddButton);
contents.appendChild(document.createElement("br")); // seperate load buttons and create button
contents.appendChild(createButon);

}, { hasClose: !forced, translationContext: "loadFile", width: 25, height: 20 });
}
9 changes: 9 additions & 0 deletions site/src/menus/newFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ editor.newFile = (forced) => {

const finalDiv = document.createElement("div");
const createButton = document.createElement("button");
const loadButton = document.createElement("button");

flipButton.className = "newFile-flip";
sizingDiv.className = "newFile-sizingDiv";
Expand All @@ -26,20 +27,23 @@ editor.newFile = (forced) => {
currentPreviewHolder.className = "newFile-tuning-previewHolder";
currentPreview.className = "newFile-tuning-preview";
createButton.className = "artimus-button";
loadButton.className = "artimus-button";

resolutionDiv.appendChild(widthInput);
resolutionDiv.appendChild(heightInput);
sizingDiv.appendChild(resolutionDiv);
sizingDiv.appendChild(flipButton);
currentPreviewHolder.appendChild(currentPreview);
finalDiv.appendChild(createButton);
finalDiv.appendChild(loadButton);
tuning.appendChild(currentPreviewHolder);
tuning.appendChild(sizingDiv);
tuning.appendChild(finalDiv);
contents.appendChild(presets);
contents.appendChild(tuning);

createButton.innerText = artimus.translate("create", "modal.newFile");
loadButton.innerText = artimus.translate("loadInstead", "modal.newFile");

fetch("site/images/flipAspect.svg").then(res => res.text()).then(text => {
if (flipButton) {
Expand Down Expand Up @@ -91,6 +95,11 @@ editor.newFile = (forced) => {
modal.close();
}

loadButton.onclick = () => {
modal.close();
editor.loadFile(true);
}

//Append resolution presets
for (let presetID in editor.resolutionPresets) {
const preset = editor.resolutionPresets[presetID];
Expand Down