dragonroll/client/src/services/Map.js

324 lines
7.9 KiB
JavaScript

import { initCustomFormatter, ref, toRaw } from 'vue';
import Server from '@/services/Server'
import { _SendMap, GetCampaign } from './Dragonroll';
import { backendUrl } from './BackendURL';
import { socket } from './Socket';
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 });
}
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();
}
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
let currentMap = {
gridSize: undefined,
images: [],
lines_of_sight: [],
backgroundColor: '#0f0f0f',
title: "Untitled map"
};
let imageData = [];
const currentMapId = ref('');
let GetMapId = () => currentMapId;
const currentGlobalMapId = ref('');
let GetGlobalMapId = () => currentGlobalMapId;
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);
imageData.forEach((image) => {
ctx.drawImage(image, toMapX(0), toMapY(0), image.naturalWidth * scale, image.naturalHeight * scale);
});
ctx.beginPath();
ctx.strokeStyle = "white";
ctx.lineWidth = 3;
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));
});
ctx.stroke();
if(currentMap.gridSize) drawGrid(currentMap.gridSize);
}
function ImportDD2VTT(data){
var image = new Image();
image.onload = function() {
UploadResource(image).then((imagePath) => {
currentMap.images.push(imagePath);
CreateMap(currentMap);
ReloadImages();
})
};
currentMap.gridSize = data.resolution.pixels_per_grid;
currentMap.lines_of_sight = data.line_of_sight;
backgroundColor.value = '#' + data.environment.ambient_light;
currentMap.backgroundColor = '#' + data.environment.ambient_light;
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;
}
const mapList = ref([]);
let GetMapList = () => mapList;
function GetMap(id){
let map = undefined;
mapList.value.forEach((m) => {
if(m._id == id) map = m;
});
return toRaw(map);
}
function UpdateMapList(){
return new Promise((resolve, reject) => {
Server().get('/maps/list?campaign=' + GetCampaign()._id).then(response => {
mapList.value = response.data.data;
resolve();
}).catch((err) => console.log(err));
})
}
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){
Server().post('/maps/update?campaign=' + GetCampaign()._id + "&map=" + id, {data: currentMap}).then(response => {
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));
Server().post('/maps/create-resource?campaign=' + GetCampaign()._id, formData, {
headers: { "Content-Type": "multipart/form-data"}
}).then(response => {
resolve(response.data.data);
}).catch(err => console.log(err));
});
}
function CreateMap(){
Server().post('/maps/create', {
campaign: GetCampaign()._id,
data: currentMap,
}).then(response => {
UpdateMapList();
}).catch(err => console.log(err));
}
function SendMap(id){
currentGlobalMapId.value = id;
_SendMap(id);
}
let GetBackgroundColor = () => backgroundColor;
function ChangeBackgroundColor(color){
backgroundColor.value = color; // XD
currentMap.backgroundColor = color;
SaveMap(currentMapId.value);
}
socket.on('change_map', data => {
UpdateMapList().then(() => {
LoadMap(GetMap(data.id));
});
})
export {
toMapX,
toMapY,
toRealX,
toRealY,
zoom,
SetupTilemap,
// Draw,
ImportDD2VTT,
GetBackgroundColor,
ChangeBackgroundColor,
GetMapId,
GetGlobalMapId,
UpdateMapList,
GetMapList,
LoadMap,
RenameMap,
GetMap,
SendMap
};