Skip to content
This repository has been archived by the owner on Aug 29, 2024. It is now read-only.

Commit

Permalink
Add array variable
Browse files Browse the repository at this point in the history
  • Loading branch information
ShaitanLyss committed Jun 25, 2024
1 parent 9b2c38c commit ab15f10
Show file tree
Hide file tree
Showing 24 changed files with 1,012 additions and 720 deletions.
12 changes: 10 additions & 2 deletions src/lib/editor/Editor.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import type { NodeEditor, NodeEditorSaveData, NodeFactory, setupEditor, Node } from '$rete';
import { XmlNode } from '$rete/node/XML/XmlNode';
import type { EditorExample } from '$rete/example/types';
import { capitalize, newLocalId, newUuid } from '$utils';
Expand Down Expand Up @@ -223,14 +224,21 @@
if (!factory) throw new Error('No factory');
const editor = factory.getEditor();
const node = editor.getNode(event.socketData.nodeId);
const value = node.getData(event.socketData.key);
const value =
node instanceof XmlNode
? node.state.attributeValues[event.socketData.key]
: node.getData(event.socketData.key);
console.log('promote to variable: node', node);
console.log('promote to variable: value', value);
console.log('promote to variable: event.socketData.payload', event.socketData.payload);
const variable: Variable = {
exposed: false,
highlighted: false,
id: newUuid('variable'),
name: event.socketData.payload.name,
type: event.socketData.payload.type,
value
value,
isArray: event.socketData.payload.isArray
};
factory.getEditor().variables.set({
...get(factory.getEditor().variables),
Expand Down
30 changes: 30 additions & 0 deletions src/lib/editor/EditorSwitcher.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@
document.documentElement.classList.remove('hide-minimap');
}
}
let lastSearch = '';
</script>

<BoxSelection
Expand All @@ -287,6 +288,35 @@

