Fix missing edges (#8461)

- Closes #8420
- Fix missing edges
- Fix displayed output type of node
- Verify that undos properly restore edges

# Important Notes
None
This commit is contained in:
somebody1234 2023-12-12 08:36:34 +10:00 committed by GitHub
parent 0974d5ff1e
commit 3d76459ba7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 30 deletions

View File

@ -1,5 +1,7 @@
<script setup lang="ts">
import NodeWidget from '@/components/GraphEditor/NodeWidget.vue'
import { ForcePort } from '@/providers/portInfo'
import type { WidgetInput } from '@/providers/widgetRegistry'
import { defineWidget, widgetProps } from '@/providers/widgetRegistry'
import { Ast } from '@/util/ast'
import { computed } from 'vue'
@ -8,6 +10,22 @@ const props = defineProps(widgetProps(widgetDefinition))
const spanClass = computed(() => props.input.typeName())
const children = computed(() => [...props.input.children()])
function transformChild(child: WidgetInput) {
if (!(props.input instanceof Ast.Ast)) return child
if (props.input instanceof Ast.PropertyAccess) {
if (child === props.input.lhs) {
return new ForcePort(child)
}
} else if (props.input instanceof Ast.OprApp) {
if (child === props.input.rhs || child === props.input.lhs) {
return new ForcePort(child)
}
} else if (props.input instanceof Ast.UnaryOprApp && child === props.input.argument) {
return new ForcePort(child)
}
return child
}
</script>
<script lang="ts">
@ -18,7 +36,11 @@ export const widgetDefinition = defineWidget((expression) => expression instance
<template>
<span :class="['Tree', spanClass]"
><NodeWidget v-for="(child, index) in children" :key="child.astId ?? index" :input="child" />
><NodeWidget
v-for="(child, index) in children"
:key="child.astId ?? index"
:input="transformChild(child)"
/>
</span>
</template>

View File

@ -3,6 +3,7 @@ import NodeWidget from '@/components/GraphEditor/NodeWidget.vue'
import { injectGraphNavigator } from '@/providers/graphNavigator'
import { injectGraphSelection } from '@/providers/graphSelection'
import { ForcePort, injectPortInfo, providePortInfo } from '@/providers/portInfo'
import type { WidgetInput } from '@/providers/widgetRegistry'
import { Score, defineWidget, widgetProps } from '@/providers/widgetRegistry'
import { injectWidgetTree } from '@/providers/widgetTree'
import { useGraphStore } from '@/stores/graph'
@ -25,8 +26,9 @@ import {
watchEffect,
} from 'vue'
const props = defineProps(widgetProps<WidgetInput>(widgetDefinition))
const graph = useGraphStore()
const props = defineProps(widgetProps(widgetDefinition))
const navigator = injectGraphNavigator()
const tree = injectWidgetTree()
@ -61,34 +63,29 @@ watchEffect((onCleanup) => {
// TODO: This should part of the `WidgetPort` component. But first, we need to make sure that the
// ports are always created when necessary.
const portRect = shallowRef<Rect>()
const rectUpdateIsUseful = computed(() => isHovered.value || hasConnection.value)
const isRectUpdateUseful = computed(() => isHovered.value || hasConnection.value)
const randomUuid = uuidv4() as ExprId
const portId = computed(() => {
const ast =
props.input instanceof Ast.Ast
? props.input
: props.input instanceof ArgumentAst || props.input instanceof ForcePort
? props.input.ast
: undefined
return ast?.astId ?? randomUuid
})
providePortInfo(
proxyRefs({
portId,
connected: hasConnection,
}),
const innerWidget = computed(() =>
props.input instanceof ForcePort ? props.input.ast : props.input,
)
const ast = computed(() =>
props.input instanceof Ast.Ast
? props.input
: props.input instanceof ArgumentAst || props.input instanceof ForcePort
? props.input.ast
: undefined,
)
const portId = computed(() => ast.value?.astId ?? randomUuid)
providePortInfo(proxyRefs({ portId, connected: hasConnection }))
watch(nodeSize, updateRect)
onUpdated(() => {
nextTick(updateRect)
})
onUpdated(() => nextTick(updateRect))
useRaf(toRef(tree, 'hasActiveAnimations'), updateRect)
watch(
() => [portId.value, portRect.value, rectUpdateIsUseful.value] as const,
() => [portId.value, portRect.value, isRectUpdateUseful.value] as const,
([id, rect, updateUseful], _, onCleanup) => {
if (id != null && rect != null && updateUseful) {
graph.updateExprRect(id, rect)
@ -112,13 +109,6 @@ function updateRect() {
if (portRect.value != null && localRect.equals(portRect.value)) return
portRect.value = localRect
}
const innerWidget = computed(() => {
if (props.input instanceof ForcePort) {
return props.input.ast
} else {
return props.input
}
})
</script>
<script lang="ts">

View File

@ -2,6 +2,8 @@
import NodeWidget from '@/components/GraphEditor/NodeWidget.vue'
import ListWidget from '@/components/widgets/ListWidget.vue'
import { injectGraphNavigator } from '@/providers/graphNavigator'
import { ForcePort } from '@/providers/portInfo'
import type { WidgetInput } from '@/providers/widgetRegistry'
import { Score, defineWidget, widgetProps } from '@/providers/widgetRegistry'
import { useGraphStore } from '@/stores/graph'
import { Ast, RawAst } from '@/util/ast'
@ -26,6 +28,10 @@ const navigator = injectGraphNavigator(true)
</script>
<script lang="ts">
function forcePort(item: WidgetInput) {
return item instanceof Ast.Ast ? new ForcePort(item) : item
}
export const widgetDefinition = defineWidget(Ast.Ast, {
priority: 1000,
score: (props) =>
@ -47,7 +53,7 @@ export const widgetDefinition = defineWidget(Ast.Ast, {
contenteditable="false"
>
<template #default="{ item }">
<NodeWidget :input="item" />
<NodeWidget :input="forcePort(item)" />
</template>
</ListWidget>
</template>