blob: cf19f792d6c3dc2b1dcce8c2d8bb3e5e9359859b [file] [log] [blame]
import {css, html, LitElement} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import {Notifiable, SimulationInfo, simulationState,} from './device-observer.js';
@customElement('ns-cube-sprite')
export class CubeSprite extends LitElement implements Notifiable {
/**
* the yaw value in orientation for ns-cube-sprite
* unit: deg
*/
@property({type: Number}) yaw = -15;
/**
* the pitch value in orientation for ns-cube-sprite
* unit: deg
*/
@property({type: Number}) pitch = -15;
/**
* the roll value in orientation for ns-cube-sprite
* unit: deg
*/
@property({type: Number}) roll = 0;
/**
* the z value in position for ns-cube-sprite
* unit: cm
*/
@property({type: Number}) posZ = 0;
/**
* the css value for color
*/
@property({type: css, attribute: 'color'}) color = css`red`;
/**
* the css value for size
*/
@property({type: css, attribute: 'size'}) size = css`30px`;
/**
* A Boolean property; if set true, the user would
* be able to control the cube's pitch, yaw, and roll
* with the info panel.
*/
@property({type: Boolean}) controls = false;
/**
* A Boolean property; if set true, the box is selected
* therefore the outline gets dotted.
*/
@property({type: Boolean}) highlighted = false;
connectedCallback() {
super.connectedCallback(); // eslint-disable-line
simulationState.registerObserver(this);
window.addEventListener('orientationEvent', this.handleOrientationEvent);
}
disconnectedCallback() {
window.removeEventListener('orientationEvent', this.handleOrientationEvent);
simulationState.removeObserver(this);
super.disconnectedCallback(); // eslint-disable-line
}
onNotify(data: SimulationInfo) {
this.highlighted = data.selectedId === this.id;
for (const device of data.devices) {
if (device.name === this.id) {
this.posZ = device.position.z * 100;
return;
}
}
}
static styles = css`
:host {
/** all sizes are relative to font-size **/
display: block;
min-height: 1.5em;
min-width: 1.5em;
width: 1em;
/* overflow: hidden; */
transform-origin: center;
transform-style: preserve-3d;
transform: translateZ(calc(var(--posZ) * 1px));
cursor: move;
}
.cube {
transform-style: preserve-3d;
transform: rotateX(calc(var(--yaw) * 1deg))
rotateY(calc(var(--pitch) * 1deg)) rotateZ(calc(var(--roll) * 1deg));
position: absolute;
left: 0.25em;
bottom: 0.25em;
width: 1em;
height: 1em;
}
.cube > div {
position: absolute;
background-color: var(--color);
width: 100%;
height: 100%;
box-shadow: 0 0 0.25em #000 inset;
}
.cube > div:nth-child(1) {
transform: translateZ(0.5em);
}
.cube > div:nth-child(2) {
transform: rotateY(180deg) translateZ(0.5em);
}
.cube > div:nth-child(3) {
right: 0;
width: 1em;
transform: rotateY(90deg) translateZ(0.5em);
}
.cube > div:nth-child(4) {
width: 1em;
transform: rotateY(270deg) translateZ(0.5em);
}
.cube > div:nth-child(5) {
bottom: -0.5em;
height: 1em;
transform: rotateX(90deg);
box-shadow: 0 0 0.25em #000 inset, 0 0 0.25em #000;
}
.cube div:nth-child(6) {
height: 1em;
transform: translateY(-0.5em) rotateX(90deg);
overflow: hidden;
}
.line {
position: absolute;
border-bottom: 5px dashed;
width: calc(var(--posZ) * 1px);
top: 50%;
left: 50%;
transform: rotateY(90deg) rotateX(90deg);
transform-origin: left;
}
.base {
position: absolute;
border: 5px solid;
border-radius: 50%;
background-color: black;
height: 5px;
width: 5px;
top: 50%;
left: 50%;
transform: translate3d(-50%, -50%, calc(var(--posZ) * -1px));
}
`;
private handleOrientationEvent = (e: Event) => {
const {detail} = e as CustomEvent;
if (detail.name === this.id && this.controls) {
if (detail.type === 'yaw') {
this.yaw = detail.value;
} else if (detail.type === 'pitch') {
this.pitch = detail.value;
} else {
this.roll = detail.value;
}
}
};
render() {
// TODO(b/255635486): Make cube easily scalable with user input size
return html`
<style>
:host {
font-size: ${this.size};
--color: ${this.color};
--yaw: ${this.yaw};
--pitch: ${this.pitch};
--roll: ${this.roll};
--posZ: ${this.controls ? this.posZ : 0};
}
.cube > div {
outline: ${this.highlighted && this.controls ? css`dashed` : css``};
}
</style>
<div class="cube" role="button" tabindex="0" aria-label="Device">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
${
this.controls ? html`
<div class="line"></div>
<div class="base"></div>
` :
html``}
`;
}
}