mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-02-14 17:14:41 +08:00
Know location fix
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user