UNPKG

onsight

Version:

Interactive, easy to use JavaScript game framework.

115 lines (101 loc) 4.18 kB
import { OUTLINE_THICKNESS, } from '../../constants.js'; import { Box } from '../../core/objects/Box.js'; import { PolyUtils } from '../../utils/PolyUtils.js'; import { Vector2 } from '../../math/Vector2.js'; const _topLeft = new Vector2(); const _topRight = new Vector2(); const _botLeft = new Vector2(); const _botRight = new Vector2(); class RubberBandBox extends Box { constructor() { super(); this.isHelper = true; this.type = 'RubberBandBox'; this.cursor = 'pointer'; this.pointerEvents = false; this.draggable = false; this.focusable = false; this.selectable = false; this.fillStyle.color = 'rgba(--icon, 0.5)'; this.fillStyle.fallback = 'rgba(0, 170, 204, 0.5)'; this.strokeStyle.color = 'rgb(--icon-light)'; this.strokeStyle.fallback = 'rgba(101, 229, 255)'; this.lineWidth = OUTLINE_THICKNESS; this.constantWidth = true; } intersected(scene, includeChildren = true) { const objects = []; const rubberBandBox = this; const rubberBandLines = this.getLines(this); function checkIntersectObject(object) { if (object.visible && object.selectable) { const objectLines = rubberBandBox.getLines(object); if (rubberBandBox.intersectsPolygon(rubberBandLines, objectLines) || rubberBandBox.containsPolygon(rubberBandLines, objectLines)) { objects.push(object); } } } if (includeChildren) { scene.traverse((object) => { if (object !== scene) checkIntersectObject(object); }); } else { for (const object of scene.children) { checkIntersectObject(object); } } return objects; } getLines(object) { const lines = []; const box = object.getWorldBoundingBox(); if (isFinite(box.min.x) && isFinite(box.min.y) && isFinite(box.max.x) && isFinite(box.max.y)) { _topLeft.copy(box.min); _topRight.copy(box.max.x, box.min.y); _botLeft.copy(box.min.x, box.max.y); _botRight.copy(box.max); lines.push({ from: new Vector2(_topLeft.x, _topLeft.y), to: new Vector2(_topRight.x, _topRight.y) }); lines.push({ from: new Vector2(_topRight.x, _topRight.y), to: new Vector2(_botRight.x, _botRight.y) }); lines.push({ from: new Vector2(_botRight.x, _botRight.y), to: new Vector2(_botLeft.x, _botLeft.y) }); lines.push({ from: new Vector2(_botLeft.x, _botLeft.y), to: new Vector2(_topLeft.x, _topLeft.y) }); return lines; } else { return []; } } intersectsPolygon(rubberBandLines, objectLines) { for (const rubberBandLine of rubberBandLines) { for (const objectLine of objectLines) { if (this.intersectsLine(rubberBandLine, objectLine)) return true; } } return false; } intersectsLine(line1, line2) { const { x: x1, y: y1 } = line1.from; const { x: x2, y: y2 } = line1.to; const { x: x3, y: y3 } = line2.from; const { x: x4, y: y4 } = line2.to; const denom = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); if (denom === 0) return false; const ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom; const ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom; return (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1); } containsPolygon(rubberBandLines, objectLines) { const rubberBandPolygon = this.linesToPolygon(rubberBandLines); const objectPolygon = this.linesToPolygon(objectLines); if (objectPolygon.length === 0) return false; for (const point of objectPolygon) { if (!PolyUtils.isPointInPolygon(point, rubberBandPolygon)) return false; } return true; } linesToPolygon(lines) { const polygon = []; for (const line of lines) { polygon.push(line.from); } return polygon; } } export { RubberBandBox };