Cook and render with Nfty.Core¶
Nfty.Core is the whole engine: reading and writing archives, validation, generation, rendering,
Sets, export, sealing and statistics. The code on this page comes from samples/Nfty.Embedding.Sample,
which references Nfty.Core and Nfty.Model.
using Nfty.Core.Formats; // CookBookArchive, LoadedCookBook
using Nfty.Core.Generation; // Generator, GenerateOptions, GeneratedSet
using Nfty.Core.Publish; // MenuRenderer
using Nfty.Model; // Riser, ModelWriter, StackDepth, RiseOptions
using Nfty.Ticket; // MenuArchive, AssetTicket
using SixLabors.ImageSharp; // SaveAsPng - arrives through Nfty.Core
Read a book and generate¶
// Reading decodes every variant PNG, so the book owns images: dispose it.
using LoadedCookBook book = CookBookArchive.Read(args[0]);
// Generate validates the book itself and throws on any problem, so there is nothing to pre-check.
using GeneratedSet set = Generator.Generate(book, new GenerateOptions(Count: 3, Seed: "embed-demo"));
foreach (GeneratedAsset asset in set.Assets) // the set owns the asset images too
{
asset.Image.SaveAsPng(Path.Combine(outDir, $"{asset.SetNumber:0000}.png"));
Console.WriteLine($"#{asset.SetNumber} {asset.RecipeName} {asset.Dna[..12]}");
}
You own the images. Reading a .cbk decodes every variant PNG, so LoadedCookBook (and the
Recipes and Ingredients inside it) is IDisposable, and using var frees the whole tree.
GeneratedSet and GeneratedAsset are disposable too; disposing the set disposes every asset image.
Generator.Generatevalidates the book itself and throws on any problem, with a message listing every one, so there is nothing to pre-check.Validator.Validatereports without throwing when you want to show problems yourself.- It holds the whole collection in memory. For a collection too big for that, use
Generator.GenerateStreaming, which yields one asset at a time and hands you its ownership (abandoning the enumeration leaves the last one undisposed). - It rolls sequentially and renders in parallel;
GenerateOptions.Parallelismsets the width. Output is byte-identical at any width. - Async twins (
GenerateAsync,CookBookArchive.ReadAsync,SetWriter.WriteAsync) report progress and honor cancellation.
SetWriter.Write(set, dir, pack) writes the Set to disk exactly as nfty generate does; give it an
IAssetModeler (Nfty.Model.SetModeler) to write models/ too.
Render a ticket¶
// A ticket rolled elsewhere (a server, nfty serve) renders to the identical pixels. Note
// MenuRenderer needs Nfty.Core; the Nfty.Ticket sample draws the same ticket without it.
using var menu = MenuArchive.Open(args[1]);
AssetTicket ticket = Ticketer.TryRoll(Ticketer.Prepare(menu.Book),
new SplitMix64Rng(7))
?? throw new InvalidOperationException("The rules rejected the roll; roll again.");
using (var image = MenuRenderer.Render(menu, ticket)) // you own the returned image
image.SaveAsPng(Path.Combine(outDir, "ticket.png"));
MenuRenderer.Render uses the same colorizer and compositor as generate, so a client rendering a
server's ticket gets identical pixels. You dispose the returned image.
Write a Menu¶
It validates first and writes nothing for a book with problems. An atlas past the pixel ceiling throws
AtlasTooLargeException; MenuArtMode.Loose avoids it.
Export and seal¶
SetExporter.Plan(...) computes every file an export would write without writing it, and
SetExporter.Export(...) writes exactly that list; ExportPlan.Parts() renders the same summary the
CLI and app print. ExportOptions and ExportPreset carry the choices from
Export a Set. Exporting from a sealed .tin is refused inside the library.
Run the sample¶
It writes three cooked PNGs, the rendered ticket, and one .glb into ./out.