<div
bind:this={container}
use:keyboardShortcut={{
key: 'f',
ctrl: true,
action() {
modalStore.trigger({
type: 'prompt',
title: $_('graph-editor.find-prompt.title'),
value: '',
buttonTextCancel: $_('button.cancel'),
buttonTextSubmit: $_('button.search'),
valueAttr: { required: true, placeholder: $_('graph-editor.find-prompt.placeholder') },
response(r) {
lastSearch = typeof r === 'string' ? r.trim() : '';
if (typeof r === 'string' && r.trim()) {
const node = activeFactory?.findNode(r);
activeFactory?.focusNode(node);
}
}
});
}
}}
use:keyboardShortcut={{
key: 'n',

action() {
const node = activeFactory?.findNode(lastSearch);
activeFactory?.focusNode(node);
}
}}
use:keyboardShortcut={{
key: 'a',
ctrl: true,
Expand Down
111 changes: 99 additions & 12 deletions src/lib/editor/code-editor-integration/CodeEditorIntegration.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import { get } from 'svelte/store';
import type { XmlAttributeDefinition } from '$rete/node/XML/types';
import { MakeArrayNode } from '$rete/node/data/MakeArrayNode';
import { GetNameNode } from '$rete/node/XML/GetNameNode';
export let editorContext: EditorContext;
let codeEditorPromise: Promise<ICodeEditor>;
Expand Down Expand Up @@ -83,7 +84,8 @@
async function push() {
const { NodeEditor, NodeFactory } = await import('$rete');
const geosSchema = newGeosContext.geosSchema;
const rootTypes = ['Problem', ...Object.keys(get(newGeosContext.typesTree)['Problem'] ?? {})];
console.log('pizza', get(newGeosContext.typesTree));
const factory = editorContext.getActiveFactory();
if (!factory) throw new ErrorWNotif('No active editor');
const editor = factory.getEditor();
Expand All @@ -105,7 +107,12 @@
editor: tmp_editor,
area: tmp_area
});
const nameToXmlNode = new Map<string, XmlNode>();
const groupNameLinks: { source: string; target: { node: Node; key: string } }[] = [];
/**
* Recursively converts the parsed xml to editor nodes
*/
async function xmlToEditor(xml: ParsedXmlNodes, schema: GeosSchema, parent?: Node) {
for (const xmlNode of xml) {
const xmlTag = getElementFromParsedXml(xmlNode);
Expand All @@ -115,20 +122,22 @@
console.warn('Complex type not found');
continue;
}
if (!xmlTag) throw new ErrorWNotif('Missing xml tag in parsed xml node');
const hasNameAttribute = complexType.attributes.has('name');
const xmlAttributes: Record<string, unknown> = getXmlAttributes(
xmlNode as Record<string, ParsedXmlNodes>
);
const arrayAttrs = new Map<string, string[]>();
for (const [k, v] of Object.entries(xmlAttributes as Record<string, string>)) {
const attrType = complexType.attributes.get(k);
const attrDef = complexType.attributes.get(k);
if (!attrType) {
if (!attrDef) {
console.warn('Attribute type not found', k, v);
continue;
}
if (attrType.type === 'R1Tensor') {
if (attrDef.type === 'R1Tensor') {
const a = v
.slice(1, -1)
.split(',')
Expand All @@ -138,6 +147,10 @@
continue;
}
if (attrDef.type.endsWith('Tensor')) {
continue;
}
const isArray = /^\s*?\{\s*?/.test(v);
if (!isArray) continue;
Expand All @@ -156,14 +169,14 @@
) as XMLNestedArrays | undefined;
if (candidate === undefined) continue;
if (attrType.type.startsWith('real') && attrType.type.endsWith('array2d')) {
if (attrDef.type.startsWith('real') && attrDef.type.endsWith('array2d')) {
console.log('candidate', candidate);
xmlAttributes[k] = candidate.map((t) => {
if (typeof t === 'string')
throw new ErrorWNotif('Expected array for type real array2d');
return { x: t[0], y: t[1], z: t[2] };
});
arrayAttrs.set(attrType.name, xmlAttributes[k] as string[]);
arrayAttrs.set(attrDef.name, xmlAttributes[k] as string[]);
continue;
}
// put nested arrays back to xml notation
Expand All @@ -184,8 +197,9 @@
}
const array1d = candidate.map(arraysToXmlNotation);
xmlAttributes[k] = array1d;
arrayAttrs.set(attrType.name, array1d);
arrayAttrs.set(attrDef.name, array1d);
}
console.log('arrayAttrs', arrayAttrs);
const node = await tmp_factory.addNode(XmlNode, {
label: xmlTag,
initialValues: xmlAttributes,
Expand Down Expand Up @@ -217,20 +231,76 @@
}
});
// Automatically select output of root types like Solvers, Mesh...
if (rootTypes.includes(complexType.name.trim())) {
console.log('good pizza', complexType.name, rootTypes);
node.selectOutput('value');
}
if (hasNameAttribute) {
const name = xmlAttributes['name'] as string;
if (!nameToXmlNode.has(name)) {
nameToXmlNode.set(name, node);
}
}
for (const [k, a] of arrayAttrs.entries()) {
const attrDef = complexType.attributes.get(k);
if (!attrDef) throw new ErrorWNotif("Couldn't find simple type for array attribute");
const initialValues: Record<string, unknown> = {};
for (const [i, t] of a.entries()) {
const attrType = complexType.attributes.get(k);
if (!attrType) throw new ErrorWNotif("Couldn't find simple type for array attribute");
console.log('attrType', attrType);
initialValues[`data-${i}`] = t;
}
console.log('zzzz');
const makeArrayNode = await tmp_factory.addNode(MakeArrayNode, {
initialValues,
numPins: a.length
});
const conn = await tmp_editor.addNewConnection(makeArrayNode, 'array', node, k);
// Gather array group name links
if (attrDef.type === 'groupNameRef_array') {
for (const [inputKey, t] of Object.entries(initialValues)) {
if (typeof t !== 'string') {
console.error(
'Value of type groupNameRef should be of string type, type :',
typeof t
);
continue;
}
groupNameLinks.push({
source: t,
target: {
node: makeArrayNode,
key: inputKey
}
});
}
}
await tmp_editor.addNewConnection(makeArrayNode, 'array', node, k);
}
// Gather group name links
for (const [k, v] of Object.entries(xmlAttributes)) {
const attrDef = complexType.attributes.get(k);
if (!attrDef) {
console.warn('Attribute type not found', k, v);
continue;
}
if (attrDef.type.startsWith('groupNameRef')) {
const isArray = attrDef.type.endsWith('array');
if (!isArray) {
if (typeof v !== 'string') {
console.error(
'Value of type groupNameRef should be of string type, type :',
typeof v
);
continue;
}
groupNameLinks.push({
source: v,
target: { node, key: k }
});
}
}
}
if (parent) {
Expand All @@ -243,6 +313,23 @@
}
console.log('Download: full_xml', full_xml);
await xmlToEditor(full_xml, geosSchema);
// TODO: name connections
const getNameNodes = new Map<string, GetNameNode>();
for (const { source, target } of groupNameLinks) {
const sourceNode = nameToXmlNode.get(source);
if (!sourceNode) {
console.warn('Source node not found', source);
continue;
}
if (!getNameNodes.has(source)) {
const getNameNode = await tmp_factory.addNode(GetNameNode, {});
getNameNodes.set(source, getNameNode);
await tmp_editor.addNewConnection(sourceNode, 'value', getNameNode, 'xml');
}
const getNameNode = getNameNodes.get(source)!;
await tmp_editor.addNewConnection(getNameNode, 'name', target.node, target.key);
}
console.log(await arrange.layout());
const area = factory.getArea();
let leftBound = 0;
Expand Down
54 changes: 54 additions & 0 deletions src/lib/editor/overlay/variables-list/ArrayEditorModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<script lang="ts">
import { getModalStore } from '@skeletonlabs/skeleton';
import { assignControl } from '$rete/customization/utils';
import { InputControl, type InputControlTypes } from '$rete/control/Control';
import InputControlComponent from '$rete/customization/presets/classic/components/InputControl.svelte';
const modalStore = getModalStore();
let { array, title, type } = $modalStore[0].meta;
let controls: InputControl<'unknown'>[] = [];
for (const [i, x] of array.entries()) {
addControl(i, x);
}
console.log(array);
function addControl(i: number, initial: unknown) {
const controlType = assignControl(type);
if (!controlType) throw new Error(`Control type not found for ${type}`);
const inputControl = new InputControl<'unknown', unknown>(controlType, {
initial,
change: (val) => {
console.log('change', val);
array[i] = val;
}
});
controls = [...controls, inputControl];
}
function addItem() {
array = [...array, undefined];
addControl(array.length - 1, undefined);
}
function validate() {
if ($modalStore[0].response) $modalStore[0].response(array);
modalStore.close();
}
</script>

<section class="p-8 space-y-8 bg-surface-200-700-token rounded-container-token">
<h2 class="h2">{title}</h2>
<ol class="space-y-2 max-h-[70vh] overflow-y-auto p-0.5">
{#each controls as control}
<InputControlComponent data={control} />
{/each}
</ol>
<div class="flex justify-end border-t-2 pt-4 gap-2 border-black">
<button type="button" class="btn variant-filled-tertiary" on:click={() => addItem()}>Add</button
>
<button type="button" class="btn variant-filled-primary" on:click={() => validate()}
>Validate</button
>
</div>
</section>
Loading

0 comments on commit ab15f10

Please sign in to comment.