diff --git a/src/steam/engine/node-builder.hpp b/src/steam/engine/node-builder.hpp index 783cf9d65..7ed3175ee 100644 --- a/src/steam/engine/node-builder.hpp +++ b/src/steam/engine/node-builder.hpp @@ -350,6 +350,25 @@ namespace engine { return move(*this); } + /** + * Embed the explicitly given parameter-functor into the FeedPrototype, + * so that it will be called on each Node invocation to generate parameters + * to be passed into the actual processing function. The TurnoutSystem acts + * as source for the base coordinates, typically the _absolute nominal Time._ + * @return adapted PortBuilder marked with the `FeedPrototype` holding \a PFX + */ + template + auto + attachParamFun (PFX paramFunctor) + { + using AdaptedWeavingBuilder = typename WAB::template Adapted; + using AdaptedPortBuilder = PortBuilder; + // + return AdaptedPortBuilder{move(*this) + ,weavingBuilder_.adaptParam (move (paramFunctor)) + }; + } + /*************************************************************//** * Terminal: complete the Port wiring and return to the node level. diff --git a/src/steam/engine/weaving-pattern-builder.hpp b/src/steam/engine/weaving-pattern-builder.hpp index 383bd225e..b6c392871 100644 --- a/src/steam/engine/weaving-pattern-builder.hpp +++ b/src/steam/engine/weaving-pattern-builder.hpp @@ -286,6 +286,28 @@ namespace engine { , prototype_{move (adaptedPrototype)} { } + + /** type builder for FeedPrototype adapted to another parameter-fun */ + template + using AdaptedPrototype = typename PROT::template Adapted; + template + using Adapted = WeavingBuilder>; + + /** Adapt a parameter-functor into the _Feed Prototype,_ + * so that it is invoked whenever a new `FeedManifold` is built. + * @return adapted WeavingBuilder marked with changed `FeedManifold` type. + */ + template + auto + adaptParam (PFX paramFunctor) + { + using AdaptedWeavingBuilder = Adapted; + // + return AdaptedWeavingBuilder{move(*this) + ,prototype_.moveAdapted (move (paramFunctor)) + }; + } + WeavingBuilder&& attachToLeadPort (ProcNode& lead, uint portNr) { diff --git a/tests/core/steam/engine/node-builder-test.cpp b/tests/core/steam/engine/node-builder-test.cpp index c64c44ece..89cbab87c 100644 --- a/tests/core/steam/engine/node-builder-test.cpp +++ b/tests/core/steam/engine/node-builder-test.cpp @@ -66,19 +66,32 @@ namespace test { CHECK (watch(node).isSrc()); CHECK (watch(node).ports().size() == 1); - // Prepare setup to invoke such a Render Node... + CHECK (LIFE_AND_UNIVERSE_4EVER == invokeRenderNode (node)); + } + + /** + * @internal Helper for Render Node invocation + * - use a DiagnosticBufferProvider to allocate a result buffer + * - assuming that the Node internally does not allocate further buffers + * - pull from Port #0 of the given node, passing the \a nomTime as argument + * - expect the buffer to hold a single `uint` value after invocation + */ + uint + invokeRenderNode (ProcNode& theNode, Time nomTime =Time::ZERO) + { BufferProvider& provider = DiagnosticBufferProvider::build(); BuffHandle buff = provider.lockBufferFor (-55); - Time nomTime = Time::ZERO; ProcessKey key{0}; uint port{0}; CHECK (-55 == buff.accessAs()); // Trigger Node invocation... - buff = node.pull (port, buff, nomTime, key); + buff = theNode.pull (port, buff, nomTime, key); - CHECK (LIFE_AND_UNIVERSE_4EVER == buff.accessAs()); + uint result = buff.accessAs(); + buff.release(); + return result; } @@ -88,6 +101,18 @@ namespace test { void build_Node_fixedParam() { + auto procFun = [](ushort param, uint* buff){ *buff = param; }; + auto paramFun = [](TurnoutSystem&){ return LIFE_AND_UNIVERSE_4EVER; }; + + ProcNode node{prepareNode("Test") + .preparePort() + .invoke("fun()",procFun) + .attachParamFun(paramFun) + .completePort() + .build()}; + + CHECK (LIFE_AND_UNIVERSE_4EVER == invokeRenderNode (node)); + UNIMPLEMENTED ("build node with fixed param"); } diff --git a/tests/core/steam/engine/node-feed-test.cpp b/tests/core/steam/engine/node-feed-test.cpp index 6c1eed43e..356d1bdbb 100644 --- a/tests/core/steam/engine/node-feed-test.cpp +++ b/tests/core/steam/engine/node-feed-test.cpp @@ -17,10 +17,20 @@ #include "lib/test/run.hpp" +#include "steam/engine/proc-node.hpp" +#include "steam/engine/node-builder.hpp" +#include "steam/engine/weaving-pattern.hpp" +#include "steam/engine/turnout-system.hpp" +#include "steam/engine/turnout.hpp" +#include "steam/engine/diagnostic-buffer-provider.hpp" +#include "lib/several-builder.hpp" +#include "lib/test/diagnostic-output.hpp"/////////////////////TODO //#include "lib/util.hpp" //using std::string; +using lib::Several; +using lib::makeSeveral; namespace steam { @@ -42,9 +52,56 @@ namespace test { UNIMPLEMENTED ("render node pulling source data from vault"); } - /** @test feed parameter data to nodes */ + + /** @test demonstrate internal setup to invoke a simple output-only function, + * passing an additional invocation parameter generated from a parameter-functor + * - embed the processing-functor and parameter-functor into a FeedPrototype + * - construct the type of the »Weaving Pattern« to use for invocation + * - setup an empty wiring (output-only, thus no predecessor ports) + * - setup a single BuffDesrc for a result puffer to pass to the processing-functor + * - create a Turnout, which implements the Port interface, using the Weaving-Pattern + * - for the actual invocation, setup a TurnoutSystem, initialised with a nominal time + * - invoke the Port::weave() function and retrieve the result from the buffer. + * @remark this is a semi-integrated setup to demonstrate the interplay of the + * internal components within a Render Node, without the _outer shell_ + * provided by the NodeBuilder and the ProcNode itself + */ void feedParam() + { + auto procFun = [](ushort param, uint* buff){ *buff = param; }; + auto paramFun = [](TurnoutSystem&){ return LIFE_AND_UNIVERSE_4EVER; }; + + auto feedPrototype = FeedPrototype{move(procFun), move(paramFun)}; + using Prototype = decltype(feedPrototype); + using WeavingPattern = MediaWeavingPattern; + using TurnoutWeaving = Turnout; + + BufferProvider& provider = DiagnosticBufferProvider::build(); + + Several noLeadPorts; // ◁————————— empty predecessor-port-sequence + Several outBuffDescr = makeSeveral({provider.getDescriptor()}) + .build(); // ◁————————— a single output buffer to hold an `uint` + uint resultSlot{0}; + + TurnoutWeaving port{ProcID::describe ("SimpleNode","procFun()") + , move (noLeadPorts) + , move (outBuffDescr) + , resultSlot + , move (feedPrototype) + }; + + // setup for invocation... + Time nomTime =Time::ZERO; + TurnoutSystem turnoutSys{nomTime}; + BuffHandle result = port.weave (turnoutSys); // ◁————————— paramFun invoked here, then procFun + CHECK (LIFE_AND_UNIVERSE_4EVER == result.accessAs());// and procFun wrote param-value into result buffer + result.release(); + } + + /** @test create extended parameter data for use in recursive Node invocation */ + void + feedParamNode() { TODO ("implement the logic for the TurnoutSystem --> node-base-test.cpp"); TODO ("implement a simple Builder for ParamAgent-Node"); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 969232f0f..e882650e4 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -29011,9 +29011,7 @@ - - - +

d.h. man erzeugt in einem einzigen Aufruf den VerbPack für eine Zielfunktion @@ -29382,9 +29380,7 @@ - - - +

und bleibt anderweitig ungenutzt @@ -29708,9 +29704,7 @@ - - - +

...und das würde auch erklären, warum trotzdem die Zelle mit der Glühbirne (=die direkten Controls) überhaupt nicht aufgespreitzt wird @@ -29945,9 +29939,7 @@ - - - +

hier können wir nicht exakt rechnen, weil aufsteigende Slopes kombiniert werden — und die Info dazu kennen wir nur beim Konstruieren des Profils. Daher überschätzt diese Höhenangabe die Track-Höhe — bleibt zu sehen, ob das relevant wird @@ -30665,9 +30657,7 @@ - - - +

das wäre der logisch richtige Ort @@ -30956,9 +30946,7 @@ - - - +

die Idee einer graphischen Benutzeroberfläche hat sich über die 60er / 70er-Jahre herausgebildet. @@ -31880,9 +31868,7 @@ - - - +

Nein. Es ist ein GDK-Wrapper/Adapter @@ -32285,9 +32271,7 @@ - - - +

g { @@ -82221,8 +82205,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
...also vor allem die Frage: wirft das jetzt alles über den Haufen, kann man es außen anbauen, oder gar in bestehende Strukturen lediglich hinein-codieren?

- -
+
@@ -82287,8 +82270,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
denn nun wird in der Regel erst mal aus dem PortBuilderRoot das Binding für die Processing-Function angelegt ⟹ PortBuilder — und erst von dort gibt man dann Parameter an ⟹ modifizierter PortBuilder

- -
+
@@ -82353,9 +82335,51 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + + +

+ »dropper-Funktion« verwenden, die einen fest hinterlegten Parameter-Wert für jede Invocation in die FeedManifold setzt +

+ + +
+
+ + + + +

+ Parameter aus TurnoutSystem per Accessor abholen; ein solcher typ-sicherer Accessor kann über das HeteroData-Framework generiert werden, welches als Storage mit verketteten, getypten Datenblöcken direkt in das TurnoutSystem eingebaut ist. In der Standard-Konfiguration enthält so ein TurnoutSystem nur einen ersten Block mit den Invocation-Parameter (absoluteNominalTime und ein processKey). Daher ist diese API-Variante nur interessant, falls vorher schon per Parameter-Node ein erweiterter Datenblock mit zusätzlichen Parametern irgendwo auf den Stack gelegt wurde +

+ +
+
+ + + + +

+ zeitbasierte Funktion adaptieren, für klassische Parameter-Automation. Der Zeit-Parameter ist dabei die absolute-nominal-Time,  welche aus dem Render-Job stammt und im TurnoutSystem abgelegt ist +

+ +
+
+ + + + +

+ beliebiger Parameter-Funktor, der auf dem TurnoutSystem arbeitet und einen passenden Parameter-Wert produziert; Typisierung wird zur compile-Zeit geprüft. +

+ + +
+
@@ -88993,7 +89017,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -91202,7 +91226,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -91955,9 +91979,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + @@ -92290,7 +92314,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -92904,9 +92928,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + @@ -92931,10 +92955,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - + @@ -93126,19 +93150,19 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + - - + + - + - + @@ -93821,7 +93845,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -93845,8 +93869,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -93872,8 +93896,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -96941,8 +96965,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + @@ -96953,8 +96978,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
⟹ also muß der WeavingBuilder seine Typ-Parameter schwenken können

- - +
@@ -96964,10 +96988,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
⟹ und der ihn umschließende PortBuilder muß diesen Schwenk mitgehen

- -
+
- + @@ -96987,8 +97010,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
schon das Ding mit PatternData ist grauenhaft — und s'werd ois no fui schmlimma

- - +
@@ -97009,7 +97031,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -97050,7 +97073,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -97070,11 +97093,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + - + @@ -97208,8 +97233,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) aber das wäre das eigentliche Problem

- - +
@@ -97258,8 +97282,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) insofern hier nämlich bereits akzidentelle Komplexität generiert wird

