playcanvas
Version:
PlayCanvas WebGL game engine
200 lines (197 loc) • 6.37 kB
JavaScript
import { Quat } from '../../../core/math/quat.js';
import { Vec3 } from '../../../core/math/vec3.js';
import { Entity } from '../../../framework/entity.js';
import { ConeGeometry } from '../../../scene/geometry/cone-geometry.js';
import { CylinderGeometry } from '../../../scene/geometry/cylinder-geometry.js';
import { Mesh } from '../../../scene/mesh.js';
import { TriData } from '../tri-data.js';
import { Shape } from './shape.js';
/** @import { ShapeArgs } from './shape.js' */ /** @import { GraphicsDevice } from '../../../platform/graphics/graphics-device.js' */ const tmpV1 = new Vec3();
const tmpV2 = new Vec3();
const tmpQ1 = new Quat();
/**
* @typedef {object} ArrowShapeArgs
* @property {number} [gap] - The gap between the arrow base and the center
* @property {number} [lineThickness] - The thickness of the line
* @property {number} [lineLength] - The length of the line
* @property {number} [arrowThickness] - The thickness of the arrow head
* @property {number} [arrowLength] - The length of the arrow head
* @property {number} [tolerance] - The tolerance for intersection tests
*/ /**
* @ignore
*/ class ArrowShape extends Shape {
/**
* Create a new ArrowShape.
*
* @param {GraphicsDevice} device - The graphics device.
* @param {ShapeArgs & ArrowShapeArgs} args - The shape options.
*/ constructor(device, args = {}){
super(device, 'arrow', args), /**
* The internal gap between the arrow base and the center.
*
* @type {number}
* @private
*/ this._gap = 0, /**
* The internal line thickness of the arrow.
*
* @type {number}
* @private
*/ this._lineThickness = 0.02, /**
* The internal line length of the arrow.
*
* @type {number}
* @private
*/ this._lineLength = 0.5, /**
* The internal arrow thickness of the arrow.
*
* @type {number}
* @private
*/ this._arrowThickness = 0.12, /**
* The internal arrow length of the arrow.
*
* @type {number}
* @private
*/ this._arrowLength = 0.18, /**
* The internal tolerance of the arrow.
*
* @type {number}
* @private
*/ this._tolerance = 0.1;
this._gap = args.gap ?? this._gap;
this._lineThickness = args.lineThickness ?? this._lineThickness;
this._lineLength = args.lineLength ?? this._lineLength;
this._arrowThickness = args.arrowThickness ?? this._arrowThickness;
this._arrowLength = args.arrowLength ?? this._arrowLength;
this._tolerance = args.tolerance ?? this._tolerance;
// intersect
this.triData = [
new TriData(new ConeGeometry()),
new TriData(new CylinderGeometry(), 1)
];
// render
this._head = new Entity(`head:${this.axis}`);
this.entity.addChild(this._head);
this._createRenderComponent(this._head, [
Mesh.fromGeometry(this.device, new ConeGeometry())
]);
this._line = new Entity(`line:${this.axis}`);
this.entity.addChild(this._line);
this._createRenderComponent(this._line, [
Mesh.fromGeometry(this.device, new CylinderGeometry())
]);
// update
this._update();
}
/**
* Set the gap between the arrow base and the center.
*
* @type {number}
*/ set gap(value) {
this._gap = value ?? this._gap;
this._update();
}
/**
* Get the gap between the arrow base and the center.
*
* @type {number}
*/ get gap() {
return this._gap;
}
/**
* Set the line thickness of the arrow.
*
* @type {number}
*/ set lineThickness(value) {
this._lineThickness = value ?? this._lineThickness;
this._update();
}
/**
* Get the line thickness of the arrow.
*
* @type {number}
*/ get lineThickness() {
return this._lineThickness;
}
/**
* Set the line length of the arrow.
*
* @type {number}
*/ set lineLength(value) {
this._lineLength = value ?? this._lineLength;
this._update();
}
/**
* Get the line length of the arrow.
*
* @type {number}
*/ get lineLength() {
return this._lineLength;
}
/**
* Set the arrow thickness of the arrow.
*
* @type {number}
*/ set arrowThickness(value) {
this._arrowThickness = value ?? this._arrowThickness;
this._update();
}
/**
* Get the arrow thickness of the arrow.
*
* @type {number}
*/ get arrowThickness() {
return this._arrowThickness;
}
/**
* Set the arrow length of the arrow.
*
* @type {number}
*/ set arrowLength(value) {
this._arrowLength = value ?? this._arrowLength;
this._update();
}
/**
* Get the arrow length of the arrow.
*
* @type {number}
*/ get arrowLength() {
return this._arrowLength;
}
/**
* Set the tolerance of the arrow.
*
* @type {number}
*/ set tolerance(value) {
this._tolerance = value;
this._update();
}
/**
* Get the tolerance of the arrow.
*
* @type {number}
*/ get tolerance() {
return this._tolerance;
}
/**
* Update the shape's transform.
*
* @protected
* @override
*/ _update() {
// intersect
tmpV1.set(0, this._gap + this._arrowLength * 0.5 + this._lineLength, 0);
tmpQ1.set(0, 0, 0, 1);
tmpV2.set(this._arrowThickness, this._arrowLength, this._arrowThickness);
this.triData[0].setTransform(tmpV1, tmpQ1, tmpV2);
tmpV1.set(0, this._gap + this._lineLength * 0.5, 0);
tmpQ1.set(0, 0, 0, 1);
tmpV2.set(this._lineThickness + this._tolerance, this._lineLength, this._lineThickness + this._tolerance);
this.triData[1].setTransform(tmpV1, tmpQ1, tmpV2);
// render
this._head.setLocalPosition(0, this._gap + this._arrowLength * 0.5 + this._lineLength, 0);
this._head.setLocalScale(this._arrowThickness, this._arrowLength, this._arrowThickness);
this._line.setLocalPosition(0, this._gap + this._lineLength * 0.5, 0);
this._line.setLocalScale(this._lineThickness, this._lineLength, this._lineThickness);
}
}
export { ArrowShape };