vs_node_view 2.1.1 copy "vs_node_view: ^2.1.1" to clipboard
vs_node_view: ^2.1.1 copied to clipboard

A Visual Scripting toolkit to create and use your own VS widgets.

example/main.dart

import 'package:flutter/material.dart';
import 'package:vs_node_view/vs_node_view.dart';

void main() async {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        scaffoldBackgroundColor: const Color.fromARGB(255, 46, 46, 46),
      ),
      home: const Scaffold(body: VSNodeExample()),
    );
  }
}

class VSNodeExample extends StatefulWidget {
  const VSNodeExample({super.key});

  @override
  State<VSNodeExample> createState() => _VSNodeExampleState();
}

class _VSNodeExampleState extends State<VSNodeExample> {
  Iterable<String>? results;

  late VSNodeDataProvider nodeDataProvider;

  @override
  void initState() {
    super.initState();

    final nodeBuilders = [
      VSSubgroup(
        name: "Numbers",
        subgroup: [
          (Offset offset, VSOutputData? ref) => VSNodeData(
                type: "Parse int",
                widgetOffset: offset,
                inputData: [
                  VSStringInputData(
                    type: "Input",
                    initialConnection: ref,
                  )
                ],
                outputData: [
                  VSIntOutputData(
                    type: "Output",
                    outputFunction: (data) => int.parse(data["Input"]),
                  ),
                ],
              ),
          (Offset offset, VSOutputData? ref) => VSNodeData(
                type: "Sum",
                widgetOffset: offset,
                inputData: [
                  VSNumInputData(
                    type: "Input 1",
                    initialConnection: ref,
                  ),
                  VSNumInputData(
                    type: "Input 2",
                    initialConnection: ref,
                  )
                ],
                outputData: [
                  VSNumOutputData(
                    type: "output",
                    outputFunction: (data) {
                      return (data["Input 1"] ?? 0) + (data["Input 2"] ?? 0);
                    },
                  ),
                ],
              ),
        ],
      ),
      VSSubgroup(
        name: "Logik",
        subgroup: [
          (Offset offset, VSOutputData? ref) => VSNodeData(
                type: "Bigger then",
                widgetOffset: offset,
                inputData: [
                  VSNumInputData(
                    type: "First",
                    initialConnection: ref,
                  ),
                  VSNumInputData(
                    type: "Second",
                    initialConnection: ref,
                  ),
                ],
                outputData: [
                  VSBoolOutputData(
                    type: "Output",
                    outputFunction: (data) => data["First"] > data["Second"],
                  ),
                ],
              ),
          (Offset offset, VSOutputData? ref) => VSNodeData(
                type: "If",
                widgetOffset: offset,
                inputData: [
                  VSBoolInputData(
                    type: "Input",
                    initialConnection: ref,
                  ),
                  VSDynamicInputData(
                    type: "True",
                    initialConnection: ref,
                  ),
                  VSDynamicInputData(
                    type: "False",
                    initialConnection: ref,
                  ),
                ],
                outputData: [
                  VSDynamicOutputData(
                    type: "Output",
                    outputFunction: (data) =>
                        data["Input"] ? data["True"] : data["False"],
                  ),
                ],
              ),
        ],
      ),
      (Offset offset, VSOutputData? ref) {
        final controller = TextEditingController();
        final input = TextField(
          controller: controller,
          decoration: const InputDecoration(
            isDense: true,
            contentPadding: EdgeInsets.symmetric(horizontal: 0, vertical: 10),
          ),
        );

        return VSWidgetNode(
          type: "Input",
          widgetOffset: offset,
          outputData: VSStringOutputData(
            type: "Output",
            outputFunction: (data) => controller.text,
          ),
          child: Expanded(child: input),
          setValue: (value) => controller.text = value,
          getValue: () => controller.text,
        );
      },
      (Offset offset, VSOutputData? ref) => VSOutputNode(
            type: "Output",
            widgetOffset: offset,
            ref: ref,
          ),
    ];

    nodeDataProvider = VSNodeDataProvider(
      nodeManager: VSNodeManager(nodeBuilders: nodeBuilders),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        InteractiveVSNodeView(
          width: 5000,
          height: 5000,
          nodeDataProvider: nodeDataProvider,
        ),
        const Positioned(
          bottom: 0,
          right: 0,
          child: Legend(),
        ),
        Positioned(
          top: 0,
          right: 0,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              ElevatedButton(
                onPressed: () => setState(() {
                  final entries =
                      nodeDataProvider.nodeManager.getOutputNodes.map(
                    (e) => e.evaluate(
                      onError: (_, __) => Future.delayed(Duration.zero, () {
                        ScaffoldMessenger.of(context).showSnackBar(
                          const SnackBar(
                            backgroundColor: Colors.deepOrange,
                            content: Text('An error occured'),
                          ),
                        );
                      }),
                    ),
                  );

                  results = entries.map((e) => "${e.key}: ${e.value}");
                }),
                child: const Text("Evaluate"),
              ),
              if (results != null)
                ...results!.map(
                  (e) => Card(
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Text(e),
                    ),
                  ),
                ),
            ],
          ),
        ),
      ],
    );
  }
}

Map<String, Color> inputTypes = {
  "String": VSStringInputData(type: "legend").interfaceColor,
  "Int": VSIntInputData(type: "legend").interfaceColor,
  "Double": VSDoubleInputData(type: "legend").interfaceColor,
  "Num": VSNumInputData(type: "legend").interfaceColor,
  "Bool": VSBoolInputData(type: "legend").interfaceColor,
  "Dynamic": VSDynamicInputData(type: "legend").interfaceColor,
};

class Legend extends StatelessWidget {
  const Legend({super.key});

  @override
  Widget build(BuildContext context) {
    final List<Widget> widgets = [];

    final entries = inputTypes.entries;

    for (final entry in entries) {
      widgets.add(
        Row(
          children: [
            Text(entry.key),
            Icon(
              Icons.circle,
              color: entry.value,
            ),
            if (entry != entries.last) const Divider(),
          ],
        ),
      );
    }

    return Card(
        child: Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        children: widgets,
      ),
    ));
  }
}
9
likes
150
points
32
downloads

Publisher

verified publisherfirebon.de

Weekly Downloads

A Visual Scripting toolkit to create and use your own VS widgets.

Repository (GitHub)
View/report issues

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

flutter

More

Packages that depend on vs_node_view