2024-08-10 20:20:16 +00:00
|
|
|
import { initCustomFormatter, ref, toRaw } from 'vue';
|
2024-08-07 20:49:59 +00:00
|
|
|
|
2024-10-05 10:57:47 +00:00
|
|
|
import Server from '@/services/Server'
|
2024-08-10 20:20:16 +00:00
|
|
|
import { _SendMap, GetCampaign } from './Dragonroll';
|
2024-08-09 17:06:38 +00:00
|
|
|
import { backendUrl } from './BackendURL';
|
2024-09-15 15:25:50 +00:00
|
|
|
import { socket } from './Socket';
|
2024-08-09 17:06:38 +00:00
|
|
|
|
|
|
|
function dataURLtoFile(dataurl, filename) {
|
|
|
|
var arr = dataurl.split(","),
|
|
|
|
mime = arr[0].match(/:(.*?);/)[1],
|
|
|
|
bstr = atob(arr[arr.length - 1]),
|
|
|
|
n = bstr.length,
|
|
|
|
u8arr = new Uint8Array(n);
|
|
|
|
while (n--) {
|
|
|
|
u8arr[n] = bstr.charCodeAt(n);
|
|
|
|
}
|
|
|
|
return new File([u8arr], filename, { type: mime });
|
|
|
|
}
|
|
|
|
|
2024-08-07 20:49:59 +00:00
|
|
|
let offsetX = 0;
|
|
|
|
let offsetY = 0;
|
|
|
|
let scale = 1;
|
|
|
|
|
|
|
|
let mouseX = 0;
|
|
|
|
let mouseY = 0;
|
|
|
|
|
|
|
|
function SetupTilemap(){
|
|
|
|
let tilemap = document.getElementById("tilemap");
|
|
|
|
tilemap.addEventListener("wheel", (event) => {
|
|
|
|
let direction = 0;
|
|
|
|
if(event.deltaY > 0) direction = 0.95;
|
|
|
|
else if(event.deltaY < 0) direction = 1.05;
|
|
|
|
|
|
|
|
zoom(direction);
|
|
|
|
})
|
|
|
|
|
|
|
|
let mouseDown = false;
|
|
|
|
let startX = 0, startY = 0;
|
|
|
|
let oldOffsetX = offsetX, oldOffsetY = offsetY;
|
|
|
|
|
|
|
|
tilemap.addEventListener("mousedown", (event) => {
|
|
|
|
mouseDown = true
|
|
|
|
startX = event.clientX;
|
|
|
|
startY = event.clientY;
|
|
|
|
oldOffsetX = offsetX;
|
|
|
|
oldOffsetY = offsetY;
|
|
|
|
});
|
|
|
|
|
|
|
|
tilemap.addEventListener("mousemove", (event) => {
|
|
|
|
mouseX = event.clientX;
|
|
|
|
mouseY = event.clientY;
|
|
|
|
|
|
|
|
if(!mouseDown) return;
|
|
|
|
offsetX = oldOffsetX + ((event.clientX - startX) * (1 / scale));
|
|
|
|
offsetY = oldOffsetY + ((event.clientY - startY) * (1 / scale));
|
|
|
|
|
|
|
|
Draw();
|
|
|
|
});
|
|
|
|
|
|
|
|
tilemap.addEventListener("mouseup", () => mouseDown = false);
|
|
|
|
|
|
|
|
addEventListener("resize", Draw)
|
|
|
|
|
|
|
|
offsetX = window.innerWidth / 2;
|
|
|
|
offsetY = window.innerHeight / 2;
|
|
|
|
|
|
|
|
Draw();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Map coords -> Real coords
|
|
|
|
function toMapX(xReal) {
|
|
|
|
return (xReal + offsetX) * scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
function toMapY(yReal){
|
|
|
|
return (yReal + offsetY) * scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Real coords -> Map coords
|
|
|
|
function toRealX(xVirt){
|
|
|
|
return xVirt / scale - offsetX;
|
|
|
|
}
|
|
|
|
|
|
|
|
function toRealY(yVirt){
|
|
|
|
return yVirt / scale - offsetY;
|
|
|
|
}
|
|
|
|
|
|
|
|
function zoom(amount){
|
|
|
|
let dx = ((mouseX) / scale - offsetX) - ((mouseX) / (scale * amount) - offsetX)
|
|
|
|
let dy = ((mouseY) / scale - offsetY) - ((mouseY) / (scale * amount) - offsetY)
|
|
|
|
scale *= amount;
|
|
|
|
offsetX -= dx;
|
|
|
|
offsetY -= dy;
|
|
|
|
Draw();
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:06:38 +00:00
|
|
|
|
2024-08-07 20:49:59 +00:00
|
|
|
let xUpperLeft = -Infinity;
|
|
|
|
let yUpperLeft = -Infinity;
|
|
|
|
let xDownRight = Infinity;
|
|
|
|
let yDownRight = Infinity;
|
|
|
|
|
|
|
|
function drawGrid(cellSize){
|
|
|
|
let canvas = document.getElementById('tilemap');
|
|
|
|
|
|
|
|
const width = canvas.clientWidth;
|
|
|
|
const height = canvas.clientHeight;
|
|
|
|
|
|
|
|
let ctx = canvas.getContext("2d");
|
|
|
|
|
|
|
|
ctx.strokeStyle = "#434343";
|
|
|
|
ctx.lineWidth = 1;
|
|
|
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
|
|
|
for (let x = (offsetX % cellSize) * scale; x <= width; x += cellSize * scale) {
|
|
|
|
if(toRealX(x) < xUpperLeft) continue;
|
|
|
|
if(toRealX(x) > xDownRight) continue;
|
|
|
|
|
|
|
|
ctx.moveTo(x, Math.max(0, toMapY(yUpperLeft)));
|
|
|
|
ctx.lineTo(x, Math.min(height, toMapY(yDownRight)));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let y = (offsetY % cellSize) * scale; y <= height; y += cellSize * scale) {
|
|
|
|
if(toRealY(y) < yUpperLeft) continue;
|
|
|
|
if(toRealY(y) > yDownRight) continue;
|
|
|
|
ctx.moveTo(Math.max(0, toMapX(xUpperLeft)), y);
|
|
|
|
ctx.lineTo(Math.min(width, toMapX(xDownRight)), y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ctx.stroke();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ok aqui coses del mapa en si
|
2024-08-09 17:06:38 +00:00
|
|
|
let currentMap = {
|
|
|
|
gridSize: undefined,
|
|
|
|
images: [],
|
|
|
|
lines_of_sight: [],
|
|
|
|
backgroundColor: '#0f0f0f',
|
|
|
|
title: "Untitled map"
|
|
|
|
};
|
|
|
|
let imageData = [];
|
|
|
|
|
|
|
|
const currentMapId = ref('');
|
|
|
|
let GetMapId = () => currentMapId;
|
|
|
|
|
2024-08-10 20:20:16 +00:00
|
|
|
const currentGlobalMapId = ref('');
|
|
|
|
let GetGlobalMapId = () => currentGlobalMapId;
|
|
|
|
|
2024-08-07 20:49:59 +00:00
|
|
|
let backgroundColor = ref('#0f0f0f');
|
|
|
|
|
|
|
|
function Draw(){
|
|
|
|
let canvas = document.getElementById('tilemap');
|
|
|
|
let ctx = canvas.getContext("2d");
|
|
|
|
canvas.width = window.innerWidth;
|
|
|
|
canvas.height = window.innerHeight;
|
|
|
|
|
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
|
2024-08-09 17:06:38 +00:00
|
|
|
imageData.forEach((image) => {
|
2024-08-07 20:49:59 +00:00
|
|
|
ctx.drawImage(image, toMapX(0), toMapY(0), image.naturalWidth * scale, image.naturalHeight * scale);
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.strokeStyle = "white";
|
|
|
|
ctx.lineWidth = 3;
|
2024-08-09 17:06:38 +00:00
|
|
|
currentMap.lines_of_sight.forEach((line) => {
|
|
|
|
ctx.moveTo(toMapX(line[0].x * currentMap.gridSize), toMapY(line[0].y * currentMap.gridSize));
|
|
|
|
ctx.lineTo(toMapX(line[1].x * currentMap.gridSize), toMapY(line[1].y * currentMap.gridSize));
|
2024-08-07 20:49:59 +00:00
|
|
|
});
|
|
|
|
ctx.stroke();
|
|
|
|
|
2024-08-09 17:06:38 +00:00
|
|
|
if(currentMap.gridSize) drawGrid(currentMap.gridSize);
|
2024-08-07 20:49:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function ImportDD2VTT(data){
|
|
|
|
var image = new Image();
|
|
|
|
image.onload = function() {
|
2024-08-09 17:06:38 +00:00
|
|
|
UploadResource(image).then((imagePath) => {
|
|
|
|
currentMap.images.push(imagePath);
|
|
|
|
CreateMap(currentMap);
|
|
|
|
ReloadImages();
|
|
|
|
})
|
2024-08-07 20:49:59 +00:00
|
|
|
};
|
|
|
|
|
2024-08-09 17:06:38 +00:00
|
|
|
currentMap.gridSize = data.resolution.pixels_per_grid;
|
|
|
|
currentMap.lines_of_sight = data.line_of_sight;
|
|
|
|
|
2024-08-07 20:49:59 +00:00
|
|
|
backgroundColor.value = '#' + data.environment.ambient_light;
|
2024-08-09 17:06:38 +00:00
|
|
|
currentMap.backgroundColor = '#' + data.environment.ambient_light;
|
2024-08-07 20:49:59 +00:00
|
|
|
|
|
|
|
xUpperLeft = data.resolution.map_origin.x * data.resolution.pixels_per_grid;
|
|
|
|
yUpperLeft = data.resolution.map_origin.y * data.resolution.pixels_per_grid;
|
|
|
|
xDownRight = xUpperLeft + data.resolution.map_size.x * data.resolution.pixels_per_grid;
|
|
|
|
yDownRight = yUpperLeft + data.resolution.map_size.y * data.resolution.pixels_per_grid;
|
|
|
|
|
|
|
|
image.src = "data:image/png;base64," + data.image;
|
2024-08-09 17:06:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const mapList = ref([]);
|
|
|
|
let GetMapList = () => mapList;
|
2024-08-07 20:49:59 +00:00
|
|
|
|
2024-08-10 20:20:16 +00:00
|
|
|
function GetMap(id){
|
|
|
|
let map = undefined;
|
|
|
|
mapList.value.forEach((m) => {
|
|
|
|
if(m._id == id) map = m;
|
|
|
|
});
|
|
|
|
return toRaw(map);
|
|
|
|
}
|
|
|
|
|
2024-08-09 17:06:38 +00:00
|
|
|
function UpdateMapList(){
|
2024-08-10 20:20:16 +00:00
|
|
|
return new Promise((resolve, reject) => {
|
2024-10-05 10:57:47 +00:00
|
|
|
Server().get('/maps/list?campaign=' + GetCampaign()._id).then(response => {
|
2024-08-10 20:20:16 +00:00
|
|
|
mapList.value = response.data.data;
|
|
|
|
resolve();
|
|
|
|
}).catch((err) => console.log(err));
|
|
|
|
})
|
2024-08-09 17:06:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function ReloadImages(){
|
|
|
|
imageData = [];
|
|
|
|
currentMap.images.forEach(path => {
|
|
|
|
let image = new Image();
|
|
|
|
image.src = backendUrl + "public/" + path;
|
|
|
|
imageData.push(image);
|
|
|
|
|
|
|
|
image.onload = Draw;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function RenameMap(id, new_title){
|
|
|
|
currentMap.title = new_title;
|
|
|
|
SaveMap(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
function SaveMap(id){
|
2024-10-05 10:57:47 +00:00
|
|
|
Server().post('/maps/update?campaign=' + GetCampaign()._id + "&map=" + id, {data: currentMap}).then(response => {
|
2024-08-09 17:06:38 +00:00
|
|
|
console.log("Map updated");
|
|
|
|
}).catch(err => console.log(err));
|
|
|
|
}
|
|
|
|
|
|
|
|
function NewMap(){
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function DeleteMap(map_id){
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function LoadMap(map){
|
|
|
|
currentMap = map.data;
|
|
|
|
currentMapId.value = map._id;
|
|
|
|
backgroundColor.value = currentMap.backgroundColor;
|
|
|
|
ReloadImages();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function UploadResource(image){
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const formData = new FormData();
|
|
|
|
formData.append("image", dataURLtoFile(image.src));
|
|
|
|
|
2024-10-05 10:57:47 +00:00
|
|
|
Server().post('/maps/create-resource?campaign=' + GetCampaign()._id, formData, {
|
2024-08-09 17:06:38 +00:00
|
|
|
headers: { "Content-Type": "multipart/form-data"}
|
|
|
|
}).then(response => {
|
|
|
|
resolve(response.data.data);
|
|
|
|
}).catch(err => console.log(err));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function CreateMap(){
|
2024-10-05 10:57:47 +00:00
|
|
|
Server().post('/maps/create', {
|
2024-08-09 17:06:38 +00:00
|
|
|
campaign: GetCampaign()._id,
|
|
|
|
data: currentMap,
|
|
|
|
}).then(response => {
|
|
|
|
UpdateMapList();
|
|
|
|
}).catch(err => console.log(err));
|
|
|
|
|
2024-08-07 20:49:59 +00:00
|
|
|
}
|
|
|
|
|
2024-08-10 20:20:16 +00:00
|
|
|
function SendMap(id){
|
|
|
|
currentGlobalMapId.value = id;
|
|
|
|
_SendMap(id);
|
|
|
|
}
|
|
|
|
|
2024-08-07 20:49:59 +00:00
|
|
|
let GetBackgroundColor = () => backgroundColor;
|
2024-08-09 17:06:38 +00:00
|
|
|
function ChangeBackgroundColor(color){
|
|
|
|
backgroundColor.value = color; // XD
|
|
|
|
currentMap.backgroundColor = color;
|
|
|
|
SaveMap(currentMapId.value);
|
|
|
|
}
|
2024-08-07 20:49:59 +00:00
|
|
|
|
2024-09-15 15:25:50 +00:00
|
|
|
|
|
|
|
socket.on('change_map', data => {
|
|
|
|
UpdateMapList().then(() => {
|
|
|
|
LoadMap(GetMap(data.id));
|
|
|
|
});
|
|
|
|
})
|
|
|
|
|
2024-08-07 20:49:59 +00:00
|
|
|
export {
|
|
|
|
toMapX,
|
|
|
|
toMapY,
|
|
|
|
toRealX,
|
|
|
|
toRealY,
|
|
|
|
zoom,
|
|
|
|
|
|
|
|
SetupTilemap,
|
|
|
|
// Draw,
|
|
|
|
ImportDD2VTT,
|
|
|
|
GetBackgroundColor,
|
2024-08-09 17:06:38 +00:00
|
|
|
ChangeBackgroundColor,
|
|
|
|
GetMapId,
|
2024-08-10 20:20:16 +00:00
|
|
|
GetGlobalMapId,
|
2024-08-09 17:06:38 +00:00
|
|
|
|
|
|
|
UpdateMapList,
|
|
|
|
GetMapList,
|
|
|
|
LoadMap,
|
|
|
|
RenameMap,
|
2024-08-10 20:20:16 +00:00
|
|
|
GetMap,
|
|
|
|
SendMap
|
2024-08-07 20:49:59 +00:00
|
|
|
};
|