Know location fix

This commit is contained in:
barsdeveloper
2023-05-01 14:42:01 +02:00
parent 74a9dd7ca3
commit fff40b7619
11 changed files with 239 additions and 144 deletions

View File

@@ -48,7 +48,7 @@ export default class Configuration {
static hexColorRegex = /^\s*#(?<r>[0-9a-fA-F]{2})(?<g>[0-9a-fA-F]{2})(?<b>[0-9a-fA-F]{2})([0-9a-fA-F]{2})?|#(?<rs>[0-9a-fA-F])(?<gs>[0-9a-fA-F])(?<bs>[0-9a-fA-F])\s*$/
static indentation = " "
static keysSeparator = /[\.\(\)]/
static knotOffset = [-26, -16]
static knotOffset = [-Configuration.gridSize, -0.5 * Configuration.gridSize]
static lineTracePattern = /LineTrace(Single|Multi)(\w*)/
static linkCurveHeight = 15 // px
static linkCurveWidth = 80 // px

View File

@@ -1,21 +1,27 @@
import ComputedType from "./entity/ComputedType.js"
import Configuration from "./Configuration.js"
import MirroredEntity from "./entity/MirroredEntity.js"
import UnionType from "./entity/UnionType.js"
/**
* @typedef {import("./Blueprint.js").default} Blueprint
* @typedef {import("./entity/IEntity.js").AnyValue} AnyValue
* @typedef {import("./entity/IEntity.js").AnyValueConstructor<*>} AnyValueConstructor
* @typedef {import("./entity/IEntity.js").AttributeInformation} TypeInformation
* @typedef {import("./entity/IEntity.js").AttributeInformation} AttributeInformation
* @typedef {import("./entity/IEntity.js").default} IEntity
* @typedef {import("./entity/IEntity.js").EntityConstructor} EntityConstructor
* @typedef {import("./entity/LinearColorEntity.js").default} LinearColorEntity
*/
/**
* @template {AnyValue} T
* @typedef {import("./entity/IEntity.js").AnyValueConstructor<T>} AnyValueConstructor
*/
/**
* @template T
* @typedef {import("./entity/IEntity.js").TypeGetter<T>} TypeGetter
*/
export default class Utility {
static emptyObj = {}
static booleanConverter = {
fromAttribute: (value, type) => {
value ? "true" : "false"
@@ -125,7 +131,7 @@ export default class Utility {
attribute = /** @type {EntityConstructor} */(entity.constructor).attributes?.[key]
) {
if (attribute?.constructor === Object) {
return /** @type {TypeInformation} */(attribute).serialized
return /** @type {AttributeInformation} */(attribute).serialized
}
return false
}
@@ -176,10 +182,7 @@ export default class Utility {
*/
static equals(a, b) {
// Here we cannot check both instanceof IEntity because this would introduce a circular include dependency
if (
/** @type {IEntity?} */(a)?.equals
&& /** @type {IEntity?} */(b)?.equals
) {
if (/** @type {IEntity?} */(a)?.equals && /** @type {IEntity?} */(b)?.equals) {
return /** @type {IEntity} */(a).equals(/** @type {IEntity} */(b))
}
a = Utility.sanitize(a)
@@ -199,8 +202,7 @@ export default class Utility {
}
/**
* @param {null | AnyValue | TypeInformation} value
* @returns {AnyValueConstructor}
* @param {null | AnyValue | AttributeInformation} value
*/
static getType(value) {
if (value === null) {
@@ -209,14 +211,17 @@ export default class Utility {
if (value?.constructor === Object && value?.type instanceof Function) {
return value.type
}
return /** @type {AnyValueConstructor} */(value?.constructor)
return /** @type {AnyValueConstructor<any>} */(value?.constructor)
}
/**
* @param {AnyValue} value
* @param {AnyValueConstructor} type
* @param {AnyValueConstructor<T>} type
*/
static isValueOfType(value, type, acceptNull = false) {
if (type instanceof MirroredEntity) {
type = type.getTargetType()
}
return (acceptNull && value === null) || value instanceof type || value?.constructor === type
}

View File

@@ -1,37 +1,42 @@
import IEntity from "./IEntity.js"
/** @typedef {import("./IEntity.js").EntityConstructor} EntityConstructor */
/**
* @typedef {import("./IEntity.js").default} IEntity
* @typedef {import("./IEntity.js").EntityConstructor} EntityConstructor
*/
export default class MirroredEntity extends IEntity {
export default class MirroredEntity {
static attributes = {
...super.attributes,
type: {
ignored: true,
},
key: {
ignored: true,
},
object: {
getter: {
ignored: true,
},
}
constructor(values = {}) {
super({})
/** @type {EntityConstructor} */ this.type
/** @type {String} */ this.key
/** @type {IEntity} */ this.object
/**
* @param {EntityConstructor} type
* @param {String} key
*/
constructor(type, key, getter = () => null) {
this.type = type
this.key = key
this.getter = getter
}
get() {
return this.object?.[this.key]
return this.getter()
}
set(value) {
if (this.object[this.key]) {
this.object[this.key] = value
getTargetType() {
const result = this.type.attributes[this.key].type
if (result instanceof MirroredEntity) {
return result.getTargetType()
}
return result
}
}

View File

@@ -14,6 +14,7 @@ import KeyBindingEntity from "../entity/KeyBindingEntity.js"
import LinearColorEntity from "../entity/LinearColorEntity.js"
import LocalizedTextEntity from "../entity/LocalizedTextEntity.js"
import MacroGraphReferenceEntity from "../entity/MacroGraphReferenceEntity.js"
import MirroredEntity from "../entity/MirroredEntity.js"
import NaturalNumberEntity from "../entity/NaturalNumberEntity.js"
import ObjectEntity from "../entity/ObjectEntity.js"
import ObjectReferenceEntity from "../entity/ObjectReferenceEntity.js"
@@ -172,6 +173,8 @@ export default class Grammar {
? this.unknownValue
: P.alt(acc, cur)
)
} else if (type instanceof MirroredEntity) {
return this.grammarFor(type.type.attributes[type.key])
} else if (attribute?.constructor === Object) {
result = this.grammarFor(undefined, type)
} else {
@@ -331,8 +334,9 @@ export default class Grammar {
valueSeparator,
).chain(([attributeName, _1]) => {
const attributeKey = attributeName.split(Configuration.keysSeparator)
const attributeValue = this.getAttribute(entityType, attributeKey)
return this
.grammarFor(this.getAttribute(entityType, attributeKey))
.grammarFor(attributeValue)
.map(attributeValue =>
values => Utility.objectSet(values, attributeKey, attributeValue, true)
)
@@ -688,7 +692,6 @@ export default class Grammar {
this.customProperty,
this.createAttributeGrammar(ObjectEntity),
this.inlinedArrayEntry,
// Legacy subobject
this.subObjectEntity
)
)

View File

@@ -13,6 +13,7 @@ import KeyBindingEntity from "../entity/KeyBindingEntity.js"
import LinearColorEntity from "../entity/LinearColorEntity.js"
import LocalizedTextEntity from "../entity/LocalizedTextEntity.js"
import MacroGraphReferenceEntity from "../entity/MacroGraphReferenceEntity.js"
import MirroredEntity from "../entity/MirroredEntity.js"
import ObjectEntity from "../entity/ObjectEntity.js"
import ObjectReferenceEntity from "../entity/ObjectReferenceEntity.js"
import ObjectSerializer from "./ObjectSerializer.js"
@@ -54,7 +55,6 @@ export default function initializeSerializerFactory() {
(array, insideString) =>
`(${array
.map(v =>
// @ts-expect-error
SerializerFactory.getSerializer(Utility.getType(v)).write(v, insideString) + ","
)
.join("")
@@ -104,7 +104,6 @@ export default function initializeSerializerFactory() {
(v, insideString) => {
let result = FormatTextEntity.lookbehind + "("
+ v.value.map(v =>
// @ts-expect-error
SerializerFactory.getSerializer(Utility.getType(v)).write(v, insideString)
).join(", ")
+ ")"
@@ -163,6 +162,11 @@ export default function initializeSerializerFactory() {
new Serializer(MacroGraphReferenceEntity, Serializer.bracketsWrapped)
)
SerializerFactory.registerSerializer(
MirroredEntity,
new Serializer(MirroredEntity)
)
SerializerFactory.registerSerializer(
Number,
new ToStringSerializer(Number)

View File

@@ -57,6 +57,10 @@ export default class BlueprintTemplate extends ITemplate {
/** @type {HTMLElement} */ nodesContainerElement
viewportSize = [0, 0]
#setViewportSize() {
}
/** @param {Blueprint} element */
initialize(element) {
super.initialize(element)
@@ -67,7 +71,13 @@ export default class BlueprintTemplate extends ITemplate {
)?.content.textContent
if (htmlTemplate) {
this.element.requestUpdate()
this.element.updateComplete.then(() => this.getPasteInputObject().pasted(htmlTemplate))
this.element.updateComplete.then(() => {
this.blueprint.mousePosition = [
Math.round(this.viewportSize[0] / 2),
Math.round(this.viewportSize[1] / 2),
]
this.getPasteInputObject().pasted(htmlTemplate)
})
}
}
@@ -252,13 +262,27 @@ export default class BlueprintTemplate extends ITemplate {
centerContentInViewport(smooth = true) {
let avgX = 0
let avgY = 0
let minX = Number.MAX_SAFE_INTEGER
let maxX = Number.MIN_SAFE_INTEGER
let minY = Number.MAX_SAFE_INTEGER
let maxY = Number.MIN_SAFE_INTEGER
const nodes = this.blueprint.getNodes()
for (const node of nodes) {
avgX += node.leftBoundary() + node.rightBoundary()
avgY += node.topBoundary() + node.bottomBoundary()
minX = Math.min(minX, node.leftBoundary())
maxX = Math.max(maxX, node.rightBoundary())
minY = Math.min(minY, node.topBoundary())
maxY = Math.max(maxY, node.bottomBoundary())
}
avgX = nodes.length > 0 ? Math.round(avgX / (2 * nodes.length)) : 0
avgY = nodes.length > 0 ? Math.round(avgY / (2 * nodes.length)) : 0
avgX = Math.round(maxX - minX <= this.viewportSize[0]
? (maxX + minX) / 2
: avgX / (2 * nodes.length)
)
avgY = Math.round(maxY - minY <= this.viewportSize[1]
? (maxY + minY) / 2
: avgY / (2 * nodes.length)
)
this.centerViewport(avgX, avgY, smooth)
}
}

View File

@@ -95,6 +95,7 @@ export default class LinkTemplate extends IFromToPositionedTemplate {
location => {
location[0] += Configuration.knotOffset[0]
location[1] += Configuration.knotOffset[1]
location = Utility.snapToGrid(location[0], location[1], Configuration.gridSize)
this.#createKnot(location)
}
)