CushyStudio
Blog
  • 🛋️CushyStudio
  • Getting Started
    • 🛠️Installation
      • Installing Cushy
      • Updating Cushy
      • Scripts
      • Installing Modules
        • Install ComfyUI
        • Install FFMpeg (optional)
        • Installing Models
        • Install ImageMagick (optional)
    • 👋First Steps
      • Intro to Generative AI
      • Making an image
      • Coming From...
    • 🎁Built-in apps
      • CushyDiffusion
      • Rotate anything
      • Cushy Cascade
      • Remove Background
      • Slay the Spire - Art Pack
      • Manga Coloring
    • 🚶Cushy Interface
      • Draft Panel
      • Welcome Panel
      • Minipaint
      • File Explorer
      • Quick-Civitai
      • Iframes
        • Minipaint
        • Civitai
      • Image Comtext menu
    • 🍏Images, Videos, 3d scenes
      • Quick Actions
      • LLM (Large Language Model)
    • 😁Unified canvas
      • Starin
      • Inpainting
      • Outpainting
    • 🧪Prompting
      • adding Loras
  • Going further
    • 💡Creating apps
      • Creating a new App file
      • Prefabs
      • App Structure
      • Contextual Apps
      • For loops
      • App UI
      • Using ImageMagick in your app
    • ⚙️CushyKit
    • 🏈Importing from ComfyUI
    • 🤝Woking on Cushy
      • Setting up VSCode
      • Contributing on the UI
      • Contributing on top-level scripts
      • Database
      • Migrations
    • 🔥Troubleshooting
      • Page 1
  • Community
    • 🤝Community
    • 💬FAQs
      • ⁉️Can Cushy...
    • 📰News
    • 😁Changelog
    • 🚀Roadmap
    • 💬Blog
      • 2024-02-18 - creating the website
    • 🚂Other Softwares
      • Coming from Krita
      • Coming from A1111
      • Coming from ComfyUI
      • Coming from InvokeAI
      • Coming from Fooocus
    • Contributing
      • Supporting the team
      • Writing Docs
  • TEMP
    • ✨CushyStudio Features
    • 🛋️TEMPORARY
      • Manual
      • GPT alt A
      • GPT alt B
      • GPT alt C
Powered by GitBook
On this page
  • Objective
  • Diff
Edit on GitHub
Export as PDF
  1. Going further
  2. Creating apps

For loops

CushyApps supports any kind of control flow. This page show how to do so

PreviousContextual AppsNextApp UI

Last updated 4 months ago

Key learnings:

Objective

Start from the default app, and enhance it to allow for a configurable number of recursive samplers.

  1. Add a new number input to control how many ksampler we want

  2. Use that number to genearte

Final Code
app({
    metadata: { name: 'demo for-loops', description: 'my app description' },
    ui: (form) => ({
        model: form.enum['CheckpointLoaderSimple.ckpt_name']({}),
        positive: form.string({ default: 'masterpiece, tree' }),
        seed: form.seed({}),
        // 1. add new UI control to display how many loops you want
        loops: form.number({ default: 3 }),
    }),
    run: async (run, ui) => {
        const workflow = run.workflow
        const graph = workflow.builder

        const ckpt = graph.CheckpointLoaderSimple({ ckpt_name: ui.model })
        // 2. here, I'm using the _LATENT annotation to allow to assign any node
        // that produce a latent, and not just an EmptyLatentImage node.
        let latent: Comfy.Signal['LATENT'] = graph.EmptyLatentImage({})

        // 3. moving embeddigns node definition outside of the Ksampler,
        // as variable, so they can be used in the loop below
        const pos = graph.CLIPTextEncode({ clip: ckpt, text: ui.positive })
        const neg = graph.CLIPTextEncode({ clip: ckpt, text: '' })
        latent = graph.KSampler({
            seed: ui.seed,
            latent_image: latent,
            model: ckpt,
            sampler_name: 'ddim',
            scheduler: 'karras',
            positive: pos, // use the variables
            negative: neg, // use the variables
        })

        // 4. add a for loop
        for (let i = 0; i < ui.loops; i++) {
            // 👇 I'm reassigning latent variable
            latent = graph.KSampler({
                seed: ui.seed,
                latent_image: latent, // 👈 from the previous latent
                model: ckpt,
                sampler_name: 'ddim',
                scheduler: 'karras',
                positive: pos,
                negative: neg,
            })
        }

        const image = graph.VAEDecode({
            samples: latent,
            vae: ckpt,
        })
        graph.PreviewImage({ images: image })
        await workflow.sendPromptAndWaitUntilDone()
    },
})

Diff

app({
         model: form.enum['CheckpointLoaderSimple.ckpt_name']({}),
         positive: form.string({ default: 'masterpiece, tree' }),
         seed: form.seed({}),
+        // 1. add new UI control to display how many loops you want
+        loops: form.number({ default: 3 }),
     }),
     run: async (run, ui) => {
         const workflow = run.workflow
         const graph = workflow.builder

         const ckpt = graph.CheckpointLoaderSimple({ ckpt_name: ui.model })
+        // 2. here, I'm using the _LATENT annotation to allow to assign any node
+        // that produce a latent, and not just an EmptyLatentImage node.
         let latent: Comfy.Signal['LATENT'] = graph.EmptyLatentImage({})

+        // 3. moving embeddigns node definition outside of the Ksampler,
+        // as variable, so they can be used in the loop below
+        const pos = graph.CLIPTextEncode({ clip: ckpt, text: ui.positive })
+        const neg = graph.CLIPTextEncode({ clip: ckpt, text: '' })
         latent = graph.KSampler({
             seed: ui.seed,
             latent_image: latent,
             model: ckpt,
             sampler_name: 'ddim',
             scheduler: 'karras',
-            positive: graph.CLIPTextEncode({ clip: ckpt, text: ui.positive }),
-            negative: graph.CLIPTextEncode({ clip: ckpt, text: '' }),
+            positive: pos, // use the variables
+            negative: neg, // use the variables
         })
+
+        // 4. add a for loop
+        for (let i = 0; i < ui.loops; i++) {
+            // 👇 I'm reassigning latent variable
+            latent = graph.KSampler({
+                seed: ui.seed,
+                latent_image: latent, // 👈 from the previous latent
+                model: ckpt,
+                sampler_name: 'ddim',
+                scheduler: 'karras',
+                positive: pos,
+                negative: neg,
+            })
+        }
+
         const image = graph.VAEDecode({
             samples: latent,
             vae: ckpt,
💡