xref: /aosp_15_r20/tools/netsim/ui/ts/cube-sprite.ts (revision cf78ab8cffb8fc9207af348f23af247fb04370a6)
1*cf78ab8cSAndroid Build Coastguard Workerimport {css, html, LitElement} from 'lit';
2*cf78ab8cSAndroid Build Coastguard Workerimport {customElement, property} from 'lit/decorators.js';
3*cf78ab8cSAndroid Build Coastguard Worker
4*cf78ab8cSAndroid Build Coastguard Workerimport {Notifiable, SimulationInfo, simulationState,} from './device-observer.js';
5*cf78ab8cSAndroid Build Coastguard Worker
6*cf78ab8cSAndroid Build Coastguard Worker@customElement('ns-cube-sprite')
7*cf78ab8cSAndroid Build Coastguard Workerexport class CubeSprite extends LitElement implements Notifiable {
8*cf78ab8cSAndroid Build Coastguard Worker  /**
9*cf78ab8cSAndroid Build Coastguard Worker   * the yaw value in orientation for ns-cube-sprite
10*cf78ab8cSAndroid Build Coastguard Worker   * unit: deg
11*cf78ab8cSAndroid Build Coastguard Worker   */
12*cf78ab8cSAndroid Build Coastguard Worker  @property({type: Number}) yaw = -15;
13*cf78ab8cSAndroid Build Coastguard Worker
14*cf78ab8cSAndroid Build Coastguard Worker  /**
15*cf78ab8cSAndroid Build Coastguard Worker   * the pitch value in orientation for ns-cube-sprite
16*cf78ab8cSAndroid Build Coastguard Worker   * unit: deg
17*cf78ab8cSAndroid Build Coastguard Worker   */
18*cf78ab8cSAndroid Build Coastguard Worker  @property({type: Number}) pitch = -15;
19*cf78ab8cSAndroid Build Coastguard Worker
20*cf78ab8cSAndroid Build Coastguard Worker  /**
21*cf78ab8cSAndroid Build Coastguard Worker   * the roll value in orientation for ns-cube-sprite
22*cf78ab8cSAndroid Build Coastguard Worker   * unit: deg
23*cf78ab8cSAndroid Build Coastguard Worker   */
24*cf78ab8cSAndroid Build Coastguard Worker  @property({type: Number}) roll = 0;
25*cf78ab8cSAndroid Build Coastguard Worker
26*cf78ab8cSAndroid Build Coastguard Worker  /**
27*cf78ab8cSAndroid Build Coastguard Worker   * the z value in position for ns-cube-sprite
28*cf78ab8cSAndroid Build Coastguard Worker   * unit: cm
29*cf78ab8cSAndroid Build Coastguard Worker   */
30*cf78ab8cSAndroid Build Coastguard Worker  @property({type: Number}) posZ = 0;
31*cf78ab8cSAndroid Build Coastguard Worker
32*cf78ab8cSAndroid Build Coastguard Worker  /**
33*cf78ab8cSAndroid Build Coastguard Worker   * the css value for color
34*cf78ab8cSAndroid Build Coastguard Worker   */
35*cf78ab8cSAndroid Build Coastguard Worker  @property({type: css, attribute: 'color'}) color = css`red`;
36*cf78ab8cSAndroid Build Coastguard Worker
37*cf78ab8cSAndroid Build Coastguard Worker  /**
38*cf78ab8cSAndroid Build Coastguard Worker   * the css value for size
39*cf78ab8cSAndroid Build Coastguard Worker   */
40*cf78ab8cSAndroid Build Coastguard Worker  @property({type: css, attribute: 'size'}) size = css`30px`;
41*cf78ab8cSAndroid Build Coastguard Worker
42*cf78ab8cSAndroid Build Coastguard Worker  /**
43*cf78ab8cSAndroid Build Coastguard Worker   * A Boolean property; if set true, the user would
44*cf78ab8cSAndroid Build Coastguard Worker   * be able to control the cube's pitch, yaw, and roll
45*cf78ab8cSAndroid Build Coastguard Worker   * with the info panel.
46*cf78ab8cSAndroid Build Coastguard Worker   */
47*cf78ab8cSAndroid Build Coastguard Worker  @property({type: Boolean}) controls = false;
48*cf78ab8cSAndroid Build Coastguard Worker
49*cf78ab8cSAndroid Build Coastguard Worker  /**
50*cf78ab8cSAndroid Build Coastguard Worker   * A Boolean property; if set true, the box is selected
51*cf78ab8cSAndroid Build Coastguard Worker   * therefore the outline gets dotted.
52*cf78ab8cSAndroid Build Coastguard Worker   */
53*cf78ab8cSAndroid Build Coastguard Worker  @property({type: Boolean}) highlighted = false;
54*cf78ab8cSAndroid Build Coastguard Worker
55*cf78ab8cSAndroid Build Coastguard Worker  connectedCallback() {
56*cf78ab8cSAndroid Build Coastguard Worker    super.connectedCallback();  // eslint-disable-line
57*cf78ab8cSAndroid Build Coastguard Worker    simulationState.registerObserver(this);
58*cf78ab8cSAndroid Build Coastguard Worker    window.addEventListener('orientationEvent', this.handleOrientationEvent);
59*cf78ab8cSAndroid Build Coastguard Worker  }
60*cf78ab8cSAndroid Build Coastguard Worker
61*cf78ab8cSAndroid Build Coastguard Worker  disconnectedCallback() {
62*cf78ab8cSAndroid Build Coastguard Worker    window.removeEventListener('orientationEvent', this.handleOrientationEvent);
63*cf78ab8cSAndroid Build Coastguard Worker    simulationState.removeObserver(this);
64*cf78ab8cSAndroid Build Coastguard Worker    super.disconnectedCallback();  // eslint-disable-line
65*cf78ab8cSAndroid Build Coastguard Worker  }
66*cf78ab8cSAndroid Build Coastguard Worker
67*cf78ab8cSAndroid Build Coastguard Worker  onNotify(data: SimulationInfo) {
68*cf78ab8cSAndroid Build Coastguard Worker    this.highlighted = data.selectedId === this.id;
69*cf78ab8cSAndroid Build Coastguard Worker    for (const device of data.devices) {
70*cf78ab8cSAndroid Build Coastguard Worker      if (device.name === this.id) {
71*cf78ab8cSAndroid Build Coastguard Worker        this.posZ = device.position.z * 100;
72*cf78ab8cSAndroid Build Coastguard Worker        return;
73*cf78ab8cSAndroid Build Coastguard Worker      }
74*cf78ab8cSAndroid Build Coastguard Worker    }
75*cf78ab8cSAndroid Build Coastguard Worker  }
76*cf78ab8cSAndroid Build Coastguard Worker
77*cf78ab8cSAndroid Build Coastguard Worker  static styles = css`
78*cf78ab8cSAndroid Build Coastguard Worker    :host {
79*cf78ab8cSAndroid Build Coastguard Worker      /** all sizes are relative to font-size **/
80*cf78ab8cSAndroid Build Coastguard Worker      display: block;
81*cf78ab8cSAndroid Build Coastguard Worker      min-height: 1.5em;
82*cf78ab8cSAndroid Build Coastguard Worker      min-width: 1.5em;
83*cf78ab8cSAndroid Build Coastguard Worker      width: 1em;
84*cf78ab8cSAndroid Build Coastguard Worker      /*  overflow: hidden; */
85*cf78ab8cSAndroid Build Coastguard Worker      transform-origin: center;
86*cf78ab8cSAndroid Build Coastguard Worker      transform-style: preserve-3d;
87*cf78ab8cSAndroid Build Coastguard Worker      transform: translateZ(calc(var(--posZ) * 1px));
88*cf78ab8cSAndroid Build Coastguard Worker      cursor: move;
89*cf78ab8cSAndroid Build Coastguard Worker    }
90*cf78ab8cSAndroid Build Coastguard Worker
91*cf78ab8cSAndroid Build Coastguard Worker    .cube {
92*cf78ab8cSAndroid Build Coastguard Worker      transform-style: preserve-3d;
93*cf78ab8cSAndroid Build Coastguard Worker      transform: rotateX(calc(var(--yaw) * 1deg))
94*cf78ab8cSAndroid Build Coastguard Worker        rotateY(calc(var(--pitch) * 1deg)) rotateZ(calc(var(--roll) * 1deg));
95*cf78ab8cSAndroid Build Coastguard Worker      position: absolute;
96*cf78ab8cSAndroid Build Coastguard Worker      left: 0.25em;
97*cf78ab8cSAndroid Build Coastguard Worker      bottom: 0.25em;
98*cf78ab8cSAndroid Build Coastguard Worker      width: 1em;
99*cf78ab8cSAndroid Build Coastguard Worker      height: 1em;
100*cf78ab8cSAndroid Build Coastguard Worker    }
101*cf78ab8cSAndroid Build Coastguard Worker    .cube > div {
102*cf78ab8cSAndroid Build Coastguard Worker      position: absolute;
103*cf78ab8cSAndroid Build Coastguard Worker      background-color: var(--color);
104*cf78ab8cSAndroid Build Coastguard Worker      width: 100%;
105*cf78ab8cSAndroid Build Coastguard Worker      height: 100%;
106*cf78ab8cSAndroid Build Coastguard Worker      box-shadow: 0 0 0.25em #000 inset;
107*cf78ab8cSAndroid Build Coastguard Worker    }
108*cf78ab8cSAndroid Build Coastguard Worker    .cube > div:nth-child(1) {
109*cf78ab8cSAndroid Build Coastguard Worker      transform: translateZ(0.5em);
110*cf78ab8cSAndroid Build Coastguard Worker    }
111*cf78ab8cSAndroid Build Coastguard Worker    .cube > div:nth-child(2) {
112*cf78ab8cSAndroid Build Coastguard Worker      transform: rotateY(180deg) translateZ(0.5em);
113*cf78ab8cSAndroid Build Coastguard Worker    }
114*cf78ab8cSAndroid Build Coastguard Worker    .cube > div:nth-child(3) {
115*cf78ab8cSAndroid Build Coastguard Worker      right: 0;
116*cf78ab8cSAndroid Build Coastguard Worker      width: 1em;
117*cf78ab8cSAndroid Build Coastguard Worker      transform: rotateY(90deg) translateZ(0.5em);
118*cf78ab8cSAndroid Build Coastguard Worker    }
119*cf78ab8cSAndroid Build Coastguard Worker    .cube > div:nth-child(4) {
120*cf78ab8cSAndroid Build Coastguard Worker      width: 1em;
121*cf78ab8cSAndroid Build Coastguard Worker      transform: rotateY(270deg) translateZ(0.5em);
122*cf78ab8cSAndroid Build Coastguard Worker    }
123*cf78ab8cSAndroid Build Coastguard Worker    .cube > div:nth-child(5) {
124*cf78ab8cSAndroid Build Coastguard Worker      bottom: -0.5em;
125*cf78ab8cSAndroid Build Coastguard Worker      height: 1em;
126*cf78ab8cSAndroid Build Coastguard Worker      transform: rotateX(90deg);
127*cf78ab8cSAndroid Build Coastguard Worker      box-shadow: 0 0 0.25em #000 inset, 0 0 0.25em #000;
128*cf78ab8cSAndroid Build Coastguard Worker    }
129*cf78ab8cSAndroid Build Coastguard Worker    .cube div:nth-child(6) {
130*cf78ab8cSAndroid Build Coastguard Worker      height: 1em;
131*cf78ab8cSAndroid Build Coastguard Worker      transform: translateY(-0.5em) rotateX(90deg);
132*cf78ab8cSAndroid Build Coastguard Worker      overflow: hidden;
133*cf78ab8cSAndroid Build Coastguard Worker    }
134*cf78ab8cSAndroid Build Coastguard Worker
135*cf78ab8cSAndroid Build Coastguard Worker    .line {
136*cf78ab8cSAndroid Build Coastguard Worker      position: absolute;
137*cf78ab8cSAndroid Build Coastguard Worker      border-bottom: 5px dashed;
138*cf78ab8cSAndroid Build Coastguard Worker      width: calc(var(--posZ) * 1px);
139*cf78ab8cSAndroid Build Coastguard Worker      top: 50%;
140*cf78ab8cSAndroid Build Coastguard Worker      left: 50%;
141*cf78ab8cSAndroid Build Coastguard Worker      transform: rotateY(90deg) rotateX(90deg);
142*cf78ab8cSAndroid Build Coastguard Worker      transform-origin: left;
143*cf78ab8cSAndroid Build Coastguard Worker    }
144*cf78ab8cSAndroid Build Coastguard Worker
145*cf78ab8cSAndroid Build Coastguard Worker    .base {
146*cf78ab8cSAndroid Build Coastguard Worker      position: absolute;
147*cf78ab8cSAndroid Build Coastguard Worker      border: 5px solid;
148*cf78ab8cSAndroid Build Coastguard Worker      border-radius: 50%;
149*cf78ab8cSAndroid Build Coastguard Worker      background-color: black;
150*cf78ab8cSAndroid Build Coastguard Worker      height: 5px;
151*cf78ab8cSAndroid Build Coastguard Worker      width: 5px;
152*cf78ab8cSAndroid Build Coastguard Worker      top: 50%;
153*cf78ab8cSAndroid Build Coastguard Worker      left: 50%;
154*cf78ab8cSAndroid Build Coastguard Worker      transform: translate3d(-50%, -50%, calc(var(--posZ) * -1px));
155*cf78ab8cSAndroid Build Coastguard Worker    }
156*cf78ab8cSAndroid Build Coastguard Worker  `;
157*cf78ab8cSAndroid Build Coastguard Worker
158*cf78ab8cSAndroid Build Coastguard Worker  private handleOrientationEvent = (e: Event) => {
159*cf78ab8cSAndroid Build Coastguard Worker    const {detail} = e as CustomEvent;
160*cf78ab8cSAndroid Build Coastguard Worker    if (detail.name === this.id && this.controls) {
161*cf78ab8cSAndroid Build Coastguard Worker      if (detail.type === 'yaw') {
162*cf78ab8cSAndroid Build Coastguard Worker        this.yaw = detail.value;
163*cf78ab8cSAndroid Build Coastguard Worker      } else if (detail.type === 'pitch') {
164*cf78ab8cSAndroid Build Coastguard Worker        this.pitch = detail.value;
165*cf78ab8cSAndroid Build Coastguard Worker      } else {
166*cf78ab8cSAndroid Build Coastguard Worker        this.roll = detail.value;
167*cf78ab8cSAndroid Build Coastguard Worker      }
168*cf78ab8cSAndroid Build Coastguard Worker    }
169*cf78ab8cSAndroid Build Coastguard Worker  };
170*cf78ab8cSAndroid Build Coastguard Worker
171*cf78ab8cSAndroid Build Coastguard Worker  render() {
172*cf78ab8cSAndroid Build Coastguard Worker    // TODO(b/255635486): Make cube easily scalable with user input size
173*cf78ab8cSAndroid Build Coastguard Worker    return html`
174*cf78ab8cSAndroid Build Coastguard Worker      <style>
175*cf78ab8cSAndroid Build Coastguard Worker        :host {
176*cf78ab8cSAndroid Build Coastguard Worker          font-size: ${this.size};
177*cf78ab8cSAndroid Build Coastguard Worker          --color: ${this.color};
178*cf78ab8cSAndroid Build Coastguard Worker          --yaw: ${this.yaw};
179*cf78ab8cSAndroid Build Coastguard Worker          --pitch: ${this.pitch};
180*cf78ab8cSAndroid Build Coastguard Worker          --roll: ${this.roll};
181*cf78ab8cSAndroid Build Coastguard Worker          --posZ: ${this.controls ? this.posZ : 0};
182*cf78ab8cSAndroid Build Coastguard Worker        }
183*cf78ab8cSAndroid Build Coastguard Worker        .cube > div {
184*cf78ab8cSAndroid Build Coastguard Worker          outline: ${this.highlighted && this.controls ? css`dashed` : css``};
185*cf78ab8cSAndroid Build Coastguard Worker        }
186*cf78ab8cSAndroid Build Coastguard Worker      </style>
187*cf78ab8cSAndroid Build Coastguard Worker      <div class="cube">
188*cf78ab8cSAndroid Build Coastguard Worker        <div></div>
189*cf78ab8cSAndroid Build Coastguard Worker        <div></div>
190*cf78ab8cSAndroid Build Coastguard Worker        <div></div>
191*cf78ab8cSAndroid Build Coastguard Worker        <div></div>
192*cf78ab8cSAndroid Build Coastguard Worker        <div></div>
193*cf78ab8cSAndroid Build Coastguard Worker        <div></div>
194*cf78ab8cSAndroid Build Coastguard Worker      </div>
195*cf78ab8cSAndroid Build Coastguard Worker      ${
196*cf78ab8cSAndroid Build Coastguard Worker        this.controls ? html`
197*cf78ab8cSAndroid Build Coastguard Worker            <div class="line"></div>
198*cf78ab8cSAndroid Build Coastguard Worker            <div class="base"></div>
199*cf78ab8cSAndroid Build Coastguard Worker          ` :
200*cf78ab8cSAndroid Build Coastguard Worker                        html``}
201*cf78ab8cSAndroid Build Coastguard Worker    `;
202*cf78ab8cSAndroid Build Coastguard Worker  }
203*cf78ab8cSAndroid Build Coastguard Worker}
204