mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-02-03 23:55:04 +08:00
Refactoring
This commit is contained in:
0
dist/css/ueblueprint-node-value-type-color.css
vendored
Normal file → Executable file
0
dist/css/ueblueprint-node-value-type-color.css
vendored
Normal file → Executable file
0
dist/css/ueblueprint-node-value-type-color.css.map
vendored
Normal file → Executable file
0
dist/css/ueblueprint-node-value-type-color.css.map
vendored
Normal file → Executable file
0
dist/css/ueblueprint-style.css
vendored
Normal file → Executable file
0
dist/css/ueblueprint-style.css
vendored
Normal file → Executable file
0
dist/css/ueblueprint-style.css.map
vendored
Normal file → Executable file
0
dist/css/ueblueprint-style.css.map
vendored
Normal file → Executable file
0
dist/font/roboto-bold.woff
vendored
Normal file → Executable file
0
dist/font/roboto-bold.woff
vendored
Normal file → Executable file
0
dist/font/roboto-bold.woff2
vendored
Normal file → Executable file
0
dist/font/roboto-bold.woff2
vendored
Normal file → Executable file
0
dist/font/roboto-light.woff
vendored
Normal file → Executable file
0
dist/font/roboto-light.woff
vendored
Normal file → Executable file
0
dist/font/roboto-light.woff2
vendored
Normal file → Executable file
0
dist/font/roboto-light.woff2
vendored
Normal file → Executable file
0
dist/font/roboto-regular.woff
vendored
Normal file → Executable file
0
dist/font/roboto-regular.woff
vendored
Normal file → Executable file
0
dist/font/roboto-regular.woff2
vendored
Normal file → Executable file
0
dist/font/roboto-regular.woff2
vendored
Normal file → Executable file
534
dist/ueblueprint.js
vendored
Normal file → Executable file
534
dist/ueblueprint.js
vendored
Normal file → Executable file
@@ -302,20 +302,30 @@ class FastSelectionModel {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {import("../Blueprint").default} Blueprint
|
||||
* @typedef {import("../entity/Entity").default} Entity
|
||||
* @typedef {import("../input/Context").default} Context
|
||||
* @typedef {import("../template/Template").default} Template
|
||||
*/
|
||||
|
||||
class GraphElement extends HTMLElement {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import("../template/Template").default} template The template to render this node
|
||||
* @param {Entity} entity The entity containing blueprint related data for this graph element
|
||||
* @param {Template} template The template to render this node
|
||||
*/
|
||||
constructor(entity, template) {
|
||||
super();
|
||||
/** @type {import("../Blueprint").default}" */
|
||||
/** @type {Blueprint}" */
|
||||
this.blueprint = null;
|
||||
/** @type {import("../entity/Entity").default}" */
|
||||
/** @type {Entity}" */
|
||||
this.entity = entity;
|
||||
/** @type {import("../template/Template").default}" */
|
||||
/** @type {Template}" */
|
||||
this.template = template;
|
||||
/** @type {Context[]} */
|
||||
this.inputObjects = [];
|
||||
}
|
||||
|
||||
getTemplate() {
|
||||
@@ -325,9 +335,15 @@ class GraphElement extends HTMLElement {
|
||||
connectedCallback() {
|
||||
this.blueprint = this.closest("ueb-blueprint");
|
||||
this.template.apply(this);
|
||||
this.inputObjects = this.createInputObjects();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.inputObjects.forEach(v => v.unlistenDOMElement());
|
||||
}
|
||||
|
||||
createInputObjects() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,6 +585,14 @@ class BlueprintTemplate extends Template {
|
||||
}
|
||||
}
|
||||
|
||||
class Configuration {
|
||||
|
||||
static deleteNodesKeyboardKey = "Delete"
|
||||
static expandGridSize = 400
|
||||
static gridSize = 16
|
||||
static gridSnap = 16
|
||||
}
|
||||
|
||||
class Context {
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
@@ -577,19 +601,19 @@ class Context {
|
||||
/** @type {import("../Blueprint").default}" */
|
||||
this.blueprint = blueprint;
|
||||
this.options = options;
|
||||
let self = this;
|
||||
this.blueprintFocusHandler = _ => self.blueprintFocused();
|
||||
this.blueprintUnfocusHandler = _ => self.blueprintUnfocused();
|
||||
if (options?.wantsFocusCallback ?? false) {
|
||||
let self = this;
|
||||
this.blueprintfocusHandler = _ => self.blueprintFocused();
|
||||
this.blueprintunfocusHandler = _ => self.blueprintUnfocused();
|
||||
this.blueprint.addEventListener("blueprintfocus", this.blueprintfocusHandler);
|
||||
this.blueprint.addEventListener("blueprintunfocus", this.blueprintunfocusHandler);
|
||||
this.blueprint.addEventListener("blueprint-focus", this.blueprintFocusHandler);
|
||||
this.blueprint.addEventListener("blueprint-unfocus", this.blueprintUnfocusHandler);
|
||||
}
|
||||
}
|
||||
|
||||
unlistenDOMElement() {
|
||||
this.blueprintUnfocused();
|
||||
this.blueprint.removeEventListener("blueprintfocus", this.blueprintfocusHandler);
|
||||
this.blueprint.removeEventListener("blueprintunfocus", this.blueprintunfocusHandler);
|
||||
this.blueprint.removeEventListener("blueprint-focus", this.blueprintFocusHandler);
|
||||
this.blueprint.removeEventListener("blueprint-unfocus", this.blueprintUnfocusHandler);
|
||||
}
|
||||
|
||||
|
||||
@@ -883,6 +907,7 @@ class PinReferenceEntity extends Entity {
|
||||
|
||||
class PinEntity$1 extends Entity {
|
||||
|
||||
static lookbehind = "Pin"
|
||||
static attributes = {
|
||||
PinId: GuidEntity,
|
||||
PinName: "",
|
||||
@@ -1099,25 +1124,28 @@ class Grammar {
|
||||
}
|
||||
}
|
||||
// Meta grammar
|
||||
static CreateAttributeGrammar = (r, attributeGrammar, attributeSupplier, valueSeparator = P.string("=").trim(P.optWhitespace)) =>
|
||||
attributeGrammar.skip(valueSeparator)
|
||||
static CreateAttributeGrammar = (r, entityType, valueSeparator = P.string("=").trim(P.optWhitespace)) =>
|
||||
r.AttributeName.skip(valueSeparator)
|
||||
.chain(attributeName => {
|
||||
const attributeKey = attributeName.split(".");
|
||||
const attribute = attributeSupplier(attributeKey);
|
||||
const attribute = Utility.objectGet(entityType.attributes, attributeKey);
|
||||
let attributeValueGrammar = Grammar.getGrammarForType(r, attribute, r.AttributeAnyValue);
|
||||
// Returns attributeSetter: a function called with an object as argument that will set the correct attribute value
|
||||
return attributeValueGrammar.map(attributeValue =>
|
||||
entity => Utility.objectSet(entity, attributeKey, attributeValue, true)
|
||||
) // returns attributeSetter: a function called with an object as argument that will set the correct attribute value
|
||||
)
|
||||
})
|
||||
// Meta grammar
|
||||
static CreateMultiAttributeGrammar = (r, keyGrammar, entityType, attributeSupplier) =>
|
||||
static CreateMultiAttributeGrammar = (r, entityType) =>
|
||||
/**
|
||||
* Basically this creates a parser that looks for a string like 'Key (A=False,B="Something",)'
|
||||
* Then it populates an object of type EntityType with the attribute values found inside the parentheses.
|
||||
*/
|
||||
P.seqMap(
|
||||
P.seq(keyGrammar, P.optWhitespace, P.string("(")),
|
||||
Grammar.CreateAttributeGrammar(r, r.AttributeName, attributeSupplier)
|
||||
entityType.lookbehind
|
||||
? P.seq(P.string(entityType.lookbehind), P.optWhitespace, P.string("("))
|
||||
: P.string("("),
|
||||
Grammar.CreateAttributeGrammar(r, entityType)
|
||||
.trim(P.optWhitespace)
|
||||
.sepBy(P.string(","))
|
||||
.skip(P.regex(/,?/).then(P.optWhitespace)), // Optional trailing comma
|
||||
@@ -1127,18 +1155,8 @@ class Grammar {
|
||||
attributes.forEach(attributeSetter => attributeSetter(result));
|
||||
return result
|
||||
})
|
||||
FunctionReference = r => Grammar.CreateMultiAttributeGrammar(
|
||||
r,
|
||||
P.succeed(),
|
||||
FunctionReferenceEntity,
|
||||
attributeKey => Utility.objectGet(FunctionReferenceEntity.attributes, attributeKey)
|
||||
)
|
||||
Pin = r => Grammar.CreateMultiAttributeGrammar(
|
||||
r,
|
||||
P.string("Pin"),
|
||||
PinEntity$1,
|
||||
attributeKey => Utility.objectGet(PinEntity$1.attributes, attributeKey)
|
||||
)
|
||||
FunctionReference = r => Grammar.CreateMultiAttributeGrammar(r, FunctionReferenceEntity)
|
||||
Pin = r => Grammar.CreateMultiAttributeGrammar(r, PinEntity$1)
|
||||
CustomProperties = r =>
|
||||
P.string("CustomProperties")
|
||||
.then(P.whitespace)
|
||||
@@ -1155,7 +1173,7 @@ class Grammar {
|
||||
P
|
||||
.alt(
|
||||
r.CustomProperties,
|
||||
Grammar.CreateAttributeGrammar(r, r.AttributeName, attributeKey => Utility.objectGet(ObjectEntity.attributes, attributeKey))
|
||||
Grammar.CreateAttributeGrammar(r, ObjectEntity)
|
||||
)
|
||||
.sepBy1(P.whitespace),
|
||||
P.seq(r.WhitespaceNewline, P.string("End"), P.whitespace, P.string("Object")),
|
||||
@@ -1317,15 +1335,15 @@ class Copy extends Context {
|
||||
super(target, blueprint, options);
|
||||
this.serializer = new ObjectSerializer();
|
||||
let self = this;
|
||||
this.copyHandle = _ => self.copied();
|
||||
this.copyHandler = _ => self.copied();
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
document.body.addEventListener("copy", this.copyHandle);
|
||||
document.body.addEventListener("copy", this.copyHandler);
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.body.removeEventListener("copy", this.copyHandle);
|
||||
document.body.removeEventListener("copy", this.copyHandler);
|
||||
}
|
||||
|
||||
copied() {
|
||||
@@ -1476,99 +1494,50 @@ class DragScroll extends MouseClickDrag {
|
||||
}
|
||||
}
|
||||
|
||||
class KeyboardShortcut extends Context {
|
||||
/**
|
||||
* @typedef {import("../graph/GraphLink").default} GraphLink
|
||||
*/
|
||||
class LinkTemplate extends Template {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true;
|
||||
super(target, blueprint, options);
|
||||
|
||||
/** @type {String[]} */
|
||||
this.key = this.options.key;
|
||||
this.ctrlKey = options.ctrlKey ?? false;
|
||||
this.shiftKey = options.shiftKey ?? false;
|
||||
this.altKey = options.altKey ?? false;
|
||||
this.metaKey = options.metaKey ?? false;
|
||||
|
||||
let self = this;
|
||||
this.keyDownHandler = e => {
|
||||
if (
|
||||
e.code == self.key
|
||||
&& e.ctrlKey === self.ctrlKey
|
||||
&& e.shiftKey === self.shiftKey
|
||||
&& e.altKey === self.altKey
|
||||
&& e.metaKey === self.metaKey
|
||||
) {
|
||||
self.fire();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Computes the html content of the target element.
|
||||
* @param {GraphLink} link Link connecting two graph nodes
|
||||
* @returns The result html
|
||||
*/
|
||||
render(link) {
|
||||
return html`
|
||||
<svg viewBox="0 0 100 100">
|
||||
<line x1="0" y1="80" x2="100" y2="20" stroke="black" />
|
||||
</svg>
|
||||
`
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} keyString
|
||||
* @returns {Object}
|
||||
* Applies the style to the element.
|
||||
* @param {GraphLink} link Element of the graph
|
||||
*/
|
||||
static keyOptionsParse(options, keyString) {
|
||||
options.key = keyString;
|
||||
return options
|
||||
}
|
||||
apply(link) {
|
||||
super.apply(link);
|
||||
|
||||
blueprintFocused() {
|
||||
document.addEventListener("keydown", this.keyDownHandler);
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.removeEventListener("keydown", this.keyDownHandler);
|
||||
}
|
||||
|
||||
fire() {
|
||||
}
|
||||
}
|
||||
|
||||
class Configuration {
|
||||
|
||||
static deleteNodesKeyboardKey = "Delete"
|
||||
static expandGridSize = 400
|
||||
static gridSize = 16
|
||||
static gridSnap = 16
|
||||
}
|
||||
|
||||
class KeyvoardCanc extends KeyboardShortcut {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} target
|
||||
* @param {import("../Blueprint").default} blueprint
|
||||
* @param {OBject} options
|
||||
* Applies the style relative to the source pin location.
|
||||
* @param {GraphLink} link Link element
|
||||
*/
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options = KeyboardShortcut.keyOptionsParse(options, Configuration.deleteNodesKeyboardKey);
|
||||
super(target, blueprint, options);
|
||||
applySourceLocation(link, initialPosition) {
|
||||
// Set initial position
|
||||
link.style.setProperty("--ueb-link-from-x", sanitizeText(initialPosition[0]));
|
||||
link.style.setProperty("--ueb-link-from-y", sanitizeText(initialPosition[1]));
|
||||
}
|
||||
|
||||
fire() {
|
||||
this.blueprint.removeGraphElement(...this.blueprint.getNodes(true));
|
||||
}
|
||||
}
|
||||
|
||||
class MouseTracking extends Pointing {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true;
|
||||
super(target, blueprint, options);
|
||||
|
||||
let self = this;
|
||||
this.mousemoveHandler = e => {
|
||||
self.blueprint.entity.mousePosition = self.getLocation(e);
|
||||
};
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
this.target.addEventListener("mousemove", this.mousemoveHandler);
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
this.target.removeEventListener("mousemove", this.mousemoveHandler);
|
||||
/**
|
||||
* Applies the style relative to the destination pin location.
|
||||
* @param {GraphLink} link Link element
|
||||
*/
|
||||
applyDestinationLocation(link, finalPosition) {
|
||||
link.style.setProperty("--ueb-link-to-x", sanitizeText(finalPosition[0]));
|
||||
link.style.setProperty("--ueb-link-to-y", sanitizeText(finalPosition[1]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1631,112 +1600,6 @@ class DragLink extends MouseClickDrag {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {import("../graph/GraphLink").default} GraphLink
|
||||
*/
|
||||
class LinkTemplate extends Template {
|
||||
|
||||
/**
|
||||
* Computes the html content of the target element.
|
||||
* @param {GraphLink} link Link connecting two graph nodes
|
||||
* @returns The result html
|
||||
*/
|
||||
render(link) {
|
||||
return html`
|
||||
<svg viewBox="0 0 100 100">
|
||||
<line x1="0" y1="80" x2="100" y2="20" stroke="black" />
|
||||
</svg>
|
||||
`
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style to the element.
|
||||
* @param {GraphLink} link Element of the graph
|
||||
*/
|
||||
apply(link) {
|
||||
super.apply(link);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style relative to the source pin location.
|
||||
* @param {GraphLink} link Link element
|
||||
*/
|
||||
applySourceLocation(link, initialPosition) {
|
||||
// Set initial position
|
||||
link.style.setProperty("--ueb-link-from-x", sanitizeText(initialPosition[0]));
|
||||
link.style.setProperty("--ueb-link-from-y", sanitizeText(initialPosition[1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style relative to the destination pin location.
|
||||
* @param {GraphLink} link Link element
|
||||
*/
|
||||
applyDestinationLocation(link, finalPosition) {
|
||||
link.style.setProperty("--ueb-link-to-x", sanitizeText(finalPosition[0]));
|
||||
link.style.setProperty("--ueb-link-to-y", sanitizeText(finalPosition[1]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {import("./GraphPin").default} GraphPin
|
||||
*/
|
||||
class GraphLink extends GraphElement {
|
||||
|
||||
/** @type {GraphPin} */
|
||||
#source
|
||||
/** @type {GraphPin} */
|
||||
#destination
|
||||
#nodeDeleteHandler = _ => this.blueprint.removeGraphElement(this)
|
||||
#nodeDragSourceHandler = _ => this.setSourceLocation(this.#source.getLinkLocation())
|
||||
#nodeDragDestinatonHandler = _ => this.setDestinationLocation(this.#destination.getLinkLocation())
|
||||
|
||||
/**
|
||||
* @param {?GraphPin} source
|
||||
* @param {?GraphPin} destination
|
||||
*/
|
||||
constructor(source, destination) {
|
||||
super(this, new LinkTemplate());
|
||||
/** @type {import("../template/LinkTemplate").default} */
|
||||
this.template;
|
||||
this.setSource(source);
|
||||
this.setDestination(destination);
|
||||
}
|
||||
|
||||
setSourceLocation(location) {
|
||||
this.template.applySourceLocation(this.#source.getLinkLocation());
|
||||
}
|
||||
|
||||
setDestinationLocation(location) {
|
||||
this.template.applyDestinationLocation(this.#destination.getLinkLocation());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GraphPin} graphPin
|
||||
*/
|
||||
setSourcePin(graphPin) {
|
||||
this.#source?.removeEventListener("ueb-node-delete", this.#nodeDeleteHandler);
|
||||
this.#source?.removeEventListener("ueb-node-drag", this.#nodeDragSourceHandler);
|
||||
this.#source = graphPin;
|
||||
this.#source?.addEventListener("ueb-node-delete", this.#nodeDeleteHandler);
|
||||
this.#source?.addEventListener("ueb-node-drag", this.#nodeDragSourceHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {GraphPin} graphPin
|
||||
*/
|
||||
setDestinationPin(graphPin) {
|
||||
this.#destination?.removeEventListener("ueb-node-delete", this.#nodeDeleteHandler);
|
||||
this.#destination?.removeEventListener("ueb-node-drag", this.#nodeDragDestinatonHandler);
|
||||
this.#destination = graphPin;
|
||||
this.#destination?.addEventListener("ueb-node-delete", this.#nodeDeleteHandler);
|
||||
this.#destination?.addEventListener("ueb-node-drag", this.#nodeDragDestinatonHandler);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("ueb-link", GraphLink);
|
||||
|
||||
class GraphPin extends GraphElement {
|
||||
|
||||
constructor(entity) {
|
||||
@@ -1747,11 +1610,12 @@ class GraphPin extends GraphElement {
|
||||
this.clickableElement = null;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
new DragLink(this.clickableElement, this.blueprint, {
|
||||
moveEverywhere: true
|
||||
});
|
||||
createInputObjects() {
|
||||
return [
|
||||
new DragLink(this.clickableElement, this.blueprint, {
|
||||
moveEverywhere: true
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1802,6 +1666,65 @@ class GraphPin extends GraphElement {
|
||||
|
||||
customElements.define("ueb-pin", GraphPin);
|
||||
|
||||
/**
|
||||
* @type {import("./GraphPin").default} GraphPin
|
||||
*/
|
||||
class GraphLink extends GraphElement {
|
||||
|
||||
/** @type {GraphPin} */
|
||||
#source
|
||||
/** @type {GraphPin} */
|
||||
#destination
|
||||
#nodeDeleteHandler = _ => this.blueprint.removeGraphElement(this)
|
||||
#nodeDragSourceHandler = _ => this.setSourceLocation(this.#source.getLinkLocation())
|
||||
#nodeDragDestinatonHandler = _ => this.setDestinationLocation(this.#destination.getLinkLocation())
|
||||
|
||||
/**
|
||||
* @param {?GraphPin} source
|
||||
* @param {?GraphPin} destination
|
||||
*/
|
||||
constructor(source, destination) {
|
||||
super(this, new LinkTemplate());
|
||||
/** @type {import("../template/LinkTemplate").default} */
|
||||
this.template;
|
||||
this.setSource(source);
|
||||
this.setDestination(destination);
|
||||
}
|
||||
|
||||
setSourceLocation(location) {
|
||||
this.template.applySourceLocation(this.#source.getLinkLocation());
|
||||
}
|
||||
|
||||
setDestinationLocation(location) {
|
||||
this.template.applyDestinationLocation(this.#destination.getLinkLocation());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GraphPin} graphPin
|
||||
*/
|
||||
setSourcePin(graphPin) {
|
||||
this.#source?.removeEventListener("ueb-node-delete", this.#nodeDeleteHandler);
|
||||
this.#source?.removeEventListener("ueb-node-drag", this.#nodeDragSourceHandler);
|
||||
this.#source = graphPin;
|
||||
this.#source?.addEventListener("ueb-node-delete", this.#nodeDeleteHandler);
|
||||
this.#source?.addEventListener("ueb-node-drag", this.#nodeDragSourceHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {GraphPin} graphPin
|
||||
*/
|
||||
setDestinationPin(graphPin) {
|
||||
this.#destination?.removeEventListener("ueb-node-delete", this.#nodeDeleteHandler);
|
||||
this.#destination?.removeEventListener("ueb-node-drag", this.#nodeDragDestinatonHandler);
|
||||
this.#destination = graphPin;
|
||||
this.#destination?.addEventListener("ueb-node-delete", this.#nodeDeleteHandler);
|
||||
this.#destination?.addEventListener("ueb-node-drag", this.#nodeDragDestinatonHandler);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("ueb-link", GraphLink);
|
||||
|
||||
/**
|
||||
* @typedef {import("../graph/SelectableDraggable").default} SelectableDraggable
|
||||
*/
|
||||
@@ -1956,16 +1879,12 @@ class SelectableDraggable extends GraphElement {
|
||||
};
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.dragObject = new DragMove(this, this.blueprint, {
|
||||
looseTarget: true
|
||||
});
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.dragObject.unlistenDOMElement();
|
||||
createInputObjects() {
|
||||
return [
|
||||
new DragMove(this, this.blueprint, {
|
||||
looseTarget: true
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
setLocation(value = [0, 0]) {
|
||||
@@ -2025,10 +1944,6 @@ class GraphNode extends SelectableDraggable {
|
||||
return new GraphNode(entity)
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.dispatchDeleteEvent();
|
||||
@@ -2065,6 +1980,94 @@ class GraphNode extends SelectableDraggable {
|
||||
|
||||
customElements.define("ueb-node", GraphNode);
|
||||
|
||||
class KeyboardShortcut extends Context {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true;
|
||||
super(target, blueprint, options);
|
||||
|
||||
/** @type {String[]} */
|
||||
this.key = this.options.key;
|
||||
this.ctrlKey = options.ctrlKey ?? false;
|
||||
this.shiftKey = options.shiftKey ?? false;
|
||||
this.altKey = options.altKey ?? false;
|
||||
this.metaKey = options.metaKey ?? false;
|
||||
|
||||
let self = this;
|
||||
this.keyDownHandler = e => {
|
||||
if (
|
||||
e.code == self.key
|
||||
&& e.ctrlKey === self.ctrlKey
|
||||
&& e.shiftKey === self.shiftKey
|
||||
&& e.altKey === self.altKey
|
||||
&& e.metaKey === self.metaKey
|
||||
) {
|
||||
self.fire();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} keyString
|
||||
* @returns {Object}
|
||||
*/
|
||||
static keyOptionsParse(options, keyString) {
|
||||
options.key = keyString;
|
||||
return options
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
document.addEventListener("keydown", this.keyDownHandler);
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.removeEventListener("keydown", this.keyDownHandler);
|
||||
}
|
||||
|
||||
fire() {
|
||||
}
|
||||
}
|
||||
|
||||
class KeyvoardCanc extends KeyboardShortcut {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} target
|
||||
* @param {import("../Blueprint").default} blueprint
|
||||
* @param {OBject} options
|
||||
*/
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options = KeyboardShortcut.keyOptionsParse(options, Configuration.deleteNodesKeyboardKey);
|
||||
super(target, blueprint, options);
|
||||
}
|
||||
|
||||
fire() {
|
||||
this.blueprint.removeGraphElement(...this.blueprint.getNodes(true));
|
||||
}
|
||||
}
|
||||
|
||||
class MouseTracking extends Pointing {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true;
|
||||
super(target, blueprint, options);
|
||||
|
||||
let self = this;
|
||||
this.mousemoveHandler = e => {
|
||||
self.blueprint.entity.mousePosition = self.getLocation(e);
|
||||
};
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
this.target.addEventListener("mousemove", this.mousemoveHandler);
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
this.target.removeEventListener("mousemove", this.mousemoveHandler);
|
||||
}
|
||||
}
|
||||
|
||||
class Paste extends Context {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
@@ -2299,30 +2302,28 @@ class Blueprint extends GraphElement {
|
||||
this.template.applyTranlate(this);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
this.copyObject = new Copy(this.getGridDOMElement(), this);
|
||||
this.pasteObject = new Paste(this.getGridDOMElement(), this);
|
||||
this.cancObject = new KeyvoardCanc(this.getGridDOMElement(), this);
|
||||
|
||||
this.zoomObject = new Zoom(this.getGridDOMElement(), this, {
|
||||
looseTarget: true,
|
||||
});
|
||||
this.selectObject = new Select(this.getGridDOMElement(), this, {
|
||||
clickButton: 0,
|
||||
exitAnyButton: true,
|
||||
moveEverywhere: true,
|
||||
});
|
||||
this.dragObject = new DragScroll(this.getGridDOMElement(), this, {
|
||||
clickButton: 2,
|
||||
exitAnyButton: false,
|
||||
looseTarget: true,
|
||||
moveEverywhere: true,
|
||||
});
|
||||
|
||||
this.unfocusObject = new Unfocus(this.getGridDOMElement(), this);
|
||||
this.mouseTrackingObject = new MouseTracking(this.getGridDOMElement(), this);
|
||||
createInputObjects() {
|
||||
return [
|
||||
new Copy(this.getGridDOMElement(), this),
|
||||
new Paste(this.getGridDOMElement(), this),
|
||||
new KeyvoardCanc(this.getGridDOMElement(), this),
|
||||
new Zoom(this.getGridDOMElement(), this, {
|
||||
looseTarget: true,
|
||||
}),
|
||||
new Select(this.getGridDOMElement(), this, {
|
||||
clickButton: 0,
|
||||
exitAnyButton: true,
|
||||
moveEverywhere: true,
|
||||
}),
|
||||
new DragScroll(this.getGridDOMElement(), this, {
|
||||
clickButton: 2,
|
||||
exitAnyButton: false,
|
||||
looseTarget: true,
|
||||
moveEverywhere: true,
|
||||
}),
|
||||
new Unfocus(this.getGridDOMElement(), this),
|
||||
new MouseTracking(this.getGridDOMElement(), this),
|
||||
]
|
||||
}
|
||||
|
||||
getGridDOMElement() {
|
||||
@@ -2332,9 +2333,6 @@ class Blueprint extends GraphElement {
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
setSelected(false);
|
||||
this.dragObject.unlistenDOMElement();
|
||||
this.selectObject.unlistenDOMElement();
|
||||
this.pasteObject.unlistenDOMElement();
|
||||
}
|
||||
|
||||
getScroll() {
|
||||
@@ -2570,7 +2568,7 @@ class Blueprint extends GraphElement {
|
||||
if (this.focused == value) {
|
||||
return;
|
||||
}
|
||||
let event = new CustomEvent(value ? "blueprintfocus" : "blueprintunfocus");
|
||||
let event = new CustomEvent(value ? "blueprint-focus" : "blueprint-unfocus");
|
||||
this.focused = value;
|
||||
this.dataset.focused = this.focused;
|
||||
if (!this.focused) {
|
||||
|
||||
0
font/roboto-bold.woff
Normal file → Executable file
0
font/roboto-bold.woff
Normal file → Executable file
0
font/roboto-bold.woff2
Normal file → Executable file
0
font/roboto-bold.woff2
Normal file → Executable file
0
font/roboto-light.woff
Normal file → Executable file
0
font/roboto-light.woff
Normal file → Executable file
0
font/roboto-light.woff2
Normal file → Executable file
0
font/roboto-light.woff2
Normal file → Executable file
0
font/roboto-regular.woff
Normal file → Executable file
0
font/roboto-regular.woff
Normal file → Executable file
0
font/roboto-regular.woff2
Normal file → Executable file
0
font/roboto-regular.woff2
Normal file → Executable file
@@ -1,7 +1,10 @@
|
||||
import BlueprintTemplate from "./template/BlueprintTemplate"
|
||||
import Configuration from "./Configuration"
|
||||
import Copy from "./input/Copy"
|
||||
import DragScroll from "./input/DragScroll"
|
||||
import GraphElement from "./graph/GraphElement"
|
||||
import GraphLink from "./graph/GraphLink"
|
||||
import GraphNode from "./graph/GraphNode"
|
||||
import GraphSelector from "./graph/GraphSelector"
|
||||
import KeyboardCanc from "./input/KeyboardCanc"
|
||||
import MouseTracking from "./input/MouseTracking"
|
||||
@@ -10,9 +13,6 @@ import Select from "./input/Select"
|
||||
import Unfocus from "./input/Unfocus"
|
||||
import Utility from "./Utility"
|
||||
import Zoom from "./input/Zoom"
|
||||
import GraphNode from "./graph/GraphNode"
|
||||
import GraphLink from "./graph/GraphLink"
|
||||
import Configuration from "./Configuration"
|
||||
|
||||
export default class Blueprint extends GraphElement {
|
||||
|
||||
@@ -93,30 +93,28 @@ export default class Blueprint extends GraphElement {
|
||||
this.template.applyTranlate(this)
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback()
|
||||
|
||||
this.copyObject = new Copy(this.getGridDOMElement(), this)
|
||||
this.pasteObject = new Paste(this.getGridDOMElement(), this)
|
||||
this.cancObject = new KeyboardCanc(this.getGridDOMElement(), this)
|
||||
|
||||
this.zoomObject = new Zoom(this.getGridDOMElement(), this, {
|
||||
looseTarget: true,
|
||||
})
|
||||
this.selectObject = new Select(this.getGridDOMElement(), this, {
|
||||
clickButton: 0,
|
||||
exitAnyButton: true,
|
||||
moveEverywhere: true,
|
||||
})
|
||||
this.dragObject = new DragScroll(this.getGridDOMElement(), this, {
|
||||
clickButton: 2,
|
||||
exitAnyButton: false,
|
||||
looseTarget: true,
|
||||
moveEverywhere: true,
|
||||
})
|
||||
|
||||
this.unfocusObject = new Unfocus(this.getGridDOMElement(), this)
|
||||
this.mouseTrackingObject = new MouseTracking(this.getGridDOMElement(), this)
|
||||
createInputObjects() {
|
||||
return [
|
||||
new Copy(this.getGridDOMElement(), this),
|
||||
new Paste(this.getGridDOMElement(), this),
|
||||
new KeyboardCanc(this.getGridDOMElement(), this),
|
||||
new Zoom(this.getGridDOMElement(), this, {
|
||||
looseTarget: true,
|
||||
}),
|
||||
new Select(this.getGridDOMElement(), this, {
|
||||
clickButton: 0,
|
||||
exitAnyButton: true,
|
||||
moveEverywhere: true,
|
||||
}),
|
||||
new DragScroll(this.getGridDOMElement(), this, {
|
||||
clickButton: 2,
|
||||
exitAnyButton: false,
|
||||
looseTarget: true,
|
||||
moveEverywhere: true,
|
||||
}),
|
||||
new Unfocus(this.getGridDOMElement(), this),
|
||||
new MouseTracking(this.getGridDOMElement(), this),
|
||||
]
|
||||
}
|
||||
|
||||
getGridDOMElement() {
|
||||
@@ -126,9 +124,6 @@ export default class Blueprint extends GraphElement {
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback()
|
||||
setSelected(false)
|
||||
this.dragObject.unlistenDOMElement()
|
||||
this.selectObject.unlistenDOMElement()
|
||||
this.pasteObject.unlistenDOMElement()
|
||||
}
|
||||
|
||||
getScroll() {
|
||||
@@ -364,7 +359,7 @@ export default class Blueprint extends GraphElement {
|
||||
if (this.focused == value) {
|
||||
return;
|
||||
}
|
||||
let event = new CustomEvent(value ? "blueprintfocus" : "blueprintunfocus")
|
||||
let event = new CustomEvent(value ? "blueprint-focus" : "blueprint-unfocus")
|
||||
this.focused = value
|
||||
this.dataset.focused = this.focused
|
||||
if (!this.focused) {
|
||||
|
||||
14
js/Configuration.js
Normal file → Executable file
14
js/Configuration.js
Normal file → Executable file
@@ -1,7 +1,7 @@
|
||||
export default class Configuration {
|
||||
|
||||
static deleteNodesKeyboardKey = "Delete"
|
||||
static expandGridSize = 400
|
||||
static gridSize = 16
|
||||
static gridSnap = 16
|
||||
}
|
||||
export default class Configuration {
|
||||
|
||||
static deleteNodesKeyboardKey = "Delete"
|
||||
static expandGridSize = 400
|
||||
static gridSize = 16
|
||||
static gridSnap = 16
|
||||
}
|
||||
|
||||
14
js/action/Actions.js
Normal file → Executable file
14
js/action/Actions.js
Normal file → Executable file
@@ -1,8 +1,8 @@
|
||||
export default class Action {
|
||||
|
||||
apply() {
|
||||
}
|
||||
|
||||
revert() {
|
||||
}
|
||||
export default class Action {
|
||||
|
||||
apply() {
|
||||
}
|
||||
|
||||
revert() {
|
||||
}
|
||||
}
|
||||
16
js/entity/KeyBinding.js
Executable file
16
js/entity/KeyBinding.js
Executable file
@@ -0,0 +1,16 @@
|
||||
import Entity from "./Entity"
|
||||
|
||||
export default class KeyBinding extends Entity {
|
||||
|
||||
static attributes = {
|
||||
bCtrlDown: false,
|
||||
bAltDown: false,
|
||||
bShiftDown: false,
|
||||
Key: String,
|
||||
CommandName: String,
|
||||
}
|
||||
|
||||
getAttributes() {
|
||||
return KeyBinding.attributes
|
||||
}
|
||||
}
|
||||
32
js/entity/PathSymbolEntity.js
Normal file → Executable file
32
js/entity/PathSymbolEntity.js
Normal file → Executable file
@@ -1,16 +1,16 @@
|
||||
import Entity from "./Entity"
|
||||
|
||||
export default class PathSymbolEntity extends Entity {
|
||||
|
||||
static attributes = {
|
||||
value: String
|
||||
}
|
||||
|
||||
getAttributes() {
|
||||
return PathSymbolEntity.attributes
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.value
|
||||
}
|
||||
}
|
||||
import Entity from "./Entity"
|
||||
|
||||
export default class PathSymbolEntity extends Entity {
|
||||
|
||||
static attributes = {
|
||||
value: String
|
||||
}
|
||||
|
||||
getAttributes() {
|
||||
return PathSymbolEntity.attributes
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import TypeInitialization from "./TypeInitialization"
|
||||
|
||||
export default class PinEntity extends Entity {
|
||||
|
||||
static lookbehind = "Pin"
|
||||
static attributes = {
|
||||
PinId: GuidEntity,
|
||||
PinName: "",
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
/**
|
||||
* @typedef {import("../Blueprint").default} Blueprint
|
||||
* @typedef {import("../entity/Entity").default} Entity
|
||||
* @typedef {import("../input/Context").default} Context
|
||||
* @typedef {import("../template/Template").default} Template
|
||||
*/
|
||||
|
||||
export default class GraphElement extends HTMLElement {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import("../template/Template").default} template The template to render this node
|
||||
* @param {Entity} entity The entity containing blueprint related data for this graph element
|
||||
* @param {Template} template The template to render this node
|
||||
*/
|
||||
constructor(entity, template) {
|
||||
super()
|
||||
/** @type {import("../Blueprint").default}" */
|
||||
/** @type {Blueprint}" */
|
||||
this.blueprint = null
|
||||
/** @type {import("../entity/Entity").default}" */
|
||||
/** @type {Entity}" */
|
||||
this.entity = entity
|
||||
/** @type {import("../template/Template").default}" */
|
||||
/** @type {Template}" */
|
||||
this.template = template
|
||||
/** @type {Context[]} */
|
||||
this.inputObjects = []
|
||||
}
|
||||
|
||||
getTemplate() {
|
||||
@@ -21,8 +31,14 @@ export default class GraphElement extends HTMLElement {
|
||||
connectedCallback() {
|
||||
this.blueprint = this.closest("ueb-blueprint")
|
||||
this.template.apply(this)
|
||||
this.inputObjects = this.createInputObjects()
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.inputObjects.forEach(v => v.unlistenDOMElement())
|
||||
}
|
||||
|
||||
createInputObjects() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ export default class GraphLink extends GraphElement {
|
||||
#nodeDragDestinatonHandler = _ => this.setDestinationLocation(this.#destination.getLinkLocation())
|
||||
|
||||
/**
|
||||
* @param {?GraphPin} source
|
||||
* @param {?GraphPin} destination
|
||||
* @param {?GraphPin} source
|
||||
* @param {?GraphPin} destination
|
||||
*/
|
||||
constructor(source, destination) {
|
||||
super(this, new LinkTemplate())
|
||||
|
||||
@@ -23,10 +23,6 @@ export default class GraphNode extends SelectableDraggable {
|
||||
return new GraphNode(entity)
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback()
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback()
|
||||
this.dispatchDeleteEvent()
|
||||
|
||||
139
js/graph/GraphPin.js
Normal file → Executable file
139
js/graph/GraphPin.js
Normal file → Executable file
@@ -1,69 +1,70 @@
|
||||
import GraphElement from "./GraphElement"
|
||||
import PinTemplate from "../template/PinTemplate"
|
||||
import DragLink from "../input/DragLink"
|
||||
import GraphLink from "./GraphLink"
|
||||
|
||||
export default class GraphPin extends GraphElement {
|
||||
|
||||
constructor(entity) {
|
||||
super(entity, new PinTemplate())
|
||||
/** @type {import("../entity/PinEntity").default} */
|
||||
this.entity
|
||||
/** @type {HTMLElement} */
|
||||
this.clickableElement = null
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback()
|
||||
new DragLink(this.clickableElement, this.blueprint, {
|
||||
moveEverywhere: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {String}
|
||||
*/
|
||||
getPinDisplayName() {
|
||||
return this.entity.PinName
|
||||
}
|
||||
|
||||
getAttributes() {
|
||||
return PinEntity.attributes
|
||||
}
|
||||
|
||||
isInput() {
|
||||
return this.entity.isInput()
|
||||
}
|
||||
|
||||
isOutput() {
|
||||
return this.entity.isOutput()
|
||||
}
|
||||
|
||||
isConnected() {
|
||||
return this.entity.isConnected()
|
||||
}
|
||||
|
||||
getType() {
|
||||
return this.entity.getType()
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {GraphLink} The link created
|
||||
*/
|
||||
dragLink() {
|
||||
let link = new GraphLink(this)
|
||||
return link
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns The exact location where the link originates from or arrives at.
|
||||
* @returns {Number[]} The location array
|
||||
*/
|
||||
getLinkLocation() {
|
||||
return [0, 0];
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("ueb-pin", GraphPin)
|
||||
import GraphElement from "./GraphElement"
|
||||
import PinTemplate from "../template/PinTemplate"
|
||||
import DragLink from "../input/DragLink"
|
||||
import GraphLink from "./GraphLink"
|
||||
|
||||
export default class GraphPin extends GraphElement {
|
||||
|
||||
constructor(entity) {
|
||||
super(entity, new PinTemplate())
|
||||
/** @type {import("../entity/PinEntity").default} */
|
||||
this.entity
|
||||
/** @type {HTMLElement} */
|
||||
this.clickableElement = null
|
||||
}
|
||||
|
||||
createInputObjects() {
|
||||
return [
|
||||
new DragLink(this.clickableElement, this.blueprint, {
|
||||
moveEverywhere: true
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {String}
|
||||
*/
|
||||
getPinDisplayName() {
|
||||
return this.entity.PinName
|
||||
}
|
||||
|
||||
getAttributes() {
|
||||
return PinEntity.attributes
|
||||
}
|
||||
|
||||
isInput() {
|
||||
return this.entity.isInput()
|
||||
}
|
||||
|
||||
isOutput() {
|
||||
return this.entity.isOutput()
|
||||
}
|
||||
|
||||
isConnected() {
|
||||
return this.entity.isConnected()
|
||||
}
|
||||
|
||||
getType() {
|
||||
return this.entity.getType()
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {GraphLink} The link created
|
||||
*/
|
||||
dragLink() {
|
||||
let link = new GraphLink(this)
|
||||
return link
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns The exact location where the link originates from or arrives at.
|
||||
* @returns {Number[]} The location array
|
||||
*/
|
||||
getLinkLocation() {
|
||||
return [0, 0];
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("ueb-pin", GraphPin)
|
||||
|
||||
@@ -17,16 +17,12 @@ export default class SelectableDraggable extends GraphElement {
|
||||
}
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback()
|
||||
this.dragObject = new DragMove(this, this.blueprint, {
|
||||
looseTarget: true
|
||||
})
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback()
|
||||
this.dragObject.unlistenDOMElement()
|
||||
createInputObjects() {
|
||||
return [
|
||||
new DragMove(this, this.blueprint, {
|
||||
looseTarget: true
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
setLocation(value = [0, 0]) {
|
||||
|
||||
62
js/input/Context.js
Normal file → Executable file
62
js/input/Context.js
Normal file → Executable file
@@ -1,31 +1,31 @@
|
||||
export default class Context {
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
/** @type {HTMLElement} */
|
||||
this.target = target
|
||||
/** @type {import("../Blueprint").default}" */
|
||||
this.blueprint = blueprint
|
||||
this.options = options
|
||||
if (options?.wantsFocusCallback ?? false) {
|
||||
let self = this
|
||||
this.blueprintfocusHandler = _ => self.blueprintFocused()
|
||||
this.blueprintunfocusHandler = _ => self.blueprintUnfocused()
|
||||
this.blueprint.addEventListener("blueprintfocus", this.blueprintfocusHandler)
|
||||
this.blueprint.addEventListener("blueprintunfocus", this.blueprintunfocusHandler)
|
||||
}
|
||||
}
|
||||
|
||||
unlistenDOMElement() {
|
||||
this.blueprintUnfocused()
|
||||
this.blueprint.removeEventListener("blueprintfocus", this.blueprintfocusHandler)
|
||||
this.blueprint.removeEventListener("blueprintunfocus", this.blueprintunfocusHandler)
|
||||
}
|
||||
|
||||
|
||||
/* Subclasses will probabily override the following methods */
|
||||
blueprintFocused() {
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
}
|
||||
}
|
||||
export default class Context {
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
/** @type {HTMLElement} */
|
||||
this.target = target
|
||||
/** @type {import("../Blueprint").default}" */
|
||||
this.blueprint = blueprint
|
||||
this.options = options
|
||||
let self = this
|
||||
this.blueprintFocusHandler = _ => self.blueprintFocused()
|
||||
this.blueprintUnfocusHandler = _ => self.blueprintUnfocused()
|
||||
if (options?.wantsFocusCallback ?? false) {
|
||||
this.blueprint.addEventListener("blueprint-focus", this.blueprintFocusHandler)
|
||||
this.blueprint.addEventListener("blueprint-unfocus", this.blueprintUnfocusHandler)
|
||||
}
|
||||
}
|
||||
|
||||
unlistenDOMElement() {
|
||||
this.blueprintUnfocused()
|
||||
this.blueprint.removeEventListener("blueprint-focus", this.blueprintFocusHandler)
|
||||
this.blueprint.removeEventListener("blueprint-unfocus", this.blueprintUnfocusHandler)
|
||||
}
|
||||
|
||||
|
||||
/* Subclasses will probabily override the following methods */
|
||||
blueprintFocused() {
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
}
|
||||
}
|
||||
|
||||
52
js/input/Copy.js
Normal file → Executable file
52
js/input/Copy.js
Normal file → Executable file
@@ -1,26 +1,26 @@
|
||||
import Context from "./Context"
|
||||
import ObjectSerializer from "../serialization/ObjectSerializer"
|
||||
|
||||
export default class Copy extends Context {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true
|
||||
super(target, blueprint, options)
|
||||
this.serializer = new ObjectSerializer()
|
||||
let self = this
|
||||
this.copyHandle = _ => self.copied()
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
document.body.addEventListener("copy", this.copyHandle)
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.body.removeEventListener("copy", this.copyHandle)
|
||||
}
|
||||
|
||||
copied() {
|
||||
const value = this.blueprint.getNodes(true).map(node => this.serializer.write(node.entity)).join("\n")
|
||||
navigator.clipboard.writeText(value)
|
||||
}
|
||||
}
|
||||
import Context from "./Context"
|
||||
import ObjectSerializer from "../serialization/ObjectSerializer"
|
||||
|
||||
export default class Copy extends Context {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true
|
||||
super(target, blueprint, options)
|
||||
this.serializer = new ObjectSerializer()
|
||||
let self = this
|
||||
this.copyHandler = _ => self.copied()
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
document.body.addEventListener("copy", this.copyHandler)
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.body.removeEventListener("copy", this.copyHandler)
|
||||
}
|
||||
|
||||
copied() {
|
||||
const value = this.blueprint.getNodes(true).map(node => this.serializer.write(node.entity)).join("\n")
|
||||
navigator.clipboard.writeText(value)
|
||||
}
|
||||
}
|
||||
|
||||
40
js/input/KeyboardCanc.js
Normal file → Executable file
40
js/input/KeyboardCanc.js
Normal file → Executable file
@@ -1,21 +1,21 @@
|
||||
import KeyboardShortcut from "./KeyboardShortcut"
|
||||
import Configuration from "../Configuration"
|
||||
|
||||
|
||||
export default class KeyvoardCanc extends KeyboardShortcut {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} target
|
||||
* @param {import("../Blueprint").default} blueprint
|
||||
* @param {OBject} options
|
||||
*/
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options = KeyboardShortcut.keyOptionsParse(options, Configuration.deleteNodesKeyboardKey)
|
||||
super(target, blueprint, options)
|
||||
}
|
||||
|
||||
fire() {
|
||||
this.blueprint.removeGraphElement(...this.blueprint.getNodes(true))
|
||||
}
|
||||
import KeyboardShortcut from "./KeyboardShortcut"
|
||||
import Configuration from "../Configuration"
|
||||
|
||||
|
||||
export default class KeyvoardCanc extends KeyboardShortcut {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} target
|
||||
* @param {import("../Blueprint").default} blueprint
|
||||
* @param {OBject} options
|
||||
*/
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options = KeyboardShortcut.keyOptionsParse(options, Configuration.deleteNodesKeyboardKey)
|
||||
super(target, blueprint, options)
|
||||
}
|
||||
|
||||
fire() {
|
||||
this.blueprint.removeGraphElement(...this.blueprint.getNodes(true))
|
||||
}
|
||||
}
|
||||
100
js/input/KeyboardShortcut.js
Normal file → Executable file
100
js/input/KeyboardShortcut.js
Normal file → Executable file
@@ -1,50 +1,50 @@
|
||||
import Context from "./Context"
|
||||
|
||||
export default class KeyboardShortcut extends Context {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true
|
||||
super(target, blueprint, options)
|
||||
|
||||
/** @type {String[]} */
|
||||
this.key = this.options.key
|
||||
this.ctrlKey = options.ctrlKey ?? false
|
||||
this.shiftKey = options.shiftKey ?? false
|
||||
this.altKey = options.altKey ?? false
|
||||
this.metaKey = options.metaKey ?? false
|
||||
|
||||
let self = this
|
||||
this.keyDownHandler = e => {
|
||||
if (
|
||||
e.code == self.key
|
||||
&& e.ctrlKey === self.ctrlKey
|
||||
&& e.shiftKey === self.shiftKey
|
||||
&& e.altKey === self.altKey
|
||||
&& e.metaKey === self.metaKey
|
||||
) {
|
||||
self.fire()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} keyString
|
||||
* @returns {Object}
|
||||
*/
|
||||
static keyOptionsParse(options, keyString) {
|
||||
options.key = keyString
|
||||
return options
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
document.addEventListener("keydown", this.keyDownHandler)
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.removeEventListener("keydown", this.keyDownHandler)
|
||||
}
|
||||
|
||||
fire() {
|
||||
}
|
||||
}
|
||||
import Context from "./Context"
|
||||
|
||||
export default class KeyboardShortcut extends Context {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true
|
||||
super(target, blueprint, options)
|
||||
|
||||
/** @type {String[]} */
|
||||
this.key = this.options.key
|
||||
this.ctrlKey = options.ctrlKey ?? false
|
||||
this.shiftKey = options.shiftKey ?? false
|
||||
this.altKey = options.altKey ?? false
|
||||
this.metaKey = options.metaKey ?? false
|
||||
|
||||
let self = this
|
||||
this.keyDownHandler = e => {
|
||||
if (
|
||||
e.code == self.key
|
||||
&& e.ctrlKey === self.ctrlKey
|
||||
&& e.shiftKey === self.shiftKey
|
||||
&& e.altKey === self.altKey
|
||||
&& e.metaKey === self.metaKey
|
||||
) {
|
||||
self.fire()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} keyString
|
||||
* @returns {Object}
|
||||
*/
|
||||
static keyOptionsParse(options, keyString) {
|
||||
options.key = keyString
|
||||
return options
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
document.addEventListener("keydown", this.keyDownHandler)
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.removeEventListener("keydown", this.keyDownHandler)
|
||||
}
|
||||
|
||||
fire() {
|
||||
}
|
||||
}
|
||||
|
||||
44
js/input/MouseTracking.js
Normal file → Executable file
44
js/input/MouseTracking.js
Normal file → Executable file
@@ -1,22 +1,22 @@
|
||||
import Pointing from "./Pointing"
|
||||
|
||||
export default class MouseTracking extends Pointing {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true
|
||||
super(target, blueprint, options)
|
||||
|
||||
let self = this
|
||||
this.mousemoveHandler = e => {
|
||||
self.blueprint.entity.mousePosition = self.getLocation(e)
|
||||
}
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
this.target.addEventListener("mousemove", this.mousemoveHandler)
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
this.target.removeEventListener("mousemove", this.mousemoveHandler)
|
||||
}
|
||||
}
|
||||
import Pointing from "./Pointing"
|
||||
|
||||
export default class MouseTracking extends Pointing {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true
|
||||
super(target, blueprint, options)
|
||||
|
||||
let self = this
|
||||
this.mousemoveHandler = e => {
|
||||
self.blueprint.entity.mousePosition = self.getLocation(e)
|
||||
}
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
this.target.addEventListener("mousemove", this.mousemoveHandler)
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
this.target.removeEventListener("mousemove", this.mousemoveHandler)
|
||||
}
|
||||
}
|
||||
|
||||
100
js/input/Paste.js
Normal file → Executable file
100
js/input/Paste.js
Normal file → Executable file
@@ -1,50 +1,50 @@
|
||||
import GraphNode from "../graph/GraphNode"
|
||||
import ObjectSerializer from "../serialization/ObjectSerializer"
|
||||
import Context from "./Context"
|
||||
|
||||
export default class Paste extends Context {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true
|
||||
super(target, blueprint, options)
|
||||
this.serializer = new ObjectSerializer()
|
||||
let self = this
|
||||
this.pasteHandle = e => self.pasted(e.clipboardData.getData("Text"))
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
document.body.addEventListener("paste", this.pasteHandle)
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.body.removeEventListener("paste", this.pasteHandle)
|
||||
}
|
||||
|
||||
pasted(value) {
|
||||
let top = 0
|
||||
let left = 0
|
||||
let count = 0
|
||||
let nodes = this.serializer.readMultiple(value).map(entity => {
|
||||
let node = new GraphNode(entity)
|
||||
top += node.location[1]
|
||||
left += node.location[0]
|
||||
++count
|
||||
return node
|
||||
})
|
||||
top /= count
|
||||
left /= count
|
||||
if (nodes.length > 0) {
|
||||
this.blueprint.unselectAll()
|
||||
}
|
||||
let mousePosition = this.blueprint.entity.mousePosition
|
||||
this.blueprint.addGraphElement(...nodes)
|
||||
nodes.forEach(node => {
|
||||
const locationOffset = [
|
||||
mousePosition[0] - left,
|
||||
mousePosition[1] - top,
|
||||
]
|
||||
node.addLocation(this.blueprint.compensateTranslation(locationOffset))
|
||||
node.setSelected(true)
|
||||
})
|
||||
}
|
||||
}
|
||||
import GraphNode from "../graph/GraphNode"
|
||||
import ObjectSerializer from "../serialization/ObjectSerializer"
|
||||
import Context from "./Context"
|
||||
|
||||
export default class Paste extends Context {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true
|
||||
super(target, blueprint, options)
|
||||
this.serializer = new ObjectSerializer()
|
||||
let self = this
|
||||
this.pasteHandle = e => self.pasted(e.clipboardData.getData("Text"))
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
document.body.addEventListener("paste", this.pasteHandle)
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.body.removeEventListener("paste", this.pasteHandle)
|
||||
}
|
||||
|
||||
pasted(value) {
|
||||
let top = 0
|
||||
let left = 0
|
||||
let count = 0
|
||||
let nodes = this.serializer.readMultiple(value).map(entity => {
|
||||
let node = new GraphNode(entity)
|
||||
top += node.location[1]
|
||||
left += node.location[0]
|
||||
++count
|
||||
return node
|
||||
})
|
||||
top /= count
|
||||
left /= count
|
||||
if (nodes.length > 0) {
|
||||
this.blueprint.unselectAll()
|
||||
}
|
||||
let mousePosition = this.blueprint.entity.mousePosition
|
||||
this.blueprint.addGraphElement(...nodes)
|
||||
nodes.forEach(node => {
|
||||
const locationOffset = [
|
||||
mousePosition[0] - left,
|
||||
mousePosition[1] - top,
|
||||
]
|
||||
node.addLocation(this.blueprint.compensateTranslation(locationOffset))
|
||||
node.setSelected(true)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
70
js/input/Unfocus.js
Normal file → Executable file
70
js/input/Unfocus.js
Normal file → Executable file
@@ -1,35 +1,35 @@
|
||||
import Context from "./Context"
|
||||
|
||||
export default class Unfocus extends Context {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true
|
||||
super(target, blueprint, options)
|
||||
|
||||
let self = this
|
||||
this.clickHandler = e => self.clickedSomewhere(e)
|
||||
if (this.blueprint.focuse) {
|
||||
document.addEventListener("click", this.clickHandler)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
clickedSomewhere(e) {
|
||||
// If target is inside the blueprint grid
|
||||
if (e.target.closest("ueb-blueprint")) {
|
||||
return
|
||||
}
|
||||
this.blueprint.setFocused(false)
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
document.addEventListener("click", this.clickHandler)
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.removeEventListener("click", this.clickHandler)
|
||||
}
|
||||
}
|
||||
import Context from "./Context"
|
||||
|
||||
export default class Unfocus extends Context {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true
|
||||
super(target, blueprint, options)
|
||||
|
||||
let self = this
|
||||
this.clickHandler = e => self.clickedSomewhere(e)
|
||||
if (this.blueprint.focuse) {
|
||||
document.addEventListener("click", this.clickHandler)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
clickedSomewhere(e) {
|
||||
// If target is inside the blueprint grid
|
||||
if (e.target.closest("ueb-blueprint")) {
|
||||
return
|
||||
}
|
||||
this.blueprint.setFocused(false)
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
document.addEventListener("click", this.clickHandler)
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.removeEventListener("click", this.clickHandler)
|
||||
}
|
||||
}
|
||||
|
||||
28
js/serialization/CustomSerializer.js
Normal file → Executable file
28
js/serialization/CustomSerializer.js
Normal file → Executable file
@@ -1,14 +1,14 @@
|
||||
import GeneralSerializer from "./GeneralSerializer"
|
||||
|
||||
export default class CustomSerializer extends GeneralSerializer {
|
||||
|
||||
constructor(objectWriter, entityType) {
|
||||
super(undefined, entityType)
|
||||
this.objectWriter = objectWriter
|
||||
}
|
||||
|
||||
write(object) {
|
||||
let result = this.objectWriter(object)
|
||||
return result
|
||||
}
|
||||
}
|
||||
import GeneralSerializer from "./GeneralSerializer"
|
||||
|
||||
export default class CustomSerializer extends GeneralSerializer {
|
||||
|
||||
constructor(objectWriter, entityType) {
|
||||
super(undefined, entityType)
|
||||
this.objectWriter = objectWriter
|
||||
}
|
||||
|
||||
write(object) {
|
||||
let result = this.objectWriter(object)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,25 +113,28 @@ export default class Grammar {
|
||||
}
|
||||
}
|
||||
// Meta grammar
|
||||
static CreateAttributeGrammar = (r, attributeGrammar, attributeSupplier, valueSeparator = P.string("=").trim(P.optWhitespace)) =>
|
||||
attributeGrammar.skip(valueSeparator)
|
||||
static CreateAttributeGrammar = (r, entityType, valueSeparator = P.string("=").trim(P.optWhitespace)) =>
|
||||
r.AttributeName.skip(valueSeparator)
|
||||
.chain(attributeName => {
|
||||
const attributeKey = attributeName.split(".")
|
||||
const attribute = attributeSupplier(attributeKey)
|
||||
const attribute = Utility.objectGet(entityType.attributes, attributeKey)
|
||||
let attributeValueGrammar = Grammar.getGrammarForType(r, attribute, r.AttributeAnyValue)
|
||||
// Returns attributeSetter: a function called with an object as argument that will set the correct attribute value
|
||||
return attributeValueGrammar.map(attributeValue =>
|
||||
entity => Utility.objectSet(entity, attributeKey, attributeValue, true)
|
||||
) // returns attributeSetter: a function called with an object as argument that will set the correct attribute value
|
||||
)
|
||||
})
|
||||
// Meta grammar
|
||||
static CreateMultiAttributeGrammar = (r, keyGrammar, entityType, attributeSupplier) =>
|
||||
static CreateMultiAttributeGrammar = (r, entityType) =>
|
||||
/**
|
||||
* Basically this creates a parser that looks for a string like 'Key (A=False,B="Something",)'
|
||||
* Then it populates an object of type EntityType with the attribute values found inside the parentheses.
|
||||
*/
|
||||
P.seqMap(
|
||||
P.seq(keyGrammar, P.optWhitespace, P.string("(")),
|
||||
Grammar.CreateAttributeGrammar(r, r.AttributeName, attributeSupplier)
|
||||
entityType.lookbehind
|
||||
? P.seq(P.string(entityType.lookbehind), P.optWhitespace, P.string("("))
|
||||
: P.string("("),
|
||||
Grammar.CreateAttributeGrammar(r, entityType)
|
||||
.trim(P.optWhitespace)
|
||||
.sepBy(P.string(","))
|
||||
.skip(P.regex(/,?/).then(P.optWhitespace)), // Optional trailing comma
|
||||
@@ -141,18 +144,8 @@ export default class Grammar {
|
||||
attributes.forEach(attributeSetter => attributeSetter(result))
|
||||
return result
|
||||
})
|
||||
FunctionReference = r => Grammar.CreateMultiAttributeGrammar(
|
||||
r,
|
||||
P.succeed(),
|
||||
FunctionReferenceEntity,
|
||||
attributeKey => Utility.objectGet(FunctionReferenceEntity.attributes, attributeKey)
|
||||
)
|
||||
Pin = r => Grammar.CreateMultiAttributeGrammar(
|
||||
r,
|
||||
P.string("Pin"),
|
||||
PinEntity,
|
||||
attributeKey => Utility.objectGet(PinEntity.attributes, attributeKey)
|
||||
)
|
||||
FunctionReference = r => Grammar.CreateMultiAttributeGrammar(r, FunctionReferenceEntity)
|
||||
Pin = r => Grammar.CreateMultiAttributeGrammar(r, PinEntity)
|
||||
CustomProperties = r =>
|
||||
P.string("CustomProperties")
|
||||
.then(P.whitespace)
|
||||
@@ -169,7 +162,7 @@ export default class Grammar {
|
||||
P
|
||||
.alt(
|
||||
r.CustomProperties,
|
||||
Grammar.CreateAttributeGrammar(r, r.AttributeName, attributeKey => Utility.objectGet(ObjectEntity.attributes, attributeKey))
|
||||
Grammar.CreateAttributeGrammar(r, ObjectEntity)
|
||||
)
|
||||
.sepBy1(P.whitespace),
|
||||
P.seq(r.WhitespaceNewline, P.string("End"), P.whitespace, P.string("Object")),
|
||||
|
||||
26
js/serialization/ToStringSerializer.js
Normal file → Executable file
26
js/serialization/ToStringSerializer.js
Normal file → Executable file
@@ -1,13 +1,13 @@
|
||||
import GeneralSerializer from "./GeneralSerializer"
|
||||
|
||||
export default class ToStringSerializer extends GeneralSerializer {
|
||||
|
||||
constructor(entityType) {
|
||||
super(undefined, entityType)
|
||||
}
|
||||
|
||||
write(object) {
|
||||
let result = object.toString()
|
||||
return result
|
||||
}
|
||||
}
|
||||
import GeneralSerializer from "./GeneralSerializer"
|
||||
|
||||
export default class ToStringSerializer extends GeneralSerializer {
|
||||
|
||||
constructor(entityType) {
|
||||
super(undefined, entityType)
|
||||
}
|
||||
|
||||
write(object) {
|
||||
let result = object.toString()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
100
js/serialization/initializeSerializerFactory.js
Normal file → Executable file
100
js/serialization/initializeSerializerFactory.js
Normal file → Executable file
@@ -1,50 +1,50 @@
|
||||
import CustomSerializer from "./CustomSerializer"
|
||||
import FunctionReferenceEntity from "../entity/FunctionReferenceEntity"
|
||||
import GeneralSerializer from "./GeneralSerializer"
|
||||
import GuidEntity from "../entity/GuidEntity"
|
||||
import IntegerEntity from "../entity/IntegerEntity"
|
||||
import LocalizedTextEntity from "../entity/LocalizedTextEntity"
|
||||
import ObjectEntity from "../entity/ObjectEntity"
|
||||
import ObjectReferenceEntity from "../entity/ObjectReferenceEntity"
|
||||
import ObjectSerializer from "./ObjectSerializer"
|
||||
import PathSymbolEntity from "../entity/PathSymbolEntity"
|
||||
import PinEntity from "../entity/PinEntity"
|
||||
import PinReferenceEntity from "../entity/PinReferenceEntity"
|
||||
import SerializerFactory from "./SerializerFactory"
|
||||
import ToStringSerializer from "./ToStringSerializer"
|
||||
|
||||
export default function initializeSerializerFactory() {
|
||||
SerializerFactory.registerSerializer(
|
||||
ObjectEntity,
|
||||
new ObjectSerializer()
|
||||
)
|
||||
SerializerFactory.registerSerializer(
|
||||
PinEntity,
|
||||
new GeneralSerializer(v => `Pin (${v})`, PinEntity, "", ",", true)
|
||||
)
|
||||
SerializerFactory.registerSerializer(
|
||||
FunctionReferenceEntity,
|
||||
new GeneralSerializer(v => `(${v})`, FunctionReferenceEntity, "", ",", false)
|
||||
)
|
||||
SerializerFactory.registerSerializer(
|
||||
LocalizedTextEntity,
|
||||
new GeneralSerializer(v => `NSLOCTEXT(${v})`, LocalizedTextEntity, "", ",", false, "", _ => "")
|
||||
)
|
||||
SerializerFactory.registerSerializer(
|
||||
PinReferenceEntity,
|
||||
new GeneralSerializer(v => v, PinReferenceEntity, "", " ", false, "", _ => "")
|
||||
)
|
||||
SerializerFactory.registerSerializer(
|
||||
ObjectReferenceEntity,
|
||||
new CustomSerializer(
|
||||
/** @param {ObjectReferenceEntity} objectReference */
|
||||
objectReference => (objectReference.type ?? "") + (
|
||||
objectReference.path
|
||||
? objectReference.type ? `'"${objectReference.path}"'` : objectReference.path
|
||||
: ""
|
||||
))
|
||||
)
|
||||
SerializerFactory.registerSerializer(PathSymbolEntity, new ToStringSerializer(PathSymbolEntity))
|
||||
SerializerFactory.registerSerializer(GuidEntity, new ToStringSerializer(GuidEntity))
|
||||
SerializerFactory.registerSerializer(IntegerEntity, new ToStringSerializer(IntegerEntity))
|
||||
}
|
||||
import CustomSerializer from "./CustomSerializer"
|
||||
import FunctionReferenceEntity from "../entity/FunctionReferenceEntity"
|
||||
import GeneralSerializer from "./GeneralSerializer"
|
||||
import GuidEntity from "../entity/GuidEntity"
|
||||
import IntegerEntity from "../entity/IntegerEntity"
|
||||
import LocalizedTextEntity from "../entity/LocalizedTextEntity"
|
||||
import ObjectEntity from "../entity/ObjectEntity"
|
||||
import ObjectReferenceEntity from "../entity/ObjectReferenceEntity"
|
||||
import ObjectSerializer from "./ObjectSerializer"
|
||||
import PathSymbolEntity from "../entity/PathSymbolEntity"
|
||||
import PinEntity from "../entity/PinEntity"
|
||||
import PinReferenceEntity from "../entity/PinReferenceEntity"
|
||||
import SerializerFactory from "./SerializerFactory"
|
||||
import ToStringSerializer from "./ToStringSerializer"
|
||||
|
||||
export default function initializeSerializerFactory() {
|
||||
SerializerFactory.registerSerializer(
|
||||
ObjectEntity,
|
||||
new ObjectSerializer()
|
||||
)
|
||||
SerializerFactory.registerSerializer(
|
||||
PinEntity,
|
||||
new GeneralSerializer(v => `Pin (${v})`, PinEntity, "", ",", true)
|
||||
)
|
||||
SerializerFactory.registerSerializer(
|
||||
FunctionReferenceEntity,
|
||||
new GeneralSerializer(v => `(${v})`, FunctionReferenceEntity, "", ",", false)
|
||||
)
|
||||
SerializerFactory.registerSerializer(
|
||||
LocalizedTextEntity,
|
||||
new GeneralSerializer(v => `NSLOCTEXT(${v})`, LocalizedTextEntity, "", ",", false, "", _ => "")
|
||||
)
|
||||
SerializerFactory.registerSerializer(
|
||||
PinReferenceEntity,
|
||||
new GeneralSerializer(v => v, PinReferenceEntity, "", " ", false, "", _ => "")
|
||||
)
|
||||
SerializerFactory.registerSerializer(
|
||||
ObjectReferenceEntity,
|
||||
new CustomSerializer(
|
||||
/** @param {ObjectReferenceEntity} objectReference */
|
||||
objectReference => (objectReference.type ?? "") + (
|
||||
objectReference.path
|
||||
? objectReference.type ? `'"${objectReference.path}"'` : objectReference.path
|
||||
: ""
|
||||
))
|
||||
)
|
||||
SerializerFactory.registerSerializer(PathSymbolEntity, new ToStringSerializer(PathSymbolEntity))
|
||||
SerializerFactory.registerSerializer(GuidEntity, new ToStringSerializer(GuidEntity))
|
||||
SerializerFactory.registerSerializer(IntegerEntity, new ToStringSerializer(IntegerEntity))
|
||||
}
|
||||
|
||||
98
js/template/LinkTemplate.js
Normal file → Executable file
98
js/template/LinkTemplate.js
Normal file → Executable file
@@ -1,49 +1,49 @@
|
||||
import html from "./html"
|
||||
import Template from "./Template"
|
||||
|
||||
/**
|
||||
* @typedef {import("../graph/GraphLink").default} GraphLink
|
||||
*/
|
||||
export default class LinkTemplate extends Template {
|
||||
|
||||
/**
|
||||
* Computes the html content of the target element.
|
||||
* @param {GraphLink} link Link connecting two graph nodes
|
||||
* @returns The result html
|
||||
*/
|
||||
render(link) {
|
||||
return html`
|
||||
<svg viewBox="0 0 100 100">
|
||||
<line x1="0" y1="80" x2="100" y2="20" stroke="black" />
|
||||
</svg>
|
||||
`
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style to the element.
|
||||
* @param {GraphLink} link Element of the graph
|
||||
*/
|
||||
apply(link) {
|
||||
super.apply(link)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style relative to the source pin location.
|
||||
* @param {GraphLink} link Link element
|
||||
*/
|
||||
applySourceLocation(link, initialPosition) {
|
||||
// Set initial position
|
||||
link.style.setProperty("--ueb-link-from-x", sanitizeText(initialPosition[0]))
|
||||
link.style.setProperty("--ueb-link-from-y", sanitizeText(initialPosition[1]))
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style relative to the destination pin location.
|
||||
* @param {GraphLink} link Link element
|
||||
*/
|
||||
applyDestinationLocation(link, finalPosition) {
|
||||
link.style.setProperty("--ueb-link-to-x", sanitizeText(finalPosition[0]))
|
||||
link.style.setProperty("--ueb-link-to-y", sanitizeText(finalPosition[1]))
|
||||
}
|
||||
}
|
||||
import html from "./html"
|
||||
import Template from "./Template"
|
||||
|
||||
/**
|
||||
* @typedef {import("../graph/GraphLink").default} GraphLink
|
||||
*/
|
||||
export default class LinkTemplate extends Template {
|
||||
|
||||
/**
|
||||
* Computes the html content of the target element.
|
||||
* @param {GraphLink} link Link connecting two graph nodes
|
||||
* @returns The result html
|
||||
*/
|
||||
render(link) {
|
||||
return html`
|
||||
<svg viewBox="0 0 100 100">
|
||||
<line x1="0" y1="80" x2="100" y2="20" stroke="black" />
|
||||
</svg>
|
||||
`
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style to the element.
|
||||
* @param {GraphLink} link Element of the graph
|
||||
*/
|
||||
apply(link) {
|
||||
super.apply(link)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style relative to the source pin location.
|
||||
* @param {GraphLink} link Link element
|
||||
*/
|
||||
applySourceLocation(link, initialPosition) {
|
||||
// Set initial position
|
||||
link.style.setProperty("--ueb-link-from-x", sanitizeText(initialPosition[0]))
|
||||
link.style.setProperty("--ueb-link-from-y", sanitizeText(initialPosition[1]))
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style relative to the destination pin location.
|
||||
* @param {GraphLink} link Link element
|
||||
*/
|
||||
applyDestinationLocation(link, finalPosition) {
|
||||
link.style.setProperty("--ueb-link-to-x", sanitizeText(finalPosition[0]))
|
||||
link.style.setProperty("--ueb-link-to-y", sanitizeText(finalPosition[1]))
|
||||
}
|
||||
}
|
||||
|
||||
74
js/template/PinTemplate.js
Normal file → Executable file
74
js/template/PinTemplate.js
Normal file → Executable file
@@ -1,38 +1,38 @@
|
||||
import html from "./html"
|
||||
import sanitizeText from "./sanitizeText"
|
||||
import Template from "./Template"
|
||||
|
||||
/**
|
||||
* @typedef {import("../graph/GraphPin").default} GraphPin
|
||||
*/
|
||||
export default class PinTemplate extends Template {
|
||||
|
||||
/**
|
||||
* Computes the html content of the pin.
|
||||
* @param {GraphPin} pin Pin entity
|
||||
* @returns The result html
|
||||
*/
|
||||
render(pin) {
|
||||
if (pin.isInput()) {
|
||||
return html`
|
||||
<span class="ueb-node-value-icon ${pin.isConnected() ? 'ueb-node-value-fill' : ''}"></span>
|
||||
${sanitizeText(pin.getPinDisplayName())}
|
||||
`
|
||||
} else {
|
||||
return html`
|
||||
${sanitizeText(pin.getPinDisplayName())}
|
||||
<span class="ueb-node-value-icon ${pin.isConnected() ? 'ueb-node-value-fill' : ''}"></span>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style to the element.
|
||||
* @param {GraphPin} pin Element of the graph
|
||||
*/
|
||||
apply(pin) {
|
||||
super.apply(pin)
|
||||
pin.classList.add("ueb-node-" + pin.isInput() ? "input" : "output", "ueb-node-value-" + sanitizeText(pin.getType()))
|
||||
pin.clickableElement = pin.querySelector(".ueb-node-value-icon")
|
||||
}
|
||||
import html from "./html"
|
||||
import sanitizeText from "./sanitizeText"
|
||||
import Template from "./Template"
|
||||
|
||||
/**
|
||||
* @typedef {import("../graph/GraphPin").default} GraphPin
|
||||
*/
|
||||
export default class PinTemplate extends Template {
|
||||
|
||||
/**
|
||||
* Computes the html content of the pin.
|
||||
* @param {GraphPin} pin Pin entity
|
||||
* @returns The result html
|
||||
*/
|
||||
render(pin) {
|
||||
if (pin.isInput()) {
|
||||
return html`
|
||||
<span class="ueb-node-value-icon ${pin.isConnected() ? 'ueb-node-value-fill' : ''}"></span>
|
||||
${sanitizeText(pin.getPinDisplayName())}
|
||||
`
|
||||
} else {
|
||||
return html`
|
||||
${sanitizeText(pin.getPinDisplayName())}
|
||||
<span class="ueb-node-value-icon ${pin.isConnected() ? 'ueb-node-value-fill' : ''}"></span>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style to the element.
|
||||
* @param {GraphPin} pin Element of the graph
|
||||
*/
|
||||
apply(pin) {
|
||||
super.apply(pin)
|
||||
pin.classList.add("ueb-node-" + pin.isInput() ? "input" : "output", "ueb-node-value-" + sanitizeText(pin.getType()))
|
||||
pin.clickableElement = pin.querySelector(".ueb-node-value-icon")
|
||||
}
|
||||
}
|
||||
58
js/template/SelectableDraggableTemplate.js
Normal file → Executable file
58
js/template/SelectableDraggableTemplate.js
Normal file → Executable file
@@ -1,29 +1,29 @@
|
||||
import sanitizeText from "./sanitizeText"
|
||||
import Template from "./Template"
|
||||
|
||||
/**
|
||||
* @typedef {import("../graph/SelectableDraggable").default} SelectableDraggable
|
||||
*/
|
||||
export default class SelectableDraggableTemplate extends Template {
|
||||
|
||||
/**
|
||||
* Returns the html elements rendered from this template.
|
||||
* @param {SelectableDraggable} element Element of the graph
|
||||
*/
|
||||
applyLocation(element) {
|
||||
element.style.setProperty("--ueb-position-x", sanitizeText(element.location[0]))
|
||||
element.style.setProperty("--ueb-position-y", sanitizeText(element.location[1]))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the html elements rendered from this template.
|
||||
* @param {SelectableDraggable} element Element of the graph
|
||||
*/
|
||||
applySelected(element) {
|
||||
if (element.selected) {
|
||||
element.classList.add("ueb-selected")
|
||||
} else {
|
||||
element.classList.remove("ueb-selected")
|
||||
}
|
||||
}
|
||||
}
|
||||
import sanitizeText from "./sanitizeText"
|
||||
import Template from "./Template"
|
||||
|
||||
/**
|
||||
* @typedef {import("../graph/SelectableDraggable").default} SelectableDraggable
|
||||
*/
|
||||
export default class SelectableDraggableTemplate extends Template {
|
||||
|
||||
/**
|
||||
* Returns the html elements rendered from this template.
|
||||
* @param {SelectableDraggable} element Element of the graph
|
||||
*/
|
||||
applyLocation(element) {
|
||||
element.style.setProperty("--ueb-position-x", sanitizeText(element.location[0]))
|
||||
element.style.setProperty("--ueb-position-y", sanitizeText(element.location[1]))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the html elements rendered from this template.
|
||||
* @param {SelectableDraggable} element Element of the graph
|
||||
*/
|
||||
applySelected(element) {
|
||||
if (element.selected) {
|
||||
element.classList.add("ueb-selected")
|
||||
} else {
|
||||
element.classList.remove("ueb-selected")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
98
js/template/SelectorTemplate.js
Normal file → Executable file
98
js/template/SelectorTemplate.js
Normal file → Executable file
@@ -1,49 +1,49 @@
|
||||
import sanitizeText from "./sanitizeText"
|
||||
import Template from "./Template"
|
||||
|
||||
/**
|
||||
* @typedef {import("../graph/GraphSelector").default} GraphSelector
|
||||
*/
|
||||
export default class SelectorTemplate extends Template {
|
||||
|
||||
/**
|
||||
* Applies the style to the element.
|
||||
* @param {GraphSelector} selector Selector element
|
||||
*/
|
||||
apply(selector) {
|
||||
super.apply(selector)
|
||||
selector.classList.add("ueb-selector")
|
||||
this.applyFinishSelecting(selector)
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style relative to selection beginning.
|
||||
* @param {GraphSelector} selector Selector element
|
||||
*/
|
||||
applyStartSelecting(selector, initialPosition) {
|
||||
// Set initial position
|
||||
selector.style.setProperty("--ueb-select-from-x", sanitizeText(initialPosition[0]))
|
||||
selector.style.setProperty("--ueb-select-from-y", sanitizeText(initialPosition[1]))
|
||||
// Final position coincide with the initial position, at the beginning of selection
|
||||
selector.style.setProperty("--ueb-select-to-x", sanitizeText(initialPosition[0]))
|
||||
selector.style.setProperty("--ueb-select-to-y", sanitizeText(initialPosition[1]))
|
||||
selector.dataset.selecting = "true"
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style relative to selection.
|
||||
* @param {GraphSelector} selector Selector element
|
||||
*/
|
||||
applyDoSelecting(selector, finalPosition) {
|
||||
selector.style.setProperty("--ueb-select-to-x", sanitizeText(finalPosition[0]))
|
||||
selector.style.setProperty("--ueb-select-to-y", sanitizeText(finalPosition[1]))
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style relative to selection finishing.
|
||||
* @param {GraphSelector} selector Selector element
|
||||
*/
|
||||
applyFinishSelecting(selector) {
|
||||
selector.dataset.selecting = "false"
|
||||
}
|
||||
}
|
||||
import sanitizeText from "./sanitizeText"
|
||||
import Template from "./Template"
|
||||
|
||||
/**
|
||||
* @typedef {import("../graph/GraphSelector").default} GraphSelector
|
||||
*/
|
||||
export default class SelectorTemplate extends Template {
|
||||
|
||||
/**
|
||||
* Applies the style to the element.
|
||||
* @param {GraphSelector} selector Selector element
|
||||
*/
|
||||
apply(selector) {
|
||||
super.apply(selector)
|
||||
selector.classList.add("ueb-selector")
|
||||
this.applyFinishSelecting(selector)
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style relative to selection beginning.
|
||||
* @param {GraphSelector} selector Selector element
|
||||
*/
|
||||
applyStartSelecting(selector, initialPosition) {
|
||||
// Set initial position
|
||||
selector.style.setProperty("--ueb-select-from-x", sanitizeText(initialPosition[0]))
|
||||
selector.style.setProperty("--ueb-select-from-y", sanitizeText(initialPosition[1]))
|
||||
// Final position coincide with the initial position, at the beginning of selection
|
||||
selector.style.setProperty("--ueb-select-to-x", sanitizeText(initialPosition[0]))
|
||||
selector.style.setProperty("--ueb-select-to-y", sanitizeText(initialPosition[1]))
|
||||
selector.dataset.selecting = "true"
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style relative to selection.
|
||||
* @param {GraphSelector} selector Selector element
|
||||
*/
|
||||
applyDoSelecting(selector, finalPosition) {
|
||||
selector.style.setProperty("--ueb-select-to-x", sanitizeText(finalPosition[0]))
|
||||
selector.style.setProperty("--ueb-select-to-y", sanitizeText(finalPosition[1]))
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the style relative to selection finishing.
|
||||
* @param {GraphSelector} selector Selector element
|
||||
*/
|
||||
applyFinishSelecting(selector) {
|
||||
selector.dataset.selecting = "false"
|
||||
}
|
||||
}
|
||||
|
||||
4
js/template/html.js
Normal file → Executable file
4
js/template/html.js
Normal file → Executable file
@@ -1,2 +1,2 @@
|
||||
const html = String.raw
|
||||
export default html
|
||||
const html = String.raw
|
||||
export default html
|
||||
|
||||
34
js/template/sanitizeText.js
Normal file → Executable file
34
js/template/sanitizeText.js
Normal file → Executable file
@@ -1,18 +1,18 @@
|
||||
const div = document.createElement("div")
|
||||
|
||||
const tagReplacement = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
"'": ''',
|
||||
'"': '"'
|
||||
}
|
||||
|
||||
function sanitizeText(value) {
|
||||
if (value.constructor === String) {
|
||||
return value.replace(/[&<>'"]/g, tag => tagReplacement[tag])
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
const div = document.createElement("div")
|
||||
|
||||
const tagReplacement = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
"'": ''',
|
||||
'"': '"'
|
||||
}
|
||||
|
||||
function sanitizeText(value) {
|
||||
if (value.constructor === String) {
|
||||
return value.replace(/[&<>'"]/g, tag => tagReplacement[tag])
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
export default sanitizeText
|
||||
74
package.json
Normal file → Executable file
74
package.json
Normal file → Executable file
@@ -1,37 +1,37 @@
|
||||
{
|
||||
"name": "ueblueprint",
|
||||
"version": "1.0.0",
|
||||
"description": "Unreal Engine's Blueprint visualisation library",
|
||||
"main": "ueblueprint.js",
|
||||
"scripts": {
|
||||
"build": "rollup --config && sass scss:dist/css --style=compressed"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/barsdeveloper/ueblueprint.git"
|
||||
},
|
||||
"keywords": [
|
||||
"unreal",
|
||||
"engine",
|
||||
"blueprint"
|
||||
],
|
||||
"author": "barsdeveloper",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/barsdeveloper/ueblueprint/issues"
|
||||
},
|
||||
"homepage": "https://github.com/barsdeveloper/ueblueprint#readme",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^21.0.0",
|
||||
"@rollup/plugin-node-resolve": "^13.0.5",
|
||||
"rollup": "^2.58.0",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"rollup-plugin-minify-html-template-literals": "^1.2.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"sass": "^1.45.1",
|
||||
"terser": "^5.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"parsimmon": "^1.18.0"
|
||||
}
|
||||
}
|
||||
{
|
||||
"name": "ueblueprint",
|
||||
"version": "1.0.0",
|
||||
"description": "Unreal Engine's Blueprint visualisation library",
|
||||
"main": "ueblueprint.js",
|
||||
"scripts": {
|
||||
"build": "rollup --config && sass scss:dist/css --style=compressed"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/barsdeveloper/ueblueprint.git"
|
||||
},
|
||||
"keywords": [
|
||||
"unreal",
|
||||
"engine",
|
||||
"blueprint"
|
||||
],
|
||||
"author": "barsdeveloper",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/barsdeveloper/ueblueprint/issues"
|
||||
},
|
||||
"homepage": "https://github.com/barsdeveloper/ueblueprint#readme",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^21.0.0",
|
||||
"@rollup/plugin-node-resolve": "^13.0.5",
|
||||
"rollup": "^2.58.0",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"rollup-plugin-minify-html-template-literals": "^1.2.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"sass": "^1.45.1",
|
||||
"terser": "^5.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"parsimmon": "^1.18.0"
|
||||
}
|
||||
}
|
||||
|
||||
52
rollup.config.js
Normal file → Executable file
52
rollup.config.js
Normal file → Executable file
@@ -1,27 +1,27 @@
|
||||
import { nodeResolve } from '@rollup/plugin-node-resolve'
|
||||
import minifyHTML from 'rollup-plugin-minify-html-template-literals'
|
||||
import commonjs from '@rollup/plugin-commonjs'
|
||||
import { terser } from 'rollup-plugin-terser'
|
||||
import copy from 'rollup-plugin-copy'
|
||||
|
||||
export default {
|
||||
input: 'js/export.js',
|
||||
output: {
|
||||
file: 'dist/ueblueprint.js',
|
||||
format: 'es'
|
||||
},
|
||||
plugins: [
|
||||
nodeResolve({ browser: true }),
|
||||
//minifyHTML(),
|
||||
commonjs(),
|
||||
//terser()
|
||||
copy({
|
||||
targets: [
|
||||
{
|
||||
src: ["font/*"],
|
||||
dest: "dist/font"
|
||||
}
|
||||
]
|
||||
})
|
||||
]
|
||||
import { nodeResolve } from '@rollup/plugin-node-resolve'
|
||||
import minifyHTML from 'rollup-plugin-minify-html-template-literals'
|
||||
import commonjs from '@rollup/plugin-commonjs'
|
||||
import { terser } from 'rollup-plugin-terser'
|
||||
import copy from 'rollup-plugin-copy'
|
||||
|
||||
export default {
|
||||
input: 'js/export.js',
|
||||
output: {
|
||||
file: 'dist/ueblueprint.js',
|
||||
format: 'es'
|
||||
},
|
||||
plugins: [
|
||||
nodeResolve({ browser: true }),
|
||||
//minifyHTML(),
|
||||
commonjs(),
|
||||
//terser()
|
||||
copy({
|
||||
targets: [
|
||||
{
|
||||
src: ["font/*"],
|
||||
dest: "dist/font"
|
||||
}
|
||||
]
|
||||
})
|
||||
]
|
||||
}
|
||||
88
scss/ueblueprint-node-value-type-color.scss
Normal file → Executable file
88
scss/ueblueprint-node-value-type-color.scss
Normal file → Executable file
@@ -1,45 +1,45 @@
|
||||
.ueb {
|
||||
$ueb-node-value-color : white;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-boolean {
|
||||
$ueb-node-value-color : #930000;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-integer {
|
||||
$ueb-node-value-color : #1fe0ad;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-float {
|
||||
$ueb-node-value-color : #9ffb44;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-vector {
|
||||
$ueb-node-value-color : #fcc823;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-rotator {
|
||||
$ueb-node-value-color : #9eb1fc;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-string {
|
||||
$ueb-node-value-color : #fc00d2;
|
||||
--ueb-node-value-color : #{$ueb-node-value-color};
|
||||
--ueb-node-value-background: linear-gradient(90deg, #fc00d220, #fc00d280 15%, #fc00d250 85%, transparent);
|
||||
}
|
||||
|
||||
.ueb-node-value-name {
|
||||
$ueb-node-value-color : #cb81fc;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-objectreference {
|
||||
$ueb-node-value-color : #00a8f2;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
.ueb {
|
||||
$ueb-node-value-color : white;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-boolean {
|
||||
$ueb-node-value-color : #930000;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-integer {
|
||||
$ueb-node-value-color : #1fe0ad;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-float {
|
||||
$ueb-node-value-color : #9ffb44;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-vector {
|
||||
$ueb-node-value-color : #fcc823;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-rotator {
|
||||
$ueb-node-value-color : #9eb1fc;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-string {
|
||||
$ueb-node-value-color : #fc00d2;
|
||||
--ueb-node-value-color : #{$ueb-node-value-color};
|
||||
--ueb-node-value-background: linear-gradient(90deg, #fc00d220, #fc00d280 15%, #fc00d250 85%, transparent);
|
||||
}
|
||||
|
||||
.ueb-node-value-name {
|
||||
$ueb-node-value-color : #cb81fc;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
|
||||
.ueb-node-value-objectreference {
|
||||
$ueb-node-value-color : #00a8f2;
|
||||
--ueb-node-value-color: #{$ueb-node-value-color};
|
||||
}
|
||||
860
scss/ueblueprint-style.css
Normal file → Executable file
860
scss/ueblueprint-style.css
Normal file → Executable file
@@ -1,431 +1,431 @@
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-style : light;
|
||||
src :
|
||||
url("../font/roboto-light.woff2") format("woff2"),
|
||||
url("../font/roboto-light.woff") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-style : regular;
|
||||
src :
|
||||
url("../font/roboto-regular.woff2") format("woff2"),
|
||||
url("../font/roboto-regular.woff") format("woff");
|
||||
}
|
||||
|
||||
:root {
|
||||
--ueb-fron-size : 13px;
|
||||
--ueb-viewport-height : 30rem;
|
||||
--ueb-viewport-width : 100%;
|
||||
--ueb-grid-size : 16px;
|
||||
--ueb-grid-line-width : 2px;
|
||||
--ueb-grid-line-color : #353535;
|
||||
--ueb-grid-set : 8;
|
||||
--ueb-grid-set-line-color : #161616;
|
||||
--ueb-grid-axis-line-color: black;
|
||||
--ueb-grid-snap : 16px;
|
||||
--ueb-node-radius : 8px;
|
||||
}
|
||||
|
||||
ueb-blueprint {
|
||||
display : block;
|
||||
position : relative;
|
||||
font-family: Roboto, Noto, Oxygen, Ubuntu, "Open Sans", "Helvetica Neue", sans-serif;
|
||||
font-size : var(--ueb-fron-size);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.ueb-viewport-header {
|
||||
display : flex;
|
||||
position : absolute;
|
||||
top : 0;
|
||||
right : 0;
|
||||
left : 0;
|
||||
height : 1.5em;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index : 1;
|
||||
}
|
||||
|
||||
.ueb-viewport-zoom {
|
||||
color: #4d4d4db7;
|
||||
}
|
||||
|
||||
.ueb-viewport-body {
|
||||
position : relative;
|
||||
height : var(--ueb-viewport-height);
|
||||
width : var(--ueb-viewport-width);
|
||||
overflow : hidden;
|
||||
scrollbar-width: 0;
|
||||
}
|
||||
|
||||
ueb-blueprint[data-focused="true"] .ueb-viewport-body {
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.ueb-grid {
|
||||
--ueb-grid-line-actual-width: calc(var(--ueb-grid-line-width) / var(--ueb-scale));
|
||||
position : absolute;
|
||||
min-width : 100%;
|
||||
min-height : 100%;
|
||||
width : calc((100% + var(--ueb-additional-x) * 1px) / var(--ueb-scale));
|
||||
height : calc((100% + var(--ueb-additional-y) * 1px) / var(--ueb-scale));
|
||||
background-color : #262626;
|
||||
background-image :
|
||||
/* Axis lines */
|
||||
linear-gradient(var(--ueb-grid-axis-line-color),
|
||||
var(--ueb-grid-axis-line-color)),
|
||||
linear-gradient(var(--ueb-grid-axis-line-color),
|
||||
var(--ueb-grid-axis-line-color)),
|
||||
/* Dark bigger grid */
|
||||
linear-gradient(to right,
|
||||
var(--ueb-grid-set-line-color),
|
||||
var(--ueb-grid-set-line-color) var(--ueb-grid-line-actual-width),
|
||||
transparent var(--ueb-grid-line-actual-width),
|
||||
transparent),
|
||||
linear-gradient(to bottom,
|
||||
var(--ueb-grid-set-line-color),
|
||||
var(--ueb-grid-set-line-color) var(--ueb-grid-line-actual-width),
|
||||
transparent var(--ueb-grid-line-actual-width),
|
||||
transparent),
|
||||
/* Light grid */
|
||||
linear-gradient(to right,
|
||||
var(--ueb-grid-line-color),
|
||||
var(--ueb-grid-line-color) var(--ueb-grid-line-actual-width),
|
||||
transparent var(--ueb-grid-line-actual-width),
|
||||
transparent),
|
||||
linear-gradient(to bottom,
|
||||
var(--ueb-grid-line-color),
|
||||
var(--ueb-grid-line-color) var(--ueb-grid-line-actual-width),
|
||||
transparent var(--ueb-grid-line-actual-width),
|
||||
transparent);
|
||||
background-size:
|
||||
/* Axis lines */
|
||||
100% var(--ueb-grid-line-actual-width),
|
||||
var(--ueb-grid-line-actual-width) 100%,
|
||||
/* Dark bigger grid */
|
||||
calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)) calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)),
|
||||
calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)) calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)),
|
||||
/* Light grid */
|
||||
var(--ueb-grid-actual-size) var(--ueb-grid-actual-size),
|
||||
var(--ueb-grid-actual-size) var(--ueb-grid-actual-size);
|
||||
background-position: calc(var(--ueb-translate-x) * 1px) calc(var(--ueb-translate-y) * 1px);
|
||||
background-repeat : repeat-x, repeat-y, repeat, repeat, repeat, repeat;
|
||||
transform : scale(var(--ueb-scale), var(--ueb-scale));
|
||||
transform-origin : 0 0;
|
||||
overflow : hidden;
|
||||
}
|
||||
|
||||
.ueb-grid[data-drag-scrolling="true"] {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.ueb-zoom--.ueb,
|
||||
.ueb {
|
||||
/* 16/16 */
|
||||
--ueb-scale : 1;
|
||||
--ueb-grid-actual-size: var(--ueb-grid-size);
|
||||
}
|
||||
|
||||
.ueb-zoom--1.ueb {
|
||||
/* 14/16 */
|
||||
--ueb-scale: 0.875;
|
||||
}
|
||||
|
||||
.ueb-zoom--2.ueb {
|
||||
/* 12/16 */
|
||||
--ueb-scale: 0.75;
|
||||
}
|
||||
|
||||
.ueb-zoom--3.ueb {
|
||||
/* 10.8/16 */
|
||||
--ueb-scale: 0.675;
|
||||
}
|
||||
|
||||
.ueb-zoom--4.ueb {
|
||||
/* 8/16 */
|
||||
--ueb-scale : 0.5;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 2);
|
||||
}
|
||||
|
||||
.ueb-zoom--5.ueb {
|
||||
/* 6/16 */
|
||||
--ueb-scale : 0.375;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 2);
|
||||
}
|
||||
|
||||
.ueb-zoom--6.ueb {
|
||||
--ueb-scale : 0.333333;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
|
||||
}
|
||||
|
||||
.ueb-zoom--7.ueb {
|
||||
--ueb-scale : 0.3;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
|
||||
}
|
||||
|
||||
.ueb-zoom--8.ueb {
|
||||
--ueb-scale : 0.266666;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
|
||||
}
|
||||
|
||||
.ueb-zoom--9.ueb {
|
||||
--ueb-scale : 0.233333;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
|
||||
}
|
||||
|
||||
.ueb-zoom--10.ueb {
|
||||
/* 12/16 */
|
||||
--ueb-scale : 0.2;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
|
||||
}
|
||||
|
||||
.ueb-zoom--11.ueb {
|
||||
/* 12/16 */
|
||||
--ueb-scale : 0.166666;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 6);
|
||||
}
|
||||
|
||||
.ueb-zoom--12.ueb {
|
||||
/* 12/16 */
|
||||
--ueb-scale : 0.133333;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 6);
|
||||
}
|
||||
|
||||
.ueb-grid-content {
|
||||
position : relative;
|
||||
width : 0;
|
||||
height : 0;
|
||||
transform: translateX(calc(var(--ueb-translate-x) * 1px)) translateY(calc(var(--ueb-translate-y) * 1px));
|
||||
}
|
||||
|
||||
ueb-node {
|
||||
display : block;
|
||||
position : absolute;
|
||||
transform : translateX(calc(var(--ueb-position-x) * 1px)) translateY(calc(var(--ueb-position-y) * 1px));
|
||||
border-radius: var(--ueb-node-radius);
|
||||
box-shadow : 0 0 1px 0 black, 1px 4px 6px 0 rgba(0, 0, 0, 0.3);
|
||||
will-change : transform;
|
||||
}
|
||||
|
||||
.ueb-grid[data-drag-scrolling="false"] ueb-selector[data-selecting="false"]~ueb-node {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.ueb-node-border {
|
||||
margin : -3px;
|
||||
padding : 3px;
|
||||
border-radius: calc(var(--ueb-node-radius) * 1.4);
|
||||
}
|
||||
|
||||
.ueb-selected {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.ueb-selected>.ueb-node-border {
|
||||
background-image:
|
||||
linear-gradient(to right, #f1b000 0%, #f1b000 100%),
|
||||
linear-gradient(to bottom, #f1b000 0%, #cc6700 100%),
|
||||
linear-gradient(to right, #cc6700 0%, #cc6700 100%),
|
||||
linear-gradient(to bottom, #f1b000 0%, #cc6700 100%);
|
||||
background-size : 100% 7px, 7px 100%, 100% 7px, 7px 100%;
|
||||
background-position: top, right, bottom, left;
|
||||
background-repeat : repeat-x, repeat-y, repeat-x, repeat-y;
|
||||
outline : 3px solid #cc6700;
|
||||
outline-offset : -6px;
|
||||
}
|
||||
|
||||
.ueb-node-content {
|
||||
position : relative;
|
||||
padding : 1px;
|
||||
box-shadow : inset 0 0 2px 0 black;
|
||||
border-radius: var(--ueb-node-radius);
|
||||
background : rgba(0, 0, 0, 0.7);
|
||||
overflow : hidden;
|
||||
}
|
||||
|
||||
.ueb-node-header {
|
||||
padding : 0.2em 0.7em;
|
||||
box-shadow : inset 0 1px 2px 0 #313631, inset 0 2px 0 0 #92c381;
|
||||
border-radius: var(--ueb-node-radius) var(--ueb-node-radius) 0 0;
|
||||
background : linear-gradient(170deg, #5f815a 0%, #5f815a 50%, transparent 100%);
|
||||
color : #c0c0c0;
|
||||
font-weight : 600;
|
||||
white-space : nowrap;
|
||||
}
|
||||
|
||||
.ueb-node-name {
|
||||
background: radial-gradient(closest-side, rgba(0, 0, 0, 0.5) 0%, transparent 90%);
|
||||
margin : -0.1em -1.6em;
|
||||
padding : 0.1em 1.6em;
|
||||
}
|
||||
|
||||
.ueb-node-body {
|
||||
display : flex;
|
||||
padding : 6px 0;
|
||||
color : white;
|
||||
font-weight: 100;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ueb-node-inputs {
|
||||
margin-right: auto;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.ueb-node-outputs {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
ueb-pin {
|
||||
display: block;
|
||||
padding: 1px 2px;
|
||||
}
|
||||
|
||||
.ueb-grid[data-drag-scrolling="false"] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
ueb-selector[data-selecting="false"]~ueb-node ueb-pin:hover {
|
||||
background: var(--ueb-node-value-background);
|
||||
}
|
||||
|
||||
.ueb-grid[data-drag-scrolling="false"] ueb-selector[data-selecting="false"]~ueb-node ueb-pin .ueb-node-value-icon {
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.ueb-node-value-icon {
|
||||
display : inline-block;
|
||||
position : relative;
|
||||
width : 0.85em;
|
||||
height : 0.85em;
|
||||
vertical-align: baseline;
|
||||
margin : 0 0.4em -1px 0.1em;
|
||||
}
|
||||
|
||||
.ueb-node-value-icon::before {
|
||||
content : "";
|
||||
display : block;
|
||||
position : absolute;
|
||||
top : 0;
|
||||
right : 0;
|
||||
bottom : 0;
|
||||
left : 0;
|
||||
border : 2px solid var(--ueb-node-value-color);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.ueb-node-value-fill::before {
|
||||
background: var(--ueb-node-value-color);
|
||||
}
|
||||
|
||||
.ueb-node-value-icon::after {
|
||||
content : "";
|
||||
display : block;
|
||||
position : absolute;
|
||||
top : calc(50% - 0.3em);
|
||||
left : calc(100% + 1px);
|
||||
width : 0;
|
||||
height : 0;
|
||||
border-top : 0.3em solid transparent;
|
||||
border-bottom: 0.3em solid transparent;
|
||||
border-left : 0.3em solid var(--ueb-node-value-color);
|
||||
}
|
||||
|
||||
.ueb-selector {
|
||||
display : block;
|
||||
position : absolute;
|
||||
visibility: hidden;
|
||||
top : 0;
|
||||
left : 0;
|
||||
width : 0;
|
||||
height : 0;
|
||||
background-image:
|
||||
/* Top */
|
||||
repeating-linear-gradient(90deg,
|
||||
transparent,
|
||||
transparent calc(1px / var(--ueb-scale)),
|
||||
white calc(2px / var(--ueb-scale)),
|
||||
white calc(7px / var(--ueb-scale)),
|
||||
transparent calc(7px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
repeating-linear-gradient(90deg,
|
||||
black,
|
||||
black calc(8px / var(--ueb-scale)),
|
||||
transparent calc(9px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
/* Bottom */
|
||||
repeating-linear-gradient(90deg,
|
||||
transparent,
|
||||
transparent calc(1px / var(--ueb-scale)),
|
||||
white calc(2px / var(--ueb-scale)),
|
||||
white calc(7px / var(--ueb-scale)),
|
||||
transparent calc(7px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
repeating-linear-gradient(90deg,
|
||||
black,
|
||||
black calc(8px / var(--ueb-scale)),
|
||||
transparent calc(9px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
/* Left */
|
||||
repeating-linear-gradient(180deg,
|
||||
transparent,
|
||||
transparent calc(1px / var(--ueb-scale)),
|
||||
white calc(1px / var(--ueb-scale)),
|
||||
white calc(7px / var(--ueb-scale)),
|
||||
transparent calc(7px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
repeating-linear-gradient(180deg,
|
||||
black,
|
||||
black calc(8px / var(--ueb-scale)),
|
||||
transparent calc(9px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
/* Right */
|
||||
repeating-linear-gradient(0deg,
|
||||
transparent,
|
||||
transparent calc(1px / var(--ueb-scale)),
|
||||
white calc(2px / var(--ueb-scale)),
|
||||
white calc(7px / var(--ueb-scale)),
|
||||
transparent calc(7px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
repeating-linear-gradient(0deg,
|
||||
black,
|
||||
black calc(8px / var(--ueb-scale)),
|
||||
transparent calc(9px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale)));
|
||||
background-size:
|
||||
/* Top */
|
||||
100% calc(1px / var(--ueb-scale)),
|
||||
100% calc(3px / var(--ueb-scale)),
|
||||
/* Bottom */
|
||||
100% calc(1px / var(--ueb-scale)),
|
||||
100% calc(3px / var(--ueb-scale)),
|
||||
/* Left */
|
||||
calc(1px / var(--ueb-scale)) 100%,
|
||||
calc(3px / var(--ueb-scale)) 100%,
|
||||
/* Right */
|
||||
calc(1px / var(--ueb-scale)) 100%,
|
||||
calc(3px / var(--ueb-scale)) 100%;
|
||||
background-position:
|
||||
/* Top */
|
||||
0 calc(1px / var(--ueb-scale)), 0 0,
|
||||
/* Bottom */
|
||||
0 calc(100% - 1px / var(--ueb-scale)), 0 100%,
|
||||
/* Left */
|
||||
calc(1px / var(--ueb-scale)) 0, 0 0,
|
||||
/* Right */
|
||||
calc(100% - 1px / var(--ueb-scale)) 0, 100% 0;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
ueb-selector>* {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
ueb-selector[data-selecting="true"] {
|
||||
visibility: visible;
|
||||
top : min(var(--ueb-select-from-y) * 1px, var(--ueb-select-to-y) * 1px);
|
||||
left : min(var(--ueb-select-from-x) * 1px, var(--ueb-select-to-x) * 1px);
|
||||
width : calc(max(var(--ueb-select-from-x) - var(--ueb-select-to-x), var(--ueb-select-to-x) - var(--ueb-select-from-x)) * 1px);
|
||||
height : calc(max(var(--ueb-select-from-y) - var(--ueb-select-to-y), var(--ueb-select-to-y) - var(--ueb-select-from-y)) * 1px);
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-style : light;
|
||||
src :
|
||||
url("../font/roboto-light.woff2") format("woff2"),
|
||||
url("../font/roboto-light.woff") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-style : regular;
|
||||
src :
|
||||
url("../font/roboto-regular.woff2") format("woff2"),
|
||||
url("../font/roboto-regular.woff") format("woff");
|
||||
}
|
||||
|
||||
:root {
|
||||
--ueb-fron-size : 13px;
|
||||
--ueb-viewport-height : 30rem;
|
||||
--ueb-viewport-width : 100%;
|
||||
--ueb-grid-size : 16px;
|
||||
--ueb-grid-line-width : 2px;
|
||||
--ueb-grid-line-color : #353535;
|
||||
--ueb-grid-set : 8;
|
||||
--ueb-grid-set-line-color : #161616;
|
||||
--ueb-grid-axis-line-color: black;
|
||||
--ueb-grid-snap : 16px;
|
||||
--ueb-node-radius : 8px;
|
||||
}
|
||||
|
||||
ueb-blueprint {
|
||||
display : block;
|
||||
position : relative;
|
||||
font-family: Roboto, Noto, Oxygen, Ubuntu, "Open Sans", "Helvetica Neue", sans-serif;
|
||||
font-size : var(--ueb-fron-size);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.ueb-viewport-header {
|
||||
display : flex;
|
||||
position : absolute;
|
||||
top : 0;
|
||||
right : 0;
|
||||
left : 0;
|
||||
height : 1.5em;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index : 1;
|
||||
}
|
||||
|
||||
.ueb-viewport-zoom {
|
||||
color: #4d4d4db7;
|
||||
}
|
||||
|
||||
.ueb-viewport-body {
|
||||
position : relative;
|
||||
height : var(--ueb-viewport-height);
|
||||
width : var(--ueb-viewport-width);
|
||||
overflow : hidden;
|
||||
scrollbar-width: 0;
|
||||
}
|
||||
|
||||
ueb-blueprint[data-focused="true"] .ueb-viewport-body {
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.ueb-grid {
|
||||
--ueb-grid-line-actual-width: calc(var(--ueb-grid-line-width) / var(--ueb-scale));
|
||||
position : absolute;
|
||||
min-width : 100%;
|
||||
min-height : 100%;
|
||||
width : calc((100% + var(--ueb-additional-x) * 1px) / var(--ueb-scale));
|
||||
height : calc((100% + var(--ueb-additional-y) * 1px) / var(--ueb-scale));
|
||||
background-color : #262626;
|
||||
background-image :
|
||||
/* Axis lines */
|
||||
linear-gradient(var(--ueb-grid-axis-line-color),
|
||||
var(--ueb-grid-axis-line-color)),
|
||||
linear-gradient(var(--ueb-grid-axis-line-color),
|
||||
var(--ueb-grid-axis-line-color)),
|
||||
/* Dark bigger grid */
|
||||
linear-gradient(to right,
|
||||
var(--ueb-grid-set-line-color),
|
||||
var(--ueb-grid-set-line-color) var(--ueb-grid-line-actual-width),
|
||||
transparent var(--ueb-grid-line-actual-width),
|
||||
transparent),
|
||||
linear-gradient(to bottom,
|
||||
var(--ueb-grid-set-line-color),
|
||||
var(--ueb-grid-set-line-color) var(--ueb-grid-line-actual-width),
|
||||
transparent var(--ueb-grid-line-actual-width),
|
||||
transparent),
|
||||
/* Light grid */
|
||||
linear-gradient(to right,
|
||||
var(--ueb-grid-line-color),
|
||||
var(--ueb-grid-line-color) var(--ueb-grid-line-actual-width),
|
||||
transparent var(--ueb-grid-line-actual-width),
|
||||
transparent),
|
||||
linear-gradient(to bottom,
|
||||
var(--ueb-grid-line-color),
|
||||
var(--ueb-grid-line-color) var(--ueb-grid-line-actual-width),
|
||||
transparent var(--ueb-grid-line-actual-width),
|
||||
transparent);
|
||||
background-size:
|
||||
/* Axis lines */
|
||||
100% var(--ueb-grid-line-actual-width),
|
||||
var(--ueb-grid-line-actual-width) 100%,
|
||||
/* Dark bigger grid */
|
||||
calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)) calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)),
|
||||
calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)) calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)),
|
||||
/* Light grid */
|
||||
var(--ueb-grid-actual-size) var(--ueb-grid-actual-size),
|
||||
var(--ueb-grid-actual-size) var(--ueb-grid-actual-size);
|
||||
background-position: calc(var(--ueb-translate-x) * 1px) calc(var(--ueb-translate-y) * 1px);
|
||||
background-repeat : repeat-x, repeat-y, repeat, repeat, repeat, repeat;
|
||||
transform : scale(var(--ueb-scale), var(--ueb-scale));
|
||||
transform-origin : 0 0;
|
||||
overflow : hidden;
|
||||
}
|
||||
|
||||
.ueb-grid[data-drag-scrolling="true"] {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.ueb-zoom--.ueb,
|
||||
.ueb {
|
||||
/* 16/16 */
|
||||
--ueb-scale : 1;
|
||||
--ueb-grid-actual-size: var(--ueb-grid-size);
|
||||
}
|
||||
|
||||
.ueb-zoom--1.ueb {
|
||||
/* 14/16 */
|
||||
--ueb-scale: 0.875;
|
||||
}
|
||||
|
||||
.ueb-zoom--2.ueb {
|
||||
/* 12/16 */
|
||||
--ueb-scale: 0.75;
|
||||
}
|
||||
|
||||
.ueb-zoom--3.ueb {
|
||||
/* 10.8/16 */
|
||||
--ueb-scale: 0.675;
|
||||
}
|
||||
|
||||
.ueb-zoom--4.ueb {
|
||||
/* 8/16 */
|
||||
--ueb-scale : 0.5;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 2);
|
||||
}
|
||||
|
||||
.ueb-zoom--5.ueb {
|
||||
/* 6/16 */
|
||||
--ueb-scale : 0.375;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 2);
|
||||
}
|
||||
|
||||
.ueb-zoom--6.ueb {
|
||||
--ueb-scale : 0.333333;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
|
||||
}
|
||||
|
||||
.ueb-zoom--7.ueb {
|
||||
--ueb-scale : 0.3;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
|
||||
}
|
||||
|
||||
.ueb-zoom--8.ueb {
|
||||
--ueb-scale : 0.266666;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
|
||||
}
|
||||
|
||||
.ueb-zoom--9.ueb {
|
||||
--ueb-scale : 0.233333;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
|
||||
}
|
||||
|
||||
.ueb-zoom--10.ueb {
|
||||
/* 12/16 */
|
||||
--ueb-scale : 0.2;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
|
||||
}
|
||||
|
||||
.ueb-zoom--11.ueb {
|
||||
/* 12/16 */
|
||||
--ueb-scale : 0.166666;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 6);
|
||||
}
|
||||
|
||||
.ueb-zoom--12.ueb {
|
||||
/* 12/16 */
|
||||
--ueb-scale : 0.133333;
|
||||
--ueb-grid-actual-size: calc(var(--ueb-grid-size) * 6);
|
||||
}
|
||||
|
||||
.ueb-grid-content {
|
||||
position : relative;
|
||||
width : 0;
|
||||
height : 0;
|
||||
transform: translateX(calc(var(--ueb-translate-x) * 1px)) translateY(calc(var(--ueb-translate-y) * 1px));
|
||||
}
|
||||
|
||||
ueb-node {
|
||||
display : block;
|
||||
position : absolute;
|
||||
transform : translateX(calc(var(--ueb-position-x) * 1px)) translateY(calc(var(--ueb-position-y) * 1px));
|
||||
border-radius: var(--ueb-node-radius);
|
||||
box-shadow : 0 0 1px 0 black, 1px 4px 6px 0 rgba(0, 0, 0, 0.3);
|
||||
will-change : transform;
|
||||
}
|
||||
|
||||
.ueb-grid[data-drag-scrolling="false"] ueb-selector[data-selecting="false"]~ueb-node {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.ueb-node-border {
|
||||
margin : -3px;
|
||||
padding : 3px;
|
||||
border-radius: calc(var(--ueb-node-radius) * 1.4);
|
||||
}
|
||||
|
||||
.ueb-selected {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.ueb-selected>.ueb-node-border {
|
||||
background-image:
|
||||
linear-gradient(to right, #f1b000 0%, #f1b000 100%),
|
||||
linear-gradient(to bottom, #f1b000 0%, #cc6700 100%),
|
||||
linear-gradient(to right, #cc6700 0%, #cc6700 100%),
|
||||
linear-gradient(to bottom, #f1b000 0%, #cc6700 100%);
|
||||
background-size : 100% 7px, 7px 100%, 100% 7px, 7px 100%;
|
||||
background-position: top, right, bottom, left;
|
||||
background-repeat : repeat-x, repeat-y, repeat-x, repeat-y;
|
||||
outline : 3px solid #cc6700;
|
||||
outline-offset : -6px;
|
||||
}
|
||||
|
||||
.ueb-node-content {
|
||||
position : relative;
|
||||
padding : 1px;
|
||||
box-shadow : inset 0 0 2px 0 black;
|
||||
border-radius: var(--ueb-node-radius);
|
||||
background : rgba(0, 0, 0, 0.7);
|
||||
overflow : hidden;
|
||||
}
|
||||
|
||||
.ueb-node-header {
|
||||
padding : 0.2em 0.7em;
|
||||
box-shadow : inset 0 1px 2px 0 #313631, inset 0 2px 0 0 #92c381;
|
||||
border-radius: var(--ueb-node-radius) var(--ueb-node-radius) 0 0;
|
||||
background : linear-gradient(170deg, #5f815a 0%, #5f815a 50%, transparent 100%);
|
||||
color : #c0c0c0;
|
||||
font-weight : 600;
|
||||
white-space : nowrap;
|
||||
}
|
||||
|
||||
.ueb-node-name {
|
||||
background: radial-gradient(closest-side, rgba(0, 0, 0, 0.5) 0%, transparent 90%);
|
||||
margin : -0.1em -1.6em;
|
||||
padding : 0.1em 1.6em;
|
||||
}
|
||||
|
||||
.ueb-node-body {
|
||||
display : flex;
|
||||
padding : 6px 0;
|
||||
color : white;
|
||||
font-weight: 100;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ueb-node-inputs {
|
||||
margin-right: auto;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.ueb-node-outputs {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
ueb-pin {
|
||||
display: block;
|
||||
padding: 1px 2px;
|
||||
}
|
||||
|
||||
.ueb-grid[data-drag-scrolling="false"] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
ueb-selector[data-selecting="false"]~ueb-node ueb-pin:hover {
|
||||
background: var(--ueb-node-value-background);
|
||||
}
|
||||
|
||||
.ueb-grid[data-drag-scrolling="false"] ueb-selector[data-selecting="false"]~ueb-node ueb-pin .ueb-node-value-icon {
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.ueb-node-value-icon {
|
||||
display : inline-block;
|
||||
position : relative;
|
||||
width : 0.85em;
|
||||
height : 0.85em;
|
||||
vertical-align: baseline;
|
||||
margin : 0 0.4em -1px 0.1em;
|
||||
}
|
||||
|
||||
.ueb-node-value-icon::before {
|
||||
content : "";
|
||||
display : block;
|
||||
position : absolute;
|
||||
top : 0;
|
||||
right : 0;
|
||||
bottom : 0;
|
||||
left : 0;
|
||||
border : 2px solid var(--ueb-node-value-color);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.ueb-node-value-fill::before {
|
||||
background: var(--ueb-node-value-color);
|
||||
}
|
||||
|
||||
.ueb-node-value-icon::after {
|
||||
content : "";
|
||||
display : block;
|
||||
position : absolute;
|
||||
top : calc(50% - 0.3em);
|
||||
left : calc(100% + 1px);
|
||||
width : 0;
|
||||
height : 0;
|
||||
border-top : 0.3em solid transparent;
|
||||
border-bottom: 0.3em solid transparent;
|
||||
border-left : 0.3em solid var(--ueb-node-value-color);
|
||||
}
|
||||
|
||||
.ueb-selector {
|
||||
display : block;
|
||||
position : absolute;
|
||||
visibility: hidden;
|
||||
top : 0;
|
||||
left : 0;
|
||||
width : 0;
|
||||
height : 0;
|
||||
background-image:
|
||||
/* Top */
|
||||
repeating-linear-gradient(90deg,
|
||||
transparent,
|
||||
transparent calc(1px / var(--ueb-scale)),
|
||||
white calc(2px / var(--ueb-scale)),
|
||||
white calc(7px / var(--ueb-scale)),
|
||||
transparent calc(7px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
repeating-linear-gradient(90deg,
|
||||
black,
|
||||
black calc(8px / var(--ueb-scale)),
|
||||
transparent calc(9px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
/* Bottom */
|
||||
repeating-linear-gradient(90deg,
|
||||
transparent,
|
||||
transparent calc(1px / var(--ueb-scale)),
|
||||
white calc(2px / var(--ueb-scale)),
|
||||
white calc(7px / var(--ueb-scale)),
|
||||
transparent calc(7px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
repeating-linear-gradient(90deg,
|
||||
black,
|
||||
black calc(8px / var(--ueb-scale)),
|
||||
transparent calc(9px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
/* Left */
|
||||
repeating-linear-gradient(180deg,
|
||||
transparent,
|
||||
transparent calc(1px / var(--ueb-scale)),
|
||||
white calc(1px / var(--ueb-scale)),
|
||||
white calc(7px / var(--ueb-scale)),
|
||||
transparent calc(7px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
repeating-linear-gradient(180deg,
|
||||
black,
|
||||
black calc(8px / var(--ueb-scale)),
|
||||
transparent calc(9px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
/* Right */
|
||||
repeating-linear-gradient(0deg,
|
||||
transparent,
|
||||
transparent calc(1px / var(--ueb-scale)),
|
||||
white calc(2px / var(--ueb-scale)),
|
||||
white calc(7px / var(--ueb-scale)),
|
||||
transparent calc(7px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale))),
|
||||
repeating-linear-gradient(0deg,
|
||||
black,
|
||||
black calc(8px / var(--ueb-scale)),
|
||||
transparent calc(9px / var(--ueb-scale)),
|
||||
transparent calc(11px / var(--ueb-scale)));
|
||||
background-size:
|
||||
/* Top */
|
||||
100% calc(1px / var(--ueb-scale)),
|
||||
100% calc(3px / var(--ueb-scale)),
|
||||
/* Bottom */
|
||||
100% calc(1px / var(--ueb-scale)),
|
||||
100% calc(3px / var(--ueb-scale)),
|
||||
/* Left */
|
||||
calc(1px / var(--ueb-scale)) 100%,
|
||||
calc(3px / var(--ueb-scale)) 100%,
|
||||
/* Right */
|
||||
calc(1px / var(--ueb-scale)) 100%,
|
||||
calc(3px / var(--ueb-scale)) 100%;
|
||||
background-position:
|
||||
/* Top */
|
||||
0 calc(1px / var(--ueb-scale)), 0 0,
|
||||
/* Bottom */
|
||||
0 calc(100% - 1px / var(--ueb-scale)), 0 100%,
|
||||
/* Left */
|
||||
calc(1px / var(--ueb-scale)) 0, 0 0,
|
||||
/* Right */
|
||||
calc(100% - 1px / var(--ueb-scale)) 0, 100% 0;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
ueb-selector>* {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
ueb-selector[data-selecting="true"] {
|
||||
visibility: visible;
|
||||
top : min(var(--ueb-select-from-y) * 1px, var(--ueb-select-to-y) * 1px);
|
||||
left : min(var(--ueb-select-from-x) * 1px, var(--ueb-select-to-x) * 1px);
|
||||
width : calc(max(var(--ueb-select-from-x) - var(--ueb-select-to-x), var(--ueb-select-to-x) - var(--ueb-select-from-x)) * 1px);
|
||||
height : calc(max(var(--ueb-select-from-y) - var(--ueb-select-to-y), var(--ueb-select-to-y) - var(--ueb-select-from-y)) * 1px);
|
||||
}
|
||||
Reference in New Issue
Block a user