UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

246 lines (243 loc) 7.86 kB
import { Color } from '../../../core/math/color.js'; import { Vec3 } from '../../../core/math/vec3.js'; import { ShaderMaterial } from '../../../scene/materials/shader-material.js'; import { MeshInstance } from '../../../scene/mesh-instance.js'; import { Entity } from '../../../framework/entity.js'; import { CULLFACE_BACK } from '../../../platform/graphics/constants.js'; import { BLEND_NORMAL } from '../../../scene/constants.js'; import { COLOR_GRAY } from '../color.js'; import { Geometry } from '../../../scene/geometry/geometry.js'; import { unlitShader } from '../shaders.js'; /** * @import { GraphicsDevice } from '../../../platform/graphics/graphics-device.js'; * @import { Mesh } from '../../../scene/mesh.js'; * @import { TriData } from '../tri-data.js'; */ const tmpG = new Geometry(); tmpG.positions = []; tmpG.normals = []; /** * @typedef {object} ShapeArgs * @property {string} [axis] - The axis of the shape (e.g., 'x', 'y', 'z'). * @property {Vec3} [position] - The position of the shape. * @property {Vec3} [rotation] - The rotation of the shape. * @property {Vec3} [scale] - The scale of the shape. * @property {boolean} [disabled] - Whether the shape is disabled. * @property {boolean} [visible] - Whether the shape is visible. * @property {number[]} [layers] - The layers the shape belongs to. * @property {Color} [defaultColor] - The default color of the shape. * @property {Color} [hoverColor] - The hover color of the shape. * @property {Color} [disabledColor] - The disabled color of the shape. * @property {number} [cull] - The culling mode of the shape. * @property {number} [depth] - The depth of the shape. -1 = interpolated depth. */ /** * @ignore */ class Shape { /** * Set the disabled state of the shape. * * @type {boolean} */ set disabled(value) { this._disabled = value ?? false; this.hover(false); } /** * Get the disabled state of the shape. * * @type {boolean} */ get disabled() { return this._disabled; } /** * Set the visibility state of the shape. * * @type {boolean} */ set visible(value) { if (value === this._visible) { return; } for(let i = 0; i < this.meshInstances.length; i++){ this.meshInstances[i].visible = value; } this._visible = value; } /** * Get the visibility state of the shape. * * @type {boolean} */ get visible() { return this._visible; } /** * Create a render component for an entity. * * @param {Entity} entity - The entity to create the render component for. * @param {Mesh[]} meshes - The meshes to create the render component with. * @protected */ _createRenderComponent(entity, meshes) { const color = this._disabled ? this._disabledColor : this._defaultColor; this._material.setDefine('DEPTH_WRITE', this._depth > 0 ? '1' : '0'); this._material.setParameter('uDepth', this._depth); this._material.setParameter('uColor', color.toArray()); this._material.cull = this._cull; this._material.blendType = BLEND_NORMAL; this._material.update(); const meshInstances = []; for(let i = 0; i < meshes.length; i++){ const mi = new MeshInstance(meshes[i], this._material); mi.cull = false; meshInstances.push(mi); this.meshInstances.push(mi); } entity.addComponent('render', { meshInstances: meshInstances, layers: this._layers, castShadows: false }); } /** * Update the shape's transform. * * @protected */ _update() { this.entity.setLocalPosition(this._position); this.entity.setLocalEulerAngles(this._rotation); this.entity.setLocalScale(this._scale); } /** * Sets the hover state of the shape. * * @param {boolean} state - Whether the shape is hovered. * @returns {void} */ hover(state) { const color = this._disabled ? this._disabledColor : state ? this._hoverColor : this._defaultColor; this._material.setParameter('uColor', color.toArray()); } /** * Destroys the shape and its entity. * * @returns {void} */ destroy() { this.entity.destroy(); } /** * Create a shape. * * @param {GraphicsDevice} device - The graphics device. * @param {string} name - The name of the shape. * @param {ShapeArgs} args - The options for the shape. */ constructor(device, name, args){ /** * The internal position of the shape. * * @type {Vec3} * @protected */ this._position = new Vec3(); /** * The internal rotation of the shape. * * @type {Vec3} * @protected */ this._rotation = new Vec3(); /** * The internal scale of the shape. * * @type {Vec3} * @protected */ this._scale = new Vec3(1, 1, 1); /** * The internal render component layers of the shape. * * @type {number[]} * @protected */ this._layers = []; /** * The internal material state of the shape. * * @type {ShaderMaterial} * @protected */ this._material = new ShaderMaterial(unlitShader); /** * The internal disabled state of the shape. * * @protected * @type {boolean} */ this._disabled = false; /** * The internal visibility state of the shape. * * @type {boolean} * @protected */ this._visible = true; /** * The internal default color of the shape. * * @type {Color} * @protected */ this._defaultColor = Color.WHITE; /** * The internal hover color of the shape. * * @type {Color} * @protected */ this._hoverColor = Color.BLACK; /** * The internal disabled color of the shape. * * @type {Color} * @protected */ this._disabledColor = COLOR_GRAY; /** * The internal culling state of the shape. * * @type {number} * @protected */ this._cull = CULLFACE_BACK; /** * The internal depth state of the shape. -1 = interpolated depth. * * @type {number} * @protected */ this._depth = -1; /** * The triangle data of the shape. * * @type {TriData[]} */ this.triData = []; /** * The mesh instances of the shape. * * @type {MeshInstance[]} */ this.meshInstances = []; this.device = device; this.axis = args.axis ?? 'x'; if (args.position instanceof Vec3) { this._position.copy(args.position); } if (args.rotation instanceof Vec3) { this._rotation.copy(args.rotation); } if (args.scale instanceof Vec3) { this._scale.copy(args.scale); } this._disabled = args.disabled ?? this._disabled; this._visible = args.visible ?? this._visible; this._layers = args.layers ?? this._layers; if (args.defaultColor instanceof Color) { this._defaultColor = args.defaultColor; } if (args.hoverColor instanceof Color) { this._hoverColor = args.hoverColor; } if (args.disabledColor instanceof Color) { this._disabledColor = args.disabledColor; } this._cull = args.cull ?? this._cull; this._depth = args.depth ?? this._depth; // entity this.entity = new Entity(`${name}:${this.axis}`); this.entity.setLocalPosition(this._position); this.entity.setLocalEulerAngles(this._rotation); this.entity.setLocalScale(this._scale); } } export { Shape };