Announcement

Collapse
No announcement yet.

Custom Bluprint nodes with C++ function code in-editor :-o

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    #31
    Hmm... So, apparently it's possible to do it.
    I've just packaged a game and ran it printing the script's result:








    What I did:

    * Custom blueprint skeleton which stores the script while in Editor ( UBlueprint* class )
    * A shiTon of custom K2Node_ classes I've created to integrate code into the Blueprint Graph
    * The custom node parses the script, generates "tokens" and then converts the script to Blueprint functions.
    * Unreal do its thing as usual as if everything were made with nodes (in fact it doesnt even know the script exists).
    * So from there it runs as a normal blueprint function which can be nativized to C++ as well.

    What I didn't do:

    * VMs... No additional Virtual Machines such as Python's running attached to the game. Script tested was "compiled" to auto generated blueprint functions.
    * A "real" version of this parser will require a database, maybe a big dummy UObject, mapping UFunctions to script keywords. I'm not even close from doing that lol.

    Big challenge:

    * Next step would be auto generation of Pins from variables declared within the script. This is a hell of a complex task to do without breaking the Blueprint Graph.



    I may play some more with this on my free sundays, was fun
    | Finite State Machine | Auto-Save Plugin | USQLite Plugin | Object-Pool | Sound-Occlusion | Anti-Cheat Plugin | Property Transfer Tool | Magic Nodes |

    Comment


      #32
      So what you did is effectively create UnrealScript node ;p If you gonna od this you could as well follow old syntax
      =========
      My Tutorials:
      Basic knowledge about Classes and UObject environment and stuff like that

      Comment


        #33
        BrUnO XaVIeR Wow, that is really cool. Other than being able to write script instead of using pre-made nodes what benefits could it bring? Theoretically could we expose C++ fully to BPs this way without performance hit? (iirc exposing C++ fully to BPs would slow things down). Would love to see where/how far this goes. Please do have more fun! :P
        HeadsAndBrains
        MARKETPLACE | YouTube

        Comment


          #34
          1 Script = 1 Blueprint Function.
          That is what Unreal understands after I tell it to delete the script after converting it to a "Graph"...

          The "script" only exist in the Editor, so whatever you can do with a Blueprint Function equates to what you could do with this node. That includes calling UFunctions not exposed to Blueprint Graphs.
          (UFunctions yes, native C++ functions no)

          Unreal has a ton of UFunctions "hidden", not exposed, to Blueprint Graphs; this could be a way to access them easily.

          Also, the "benefit" I dig the most is the possibility of "writing nodes" faster than dragging pins wires around which is sometimes annoying for simple "for loops", array/set manipulations, etc... Typing words to do things like is simply faster than dragging wires around.


          But anyway, I don't have the human resources to effectively develop something "this big". A fully working scripting node would require a team working on it full-time, it's a lot of code to maintain.

          I was just curious to see if it would run at all
          I will learn how to generate node pins extracted from the compiled scripts, after that I am probably done with this!
          | Finite State Machine | Auto-Save Plugin | USQLite Plugin | Object-Pool | Sound-Occlusion | Anti-Cheat Plugin | Property Transfer Tool | Magic Nodes |

          Comment


            #35
            Originally posted by BrUnO XaVIeR View Post
            1 Script = 1 Blueprint Function.
            That is what Unreal understands after I tell it to delete the script after converting it to a "Graph"...

            The "script" only exist in the Editor, so whatever you can do with a Blueprint Function equates to what you could do with this node. That includes calling UFunctions not exposed to Blueprint Graphs.
            (UFunctions yes, native C++ functions no)

            Unreal has a ton of UFunctions "hidden", not exposed, to Blueprint Graphs; this could be a way to access them easily.

            Also, the "benefit" I dig the most is the possibility of "writing nodes" faster than dragging pins wires around which is sometimes annoying for simple "for loops", array/set manipulations, etc... Typing words to do things like is simply faster than dragging wires around.


            But anyway, I don't have the human resources to effectively develop something "this big". A fully working scripting node would require a team working on it full-time, it's a lot of code to maintain.

            I was just curious to see if it would run at all
            I will learn how to generate node pins extracted from the compiled scripts, after that I am probably done with this!
            Thanks for explanation. Calling non-exposed UFunctions is what I meant. And yes, there are times I wish I could write some scripts instead of playing with nodes.

            You have probably thought/tried this but you should check out math node to see how they did it. It is kind of similar on the outside at least.

            Well now that we know it can be done, we'll just ask Epic to implement it as a feature, surely they'll do it ... oh wait, we don't even have Quats in BPs by default . Yes I'm and will forever be salty about that.

            Anyways, thanks for your awesome contributions .
            HeadsAndBrains
            MARKETPLACE | YouTube

            Comment


              #36
              Blueprints with some kind of Scripting node, similar to the BP 'Math' node...
              What's not to like? It always seemed like a node like this was on the cards.
              Epic would've created something like this by now too, except for 'Forknite'.
              This is another mind blowing project Bruno similar to your Property Copier.

              Comment


                #37
                I went full retãrd... Changed the custom K2Node_ system to generate C++ classes out of itself;
                Now, making use of Editor's "hot reload" feature, I'm writing C++ nodes from inside Blueprints and using those nodes to code their own source code... Blueception!






                ( Game Project's main Build.cs now gonna need this )



                Self-generated Node class:



                Runtime result:




                But now it only works on projects with C++ source code (100% Blueprint projects cannot use hot reload I guess, not sure)
                | Finite State Machine | Auto-Save Plugin | USQLite Plugin | Object-Pool | Sound-Occlusion | Anti-Cheat Plugin | Property Transfer Tool | Magic Nodes |

                Comment


                  #38
                  So, I figure out how to generate the pins dynamically from code...
                  Works well, but there's two problems:

                  * For some reason no matter what I do, default values are ignored.
                  * Now because pins when hot reloaded, trying to refresh pointer to the runtime class, I get crash probably because it store the new class inside a new DLL.


                  Edit:

                  Fixed the crash post hot-reload by changing from this:
                  Code:
                  TWeakObjectPtr<UMagicNodeRuntimeObject>
                      RuntimeScriptObject = NewObject<UMagicNodeRuntimeObject>(this,Class,*Name,RF_NoFlags);
                  to doing this instead (was just a gamble that ended up well):
                  Code:
                  TWeakObjectPtr<UMagicNodeRuntimeObject>
                      RuntimeScriptObject = NewObject<UMagicNodeRuntimeObject>(GetTransientPackage(),Class,*Name,(RF_Transient & RF_Dynamic));

                  Packaged game now is happy:
                  [2018.12.02-00.43.41:526][ 0]LogTemp: Warning: Hello World! | Output Value is: 55.000000

                  And now, after 5 ~ 9 seconds of hot reload, when I click the "refresh" button on script panel, the new variables from script are loaded as pin while old pins have their values kept intact....

                  I now consider this experiment a functional success

                  Last edited by BrUnO XaVIeR; 12-01-2018, 10:08 PM.
                  | Finite State Machine | Auto-Save Plugin | USQLite Plugin | Object-Pool | Sound-Occlusion | Anti-Cheat Plugin | Property Transfer Tool | Magic Nodes |

                  Comment


                    #39
                    Improve in-node code editor a bit and have setup a "script parser" (it takes your code in node editor and generates a C++ class out of it that later can be compiled by the Engine, instead of running yet another virtual machine which slows things down):


                    | Finite State Machine | Auto-Save Plugin | USQLite Plugin | Object-Pool | Sound-Occlusion | Anti-Cheat Plugin | Property Transfer Tool | Magic Nodes |

                    Comment


                      #40
                      Originally posted by BrUnO XaVIeR View Post
                      Improve in-node code editor a bit and have setup a "script parser" (it takes your code in node editor and generates a C++ class out of it that later can be compiled by the Engine, instead of running yet another virtual machine which slows things down):


                      How does it work with referencing Blueprint Variables?

                      Comment


                        #41
                        Originally posted by Raildex_ View Post

                        How does it work with referencing Blueprint Variables?
                        You declare variables in the body of the node's Execute function; (then compile)

                        The system transforms the declaration into "pins"...
                        Code away using the variables declared in function body, when the node is executed by the Blueprint the value of variable in function body is whatever value you have wired to the generated pin.

                        It will take the value of pins in Blueprint node and send to the C++ function written by you, automatically.

                        I think it's an interesting way to learn C++, no need to setup class files, modules, project files in visual studio, etc
                        | Finite State Machine | Auto-Save Plugin | USQLite Plugin | Object-Pool | Sound-Occlusion | Anti-Cheat Plugin | Property Transfer Tool | Magic Nodes |

                        Comment


                          #42
                          You really never needed to make VS project
                          What you doing is interesting, keep it up. Does it create static function btw?
                          Last edited by Shadowriver; 12-12-2018, 02:04 AM.
                          =========
                          My Tutorials:
                          Basic knowledge about Classes and UObject environment and stuff like that

                          Comment


                            #43
                            Originally posted by BrUnO XaVIeR View Post

                            You declare variables in the body of the node's Execute function; (then compile)

                            The system transforms the declaration into "pins"...
                            Code away using the variables declared in function body, when the node is executed by the Blueprint the value of variable in function body is whatever value you have wired to the generated pin.

                            It will take the value of pins in Blueprint node and send to the C++ function written by you, automatically.

                            I think it's an interesting way to learn C++, no need to setup class files, modules, project files in visual studio, etc
                            sounds promising

                            Comment


                              #44
                              Originally posted by Shadowriver View Post
                              What you doing is interesting, keep it up. Does it create static function btw?
                              An UObject is created by the K2Node_ custom node then the K2 uses KismetCompiler utilities to copy the generated UFunction from that UObject, spawn that "node" (invisible) onto the Ubergraph, move it's own connections from generated pins into the spawned node, detach itself to not be called twice and then let the Blueprint Graph do its job executing the "generated" node.
                              Later the UObject is GCed if there's no more K2Node_ referencing him anymore (Kismet Compiler has no use to it anymore so it's garbage collected).
                              It's the same thing all Blueprint Nodes behind the scenes in runtime..



                              Originally posted by Shadowriver View Post
                              You really never needed to make VS project
                              I'm building my own IntelliSense tech.
                              I call it IntelliNonsenseâ„¢
                              | Finite State Machine | Auto-Save Plugin | USQLite Plugin | Object-Pool | Sound-Occlusion | Anti-Cheat Plugin | Property Transfer Tool | Magic Nodes |

                              Comment


                                #45
                                LOL.. this is totally not Unity rofl





                                | Finite State Machine | Auto-Save Plugin | USQLite Plugin | Object-Pool | Sound-Occlusion | Anti-Cheat Plugin | Property Transfer Tool | Magic Nodes |

                                Comment

                                Working...
                                X