Various fixes

This commit is contained in:
barsdeveloper
2022-10-09 19:20:22 +02:00
parent cdc5e5b91b
commit a55a475f70
23 changed files with 852 additions and 781 deletions

1276
dist/ueblueprint.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -106,15 +106,6 @@ export default class PinElement extends IElement {
connections = 0
get defaultValue() {
return this.unreactiveDefaultValue
}
set defaultValue(value) {
let oldValue = this.unreactiveDefaultValue
this.unreactiveDefaultValue = value
this.requestUpdate("defaultValue", oldValue)
}
/** @param {PinEntity<T>} entity */
constructor(entity) {
super(
@@ -122,14 +113,14 @@ export default class PinElement extends IElement {
new (PinElement.getTypeTemplate(entity))()
)
this.advancedView = entity.bAdvancedView
this.unreactiveDefaultValue = entity.getDefaultValue()
this.defaultValue = entity.getDefaultValue()
this.pinType = this.entity.getType()
// @ts-expect-error
this.color = this.constructor.properties.color.converter.fromAttribute(Configuration.pinColor[this.pinType]?.toString())
this.isLinked = false
this.pinDirection = entity.isInput() ? "input" : entity.isOutput() ? "output" : "hidden"
this.entity.subscribe("DefaultValue", value => this.defaultValue = value.toString())
// this.entity.subscribe("DefaultValue", value => this.defaultValue = value.toString())
this.entity.subscribe("PinToolTip", value => {
let matchResult = value.match(/\s*(.+?(?=\n)|.+\S)\s*/)
if (matchResult) {
@@ -191,8 +182,10 @@ export default class PinElement extends IElement {
return this.entity.LinkedTo ?? []
}
/** @param {T} value */
setDefaultValue(value) {
this.entity.DefaultValue = value
this.defaultValue = value
}
/** @param {IElement[]} nodesWhitelist */

View File

@@ -0,0 +1,9 @@
import Utility from "../Utility"
import IntegerEntity from "./IntegerEntity"
export default class ColorChannelRealValueEntity extends IntegerEntity {
toString() {
return (this.value / 255).toFixed(6)
}
}

View File

@@ -0,0 +1,15 @@
import Utility from "../Utility"
import IntegerEntity from "./IntegerEntity"
export default class ColorChannelValueEntity extends IntegerEntity {
static attributes = {
value: Number,
}
/** @param {Object | Number | String} options */
constructor(options = 0) {
super(options)
this.value = Utility.clamp(this.value, 0, 255)
}
}

View File

@@ -65,7 +65,7 @@ export default class IEntity extends Observable {
&& defaultValue.type !== String
) {
// @ts-expect-error
value = SerializerFactory.getSerializer((defaultValue.type)).deserialize(value)
value = SerializerFactory.getSerializer(defaultValue.type).deserialize(value)
}
target[property] = TypeInitialization.sanitize(value, Utility.getType(defaultValue))
continue // We have a value, need nothing more

View File

@@ -1,13 +1,14 @@
import Utility from "../Utility"
import ColorChannelRealValueEntity from "./ColorChannelRealValueEntity"
import IEntity from "./IEntity"
import Utility from "../Utility"
export default class LinearColorEntity extends IEntity {
static attributes = {
R: Number,
G: Number,
B: Number,
A: Number,
R: ColorChannelRealValueEntity,
G: ColorChannelRealValueEntity,
B: ColorChannelRealValueEntity,
A: ColorChannelRealValueEntity,
}
static fromWheelLocation([x, y], radius) {
@@ -18,10 +19,10 @@ export default class LinearColorEntity extends IEntity {
constructor(options = {}) {
super(options)
/** @type {Number} */ this.R
/** @type {Number} */ this.G
/** @type {Number} */ this.B
/** @type {Number} */ this.A
/** @type {ColorChannelRealValueEntity} */ this.R
/** @type {ColorChannelRealValueEntity} */ this.G
/** @type {ColorChannelRealValueEntity} */ this.B
/** @type {ColorChannelRealValueEntity} */ this.A
}
toRGBA() {
@@ -29,24 +30,24 @@ export default class LinearColorEntity extends IEntity {
}
toHSV() {
const max = Math.max(this.R, this.G, this.B)
const min = Math.min(this.R, this.G, this.B)
const max = Math.max(this.R.value, this.G.value, this.B.value)
const min = Math.min(this.R.value, this.G.value, this.B.value)
const d = max - min
let h
const s = (max === 0 ? 0 : d / max)
const s = (max == 0 ? 0 : d / max)
const v = max / 255
switch (max) {
case min:
h = 0
break
case this.R:
h = (this.G - this.B) + d * (this.G < this.B ? 6 : 0)
case this.R.value:
h = (this.G.value - this.B.value) + d * (this.G.value < this.B.value ? 6 : 0)
break
case this.G:
h = (this.B - this.R) + d * 2
case this.G.value:
h = (this.B.value - this.R.value) + d * 2
break
case this.B:
h = (this.R - this.G) + d * 4
case this.B.value:
h = (this.R.value - this.G.value) + d * 4
break
}
h /= 6 * d
@@ -54,7 +55,7 @@ export default class LinearColorEntity extends IEntity {
}
toNumber() {
return this.A + this.B << 8 + this.G << 16 + this.R << 24
return (this.R.value << 24) + (this.G.value << 16) + (this.B.value << 8) + this.A.value
}
toString() {

View File

@@ -1,4 +1,5 @@
// @ts-nocheck
import ColorChannelValueEntity from "../entity/ColorChannelValueEntity"
import FunctionReferenceEntity from "../entity/FunctionReferenceEntity"
import GuidEntity from "../entity/GuidEntity"
import IdentifierEntity from "../entity/IdentifierEntity"
@@ -20,29 +21,13 @@ import TypeInitialization from "../entity/TypeInitialization"
import Utility from "../Utility"
import VectorEntity from "../entity/VectorEntity"
/** @typedef {import("../entity/IEntity").default} IEntity */
/**
* @template {IEntity} T
* @typedef {import("../entity/IEntity").IEntityConstructor<T>} IEntityConstructor
*/
/**
* @template T
* @typedef {import("../entity/TypeInitialization").AnyValueConstructor<T>} AnyValueConstructor
*/
let P = Parsimmon
export default class Grammar {
/* --- Factory --- */
/**
* @template T, U
* @param {Grammar} r
* @param {AnyValueConstructor<T>} attributeType
* @param {Parsimmon<U>} defaultGrammar
* @returns
*/
/** @param {Grammar} r */
static getGrammarForType(r, attributeType, defaultGrammar = r.AttributeAnyValue) {
if (attributeType instanceof TypeInitialization) {
let result = Grammar.getGrammarForType(r, attributeType.type, defaultGrammar)
@@ -80,6 +65,10 @@ export default class Grammar {
return r.SimpleSerializationRotator
case SimpleSerializationVectorEntity:
return r.SimpleSerializationVector
case ColorChannelValueEntity:
return r.ColorChannelValue
case ColorChannelRealValue:
return r.ColorChannelRealValue
case LinearColorEntity:
return r.LinearColor
case FunctionReferenceEntity:
@@ -107,12 +96,7 @@ export default class Grammar {
}
}
/**
* @param {Grammar} r
* @param {IEntityConstructor<IEntity>} entityType
* @param {Parsimmon.Parser<String>} valueSeparator
* @returns
*/
/** @param {Grammar} r */
static createPropertyGrammar = (r, entityType, valueSeparator = P.string("=").trim(P.optWhitespace)) =>
r.AttributeName.skip(valueSeparator)
.chain(attributeName => {
@@ -126,11 +110,7 @@ export default class Grammar {
)
})
/**
* @param {Grammar} r
* @param {IEntityConstructor<IEntity>} entityType
* @returns
*/
/** @param {Grammar} r */
static createEntityGrammar = (r, entityType) =>
P.seqMap(
entityType.lookbehind
@@ -175,7 +155,10 @@ export default class Grammar {
HexDigit = r => P.regex(/[0-9a-fA-f]/).desc("hexadecimal digit")
/** @param {Grammar} r */
Number = r => P.regex(/[\-\+]?[0-9]+(?:\.[0-9]+)?/).map(Number).desc("a number")
Number = r => P.regex(/[-\+]?[0-9]+(?:\.[0-9]+)?/).map(Number).desc("a number")
/** @param {Grammar} r */
RealNumber = r => P.regex(/[-\+]?[0-9]+\.[0-9]+/).map(Number).desc("a number written as real")
/** @param {Grammar} r */
NaturalNumber = r => P.regex(/0|[1-9]\d*/).map(Number).desc("a natural number")
@@ -327,6 +310,17 @@ export default class Grammar {
})
)
/** @param {Grammar} r */
ColorChannelValue = r => P.alt(
r.RealNumber.map(v => new ColorChannelValueEntity(v * 255)),
r.ColorNumber.map(v => new ColorChannelValueEntity(v)),
)
/** @param {Grammar} r */
ColorChannelRealValue = r => P.alt(
r.RealNumber.map(v => new ColorChannelValueEntity(v * 255))
)
/** @param {Grammar} r */
LinearColor = r => Grammar.createEntityGrammar(r, LinearColorEntity)

View File

@@ -1,3 +1,5 @@
import ColorChannelRealValueEntity from "../entity/ColorChannelRealValueEntity"
import ColorChannelValueEntity from "../entity/ColorChannelValueEntity"
import CustomSerializer from "./CustomSerializer"
import FunctionReferenceEntity from "../entity/FunctionReferenceEntity"
import GeneralSerializer from "./GeneralSerializer"
@@ -64,16 +66,35 @@ export default function initializeSerializerFactory() {
)
)
SerializerFactory.registerSerializer(
ColorChannelRealValueEntity,
new ToStringSerializer(ColorChannelValueEntity)
)
SerializerFactory.registerSerializer(
ColorChannelValueEntity,
new ToStringSerializer(ColorChannelValueEntity)
)
SerializerFactory.registerSerializer(
FunctionReferenceEntity,
new GeneralSerializer(bracketsWrapped, FunctionReferenceEntity)
)
SerializerFactory.registerSerializer(GuidEntity, new ToStringSerializer(GuidEntity))
SerializerFactory.registerSerializer(
GuidEntity,
new ToStringSerializer(GuidEntity)
)
SerializerFactory.registerSerializer(IdentifierEntity, new ToStringSerializer(IdentifierEntity))
SerializerFactory.registerSerializer(
IdentifierEntity,
new ToStringSerializer(IdentifierEntity)
)
SerializerFactory.registerSerializer(IntegerEntity, new ToStringSerializer(IntegerEntity))
SerializerFactory.registerSerializer(
IntegerEntity,
new ToStringSerializer(IntegerEntity)
)
SerializerFactory.registerSerializer(
InvariantTextEntity,
@@ -112,7 +133,6 @@ export default function initializeSerializerFactory() {
SerializerFactory.registerSerializer(
ObjectReferenceEntity,
new CustomSerializer(
/** @param {ObjectReferenceEntity} objectReference */
objectReference => (objectReference.type ?? "") + (
objectReference.path
? objectReference.type ? `'"${objectReference.path}"'` : `"${objectReference.path}"`
@@ -122,7 +142,10 @@ export default function initializeSerializerFactory() {
)
)
SerializerFactory.registerSerializer(PathSymbolEntity, new ToStringSerializer(PathSymbolEntity))
SerializerFactory.registerSerializer(
PathSymbolEntity,
new ToStringSerializer(PathSymbolEntity)
)
SerializerFactory.registerSerializer(
PinEntity,
@@ -154,7 +177,6 @@ export default function initializeSerializerFactory() {
SerializerFactory.registerSerializer(
SimpleSerializationRotatorEntity,
new CustomSerializer(
/** @param {SimpleSerializationRotatorEntity} value */
(value, insideString) => `${value.P}, ${value.Y}, ${value.R}`,
SimpleSerializationRotatorEntity
)
@@ -163,7 +185,6 @@ export default function initializeSerializerFactory() {
SerializerFactory.registerSerializer(
SimpleSerializationVectorEntity,
new CustomSerializer(
/** @param {SimpleSerializationVectorEntity} value */
(value, insideString) => `${value.X}, ${value.Y}, ${value.Z}`,
SimpleSerializationVectorEntity
)

View File

@@ -95,9 +95,7 @@ export default class BlueprintTemplate extends ITemplate {
`
}
/**
* @param {Map} changedProperties
*/
/** @param {Map} changedProperties */
firstUpdated(changedProperties) {
super.firstUpdated(changedProperties)
this.element.headerElement = /** @type {HTMLElement} */(this.element.querySelector('.ueb-viewport-header'))

View File

@@ -1,9 +1,10 @@
import { html } from "lit"
import IInputPinTemplate from "./IInputPinTemplate"
import { html, nothing } from "lit"
import PinTemplate from "./PinTemplate"
/** @typedef {import("../element/PinElement").default} PinElement */
export default class BoolPinTemplate extends IInputPinTemplate {
/**
* @extends PinTemplate<Boolean>
*/
export default class BoolPinTemplate extends PinTemplate {
/** @type {HTMLInputElement} */
#input
@@ -13,7 +14,7 @@ export default class BoolPinTemplate extends IInputPinTemplate {
super.firstUpdated(changedProperties)
this.#input = this.element.querySelector(".ueb-pin-input")
let self = this
this.onChangeHandler = _ => this.element.entity.DefaultValue = self.#input.checked ? "true" : "false"
this.onChangeHandler = _ => this.element.setDefaultValue(self.#input.checked ? true : false)
this.#input.addEventListener("change", this.onChangeHandler)
}
@@ -26,14 +27,18 @@ export default class BoolPinTemplate extends IInputPinTemplate {
return [this.#input.checked ? "true" : "false"]
}
setDefaultValue(values = [], rawValues = values) {
this.element.setDefaultValue(values[0] == "true")
/**
* @param {Boolean[]} values
* @param {String[]} rawValues
*/
setDefaultValue(values = [], rawValues) {
this.element.setDefaultValue(values[0])
}
renderInput() {
if (this.element.isInput()) {
return html`
<input type="checkbox" class="ueb-pin-input" .checked=${this.element.entity.getDefaultValue()} />
<input type="checkbox" class="ueb-pin-input" checked="${this.element.defaultValue ? "" : nothing}" />
`
}
return super.renderInput()

View File

@@ -12,7 +12,7 @@ export default class ColorHandlerTemplate extends IDraggableTemplate {
}
createDraggableObject() {
new MouseMoveDraggable(this.element, this.element.blueprint, {
return new MouseMoveDraggable(this.element, this.element.blueprint, {
draggableElement: this.element.parentElement,
ignoreTranslateCompensate: true,
looseTarget: true,

View File

@@ -16,7 +16,7 @@ export default class ColorPickerWindowTemplate extends WindowTemplate {
}
/** @param {LinearColorEntity} value */
set color(value) {
if (value.num() == this.color.num()) {
if (value.toNumber() == this.color.toNumber()) {
this.element.requestUpdate("color", this.#color)
this.#color = value
}
@@ -32,10 +32,9 @@ export default class ColorPickerWindowTemplate extends WindowTemplate {
}
renderContent() {
const rgba = this.color.rgba()
return html`
<div class="ueb-color-picker"
.style="--ueb-color-r: ${rgba[0]}; --ueb-color-g: ${rgba[1]}; --ueb-color-b: ${rgba[2]}; --ueb-color-a: ${rgba[3]};">
.style="--ueb-color-r: ${this.color.R}; --ueb-color-g: ${this.color.G}; --ueb-color-b: ${this.color.B}; --ueb-color-a: ${this.color.A};">
<div class="ueb-color-picker-toolbar">
<div class="ueb-color-picker-theme"></div>
<div class="ueb-color-picker-srgb"></div>

View File

@@ -5,8 +5,7 @@ import PinTemplate from "./PinTemplate"
export default class ExecPinTemplate extends PinTemplate {
/** @param {PinElement} pin */
renderIcon(pin) {
renderIcon() {
return html`
<svg viewBox="-2 0 16 16">
<path class="ueb-pin-tofill" stroke-width="1.25" stroke="white" fill="none"

View File

@@ -0,0 +1,34 @@
import IInputPinTemplate from "./IInputPinTemplate"
/**
* @template T
* @extends IInputPinTemplate<T>
*/
export default class INumericPinTemplate extends IInputPinTemplate {
/** @param {String[]} values */
setInputs(values = [], updateDefaultValue = false) {
if (!values || values.length == 0) {
values = [this.getInput()]
}
let parsedValues = []
for (const value of values) {
let num = parseFloat(value)
if (isNaN(num)) {
num = 0
updateDefaultValue = false
}
parsedValues.push(num)
}
super.setInputs(values, false)
this.setDefaultValue(parsedValues, values)
}
/**
* @param {Number[]} values
* @param {String[]} rawValues
*/
setDefaultValue(values = [], rawValues) {
this.element.setDefaultValue(/** @type {T} */(values[0]))
}
}

View File

@@ -5,7 +5,7 @@ import MouseOpenWindow from "../input/mouse/MouseOpenWindow"
/**
* @typedef {import("../element/PinElement").default} PinElement
* @typedef {import("../entity/LinearColorEntity").default} LinearColorEntity}
* @typedef {import("../entity/LinearColorEntity").default} LinearColorEntity
*/
export default class LinearColorPinTemplate extends IInputPinTemplate {
@@ -19,7 +19,6 @@ export default class LinearColorPinTemplate extends IInputPinTemplate {
this.#input = this.element.querySelector(".ueb-pin-input")
}
/** @returns {IInput[]} */
createInputObjects() {
return [
...super.createInputObjects(),
@@ -37,8 +36,7 @@ export default class LinearColorPinTemplate extends IInputPinTemplate {
]
}
/** @param {PinElement} pin */
getInputs(pin) {
getInputs() {
return [this.#input.dataset.linearColor]
}

View File

@@ -7,10 +7,7 @@ export default class NamePinTemplate extends IInputPinTemplate {
/** @type {(e : InputEvent) => void} */
onInputHandler
/**
* @param {PinElement} pin
* @param {Map} changedProperties
*/
/** @param {Map} changedProperties */
firstUpdated(changedProperties) {
super.firstUpdated(changedProperties)
this.onInputHandler = e => {
@@ -36,12 +33,11 @@ export default class NamePinTemplate extends IInputPinTemplate {
})
}
/** @param {PinElement} pin */
getInputs(pin) {
getInputs() {
return this.inputContentElements.map(element => element.textContent) // textContent for performance reason
}
/** @param {String[]?} values */
/** @param {String[]} values */
setInputs(values = [], updateDefaultValue = true) {
values = values.map(value => value.replaceAll("\n", "")) // get rid of the new lines
super.setInputs(values, updateDefaultValue)

View File

@@ -1,4 +1,4 @@
import { html } from "lit"
import { html, nothing } from "lit"
import PinElement from "../element/PinElement"
import SelectableDraggableTemplate from "./SelectableDraggableTemplate"
@@ -32,7 +32,7 @@ export default class NodeTemplate extends SelectableDraggableTemplate {
</div>
${this.element.enabledState?.toString() == "DevelopmentOnly" ? html`
<div class="ueb-node-developmentonly">Development Only</div>
` : html``}
` : nothing}
${this.element.advancedPinDisplay ? html`
<div class="ueb-node-expansion" @click="${this.toggleAdvancedDisplayHandler}">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
@@ -40,7 +40,7 @@ export default class NodeTemplate extends SelectableDraggableTemplate {
<path d="M 16.003 18.626 l 7.081 -7.081 L 25 13.46 l -8.997 8.998 -9.003 -9 1.917 -1.916 z" />
</svg>
</div>
` : html``}
` : nothing}
</div>
</div>
`

View File

@@ -4,7 +4,6 @@ import MouseCreateLink from "../input/mouse/MouseCreateLink"
import Utility from "../Utility"
/**
* @typedef {import("../element/NodeElement").default} NodeElement
* @typedef {import("../input/IInput").default} IInput
*/
/**

View File

@@ -1,38 +1,13 @@
import { html } from "lit"
import IInputPinTemplate from "./IInputPinTemplate"
import INumericPinTemplate from "./INumericPinTemplate"
import Utility from "../Utility"
/**
* @typedef {import("../entity/VectorEntity").default} VectorEntity
*/
/**
* @template T
* @typedef {import("../element/PinElement").default<T>} PinElement
*/
/**
* @template {Number} T
* @extends IInputPinTemplate<T>
* @extends INumericPinTemplate<T>
*/
export default class RealPinTemplate extends IInputPinTemplate {
/** @param {String[]} values */
setInputs(values = [], updateDefaultValue = false) {
if (!values || values.length == 0) {
values = [this.getInput()]
}
let parsedValues = []
for (let i = 0; i < values.length; ++i) {
let num = parseFloat(values[i])
if (isNaN(num)) {
num = 0
updateDefaultValue = false
}
parsedValues.push(num)
}
super.setInputs(values, false)
this.setDefaultValue(parsedValues, values)
}
export default class RealPinTemplate extends INumericPinTemplate {
setDefaultValue(values = [], rawValues = values) {
this.element.setDefaultValue(values[0])

View File

@@ -1,30 +1,12 @@
import { html } from "lit"
import RotatorEntity from "../entity/RotatorEntity"
import IInputPinTemplate from "./IInputPinTemplate"
import RealPinTemplate from "./RealPinTemplate"
import INumericPinTemplate from "./INumericPinTemplate"
import RotatorEntity from "../entity/RotatorEntity"
/** @typedef {import("../entity/RotatorEntity").default} Rotator */
/** @extends IInputPinTemplate<Rotator> */
export default class RotatorPinTemplate extends IInputPinTemplate {
/** @param {String[]} values */
setInputs(values = [], updateDefaultValue = false) {
if (!values || values.length == 0) {
values = [this.getInput()]
}
let parsedValues = []
for (let i = 0; i < values.length; ++i) {
let num = parseFloat(values[i])
if (isNaN(num)) {
num = 0
updateDefaultValue = false
}
parsedValues.push(num)
}
super.setInputs(values, false)
this.setDefaultValue(parsedValues, values)
}
/** @extends INumericPinTemplate<Rotator> */
export default class RotatorPinTemplate extends INumericPinTemplate {
setDefaultValue(values = [], rawValues = values) {
if (!(this.element.entity.DefaultValue instanceof RotatorEntity)) {

View File

@@ -1,4 +1,5 @@
import IInputPinTemplate from "./IInputPinTemplate"
/** @extends IInputPinTemplate<String> */
export default class StringPinTemplate extends IInputPinTemplate {
}

View File

@@ -1,38 +1,22 @@
import { html } from "lit"
import IInputPinTemplate from "./IInputPinTemplate"
import INumericPinTemplate from "./INumericPinTemplate"
import Utility from "../Utility"
import VectorEntity from "../entity/VectorEntity"
/**
* @typedef {import("../element/PinElement").default} PinElement
* @typedef {import("../entity/LinearColorEntity").default} LinearColorEntity
*/
/** @typedef {import("../entity/LinearColorEntity").default} LinearColorEntity */
/**
* @template {VectorEntity} T
* @extends IInputPinTemplate<T>
* @extends INumericPinTemplate<T>
*/
export default class VectorPinTemplate extends IInputPinTemplate {
export default class VectorPinTemplate extends INumericPinTemplate {
/** @param {String[]} values */
setInputs(values = [], updateDefaultValue = false) {
if (!values || values.length == 0) {
values = [this.getInput()]
}
let parsedValues = []
for (let i = 0; i < values.length; ++i) {
let num = parseFloat(values[i])
if (isNaN(num)) {
num = 0
updateDefaultValue = false
}
parsedValues.push(num)
}
super.setInputs(values, false)
this.setDefaultValue(parsedValues, values)
}
setDefaultValue(values = [], rawValues = values) {
/**
* @param {Number[]} values
* @param {String[]} rawValues
*/
setDefaultValue(values, rawValues) {
if (!(this.element.entity.DefaultValue instanceof VectorEntity)) {
throw new TypeError("Expected DefaultValue to be a VectorEntity")
}