Ok, hover and firing arc doesn't get stuck at all

Not sure about counters
This commit is contained in:
Catalin Constantin Mititiuc 2024-07-30 21:02:13 -07:00
parent 48e7675eb0
commit 1687e0e790
5 changed files with 197 additions and 82 deletions

View File

@ -184,7 +184,6 @@ g.counter.selected {
g.counter use.primary-weapon { g.counter use.primary-weapon {
r: inherit; r: inherit;
pointer-events: none;
} }
g.counter use.troop-number, g.counter use.squad-number { g.counter use.troop-number, g.counter use.squad-number {
@ -480,7 +479,7 @@ text.elevation {
fill: black; fill: black;
} }
.grid-top:hover use[href="#hex"] { [data-q][data-r][data-s][data-t].hover use[href="#hex"] {
opacity: 1; opacity: 1;
fill: orange; fill: orange;
stroke: black; stroke: black;
@ -502,12 +501,12 @@ g.counter use[class^="counter-"] {
--translateY: calc(var(--y) / 6 - 5px); --translateY: calc(var(--y) / 6 - 5px);
} }
.grid-top .container > g.counter ~ use[class^="counter-"] { .frontmost > g.counter ~ use[class^="counter-"] {
--translateX: calc(var(--x) * 2 - 5px); --translateX: calc(var(--x) * 2 - 5px);
--translateY: calc(var(--y) * 2 - 5px); --translateY: calc(var(--y) * 2 - 5px);
} }
.grid-top .container > use[class^="counter-"] { .frontmost > use[class^="counter-"] {
--translateX: calc(var(--x) * 1.5 - 5px); --translateX: calc(var(--x) * 1.5 - 5px);
--translateY: calc(var(--y) * 1.5 - 5px); --translateY: calc(var(--y) * 1.5 - 5px);
} }

View File

@ -70,10 +70,8 @@
<g id="lines"/> <g id="lines"/>
</g> </g>
<g class="grid"/> <g class="grid">
<g class="grid-top"> <g class="frontmost"/>
<use href="#hex"/>
<g class="container"/>
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -10,6 +10,8 @@ const top = {
collection: new Map() collection: new Map()
}; };
const frontmostStore = new Map();
function getCellContents(cell) { function getCellContents(cell) {
return cell.querySelectorAll('*:not(use[href="#hex"])'); return cell.querySelectorAll('*:not(use[href="#hex"])');
} }
@ -215,46 +217,142 @@ function workaroundForWebKitBug233432(listener) {
export function start(el) { export function start(el) {
svg = el; svg = el;
const gridTop = svg.querySelector('.grid-top'); //const gridTop = svg.querySelector('.grid-top');
top.container = svg.querySelector('.grid-top > .container'); //top.container = svg.querySelector('.grid-top > .container');
const topHex = svg.querySelector('.grid-top > use[href="#hex"]'); //const topHex = svg.querySelector('.grid-top > use[href="#hex"]');
const clearHexDialog = document.querySelector('#clear-hex'); const grid = svg.querySelector('.grid');
clearHexDialog.addEventListener('close', e => { const frontmost = grid.querySelector('.frontmost');
if (clearHexDialog.returnValue === 'confirm') {
[...top.container.children].forEach(child => { svg.addEventListener('pointerover', e => {
top.collection.delete(child); //console.log('pointerover', e.target.closest('[data-q][data-r][data-s][data-t], .frontmost'), e);
child.remove(); const targetCell = e.target.closest('[data-q][data-r][data-s][data-t]');
console.log('SVG pointerover', targetCell);
const counter = targetCell && targetCell.querySelector('.counter');
//console.log('pointerover', 'targetCell', targetCell);
if (counter) {
firingArc.toggleCounterVisibility(svg, counter, true);
frontmost.setAttributeNS(null, 'transform', targetCell.getAttributeNS(null, 'transform'));
frontmostStore.set(counter, targetCell);
frontmost.append(counter);
}
targetCell && targetCell.classList.add('hover');
//if (targetCell && !targetCell.classList.contains('frontmost')) {
// targetCell.classList.add('hover');
// const occupant = targetCell.querySelector('.counter');
//
// if (occupant) {
// firingArc.toggleCounterVisibility(svg, occupant, true);
// }
// const children = [...targetCell.children].filter(c => c.getAttributeNS(null, 'href') !== '#hex');
// if (children.length > 0) {
// frontmost.setAttributeNS(null, 'transform', targetCell.getAttributeNS(null, 'transform'));
// children.forEach(child => {
// frontmostStore.set(child, targetCell);
// frontmost.append(child);
// });
// }
//}
//console.log('frontmost contents', frontmost.children);
});
svg.addEventListener('pointerout', e => {
//const targetCell = e.target.closest('[data-q][data-r][data-s][data-t], .frontmost');
console.log('pointer out target', e.target);
const targetCell = e.target.closest('[data-q][data-r][data-s][data-t], .frontmost');
if (targetCell) {
console.log('SVG pointerout', targetCell);
[...frontmost.children].forEach(child => {
//console.log('child', child, 'relatedTarget', e.relatedTarget);
//if ([
// !e.relatedTarget, // out of the window
// targetCell.classList.contains('frontmost') && !e.relatedTarget.closest('.frontmost'), // from one element in frontmost to another element in frontmost
// !targetCell.classList.contains('frontmost') && frontmostStore.get(child) === targetCell, // leaving from a hex under frontmost
//].some(e => e)) {
console.log('child', child, 'belongs to', frontmostStore.get(child));
console.log('relatedTarget', e.relatedTarget);
if (!e.relatedTarget || frontmostStore.get(child) !== targetCell || (e.relatedTarget !== child && !child.contains(e.relatedTarget))) {
//if (!e.relatedTarget || frontmostStore.get(child) !== targetCell || e.relatedTarget !== child) {
const parent = frontmostStore.get(child);
console.log('returning to', parent);
//console.log('RETURNING to', parent);
parent.append(child);
//if (child.classList.contains('.counter')) {
// firingArc.toggleCounterVisibility(svg, child, false);
//}
firingArc.toggleCounterVisibility(svg, child, false);
parent.classList.remove('hover');
frontmostStore.delete(child);
}
});
//targetCell.classList.remove('hover');
if (frontmost.children.length < 1) targetCell.classList.remove('hover');
} else {
[...frontmost.children].forEach(child => {
const parent = frontmostStore.get(child);
parent.append(child);
parent.classList.remove('hover');
frontmostStore.delete(child);
}); });
} }
//console.log('frontmost contents', frontmost.children);
}); });
clearHexDialog.querySelector('button[value="confirm"]').addEventListener('click', function(e) { grid.addEventListener('click', e => {
e.preventDefault(); console.log('click', e.target);
clearHexDialog.close(this.value);
}); });
gridTop.addEventListener('pointerleave', workaroundForWebKitBug233432(e => { const clearHexDialog = document.querySelector('#clear-hex');
[...top.container.children].forEach(child => { //clearHexDialog.addEventListener('close', e => {
top.collection.get(child).parent.append(child); // if (clearHexDialog.returnValue === 'confirm') {
top.collection.delete(child); // [...top.container.children].forEach(child => {
}); // top.collection.delete(child);
// child.remove();
// });
// }
//});
top.cell = null; //clearHexDialog.querySelector('button[value="confirm"]').addEventListener('click', function(e) {
})); // e.preventDefault();
// clearHexDialog.close(this.value);
//});
topHex.addEventListener('click', clickHandler); //gridTop.addEventListener('pointerleave', workaroundForWebKitBug233432(e => {
// console.log('pointerleave top', performance.now(), top.cell);
// const occupant = svg.querySelector('.grid-top .container .counter');
//
// if (occupant) {
// firingArc.toggleCounterVisibility(svg, occupant, false);
// }
//
// [...top.container.children].forEach(child => {
// top.collection.get(child).parent.append(child);
// top.collection.delete(child);
// });
//
// top.cell = null;
//
// getActiveSightLine(svg) && clearSightLine();
//}));
topHex.addEventListener('contextmenu', e => { //topHex.addEventListener('click', clickHandler);
e.preventDefault(); //
getSelected() ? sightLine.toggleLock(top.cell) : clearHexDialog.showModal(); //topHex.addEventListener('contextmenu', e => {
}); // e.preventDefault();
// getSelected() ? sightLine.toggleLock(top.cell) : clearHexDialog.showModal();
//});
const startingLocations = svg.querySelector('.start-locations'); const startingLocations = svg.querySelector('.start-locations');
startingLocations && getUnits(startingLocations).forEach(unit => unit.addEventListener('click', selectOffBoard)); startingLocations && getUnits(startingLocations).forEach(unit => unit.addEventListener('click', selectOffBoard));
function clickHandler(e) { function clickHandler(e) {
const occupant = svg.querySelector('.grid-top .container .counter') const occupant = svg.querySelector('.grid-top .container .counter');
let toPlace = placing.pop(); let toPlace = placing.pop();
if (isCounter(toPlace) || isMechTemplate(toPlace)) { if (isCounter(toPlace) || isMechTemplate(toPlace)) {
@ -280,43 +378,47 @@ export function start(el) {
const selected = getSelected(); const selected = getSelected();
} }
getCells(svg).forEach(cell => { //getCells(svg).forEach(cell => {
cell.addEventListener('pointerover', () => { // cell.addEventListener('pointerleave', () => {
//console.log(['pointerenter', cell]); // console.log('pointerleave cell', performance.now(), cell);
// });
top.cell = cell; //
// cell.addEventListener('pointerover', () => {
[...top.container.children].forEach(child => { // console.log('pointerenter', performance.now(), cell);
top.collection.get(child).parent.append(child); //
top.collection.delete(child); // top.cell = cell;
}); //
// [...top.container.children].forEach(child => {
top.container.parentElement.setAttributeNS(null, 'transform', cell.getAttributeNS(null, 'transform')); // top.collection.get(child).parent.append(child);
// top.collection.delete(child);
[...cell.children].filter(c => c.getAttributeNS(null, 'href') !== '#hex').forEach(child => { // });
top.collection.set(child, { parent: cell }); //
top.container.append(child); // top.container.parentElement.setAttributeNS(null, 'transform', cell.getAttributeNS(null, 'transform'));
}); //
// [...cell.children].filter(c => c.getAttributeNS(null, 'href') !== '#hex').forEach(child => {
let occupant = svg.querySelector('.grid-top .container .counter'); // top.collection.set(child, { parent: cell });
const selected = getSelected(); // top.container.append(child);
// });
if (placing[0]?.getAttributeNS(null, 'class') == 'mech-template') { //
cell.appendChild(placing[0]); // let occupant = svg.querySelector('.grid-top .container .counter');
} // const selected = getSelected();
//
if (selected && svg.querySelector('.grid').contains(selected) && !getLockedSightLine(svg) && cell !== selected.parentElement) { // if (placing[0]?.getAttributeNS(null, 'class') == 'mech-template') {
clearSightLine(); // cell.appendChild(placing[0]);
drawSightLine(selected.parentElement, cell); // }
} //
// if (selected && svg.querySelector('.grid').contains(selected) && !getLockedSightLine(svg) && cell !== selected.parentElement) {
occupant = getCellOccupant(cell); // clearSightLine();
// drawSightLine(selected.parentElement, cell);
if (occupant) { // }
firingArc.toggleCounterVisibility(svg, occupant, true); //
} // occupant = getCellOccupant(cell);
}); //
}); // if (occupant) {
// firingArc.toggleCounterVisibility(svg, occupant, true);
// }
// });
//});
//const cell = document.querySelector('[data-q="0"][data-r="0"][data-s="0"][data-t="0"]'); //const cell = document.querySelector('[data-q="0"][data-r="0"][data-s="0"][data-t="0"]');
//const povr = new PointerEvent('pointerover'); //const povr = new PointerEvent('pointerover');
@ -326,17 +428,29 @@ export function start(el) {
// debug // // debug //
// Add a trooper counter // Add a trooper counter
//const attacker = { dataset: { allegiance: 'attacker', number: 1, squad: 1 }};
// const defender = { dataset: { allegiance: 'defender', number: 1, squad: 2 }}; // const defender = { dataset: { allegiance: 'defender', number: 1, squad: 2 }};
//const cell = getCell(0, 0, 0, 0);
//const trooper = soldier.createCounter(attacker, 'blazer'); const cell = getCell(0, 0, 0, 0);
//const trooperSack = document.createElementNS(svgns, 'g'); const attacker = { dataset: { allegiance: 'attacker', number: 1, squad: 1 }};
//trooperSack.classList.add('cell-contents'); const trooper = soldier.createCounter(attacker, 'blazer');
//trooperSack.append(trooper); soldier.place(svg, trooper, cell);
//soldier.place(svg, trooper, cell);
// Add some counters in an unoccupied cell // Add some counters in an unoccupied cell
//const countersCell = getCell(-1, 1, 0, 0); //const countersCell = getCell(-1, 1, 0, 0);
const counter = document.createElementNS(svgns, 'use');
const name = 'grenade';
//counter.addEventListener('click', e => {
// e.stopPropagation()
// const container = counter.parentElement;
// counter.remove()
// arrangeCounters(container);
//});
//counter.setAttributeNS(null, 'href', `#counter-${name}`);
//counter.classList.add(`counter-${name}`);
//cell.append(counter);
//arrangeCounters(cell)
//setCounter('grenade'); //setCounter('grenade');
//setCounter('prone'); //setCounter('prone');
//setCounter('1st-floor'); //setCounter('1st-floor');
@ -374,7 +488,7 @@ export function setFiringArc() {
isOnBoard = counter => counter && counter.parentElement.hasAttribute('data-q'); isOnBoard = counter => counter && counter.parentElement.hasAttribute('data-q');
if (isOnBoard(counter)) { if (isOnBoard(counter)) {
returnToParent(top); //returnToParent(top);
firingArc.set(svg, this.dataset.size, counter, getCellPosition(counter.parentElement)); firingArc.set(svg, this.dataset.size, counter, getCellPosition(counter.parentElement));
} }
} }

View File

@ -97,7 +97,8 @@ export async function build(svg, request) {
const scenarioBuildings = scenario.querySelector('.gameboard .buildings'); const scenarioBuildings = scenario.querySelector('.gameboard .buildings');
if (scenarioGrid) { if (scenarioGrid) {
grid.replaceWith(svg.ownerDocument.importNode(scenarioGrid, true)); const frontmost = grid.querySelector('.frontmost');
[...scenarioGrid.children].forEach(child => frontmost.before(svg.ownerDocument.importNode(child, true)));
} }
if (scenarioBuildings) if (scenarioBuildings)

View File

@ -1,5 +1,6 @@
const xmlns = 'http://www.w3.org/2000/svg'; const xmlns = 'http://www.w3.org/2000/svg';
const grid = document.querySelector('svg .grid'); const grid = document.querySelector('svg .grid');
const frontmost = grid.querySelector('.frontmost');
const hex = { const hex = {
inradius: 8.66, inradius: 8.66,
@ -247,10 +248,10 @@ function drawBuildings(buildings, container, { q: pq, r: pr, s: ps }, features)
}, new Map()); }, new Map());
} }
function drawMapsheet(gameboard, mapsheet, position) { function drawMapsheet(placementMarker, mapsheet, position) {
const container = document.createElementNS(xmlns, 'g'); const container = document.createElementNS(xmlns, 'g');
container.classList.add(mapsheet.id); container.classList.add(mapsheet.id);
gameboard.appendChild(container); placementMarker.before(container);
const buildingContainer = document.createElementNS(xmlns, 'g'); const buildingContainer = document.createElementNS(xmlns, 'g');
buildingContainer.classList.add(mapsheet.id); buildingContainer.classList.add(mapsheet.id);
@ -440,11 +441,13 @@ findScalar(findMult(sheets), +width + 1, +height).forEach(([vscalar, row]) => {
return vectorAdd(coords, { q: -1, r: 0, s: 1 }, hscalar); return vectorAdd(coords, { q: -1, r: 0, s: 1 }, hscalar);
} }
ms = drawMapsheet(grid, ms, horzMapVect(vertMapVect({ q: 0, r: 0, s: 0 }))); ms = drawMapsheet(frontmost, ms, horzMapVect(vertMapVect({ q: 0, r: 0, s: 0 })));
finalGrid = new Map([...finalGrid, ...ms]); finalGrid = new Map([...finalGrid, ...ms]);
}) })
}); });
document.querySelector('.grid .mapsheets').remove();
function addGroup(container, className) { function addGroup(container, className) {
const g = document.createElementNS(xmlns, 'g'); const g = document.createElementNS(xmlns, 'g');
g.classList.add(className); g.classList.add(className);