- - +
@@ -97269,8 +97292,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) Man kann die Struktur zwar extrahieren, aber die extrahierte Version läßt sich nicht sinnvoll in einfachereren Begriffen darstellen

- -
+
@@ -97280,8 +97302,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) ...insofern hier Komplexität nicht durch eine Abstraktion reduziert wurde, sondern nur durch Modularisierbarkeit und Zwischenschritte beherrschbarer gemacht wird; aber dies wird durch Generieren zusätzlicher Komplexität erkauft, was den Ansatz insgesamt in Frage stellt

- -
+
@@ -97289,7 +97310,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
- + @@ -97297,19 +97318,24 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) Fazit: bite the bullet...

- -
- - + + + + + + + + + - - - + + + @@ -97319,17 +97345,18 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - - + + - - + + - - + + + @@ -97345,7 +97372,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + @@ -97353,6 +97380,23 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) + + + + + + + + + + + + + + + + + @@ -97379,8 +97423,7 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) Das Pattern heißt jetzt auch MediaWeavingPattern und ist zum Standard geworden; der Build-Mechanismus im Port-Builder könnte jedes dazu kompatible Pattern  ebenfalls handhaben

- - +
@@ -97420,11 +97463,36 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
- + - + + + + + +

+ erfolgt als Teil der Konfiguration eines Ports +

+ + +
+
+ + + + +

+ also nachdem man den Processing-Functor gegeben hat +

+ + +
+
+ + +
@@ -97476,8 +97544,11 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension)
- - + + + + +