const svgns = "http://www.w3.org/2000/svg",
targetClassName = 'sight-line-target',
activeClassName = 'active';
function evenr_to_axial(x, y) {
return { q: x - (y + (y & 1)) / 2, r: y };
}
function axial_to_evenr(q, r) {
return { x: q + (r + (r & 1)) / 2, y: r };
}
function axial_distance(q1, r1, q2, r2) {
return (Math.abs(q1 - q2) + Math.abs(q1 + r1 - q2 - r2) + Math.abs(r1 - r2)) / 2;
}
function offset_distance(x1, y1, x2, y2) {
const { q: q1, r: r1 } = evenr_to_axial(x1, y1),
{ q: q2, r: r2 } = evenr_to_axial(x2, y2);
return axial_distance(q1, r1, q2, r2);
}
function cube_to_axial(q, r, _) {
return { q, r };
}
function axial_to_cube(q, r) {
return { q, r, s: -q - r };
}
function cube_round(q, r, s) {
let rQ = Math.round(q),
rR = Math.round(r),
rS = Math.round(s);
const q_diff = Math.abs(rQ - q),
r_diff = Math.abs(rR - r),
s_diff = Math.abs(rS - s);
if (q_diff > r_diff && q_diff > s_diff) {
rQ = -rR - rS;
} else if (r_diff > s_diff) {
rR = -rQ - rS;
} else {
rS = -rQ - rR;
}
return { q: rQ, r: rR, s: rS };
}
function axial_round(q, r) {
const cube = axial_to_cube(q, r),
round = cube_round(cube.q, cube.r, cube.s),
axial = cube_to_axial(round.q, round.r, round.s);
return { q: axial.q, r: axial.r };
}
function lerp(a, b, t) {
return a + (b - a) * t;
}
function axial_lerp(q1, r1, q2, r2, t) {
return { q: lerp(q1, q2, t), r: lerp(r1, r2, t) };
}
function linedraw(x1, y1, x2, y2) {
const axial1 = evenr_to_axial(x1, y1),
axial2 = evenr_to_axial(x2, y2),
n = offset_distance(x1, y1, x2, y2),
results = [];
for (let i = 0; i <= n; i++) {
const lerp = axial_lerp(axial1.q, axial1.r, axial2.q, axial2.r, 1.0 / n * i),
round = axial_round(lerp.q, lerp.r),
{ x, y } = axial_to_evenr(round.q, round.r);
results.push([x, y]);
}
return results;
}
function create({ x: x1, y: y1 }, { x: x2, y: y2 }) {
const sightLine = document.createElementNS(svgns, 'line');
sightLine.classList.add('sight-line');
sightLine.classList.add(activeClassName);
sightLine.setAttributeNS(null, 'x1', x1);
sightLine.setAttributeNS(null, 'y1', y1);
sightLine.setAttributeNS(null, 'x2', x2);
sightLine.setAttributeNS(null, 'y2', y2);
return sightLine;
}
export default function(svg, board) {
let activeHexes = [],
lockTarget,
distanceCallback,
sightLine;
function drawHexes(...coords) {
clearHexes();
distanceCallback && distanceCallback(offset_distance(...coords));
const lineCoords = linedraw(...coords),
selector = lineCoords
.map(([x, y]) => `g[data-y="${y}"] g[data-x="${x}"] use[href="#hex"]`)
.join(', ');
activeHexes = svg.querySelectorAll(selector);
activeHexes.forEach(p => p.classList.add(activeClassName));
}
function clearHexes() {
distanceCallback && distanceCallback();
activeHexes.forEach(el => el.classList.remove(activeClassName));
activeHexes = [];
}
function clear() {
if (sightLine) {
sightLine.remove();
sightLine = null;
}
if (lockTarget) {
lockTarget.classList.remove(targetClassName);
lockTarget = null;
}
clearHexes();
}
function draw(source, target) {
clear();
sightLine = create(source.position, target.position);
board.appendChild(sightLine);
drawHexes(+source.index.x, +source.index.y, +target.index.x, +target.index.y);
}
function update(source) {
const { dataset: { x }, parentElement: { dataset: { y }}} = lockTarget;
sightLine.setAttributeNS(null, 'x1', source.position.x);
sightLine.setAttributeNS(null, 'y1', source.position.y);
drawHexes(+source.index.x, +source.index.y, +x, +y);
}
function toggleLock(cell) {
if (lockTarget) {
sightLine.classList.add(activeClassName);
lockTarget.classList.remove(targetClassName);
lockTarget = null;
} else {
sightLine.classList.remove(activeClassName);
cell.classList.add(targetClassName);
lockTarget = cell;
}
}
return {
draw,
clear,
update,
toggleLock,
get sightLine() {
return sightLine;
},
set distanceCallback(callback) {
distanceCallback = callback;
}
};
}