{"id":"hakochanjp/gui-lcd","name":"gui-lcd","scope":"hakochanjp","platform":"roblox","description":"Adafruit_GFX-style dot-matrix LCD as a Frame with per-pixel framebuffer","version":"0.4.0","latest":"0.4.0","versions":["0.4.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":["The package archive does not include its license text; the license is declared in its manifest metadata."],"licenseVerified":false,"dependencies":{},"integrity":"592653e7e5607d513820230caa6f0438975a880a728695e1d069819cf99ef06e","likes":0,"downloads":0,"install":"forest install hakochanjp/gui-lcd","url":"https://forest.dev/p/roblox/hakochanjp/gui-lcd","files":"https://api.forest.dev/ai/package/roblox/hakochanjp/gui-lcd/files","readme":"# GuiLcd\n\nAdafruit_GFX 風の API でドット液晶を描画する Roblox 用ライブラリ。\n返り値は **Frame として扱える**ので、ScreenGui / SurfaceGui / BillboardGui のどこにでも置ける。\n\n## インストール\n\nWally:\n\n```toml\n[dependencies]\nGuiLcd = \"hakochanjp/gui-lcd@0.4.0\"\n```\n\nまたは利用側 Rojo プロジェクトから相対 `$path` で `src/` を参照する。\n\n## 使い方\n\n```lua\nlocal GuiLcd = require(ReplicatedStorage.GuiLcd)\n\nlocal lcd = GuiLcd.new({ cols = 32, rows = 16 })\nlcd.Size = UDim2.fromScale(0.5, 0.25)\nlcd.Position = UDim2.fromScale(0.25, 0.1)\nlcd.Parent = playerGui.ScreenGui          -- Frame として配置\n\nlcd:ClearDisplay()\nlcd:DrawRect(1, 1, 32, 16)                -- 枠\nlcd:DrawLine(1, 1, 32, 16)                -- 対角線\nlcd:FillRect(4, 4, 6, 6, GuiLcd.INVERSE)  -- 反転\nlcd:DrawBitmap(20, 5, { \"01110\", \"10001\", \"10101\", \"10001\", \"01110\" })\nlcd:Display()                             -- ここで初めて画面に出る\n```\n\nSurfaceGui に貼る場合は利用側で SurfaceGui を作り、その子にする:\n\n```lua\nlocal sg = Instance.new(\"SurfaceGui\")\nsg.Face = Enum.NormalId.Front\nsg.SizingMode = Enum.SurfaceGuiSizingMode.PixelsPerStud\nsg.PixelsPerStud = 50\nsg.LightInfluence = 0\nsg.Parent = part\nlcd.Parent = sg\n```\n\n## API\n\n### 生成\n\n`GuiLcd.new(config?)` — config は全て省略可:\n\n| キー | 既定 | 内容 |\n| --- | --- | --- |\n| `cols` | 32 | 横ドット数 |\n| `rows` | 16 | 縦ドット数 |\n| `onColor` | `fromRGB(80,220,255)` | 点灯色 |\n| `offColor` | `fromRGB(20,40,48)` | 消灯色 |\n| `backgroundColor` | `fromRGB(8,12,16)` | 背景色 |\n| `lockAspect` | `true` | `UIAspectRatioConstraint(cols/rows)` を付けてドットを正方形に保つ |\n\n### 座標と色\n\n- 座標は `(x, y)`、**1 始まり**、左上原点。x: 1〜Width、y: 1〜Height。小数は切り捨て\n- 色は `GuiLcd.BLACK`（消灯）/ `GuiLcd.WHITE`（点灯）/ `GuiLcd.INVERSE`（反転）。省略時は WHITE\n- 画面外への描画は黙って無視される（クリップ）\n- NaN / ±inf の座標は画面外として無視される\n\n### 描画（バッファに書くだけ。`Display()` で反映）\n\n| メソッド | 内容 |\n| --- | --- |\n| `DrawPixel(x, y, color?)` | 1 画素 |\n| `GetPixel(x, y) -> boolean` | 範囲外は false |\n| `DrawLine(x0, y0, x1, y1, color?)` | 両端を含む直線 |\n| `DrawFastHLine(x, y, w, color?)` / `DrawFastVLine(x, y, h, color?)` | 水平 / 垂直線 |\n| `DrawRect(x, y, w, h, color?)` / `FillRect(x, y, w, h, color?)` | 矩形の枠 / 塗り |\n| `DrawBitmap(x, y, pattern, color?)` | 0/1 文字列配列の `\"1\"` だけを描く（`\"0\"` は触らない） |\n| `FillScreen(color?)` / `ClearDisplay()` | 全面塗り / 全消去 |\n| `ToPattern() -> {string}` | 現在のバッファを 0/1 文字列配列で取得 |\n\n### 転送・破棄\n\n- `Display()` — バッファと画面の差分だけを反映する\n- `Destroy()` — Frame を破棄。冪等。以後の描画は error\n\n### Frame として\n\n上記以外のキーは全て実 Frame に透過する（`Size`, `Position`, `Parent`, `Visible`, `MouseEnter`, `FindFirstChild`, ...）。\n\n**例外:** 他の Instance の `Parent` など「Instance そのもの」が要る場面では `lcd.Instance` を渡す。`lcd` は型上 Frame だが実体は table なので、`label.Parent = lcd` は実行時エラーになる。\n\n### 読み取り\n\n`lcd.Width` / `lcd.Height` / `lcd.Instance`（いずれも読み取り専用）\n\n### 静的\n\n- `GuiLcd.validatePattern(pattern)` — 矩形の 0/1 文字列配列か検証する純関数\n- `GuiLcd.Framebuffer` — 描画ロジックのみのクラス（Roblox API 非依存）。`GuiLcd.Framebuffer.new(w, h)` で単体利用可\n\n## 文字描画\n\n5×7 ドットフォント（ASCII + 半角カタカナ）を内蔵。全角カタカナ・全角英数は自動で半角に正規化し、「ガ」は「ｶﾞ」の 2 セルで描く（JIS X 0201 の LED 表示と同じ）。ひらがな・漢字など未対応の文字は □ で描く。\n\n```lua\nlcd:SetCursor(1, 1)\nlcd:Print(\"ヨウコソ\\nGuiLcd\")          -- 改行で次の行へ\nlcd:DrawText(10, 9, \"ABC\", GuiLcd.INVERSE)\nlocal w, h = lcd:GetTextBounds(\"ヨウコソ\")  -- 描画サイズ（px）\nlcd:Display()\n```\n\n| メソッド | 内容 |\n| --- | --- |\n| `SetCursor(x, y)` / `GetCursor() -> x, y` | `Print` の開始位置 |\n| `SetTextColor(color)` | `Print` の色（既定 WHITE） |\n| `SetTextSize(scale)` | 文字の拡大率（既定 1）。1 以上の整数。`DrawText` / `Print` / `GetTextBounds` に適用。`DrawBitmap` 等のビットマップ系には非適用 |\n| `Print(text)` | カーソル位置に描き、カーソルを進める。`\\n` で改行 |\n| `DrawText(x, y, text, color?) -> nextX` | 指定位置に描く。戻り値は次のセルの x |\n| `GetTextBounds(text) -> w, h` | 描画サイズ（px）。スクロールの終端判定などに |\n| `SetFont(font)` | 別フォントに差し替え（契約は `src/Font5x7.luau` 参照） |\n\n送りは 6 px（5 + 字間 1）、行送りは 8 px。`GuiLcd.Font5x7` でフォントを直接参照できる。\n\n半角カナの字形は HD44780U（A00 CGROM）の実機ビットパターンと同一。そのため実機同様に `ｳ/ﾜ`（1 ドット差）・`ｸ/ﾀ`・`ｽ/ﾇ` は酷似する。判読性を上げたい場合は `SetTextSize(2)` とドットのコントラスト確保が有効。\n\n## サンプル: 電光掲示板\n\n`dev.project.json` を Rojo で同期すると、`Workspace.DenkoSign` の前面に 96×32 の赤 LED 看板が出る。`SetTextSize(2)` で 10×14 ドット相当の大きな文字を描いている。\n\n```\nrojo serve dev.project.json\n```\n\nPart の Attribute で文面と速度を変えられる: `Title`（上段固定文）/ `Message`（下段の流れる文）/ `Speed`（px/s）。実装は `examples/DenkoKeijiban.client.luau`。 `Speed` が 0 以下（または数値でない）のときは停止扱いで、`Title` / `Message` の変更はその場で反映される。\n\n### サンプル: ロボットの顔\n\n同じ `dev.project.json` で `Workspace.RobotFaceHead`（看板の上）に 32×16 の顔が出る。12 種の表情プリセット（`examples/RobotFace/Expressions.luau`。旧 RobotFaceLcd から移植）を `Interval` 秒ごとに巡回し、Part の Attribute `Expression` に名前（`happy` / `sad_nomouth` など）を入れるとその表情で固定する。表情の適用は `ClearDisplay()` → `DrawBitmap(1, 1, pattern)` → `Display()` の 3 行で、ビットマップ描画の最小例になっている。実装は `examples/RobotFace/init.client.luau`。\n\nどちらのサンプルも `StreamingEnabled` のプレイスでは Part のストリーミング待ちで `Infinite yield possible` の警告が出ることがあるが、Part が届き次第そのまま動く。\n\n## Adafruit_GFX との対応\n\n| GFX | GuiLcd | 差異 |\n| --- | --- | --- |\n| `drawPixel(x, y, c)` | `DrawPixel(x, y, c?)` | 1-indexed |\n| `drawLine` / `drawFastHLine` / `drawFastVLine` | `DrawLine` / `DrawFastHLine` / `DrawFastVLine` | |\n| `drawRect` / `fillRect` | `DrawRect` / `FillRect` | `DrawRect` は INVERSE で角を二重反転しない（本家 GFX は二重反転する） |\n| `drawBitmap(x, y, bitmap, w, h, c)` | `DrawBitmap(x, y, pattern, c?)` | ビットマップは 0/1 文字列配列。w/h は pattern から |\n| `fillScreen` / `clearDisplay` | `FillScreen` / `ClearDisplay` | |\n| `display()` | `Display()` | |\n| `width()` / `height()` | `Width` / `Height` | フィールド |\n| `setCursor` / `print` / `getTextBounds` | `SetCursor` / `Print` / `GetTextBounds` | 文字列は UTF-8。drawChar は DrawText に統合 |\n| `setTextSize(s)` | `SetTextSize(scale)` | 1 以上の整数のみ（floor しない） |\n| `drawCircle` 等 | （未実装） | v2 以降 |\n\n## 0.1.0 からの移行\n\n| 0.1.0 | 0.2.0 |\n| --- | --- |\n| `GuiLcd.new(part, config)` | `GuiLcd.new(config)` + 利用側で SurfaceGui を作り `lcd.Parent = sg` |\n| `SetPixel(row, col, on)` | `DrawPixel(col, row, on and WHITE or BLACK)` + `Display()` |\n| `SetPattern(pattern)` | `ClearDisplay()` + `DrawBitmap(1, 1, pattern)` + `Display()` |\n| `Clear()` | `ClearDisplay()` + `Display()` |\n| `Rows` / `Cols` | `Height` / `Width` |\n| `validatePattern(pattern, rows, cols)` | `validatePattern(pattern)` |\n\n## テスト\n\n```\nrokit install\nlune run tests/Font5x7.spec.luau\nlune run tests/Expressions.spec.luau  # ロボットの顔サンプルの表情データ       # フォント構造 + 正規化\nlune run tests/Framebuffer.spec.luau   # 描画ロジック\nbash tests/typecheck/run.sh             # 利用側視点の型検査（luau-lsp）\n```\n","readmeTruncated":false}