Code Monkey home page Code Monkey logo

kznodes's Introduction

KZNodes - editors like Origami made easy.

Version License Platform

Watch demo

Have you ever wondered how you could create an editor like Origami? How about creating a subset of Origami in less than 100 lines of code?

Joining nodes is like functional programming, only visual.

Features:

  • Domain agnostic, can be used to create editors for:
    • Animations
    • 3D Graphics
    • Image processing
    • Data Processing
    • Artificial Inteligence
    • Anything that you can express as a data / function pipeline?
  • Sockets have data types, you specify what classes are supported, that way you never get unsupported connections.
  • Fully native with 0 dependencies
  • Slick looking out of the box
  • Ultra simple to create new node classes, want to add class that can be used to apply sqrtf to it's input? 3 lines of code.

NodeType creation

Think of NodeTypes like objc classes, they define common behaviour for all instances. You can create a new node class as follows:

[KZNNodeType registerType:@"sqrtf" inputs:@{ @"Input" : NSNumber.class } outputs:@{ @"Output" : NSNumber.class } processingBlock:^(KZNNode *node, NSDictionary *inputs, NSMutableDictionary *outputs) {
    outputs[@"Output"] = @(sqrtf([inputs[@"Input"] floatValue]));
  }];
  • sqrtf is the name
  • it has input socket "Input" that accepts NSNumbers
  • it has output socket "Output" that generates NSNumbers
  • Output = sqrtf(input)

There are also 2 more advanced creator functions:

  1. KZNNodeType withClass allows you to change base class used for a node, eg. use node with slider.
  2. KZNNodeType withBuilder allows you to use builder pattern instead of simplified syntax.

Setup block

You can also add setup block which will allow you to further configure new instances of your NodeType, eg. disable continuous slider.

Node evaluation mode

Nodes are lazy evaluated by default, they will only evaluate when there is a change on their sockets or connected nodes. Changes propagate to connections, so if you modify a node in the beginning of a graph it will propagate to all connected nodes.

If you mark node type to use continuous evaluation, it will evaluate 60 times per second if possible, eg. time node in sample app.

Built-in node classes

KZNNodeWithSlider

KZNNodeWithText

Adding new node classes

It's simple:

  1. Create a subclass of KZNNode
  2. Do whatever you want with it
  3. when you register Node type you can specify your class as baseClass, and reference it in processingBlock.

Installation and setup

KZNodes is distributed as a CocoaPod: pod 'KZNodes' so you can either add it to your existing project or clone this repository and play with it.

Roadmap & Contributing

  • Serialization of workspaces.
  • Idiot-proofing.
  • Lazy evaluation of sockets.

Pull-requests are welcomed.

It took me around 18h to get from idea to release so the code is likely to change before 1.0 release.

If you'd like to get specific features I'm available for iOS consulting.

Changelog

0.1.1

  • much nicer bezier curves, based on the-graph

0.1.0

  • initial release

License

KZNodes is available under the MIT license. See the LICENSE file for more info.

Author

Krzysztof Zablocki, [email protected]

Follow me on twitter.

Check-out my blog or GitHub profile for more cool stuff.

kznodes's People

Contributors

filemaster avatar krzysztofzablocki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kznodes's Issues

iPad - crash on start iOS 11

Building in Xcode 9. Runs fine in simulator but crashes when run on device.

Backtrace:

2017-11-02 13:24:19.857751+0000 KZNodes[387:21044] [DYMTLInitPlatform] platform initialization successful
2017-11-02 13:24:19.872168+0000 KZNodes[387:20887] *** Assertion failure in void swizzle(__unsafe_unretained Class, SEL, __strong RSSwizzleImpFactoryBlock)(), /Users/drh/dev/KZNodes/Example/Pods/RSSwizzle/RSSwizzle/RSSwizzle.m:190
2017-11-02 13:24:19.872381+0000 KZNodes[387:20887] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Selector performInjectionWithClass: not found in instance methods of class SFDynamicCodeInjection.'
*** First throw call stack:
(0x181b9a2d4 0x180de4528 0x181b9a1a8 0x18252e7fc 0x10076d178 0x10076cd84 0x100761e28 0x180de69cc 0x180de7a84 0x1007ce170 0x1007dece8 0x1007ddd40 0x1007dddfc 0x1007ce5e4 0x1007d3320 0x1007cd21c)
libc++abi.dylib: terminating with uncaught exception of type NSException

