view light9/fade/web/Light9FadeUi.ts @ 2108:e92db17f3e7e

effectSequencer can now also process some note-like values coming from the fade/ ui
author drewp@bigasterisk.com
date Wed, 01 Jun 2022 17:02:46 -0700
parents 8bb2f526d457
children 611c3e97de2f
line wrap: on
line source

import { fastSlider, fastSliderLabel, provideFASTDesignSystem } from "@microsoft/fast-components";
import debug from "debug";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators.js";
import { NamedNode } from "n3";
import { getTopGraph } from "../../web/RdfdbSyncedGraph";
import { SyncedGraph } from "../../web/SyncedGraph";
export { EditChoice } from "../../web/EditChoice";

provideFASTDesignSystem().register(fastSlider(), fastSliderLabel());

debug.enable("*");
const log = debug("fade");

@customElement("light9-fade-ui")
export class Light9FadeUi extends LitElement {
  static styles = [
    css`
      :host {
        display: block;
      }
    `,
  ];
  render() {
    return html`
      <rdfdb-synced-graph></rdfdb-synced-graph>

      <h1>Fade <a href="metrics">[metrics]</a></h1>
      ${this.faders.map((fd) => html` <light9-fader .uri=${fd}></light9-fader> `)}
    `;
  }

  graph!: SyncedGraph;

  @property() faders: NamedNode[] = [];

  constructor() {
    super();
    getTopGraph().then((g) => {
      this.graph = g;
      // todo: start with a page, then find the faders on that page
      this.faders = [
        g.Uri(":show/dance2019/fadePage1f0"),
        g.Uri(":show/dance2019/fadePage1f1"),
        g.Uri(":show/dance2019/fadePage1f2"),
        g.Uri(":show/dance2019/fadePage1f3"),
        g.Uri(":show/dance2019/fadePage1f4"),
        g.Uri(":show/dance2019/fadePage1f5"),
        g.Uri(":show/dance2019/fadePage1f6"),
        g.Uri(":show/dance2019/fadePage1f7"),
      ];
    });
  }
}

@customElement("light9-fader")
export class Light9Fader extends LitElement {
  static styles = [
    css`
      :host {
        display: inline-block;
      }
      fast-slider {
        height: 256px;
      }
      fast-slider > .track {
        background: #e3bbc0;
        box-shadow: 0 0 8px;
      }
      fast-slider {
        --accent-foreground-rest: #0a0a0c;
      }
    `,
  ];
  render() {
    return html`
      <fast-slider orientation="vertical" .value=${this.value} step=${1 / 255} min="1" max="0" @change=${this.onSliderInput}>
        <fast-slider-label label="0"></fast-slider-label>
        <fast-slider-label label="1.0"></fast-slider-label>
      </fast-slider>
      <div>${this.value.toPrecision(3)}</div>
      <div>eff: <edit-choice .uri=${this.effect} @edited=${this.onEffectChange}></edit-choice></div>
      <div>attr: <edit-choice .uri=${this.effectAttr}></edit-choice></div>
      <div>&lt;=&gt; Slider ${this.column}</div>
    `;
  }

  graph!: SyncedGraph;
  ctx: NamedNode = new NamedNode("http://light9.bigasterisk.com/show/dance2019/fade");
  @property() uri!: NamedNode;
  @property() column!: string;
  @property() effect: NamedNode | null = null;
  @property() effectAttr: NamedNode | null = null;

  @property() value: number = 0.111;

  constructor() {
    super();
    getTopGraph().then((g) => {
      this.graph = g;
      this.graph.runHandler(this.configure.bind(this), `config ${this.uri.value}`);
      this.graph.runHandler(this.valueSync.bind(this), `valueSync ${this.uri.value}`);
    });
  }

  configure() {
    //   console.time(`fader configure ${this.uri.value}`)
    const U = this.graph.U();
    if (!this.graph.contains(this.uri, U("rdf:type"), U(":Fader"))) {
      // not loaded yet
      //   console.timeEnd(`fader configure ${this.uri.value}`)

      return;
    }
    this.column = this.graph.stringValue(this.uri, U(":column"));
    this.effect = this.graph.uriValue(this.uri, U(":effectClass"));
    this.effectAttr = this.graph.uriValue(this.uri, U(":effectAttr"));
    // console.timeEnd(`fader configure ${this.uri.value}`)
  }

  valueSync() {
    // console.time(`valueSync ${this.uri.value}`)
    const U = this.graph.U();
    if (!this.graph.contains(this.uri, U("rdf:type"), U(":Fader"))) {
      // not loaded yet
      // console.timeEnd(`valueSync ${this.uri.value}`)
      return;
    }

    this.value = this.graph.floatValue(this.uri, this.graph.Uri(":value"));
    // console.timeEnd(`valueSync ${this.uri.value}`)
  }

  onSliderInput(ev: CustomEvent) {
    const prev = this.value;
    const v: number = (ev.target as any).valueAsNumber;
    this.value = parseFloat(v.toPrecision(3)); // rewrite pls
    if (this.value == prev) {
      return;
    }
    log(`new value ${this.value}`);

    this.graph.patchObject(this.uri, this.graph.Uri(":value"), this.graph.LiteralRoundedFloat(this.value), this.ctx);
  }

  onEffectChange(ev: CustomEvent) {
    const { newValue } = ev.detail;
    this.graph.patchObject(this.uri, this.graph.Uri(":effectClass"), newValue, this.ctx);
  }
}