mittens-engine 0.6.0

A Vulkan and OpenXR scene engine with ECS, reactive signals, and Meow Meow scripting
Documentation
// html-layout.mms — layout system authoring demo ( ˘ω˘ )
//
// Exercises: Layout root, display block/inline/flex, flex-row, flex-column,
//            justify-content, align-items, relative/absolute positioning,
//            overflow:scroll.
//
// All dimensions in glyph units (1 gu = one monospace character cell).
// World scale: T.scale(0.08, 0.08, 0.08) converts gu → world units.
//
// NOTE: LayoutSystem is not yet implemented. Components spawn correctly and
// are queryable, but no UpdateTransform is emitted from layout passes yet.
// Text children will all render at their parent's origin until LayoutSystem
// is wired. This file is the authoring contract and integration smoke-test.

// ── Camera + input ──────────────────────────────────────────────────────────
I {
    InputTransformMode.forward_z() {
        roll_axis_y()
        fps_rotation()
    }
    T.position(0.0, 1.0, 3.5) {
        C3D {
            Pointer {}
        }
    }
}

// ── Layout root ─────────────────────────────────────────────────────────────
// 60 gu wide × 50 gu tall viewport. Scale 0.08 → 4.8 × 4.0 world units.
T.position(-2.4, 2.0, 0.0).scale(0.08, 0.08, 0.08) {
    LayoutRoot {
        available_width(60.0)
        available_height(50.0)

        // Body — block container, fills the layout root
        HtmlElement.body {

            // ── 1. Display: block ──────────────────────────────────────────
            // div/p/h* are block by default; they stack vertically.
            HtmlElement.section {
                Style {
                    padding(1.0)
                }
                HtmlElement.h2 {
                    Text { "1. Block layout" }
                }
                HtmlElement.p {
                    Text { "Paragraph A stacks below h2 (display: block)." }
                }
                HtmlElement.p {
                    Text { "Paragraph B stacks below A." }
                }
            }

            // ── 2. Display: inline ─────────────────────────────────────────
            // span is inline by default; items flow left-to-right.
            HtmlElement.section {
                Style {
                    padding(1.0)
                }
                HtmlElement.h2 {
                    Text { "2. Inline layout" }
                }
                HtmlElement.p {
                    HtmlElement.span { Text { "word1 " } }
                    HtmlElement.span { Text { "word2 " } }
                    HtmlElement.span { Text { "word3" } }
                }
            }

            // ── 3. Flex row ────────────────────────────────────────────────
            // Three equal columns via flex-grow:1.
            HtmlElement.section {
                Style {
                    padding(1.0)
                }
                HtmlElement.h2 {
                    Text { "3. Flex row — equal columns" }
                }
                HtmlElement.div {
                    Style {
                        display("flex")
                        flex_direction("row")
                        gap(1.0)
                    }
                    HtmlElement.div {
                        Style { flex_grow(1.0) }
                        Text { "[col A]" }
                    }
                    HtmlElement.div {
                        Style { flex_grow(1.0) }
                        Text { "[col B]" }
                    }
                    HtmlElement.div {
                        Style { flex_grow(1.0) }
                        Text { "[col C]" }
                    }
                }
            }

            // ── 4. Flex column ─────────────────────────────────────────────
            HtmlElement.section {
                Style {
                    padding(1.0)
                }
                HtmlElement.h2 {
                    Text { "4. Flex column" }
                }
                HtmlElement.div {
                    Style {
                        display("flex")
                        flex_direction("column")
                        gap(0.5)
                        width(20.0)
                    }
                    HtmlElement.div { Text { "row A" } }
                    HtmlElement.div { Text { "row B" } }
                    HtmlElement.div { Text { "row C" } }
                }
            }

            // ── 5. justify-content + align-items ──────────────────────────
            HtmlElement.section {
                Style {
                    padding(1.0)
                }
                HtmlElement.h2 {
                    Text { "5. justify: space_between, align: center" }
                }
                HtmlElement.div {
                    Style {
                        display("flex")
                        flex_direction("row")
                        justify_content("space_between")
                        align_items("center")
                        height(4.0)
                    }
                    HtmlElement.span { Text { "[left]" } }
                    HtmlElement.span { Text { "[mid]" } }
                    HtmlElement.span { Text { "[right]" } }
                }
            }

            // ── 6. Mixed flex sidebar + main ───────────────────────────────
            // Two-column layout: narrow sidebar + flex-grow main area.
            HtmlElement.section {
                Style {
                    padding(1.0)
                }
                HtmlElement.h2 {
                    Text { "6. Sidebar + main (flex row)" }
                }
                HtmlElement.div {
                    Style {
                        display("flex")
                        flex_direction("row")
                        gap(1.0)
                    }
                    HtmlElement.aside {
                        Style { width(12.0) }
                        HtmlElement.p { Text { "nav A" } }
                        HtmlElement.p { Text { "nav B" } }
                        HtmlElement.p { Text { "nav C" } }
                    }
                    HtmlElement.main {
                        Style { flex_grow(1.0) }
                        HtmlElement.p {
                            Text { "Main content area. flex-grow:1 so it takes remaining width." }
                        }
                    }
                }
            }

            // ── 7. Relative + absolute positioning ─────────────────────────
            // Badge pinned top-right of a relative-positioned container.
            HtmlElement.section {
                Style {
                    padding(1.0)
                }
                HtmlElement.h2 {
                    Text { "7. Absolute positioning" }
                }
                HtmlElement.div {
                    Style {
                        position("relative")
                        height(5.0)
                    }
                    HtmlElement.p {
                        Text { "Container with position:relative and explicit height." }
                    }
                    HtmlElement.div {
                        Style {
                            position("absolute")
                            top(0.0)
                            right(0.0)
                        }
                        Text { "[badge]" }
                    }
                }
            }

            // ── 8. Overflow: scroll ────────────────────────────────────────
            // Scroll container — fixed height, content overflows.
            // Stencil clipping defines correctness; conservative CPU reject can
            // be added later once clip/content bounding volumes exist.
            HtmlElement.section {
                Style {
                    padding(1.0)
                }
                HtmlElement.h2 {
                    Text { "8. Overflow: scroll" }
                }
                HtmlElement.div {
                    Style {
                        overflow("scroll")
                        height(6.0)
                    }
                    for i in range(20) {
                        HtmlElement.div {
                            Text { "scroll item " + i }
                        }
                    }
                }
            }

        }
    }
}

// ── Lighting ─────────────────────────────────────────────────────────────────
AL {
    C.rgba(0.25, 0.25, 0.28, 1.0)
}
T.position(2.0, 3.0, 2.0) {
    DL {
        intensity(0.85)
        C.rgba(1.0, 0.96, 0.92, 1.0)
    }
}
T.position(-1.0, 1.0, 2.0) {
    DL {
        intensity(0.3)
        C.rgba(0.8, 0.85, 1.0, 1.0)
    }
}