screen shot 2017-11-02 at 13 26 32

nicer curves

Nice work! ๐Ÿ‘ I've been building something similar on the web side: the-graph. Currently SVG-based, but I'm refactoring now to try to make it faster with more Canvas.

I put some work into making nice default bezier curves. If you like them, feel free to port to KZNodes.

screen shot 2014-11-06 at 12 19 29 pm

More notes or comments please.

Not to sound critical as I appreciate this is open source, but the code is very difficult to decipher for someone who's never seen it. More comments or a document of the architecture would be of immense help. For example the following was really confusing so I added some comments and indenting:

[KZNNodeType registerType:name inputs:@{ @"Image" : CIImage.class } outputs:@{ @"Output" : CIImage.class } processingBlock:^(id node, NSDictionary *inputs, NSMutableDictionary *outputs)
        {
            //processing Block definition
            //processing block only is called from evaluateWithTick:(..)
            
            // WHY NOT CIImage *image = [CIImage new]; ???
            // probably because image already has data since it is from an input socket
            CIImage *image = inputs[@"Image"];
              if (!image) {
                return;
              }
            
            // create a filter object with the input image:
            //Note in the following the list of key value pairs is "kCIInputImageKey, image, nil" where nil is the end of the list
            CIFilter *filter = [CIFilter filterWithName:filterName
                                       keysAndValues:kCIInputImageKey, image, nil];
            //apply the filter and set the output image returned:
            CIImage *outputImage = [filter outputImage];
            outputs[@"Output"] = outputImage;
        }
         ];

The above has two sets of paramaters named "inputs" and "outputs" (one for the method and one for the block) so I easily confused that inputs and outputs used in the block was the same as that for the method. That made the code appear incorrect per the line:

CIImage *image = inputs[@"Image"];

Because I thought inputs was: @{ @"Image" : CIImage.class } which would make
CIImage *image = CIImage.class which would not work.

Next you have 3 versions of the method registerType:
The first version does nothing more than call the second version having the param:
withClass:KZNNode.class
But you are calling this second version many times within KZPlaygroundExample.m so why have this first version?

In the third version of the registerType method you have the line:
self.nodeTypes[typeName] = type;

where nodeTypes is not actually a dictionary as it would appear at a glance, but is a class method that returns a dictionary. This line is actually "registering" the type. The whole method is creating and registering the type. KZNNodeType it appears is not just a type of node but is also serving as a registry and factory of types and in addition a factory of nodes.

Here is the definition of the class method but where I'm at now is trying to understand what it is doing exactly? (update: I'm thinking that this was a work around for Objective-C not supporting class properties until Xcode 8, correct me if I'm wrong):

+ (NSMutableDictionary *)nodeTypes
{
  NSMutableDictionary *nodeTypes = objc_getAssociatedObject(self, kNodeTypesKey);
  if (!nodeTypes) {
    nodeTypes = [NSMutableDictionary new];
  }
  objc_setAssociatedObject(self, kNodeTypesKey, nodeTypes, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  return nodeTypes;
}

In the project there are pod dependencies: KZPlayground, NHBalancedFlowLayout, RSSwizzle, and dyci. From their names I can guess what they are for, but some documentation of where, why and how much they are used in the project would be of help. When I looked at this project initially I had no idea that it used your own version of a Playground.

I'm still wondering why the project is seeming to use Class or why it needs it unless the plan were to do some runtime injection of classes.

I may add more comments to this as I proceed. The UI concept of nodes and sockets and connections seems too tightly coupled to the graph data model of same.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.