shogiground
Version:
lishogi.org shogi ui
235 lines • 10.6 kB
JavaScript
import { key2pos, createEl, setDisplay, posToTranslateRel, translateRel, pieceNameOf, sentePov, isPieceNode, isSquareNode, } from './util.js';
export function render(s, boardEls) {
var _a, _b, _c;
const asSente = sentePov(s.orientation), scaleDown = s.scaleDownPieces ? 0.5 : 1, posToTranslate = posToTranslateRel(s.dimensions), squaresEl = boardEls.squares, piecesEl = boardEls.pieces, draggedEl = boardEls.dragged, squareOverEl = boardEls.squareOver, promotionEl = boardEls.promotion, pieces = s.pieces, curAnim = s.animation.current, anims = curAnim ? curAnim.plan.anims : new Map(), fadings = curAnim ? curAnim.plan.fadings : new Map(), promotions = curAnim ? curAnim.plan.promotions : new Map(), curDrag = s.draggable.current, curPromKey = ((_a = s.promotion.current) === null || _a === void 0 ? void 0 : _a.dragged) ? s.selected : undefined, squares = computeSquareClasses(s), samePieces = new Set(), movedPieces = new Map();
// if piece not being dragged anymore, hide it
if (!curDrag && (draggedEl === null || draggedEl === void 0 ? void 0 : draggedEl.sgDragging)) {
draggedEl.sgDragging = false;
setDisplay(draggedEl, false);
if (squareOverEl)
setDisplay(squareOverEl, false);
}
let k, el, pieceAtKey, elPieceName, anim, fading, prom, pMvdset, pMvd;
// walk over all board dom elements, apply animations and flag moved pieces
el = piecesEl.firstElementChild;
while (el) {
if (isPieceNode(el)) {
k = el.sgKey;
pieceAtKey = pieces.get(k);
anim = anims.get(k);
fading = fadings.get(k);
prom = promotions.get(k);
elPieceName = pieceNameOf({ color: el.sgColor, role: el.sgRole });
// if piece dragged add or remove ghost class or if promotion dialog is active for the piece add prom class
if ((((curDrag === null || curDrag === void 0 ? void 0 : curDrag.started) && ((_b = curDrag.fromBoard) === null || _b === void 0 ? void 0 : _b.orig) === k) || (curPromKey && curPromKey === k)) &&
!el.sgGhost) {
el.sgGhost = true;
el.classList.add('ghost');
}
else if (el.sgGhost &&
(!curDrag || ((_c = curDrag.fromBoard) === null || _c === void 0 ? void 0 : _c.orig) !== k) &&
(!curPromKey || curPromKey !== k)) {
el.sgGhost = false;
el.classList.remove('ghost');
}
// remove fading class if it still remains
if (!fading && el.sgFading) {
el.sgFading = false;
el.classList.remove('fading');
}
// there is now a piece at this dom key
if (pieceAtKey) {
// continue animation if already animating and same piece or promoting piece
// (otherwise it could animate a captured piece)
if (anim &&
el.sgAnimating &&
(elPieceName === pieceNameOf(pieceAtKey) || (prom && elPieceName === pieceNameOf(prom)))) {
const pos = key2pos(k);
pos[0] += anim[2];
pos[1] += anim[3];
translateRel(el, posToTranslate(pos, asSente), scaleDown);
}
else if (el.sgAnimating) {
el.sgAnimating = false;
el.classList.remove('anim');
translateRel(el, posToTranslate(key2pos(k), asSente), scaleDown);
}
// same piece: flag as same
if (elPieceName === pieceNameOf(pieceAtKey) && (!fading || !el.sgFading)) {
samePieces.add(k);
}
// different piece: flag as moved unless it is a fading piece or an animated promoting piece
else {
if (fading && elPieceName === pieceNameOf(fading)) {
el.sgFading = true;
el.classList.add('fading');
}
else if (prom && elPieceName === pieceNameOf(prom)) {
samePieces.add(k);
}
else {
appendValue(movedPieces, elPieceName, el);
}
}
}
// no piece: flag as moved
else {
appendValue(movedPieces, elPieceName, el);
}
}
el = el.nextElementSibling;
}
// walk over all squares and apply classes
let sqEl = squaresEl.firstElementChild;
while (sqEl && isSquareNode(sqEl)) {
sqEl.className = squares.get(sqEl.sgKey) || '';
sqEl = sqEl.nextElementSibling;
}
// walk over all pieces in current set, apply dom changes to moved pieces
// or append new pieces
for (const [k, p] of pieces) {
const piece = promotions.get(k) || p;
anim = anims.get(k);
if (!samePieces.has(k)) {
pMvdset = movedPieces.get(pieceNameOf(piece));
pMvd = pMvdset === null || pMvdset === void 0 ? void 0 : pMvdset.pop();
// a same piece was moved
if (pMvd) {
// apply dom changes
pMvd.sgKey = k;
if (pMvd.sgFading) {
pMvd.sgFading = false;
pMvd.classList.remove('fading');
}
const pos = key2pos(k);
if (anim) {
pMvd.sgAnimating = true;
pMvd.classList.add('anim');
pos[0] += anim[2];
pos[1] += anim[3];
}
translateRel(pMvd, posToTranslate(pos, asSente), scaleDown);
}
// no piece in moved obj: insert the new piece
else {
const pieceNode = createEl('piece', pieceNameOf(p)), pos = key2pos(k);
pieceNode.sgColor = p.color;
pieceNode.sgRole = p.role;
pieceNode.sgKey = k;
if (anim) {
pieceNode.sgAnimating = true;
pos[0] += anim[2];
pos[1] += anim[3];
}
translateRel(pieceNode, posToTranslate(pos, asSente), scaleDown);
piecesEl.appendChild(pieceNode);
}
}
}
// remove any element that remains in the moved sets
for (const nodes of movedPieces.values()) {
for (const node of nodes) {
piecesEl.removeChild(node);
}
}
if (promotionEl)
renderPromotion(s, promotionEl);
}
function appendValue(map, key, value) {
const arr = map.get(key);
if (arr)
arr.push(value);
else
map.set(key, [value]);
}
function computeSquareClasses(s) {
var _a, _b;
const squares = new Map();
if (s.lastDests && s.highlight.lastDests)
for (const k of s.lastDests)
addSquare(squares, k, 'last-dest');
if (s.checks && s.highlight.check)
for (const check of s.checks)
addSquare(squares, check, 'check');
if (s.hovered)
addSquare(squares, s.hovered, 'hover');
if (s.selected) {
if (s.activeColor === 'both' || s.activeColor === s.turnColor)
addSquare(squares, s.selected, 'selected');
else
addSquare(squares, s.selected, 'preselected');
if (s.movable.showDests) {
const dests = (_a = s.movable.dests) === null || _a === void 0 ? void 0 : _a.get(s.selected);
if (dests)
for (const k of dests) {
addSquare(squares, k, 'dest' + (s.pieces.has(k) ? ' oc' : ''));
}
const pDests = s.premovable.dests;
if (pDests)
for (const k of pDests) {
addSquare(squares, k, 'pre-dest' + (s.pieces.has(k) ? ' oc' : ''));
}
}
}
else if (s.selectedPiece) {
if (s.droppable.showDests) {
const dests = (_b = s.droppable.dests) === null || _b === void 0 ? void 0 : _b.get(pieceNameOf(s.selectedPiece));
if (dests)
for (const k of dests) {
addSquare(squares, k, 'dest');
}
const pDests = s.predroppable.dests;
if (pDests)
for (const k of pDests) {
addSquare(squares, k, 'pre-dest' + (s.pieces.has(k) ? ' oc' : ''));
}
}
}
const premove = s.premovable.current;
if (premove) {
addSquare(squares, premove.orig, 'current-pre');
addSquare(squares, premove.dest, 'current-pre' + (premove.prom ? ' prom' : ''));
}
else if (s.predroppable.current)
addSquare(squares, s.predroppable.current.key, 'current-pre' + (s.predroppable.current.prom ? ' prom' : ''));
for (const sqh of s.drawable.squares) {
addSquare(squares, sqh.key, sqh.className);
}
return squares;
}
function addSquare(squares, key, klass) {
const classes = squares.get(key);
if (classes)
squares.set(key, `${classes} ${klass}`);
else
squares.set(key, klass);
}
function renderPromotion(s, promotionEl) {
const cur = s.promotion.current, key = cur === null || cur === void 0 ? void 0 : cur.key, pieces = cur ? [cur.promotedPiece, cur.piece] : [], hash = promotionHash(!!cur, key, pieces);
if (s.promotion.prevPromotionHash === hash)
return;
s.promotion.prevPromotionHash = hash;
if (key) {
const asSente = sentePov(s.orientation), initPos = key2pos(key), color = cur.piece.color, promotionSquare = createEl('sg-promotion-square'), promotionChoices = createEl('sg-promotion-choices');
if (s.orientation !== color)
promotionChoices.classList.add('reversed');
translateRel(promotionSquare, posToTranslateRel(s.dimensions)(initPos, asSente), 1);
for (const p of pieces) {
const pieceNode = createEl('piece', pieceNameOf(p));
pieceNode.sgColor = p.color;
pieceNode.sgRole = p.role;
promotionChoices.appendChild(pieceNode);
}
promotionEl.innerHTML = '';
promotionSquare.appendChild(promotionChoices);
promotionEl.appendChild(promotionSquare);
setDisplay(promotionEl, true);
}
else {
setDisplay(promotionEl, false);
}
}
function promotionHash(active, key, pieces) {
return [active, key, pieces.map((p) => pieceNameOf(p)).join(' ')].join(' ');
}
//# sourceMappingURL=render.js.map