可视化搭建跨平台原生界面

在 LOPPE 编辑器里创建桌面、Android 与 ESP32S3 工程:界面写在声明式 .lui 里,不依赖系统控件,同一份工程在各端呈现一致的外观。

  • C++17 + OpenGL
  • 声明式 .lui
  • 桌面 / 移动端 / 嵌入式
LOPPE 编辑器首页的界面截图

功能特性

  • 可视化编辑器

    新建桌面 / Android / ESP32S3 工程、编辑 .lui、构建与更新都在同一个工具里完成,编辑器自己也用它做界面。

  • 声明式界面

    一份文件同时描述外观、排布与控件层级,选择器写法接近 CSS。

  • 多端一套工程

    同一份工程与 .lui 覆盖 Windows、Linux 桌面、Android 与 ESP32S3 嵌入式,不需要为各端分别维护界面代码。

  • 原生渲染

    不依赖系统控件,每一处样式都由 .lui 决定:各平台外观一致,布局结果可预测。

  • 轻量运行

    体积小、依赖少,不引入重型运行时,也不套 Web 容器。

支持平台

桌面、移动端与嵌入式目标的当前支持情况。

  • Windows (x64)

    已支持

    GLFW 创建窗口并处理输入,OpenGL 渲染。

    运行前提显卡驱动需支持 OpenGL 3.3 及以上。

  • Linux (x64)

    已支持

    X11 窗口,OpenGL 渲染。

    运行前提需要 X11 与 FreeType 运行库。

  • Android (arm64-v8a)

    已支持

    NDK 交叉编译,触摸输入可用。

    运行前提在 LOPPE 编辑器里创建 Android 工程即可构建。

  • ESP32S3(嵌入式)

    已支持

    软件光栅化 + framebuffer 输出,面向资源受限设备。

    运行前提需自备 ESP-IDF 工具链;LCD 与触摸驱动按自己的板卡适配(内置字库只覆盖 ASCII)。

  • macOS / iOS

    规划中

    尚未开始,暂未提供构建。

界面用 .lui 描述

外观、排布与控件层级写在同一个 .lui 文件里,选择器用法贴近 CSS。

登录面板 · login.lui
@version(1.0)

@style {
    .page {
        width: 100%;
        height: 100%;
        background-color: #f5f5f5;
    }
    .card {
        width: 320px;
        margin: auto;
        padding: 40px 32px;
        background-color: #ffffff;
        border-radius: 12px;
    }
    .title {
        font-size: 24px;
        font-weight: bold;
        color: #333333;
        text-align: center;
        margin-bottom: 32px;
    }
    .input-field {
        width: 100%;
        padding: 12px;
        margin-bottom: 16px;
        border: 1px #dddddd;
        border-radius: 8px;
        font-size: 14px;
    }
    .login-btn {
        width: 100%;
        padding: 14px;
        background-color: #007aff;
        color: #ffffff;
        font-size: 16px;
        font-weight: bold;
        border-radius: 8px;
    }
}

@layout {
    .page {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .card {
        display: flex;
        flex-direction: column;
        align-items: stretch;
    }
}

panel(class="page") {
    panel(class="card") {
        text(class="title", value="账号登录"),
        input:username(class="input-field", placeholder="请输入用户名"),
        input:password(class="input-field", placeholder="请输入密码", type="password"),
        button:loginBtn(class="login-btn") { text(value="登 录") }
    }
}