Changeset - 2210d934d62d
[Not reviewed]
default
0 2 0
drewp@bigasterisk.com - 20 months ago 2023-06-03 00:34:24
drewp@bigasterisk.com
fader was echoing external edits as patches back into the graph. This fixes that the wrong way, circumventing lit
2 files changed with 29 insertions and 21 deletions:
0 comments (0 inline, 0 general)
light9/fade/Light9EffectFader.ts
Show inline comments
 
import debug from "debug";
 
import { css, html, LitElement } from "lit";
 
import { customElement, property, state } from "lit/decorators.js";
 
import { NamedNode, Quad } from "n3";
 
import { getTopGraph } from "../web/RdfdbSyncedGraph";
 
import { showRoot } from "../web/show_specific";
 
import { SyncedGraph } from "../web/SyncedGraph";
 
import { Patch } from "../web/patch";
 
import { Literal } from "n3";
 
export { Light9Fader } from "./Light9Fader";
 

	
 
const log = debug("efffader")
 

	
 
//////////////////////////////////////
 
const RETURN_URI = new NamedNode("");
 
const RETURN_FLOAT = 1;
 
function get2Step<T extends NamedNode | number>(returnWhat: T, graph: SyncedGraph, subj1: NamedNode, pred1: NamedNode, pred2: NamedNode): T | undefined {
 
  // ?subj1 ?pred1 ?x . ?x ?pred2 ?returned .
 
  let x: NamedNode;
 
  try {
 
    x = graph.uriValue(subj1, pred1);
 
  } catch (e) {
 
    return undefined;
 
  }
 
  try {
 
@@ -81,24 +84,25 @@ export class Light9EffectFader extends L
 
      }
 
      light9-fader {
 
        margin: 4px;
 
        width: 100%;
 
      }
 
    `,
 
  ];
 
  render() {
 
    if (this.conf === undefined || this.conf.value === undefined) {
 
      return html`...`;
 
    }
 
    return html`
 
      <div><resource-display .uri=${this.uri}></resource-display>
 
      <light9-fader .value=${this.conf.value} @change=${this.onSliderInput}></light9-fader>
 
      <div>${this.conf.value.toPrecision(3)}</div>
 
      <div>effect <edit-choice nounlink .uri=${this.conf.effect} @edited=${this.onEffectChange}></edit-choice></div>
 
      <div>attr <edit-choice nounlink .uri=${this.conf.effectAttr} @edited=${this.onEffectAttrChange}></edit-choice></div>
 
    `;
 
  }
 

	
 
  graph?: SyncedGraph;
 
  ctx: NamedNode = new NamedNode(showRoot + "/fade");
 
  @property() uri!: NamedNode;
 
  @state() conf?: EffectFader; // compiled from graph
 

	
 
@@ -124,56 +128,53 @@ export class Light9EffectFader extends L
 
    conf.column = maybeStringValue(graph, this.uri, U(":column")) || "unset";
 
    conf.effect = maybeUriValue(graph, this.uri, U(":effect"));
 
    conf.effectAttr = get2Step(RETURN_URI, graph, this.uri, U(":setting"), U(":effectAttr"));
 

	
 
    this.conf = conf;
 
    graph.runHandler(this.compileValue.bind(this, graph, this.conf), `fader config.value ${this.uri.value}`);
 
  }
 

	
 
  private compileValue(graph: SyncedGraph, conf: EffectFader) {
 
    //  external graph change -> conf.value
 
    const U = graph.U();
 
    conf.value = get2Step(RETURN_FLOAT, graph, this.uri, U(":setting"), U(":value"));
 
    // since conf attrs aren't watched as property:
 
    this.requestUpdate()
 
  }
 

	
 
  onSliderInput(ev: CustomEvent) {
 
    // slider user input -> graph
 
    if (this.conf === undefined) return;
 
    this.conf.value = ev.detail.value
 
    this.writeValueToGraph()
 
  }
 

	
 
  writeValueToGraph() {
 
    // this.value -> graph
 
    if (this.graph === undefined) {
 
      return;
 
    }
 
    const U = this.graph.U();
 
    // const prev = this.value;
 
    // const v: number = ev.detail.value;
 
    // this.value = parseFloat(v.toPrecision(3)); // rewrite pls
 
    // if (this.value == prev) {
 
    //   return;
 
    // }
 
    // if (!this.setting) {
 
    //   throw new Error("can't make new settings yet");
 
    // }
 

	
 
    if (this.conf === undefined) {
 
      return;
 
    }
 
    let patch = new Patch([], []);
 
    let settingNode: NamedNode;
 
    const valueTerm = this.graph.LiteralRoundedFloat(ev.detail.value);
 
    try {
 
      settingNode = this.graph.uriValue(this.uri, U(":setting"));
 
    } catch (e) {
 
      settingNode = this.graph.nextNumberedResource(U(":fadeset"));
 
      patch = patch.update(new Patch([], [new Quad(this.conf.uri, U(":setting"), settingNode, this.ctx)]));
 
    if (this.conf.value === undefined) {
 
      log(`value of ${this.uri} is undefined`)
 
      return;
 
    }
 
    patch = patch.update(this.graph.getObjectPatch(settingNode, this.graph.Uri(":value"), valueTerm, this.ctx));
 
    this.graph.applyAndSendPatch(patch);
 
    log('writeValueToGraph', this.conf.value)
 
    const valueTerm = this.graph.LiteralRoundedFloat(this.conf.value);
 
    const settingNode = this.graph.uriValue(this.uri, U(":setting"));
 
    this.graph.patchObject(settingNode, this.graph.Uri(":value"), valueTerm, this.ctx);
 

	
 
  }
 

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

	
 
  onEffectAttrChange(ev: CustomEvent) {
 
    if (this.graph === undefined) {
light9/fade/Light9Fader.ts
Show inline comments
 
@@ -37,28 +37,31 @@ export class Light9Fader extends LitElem
 
  handleHeight = 20;
 

	
 
  drag?: Drag;
 
  unmutedValue: number = 1;
 

	
 
  render() {
 
    return html` <div id="handle"><hr /></div> `;
 
  }
 

	
 
  protected update(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
 
    super.update(changedProperties);
 
    if (changedProperties.has("value")) {
 
      
 
    }
 
  }
 
  valueChangedFromUi() {
 
      this.value= clamp(this.value, 0, 1)
 
      this.dispatchEvent(new CustomEvent("change", { detail: { value: this.value } }));
 
    }
 
  }
 

	
 
  protected updated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
 
    super.updated(_changedProperties);
 
    const y = this.sliderTopY(this.value);
 
    this.handleEl.style.top = y + "px";
 
  }
 

	
 
  protected firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void {
 
    super.firstUpdated(_changedProperties);
 
    this.handleEl.style.height = this.handleHeight + "px";
 
    this.events();
 
  }
 
@@ -68,38 +71,40 @@ export class Light9Fader extends LitElem
 
    hand.addEventListener("mousedown", (ev: MouseEvent) => {
 
      ev.stopPropagation();
 
      if (ev.buttons == 1) {
 
        this.drag = new Drag(ev.clientY, this.value);
 
      } else if (ev.buttons == 2) {
 
        this.onRmb();
 
      }
 
    });
 
    this.addEventListener("mousedown", (ev: MouseEvent) => {
 
      ev.stopPropagation();
 
      if (ev.buttons == 1) {
 
        this.value = this.sliderValue(ev.offsetY);
 
        this.valueChangedFromUi()
 
        this.drag = new Drag(ev.clientY, this.value);
 
      } else if (ev.buttons == 2) {
 
        // RMB in trough
 
        this.onRmb();
 
      }
 
    });
 

	
 
    this.addEventListener("contextmenu", (event) => {
 
      event.preventDefault();
 
    });
 

	
 
    this.addEventListener("wheel", (ev: WheelEvent) => {
 
      ev.preventDefault();
 
      this.value += ev.deltaY / 120 * -.05;
 
      this.valueChangedFromUi()
 
    });
 

	
 
    const maybeDrag = (ev: MouseEvent) => {
 
      if (ev.buttons != 1) return;
 
      if (this.drag === undefined) return;
 
      ev.stopPropagation();
 
      this.onMouseDrag(ev.clientY - this.drag.startDragPxY!);
 
    };
 
    hand.addEventListener("mousemove", maybeDrag);
 
    this.addEventListener("mousemove", maybeDrag);
 
    window.addEventListener("mousemove", maybeDrag);
 

	
 
@@ -107,28 +112,30 @@ export class Light9Fader extends LitElem
 
    this.addEventListener("mouseup", this.onMouseUpAnywhere.bind(this));
 
    window.addEventListener("mouseup", this.onMouseUpAnywhere.bind(this));
 
  }
 
  onRmb() {
 
    if (this.value > 0.1) {
 
      // mute
 
      this.unmutedValue = this.value;
 
      this.value = 0;
 
    } else {
 
      // unmute
 
      this.value = this.unmutedValue;
 
    }
 
    this.valueChangedFromUi()
 
  }
 
  onMouseDrag(dy: number) {
 
    if (this.drag === undefined) throw "unexpected";
 
    this.value = this.drag.startDragValue - dy / this.troughHeight;
 
    this.valueChangedFromUi()
 
  }
 

	
 
  onMouseUpAnywhere() {
 
    this.drag = undefined;
 
  }
 

	
 
  sliderTopY(value: number): number {
 
    const usableY = this.troughHeight - this.handleHeight;
 
    const yAdj = this.handleHeight / 2 - 5 - 2;
 
    return (1 - value) * usableY + yAdj;
 
  }
 
  sliderValue(offsetY: number): number {
0 comments (0 inline, 0 general)