dikdimon's picture
Upload extensionsa using SD-Hub extension
7bed60d verified
//create a class called Region
class Region {
#weight = 1;
constructor(x, y, width, height, prompt, weight) {
this.enabled = true;
this.x = x;
this.y = y;
this.width = Math.max(width, 16);
this.height = Math.max(height, 16);
this.prompt = prompt;
this.weight = weight;
this.mouse_drag_offset = { x: 0, y: 0 };
this.tool_operation_mode = "none";
this.selected = false;
}
get weight() {
return this.#weight;
}
set weight(value) {
if (value > 1) {
value = 1;
} else if (value < -1) {
value = -1;
}
this.#weight = value;
}
snap(canvas_width, canvas_height, rows, columns) {
this.stayWithinBounds(canvas_width, canvas_height);
let cell_width = Math.round(canvas_width / columns);
let cell_height = Math.round(canvas_height / rows);
//snap the x and y values to the nearest grid point
this.x = Math.round(this.x / cell_width) * cell_width;
this.y = Math.round(this.y / cell_height) * cell_height;
this.width = Math.max(Math.round(this.width / cell_width) * cell_width, 16);
this.height = Math.max(Math.round(this.height / cell_height) * cell_height, 16);
}
getRatios(canvas_width, canvas_height) {
let w = canvas_width / (this.width)
let h = canvas_height / (this.height)
return {
division: [h, w],
position: [this.y / (canvas_height / h), this.x / (canvas_width / w)]
};
}
onMouseMove(mouse_position, canvas_width, canvas_height) {
if (this.enabled == false) {
return
}
if (this.selected) {
if(this.tool_operation_mode == "move") {
this.move({
x: mouse_position.x - this.mouse_drag_offset.x,
y: mouse_position.y - this.mouse_drag_offset.y},
canvas_width, canvas_height);
}
if(this.tool_operation_mode == "scale") {
this.scale({
x: mouse_position.x,
y: mouse_position.y},
canvas_width, canvas_height);
}
}
}
selectIfMouseOver(mouse_position) {
if (this.enabled == false) {
return
}
//determine if the mouse is over this region.
if (this.pointInside(mouse_position)) {
this.mouse_drag_offset = { x: mouse_position.x - this.x, y: mouse_position.y - this.y };
this.selected = true;
this.tool_operation_mode = "move";
}
//determine if the mouse is over the scale control
if (this.pointInsideScaleControl(mouse_position)) {
this.tool_operation_mode = "scale";
}
return this.selected;
}
// When the mouse is clicked and released.
onMouseUp(mouse_position) {
if (this.enabled == false) {
return
}
if (this.selected) {
this.selected = false;
this.tool_operation_mode = "none";
}
}
// When the mouse leaves the canvas element.
onMouseLeave(canvas_width, canvas_height) {
if (this.enabled == false) {
return
}
if (this.selected) {
this.selected = false;
this.tool_operation_mode = "none";
//move this region so that is back within the bounds of the canvas
this.stayWithinBounds(canvas_width, canvas_height);
}
}
stayWithinBounds(canvas_width, canvas_height) {
this.stayInBoundsWhileMoving(canvas_width, canvas_height);
this.stayWithinBoundsWhileScaling(canvas_width, canvas_height);
}
stayWithinBoundsWhileScaling(canvas_width, canvas_height) {
if (this.x + this.width > canvas_width) {
this.width = canvas_width - this.x;
}
if (this.y + this.height > canvas_height) {
this.height = canvas_height - this.y;
}
}
stayInBoundsWhileMoving(canvas_width, canvas_height) {
this.x = Math.max(0, Math.min(this.x, canvas_width - this.width));
this.y = Math.max(0, Math.min(this.y, canvas_height - this.height));
}
move(point, canvas_width, canvas_height) {
this.x = Math.round(point.x);
this.y = Math.round(point.y);
this.stayInBoundsWhileMoving(canvas_width, canvas_height);
}
scale(point, canvas_width, canvas_height) {
console.log("Scaling")
this.width = point.x - this.x + 8;
this.height = point.y - this.y + 8;
//ensure that the width and height of the region are not less than 1
if (this.width < 16) {
this.width = 16;
}
if (this.height < 16) {
this.height = 16;
}
this.stayWithinBoundsWhileScaling(canvas_width, canvas_height);
}
pointInside(point) {
return (
point.x >= this.x &&
point.x <= this.x + this.width &&
point.y >= this.y &&
point.y <= this.y + this.height
);
}
pointInsideScaleControl(point) {
return (
point.x >= this.x + this.width - 16 &&
point.x <= this.x + this.width &&
point.y >= this.y + this.height - 16 &&
point.y <= this.y + this.height);
}
draw(ctx, label) {
if (this.enabled == false) {
return
}
ctx.beginPath();
ctx.fillStyle = 'rgba(0,0,0,0.65)';
ctx.lineWidth = 1;
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.stroke();
ctx.closePath();
//draw a red rangle in the bottom-right corner
ctx.beginPath();
ctx.fillStyle = 'rgba(255,0,0,0.5)';
ctx.lineWidth = 1;
ctx.fillRect(this.x + this.width - 16, this.y + this.height - 16, 16, 16);
ctx.stroke();
ctx.closePath();
//draw a white line around the region
ctx.beginPath();
ctx.strokeStyle = 'rgba(255,255,255,1)';
ctx.lineWidth = 2;
ctx.strokeRect(this.x, this.y, this.width, this.height);
ctx.closePath();
ctx.fill();
if(this.selected) {
ctx.beginPath();
//set color to red
ctx.strokeStyle = 'rgba(255,0,0,1)';
ctx.lineWidth = 4;
ctx.rect(this.x, this.y, this.width, this.height);
ctx.stroke();
ctx.closePath();
}
//draw the label text inside the rectangle
ctx.fillStyle = 'rgba(255,255,255,1)';
ctx.font = '16px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(label, this.x + this.width / 2, this.y + this.height / 2);
}
}
var latent_couple_mapper = new Vue({
el: '#latent_couple_mapper',
mounted:function(){
this.redrawCanvas();
},
data: {
regions: [],
grid_enabled: true,
grid_rows: 8,
grid_columns: 8,
image_loaded: false,
image_resource: null,
canvas_width: 512,
canvas_height: 512,
global_region: new Region(0, 0, 512, 512, "", 0.2),
instructions_visible: false,
},
watch: {
canvas_width: function() {
this.$refs.canvas.width = Math.max(this.canvas_width, 64);
this.global_region.width = this.$refs.canvas.width;
for(let i = 0; i < this.regions.length; i++) {
this.regions[i].stayWithinBounds(this.$refs.canvas.width, this.$refs.canvas.height);
}
this.redrawCanvas();
},
canvas_height: function() {
this.$refs.canvas.height = Math.max(this.canvas_height, 64);
this.global_region.height = this.$refs.canvas.height;
for(let i = 0; i < this.regions.length; i++) {
this.regions[i].stayWithinBounds(this.$refs.canvas.width, this.$refs.canvas.height);
}
this.redrawCanvas();
},
regions: {
handler(_) {
this.redrawCanvas();
},
deep: true
},
grid_enabled: function(enabled) {
this.redrawCanvas();
},
grid_rows: function(rows) {
this.redrawCanvas();
},
grid_columns: function(columns) {
this.redrawCanvas();
}
},
methods: {
toggle_instructions: function() {
this.instructions_visible = !this.instructions_visible;
},
canvas_loaded: function() {
return this.$refs.canvas != null;
},
divisions: function() {
if (this.canvas_loaded() == false) {
return "???";
}
output = ""
all_regions = [this.global_region].concat(this.regions).filter(function(region) {
return region.enabled;
});
for (var i = 0; i < all_regions.length; i++) {
d = all_regions[i].getRatios(this.$refs.canvas.width, this.$refs.canvas.height).division
output += `${d[0].toFixed(2)}:${d[1].toFixed(2)}`
if (i < all_regions.length - 1) {
output += ',';
}
}
return output;
},
positions: function() {
if (this.canvas_loaded() == false) {
return "???";
}
output = ""
all_regions = [this.global_region].concat(this.regions).filter(function(region) {
return region.enabled;
});
for (var i = 0; i < all_regions.length; i++) {
p = all_regions[i].getRatios(this.$refs.canvas.width, this.$refs.canvas.height).position
output += `${p[0].toFixed(2)}:${p[1].toFixed(2)}`
if (i < all_regions.length - 1) {
output += ',';
}
}
return output;
},
weights: function() {
if (this.canvas_loaded() == false) {
return "???";
}
output = ""
all_regions = [this.global_region].concat(this.regions).filter(function(region) {
return region.enabled;
});
for (var i = 0; i < all_regions.length; i++) {
output += all_regions[i].weight.toFixed(2).toString()
if (i < all_regions.length - 1) {
output += ',';
}
}
return output;
},
prompt: function() {
output = ""
all_regions = [this.global_region].concat(this.regions).filter(function(region) {
return region.enabled;
});
for (var i = 0; i < all_regions.length; i++) {
output += all_regions[i].prompt
if (i < all_regions.length - 1) {
output += '\nAND ';
}
}
return output;
},
setCanvasWidth(canvas_width) {
this.$refs.canvas.width = canvas_width;
this.redrawCanvas();
},
setCanvasHeight(canvas_height) {
this.$refs.canvas.height = canvas_height;
this.redrawCanvas();
},
uploadImage: function(e) {
this.image_loaded = false;
const reader = new FileReader();
reader.onload = (event) => {
this.image_resource = new Image();
this.image_resource.onload = () => {
this.canvas_width = this.image_resource.width;
this.canvas_height = this.image_resource.height;
this.image_loaded = true;
for(let i = 0; i < this.regions.length; i++) {
this.regions[i].stayWithinBounds(this.$refs.canvas.width, this.$refs.canvas.height);
}
this.redrawCanvas();
};
this.image_resource.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
},
selectNone: function() {
for (let i = 0; i < this.regions.length; i++) {
this.regions[i].selected = false;
}
this.redrawCanvas();
},
selectRegion: function(region) {
this.selectNone();
region.selected = true;
this.redrawCanvas();
},
getSelectedRegion: function() {
for (let i = 0; i < this.regions.length; i++) {
if(this.regions[i].selected == true) {
return this.regions[i];
}
}
return null;
},
snapAllRegions: function() {
for (let i = 0; i < this.regions.length; i++) {
this.regions[i].snap(this.$refs.canvas.width, this.$refs.canvas.height, this.grid_rows, this.grid_columns);
}
this.redrawCanvas();
},
redrawCanvas: function () {
var ctx = this.$refs.canvas.getContext('2d');
//clear the canvas
ctx.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height);
//draw the image if it exists
if (this.image_loaded) {
ctx.drawImage(this.image_resource, 0, 0);
}
else {
ctx.fillStyle = "white";
ctx.fillRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height);
}
//draw the grid...\
if (this.grid_enabled) {
var cell_width = this.$refs.canvas.width / this.grid_columns;
var cell_height = this.$refs.canvas.height / this.grid_rows;
ctx.strokeStyle = 'rgba(0,0,0,0.6)';
for (var i = 0; i < this.grid_columns; i++) {
ctx.beginPath();
ctx.moveTo(i * cell_width, 0);
ctx.lineWidth = 1;
ctx.lineTo(i * cell_width, this.$refs.canvas.height);
ctx.stroke();
ctx.closePath();
}
for (var j = 0; j < this.grid_rows; j++) {
ctx.beginPath();
ctx.moveTo(0, j * cell_height);
ctx.lineWidth = 1;
ctx.lineTo(this.$refs.canvas.width, j * cell_height);
ctx.stroke();
ctx.closePath();
}
}
//draw the regions
for (var i = 0; i < this.regions.length; i++) {
this.regions[i].draw(ctx, (i + 1).toString());
}
},
deleteRegion(region) {
this.regions.splice(this.regions.indexOf(region), 1);
this.selectNone();
},
onCanvasMouseDown: function(event) {
var canvas = event.target;
var x = event.pageX - canvas.offsetLeft;
var y = event.pageY - canvas.offsetTop;
for (var i = this.regions.length - 1; i >= 0; i--) {
if (event.which == 1) { //left click
if (this.regions[i].selectIfMouseOver({x: x, y: y})){
break;
}
} else if (event.which == 3) { // right click
if (this.regions[i].selectIfMouseOver({x: x, y: y})){
this.deleteRegion(this.getSelectedRegion());
break;
}
}
}
if (this.getSelectedRegion() == null) {
if (event.which == 1) { //left click
new_region = new Region(x, y, 16, 16, "", 0.8);
this.regions.push(new_region);
this.selectRegion(new_region);
new_region.tool_operation_mode = "scale";
}
}
this.redrawCanvas();
},
onCanvasMouseMove: function (event) {
var canvas = event.target;
var x = event.pageX - canvas.offsetLeft;
var y = event.pageY - canvas.offsetTop;
for (var i = 0; i < this.regions.length; i++) {
this.regions[i].onMouseMove({x: x, y: y}, this.$refs.canvas.width, this.$refs.canvas.height);
}
this.redrawCanvas();
},
onCanvasMouseUp: function(event) {
var canvas = event.target;
var x = event.pageX - canvas.offsetLeft;
var y = event.pageY - canvas.offsetTop;
for (var i = 0; i < this.regions.length; i++) {
this.regions[i].onMouseUp({x: x, y: y});
}
this.redrawCanvas();
},
onCanvasMouseLeave: function(event) {
for (var i = 0; i < this.regions.length; i++) {
this.regions[i].onMouseLeave(this.$refs.canvas.width, this.$refs.canvas.height);
}
},
getRatios: function(region){
return region.getRatios(this.$refs.canvas.width, this.$refs.canvas.height)
},
copyText(text) {
navigator.clipboard.writeText(text);
}
},
computed: {
nick: function() {
//returns a random nickname from the list of nicknames in the variable nicknames
let nicknames = ["DeepDreamDestroyer", "Artificial Artist", "Synthetic Sorcerer", "The IP Bandit", "Hue Hacker", "AInomaly", "Deep Dream Disaster", "The Property Intellectual", "Content Crook, Let Him Cook", "The Canvas Caper", "Cyber Surrealist", "The Trademark Terrorist", "Infringe This", "NeuralNetNinja", "The Photo Copyer", "GANtastic", "Pixel Pirate", "Oops I Stole Your Art :3"]
return nicknames[Math.floor(Math.random() * nicknames.length)];
}
}
});