SheetForge Web
SheetForge 在 web.sheetforge.workers.dev 提供一個隨附的網頁應用。它將編寫、驗證與試算表反射能力帶進瀏覽器——不需要 Unity,也不需要安裝。
相同的核心,而非重新實作
這個網頁應用會將完全相同的 C# 核心原始碼——也就是無頭 .NET 測試框架所執行的那一份——編譯為 .NET 的 browser-wasm 組件。剖析器或驗證器並不存在第二份副本,因此兩者絕不可能產生分歧:一項規則修好一次,就等於兩處同時修好。
由這項設計直接衍生出兩件事。
- 你編譯完成的外掛 DLL 可以原封不動載入,並在此處點亮與編輯器中相同的插槽(詳見下方)。
- 本站的試算表語法規則,在瀏覽器中同樣完全成立。 標記、型別系統、
@overlap、@style、@enum、@loc,以及參照完整性,全都以相同方式運作,因為回答問題的是同一份程式碼。這也包括IntId@Tab、LocRef@Tab的對等性——請參閱試算表語法。
一個外掛,十二個插槽,兩個主機
一個外掛並沒有所謂的「網頁子集」。組裝——實體化、排序、隔離與相容性關卡——是一個單一、純粹的 Core 功能,由兩個主機共同呼叫。唯一不同的是發現方式:Unity 會索引專案中的型別,瀏覽器則會掃描你所上傳的組件。
因此,一個外掛可以填入的十二個插槽,在兩側都是相同的:
| 插槽 | 在瀏覽器中的作用 |
|---|---|
| Enum.儲存格剖析器.wrapper 型別 | 儲存格會透過你自己的記法進行剖析、驗證與往返 |
| 領域驗證器 | 你的規則會與核心規則一同顯示於 Problems 中 |
| 邊貢獻者 | 深埋在你記法中的連結,會被繪製於畫布上,並計入參照索引中 |
| 結構標記 | 你的 @marker 列會被接受並驗證 |
| 試算表範本 | 你的範本會出現在 Create sheet 中 |
| 畫布擴增器 | 虛擬節點、額外的邊、圖層與顯示提示 |
| 程式碼註冊表 | 存放於程式碼中的鍵值,不再被繪製為失效的參照 |
| 色彩預設集 | 對應到應用程式的 CSS 變數上 |
| 宣告式 Studio UI | 你的動作、面板、欄徽章與儲存格元件提示,以 React 渲染 |
| UI 字串 | 你的標籤會透過與 t() 所查詢的相同疊加層,跟隨使用者的語言 |
| 管線觀察者 | 在一次匯入循環結束時收到通知,與編輯器中完全相同 |
宣告式介面正是一個外掛的編寫擴充功能之所以能存在於此的原因。一項會回傳 UIToolkit 元件的合約,永遠無法在瀏覽器中載入,因此外殼被描述為資料——一個 id、一個標籤鍵值、一個放置位置、一種色調——各主機再各自以自己的元件繪製它。
當一個套件需要某樣詞彙表無法表達的東西時,它會以相同的 id 註冊一個僅限編輯器使用的豐富面板。編輯器會繪製那一個,瀏覽器則繪製描述式的那一個,該擴充功能絕不會就此單純消失。
繪製時會遵守兩條規則。來自外掛的文字會被跳脫處理,而一個自繪製以來狀況已經改變的動作,會以一次誠實的無動作來回應,而不是依據一個過時的 id 採取行動。
一個外掛組件也可以宣告自己是依照哪一代外掛格式編譯的。若超出此主機所能讀取的範圍,整個組件都會被拒絕,並附上可讀的原因,而不是半載入。無論是在市集路徑、側載路徑,還是本機檔案路徑上,都是同一道關卡在讀取同一項宣告。請參閱外掛開發。
留在 Unity 端的部分
程式碼產生與烘焙,仍然是僅限 Unity 的職責。瀏覽器無法產生 .cs 檔案,也無法寫入 ScriptableObject,它也不會假裝自己可以。同樣的誠實也適用於在地化:一份在地化試算表在這裡完整可編寫、可驗證,但同步 Unity Localization StringTable 是編輯器的工作——瀏覽器沒有 Unity 專案可以把表格寫進去。任何需要用到專案本身的功能也是如此:資源選取器、從 Project 視窗進行的拖放,以及它們所暫存的 Addressables 註冊,都只存在於編輯器中;AssetRef@Group<Type> 的 <Type> 會在瀏覽器中被剖析並顯示,但只有在專案的型別已被載入之處,才會進行解析——以及型別檢查;而編輯器的資源縮圖、放大檢視與音訊播放,在網頁端沒有對應功能,因為瀏覽器沒有專案資源可供讀取——網頁表格中的資源儲存格,就只是它的位址文字。
網頁端的輸出是反射後的試算表——經過驗證、完成往返的來源——而非烘焙後的資源。你在瀏覽器中編寫與驗證,需要強型別類別與烘焙後的 SO 時,再到 Unity 中執行一次匯入。無論哪種情況,試算表都是唯一真實來源,因此兩個介面最終都會在試算表這一點上會合。
這個網頁應用能做什麼
一切都透過單一的 JSON 邊界合約與 WebAssembly 核心往返,因此瀏覽器 UI 絕不需要重新推導一項核心早已擁有的規則。
| 領域 | 你能獲得什麼 |
|---|---|
| 編寫工作階段 | 匯入、投影,以及一個由相同匯入驗證器餵入內容的 Problems 面板——這是預檢診斷,而非另一套獨立的檢查。匯入可接受 TSV 與 CSV 檔案,以及**.xlsx 活頁簿**——活頁簿中的每一張工作表都會以自己的分頁抵達,並由編輯器所用的同一個讀取器(編譯為 WebAssembly)讀取;當有內容必須被判讀時——公式的快取值、以 yyyy-MM-dd 呈現的日期文字、未被讀取的格式——匯入對話框會在一則**「本活頁簿的讀取方式」**說明中告知你。 |
| 表格編輯 | 依型別而定的儲存格元件、復原、欄固定、排序、搜尋、@style 分組與配色——外加編輯器所具備的試算表欄功能集:拖曳標頭把手可設定欄寬(按兩下可自動調整;會依試算表儲存在此瀏覽器中)、隱藏與顯示欄,同時讓字母與邊界標記保持誠實準確、與搜尋結合運作的逐欄數值篩選,以及作為單一復原步驟的清除欄資料功能。+ Row 會立即暫存一列並附上建議鍵值——整數 id 欄會預先填入——可在鍵值儲存格中重新命名,而沒有鍵值欄的試算表則會停用此功能,並顯示原因。Enum 與選填布林儲存格會開啟與參照儲存格相同的可搜尋選取器——而且永遠只會有一個選取器視窗處於開啟狀態:開啟另一個會關閉前一個,點擊別處或按 Esc 也會將其關閉。列號與欄字母可供選取(Ctrl 用於切換加選、Shift 用於選取範圍),標頭與內容區會醒目標示選取範圍,被選取的儲存格會畫出一個跟隨鍵盤移動的外框,而一個選取範圍可以拖曳到新位置,並以一條插入線標示——不連續的選取範圍會依選取順序一併聚集到放開的位置,且整個動作只算一個復原步驟——同時右鍵選單會將欄寬、自動調整、隱藏、移動、刪除與清除資料套用到每一個被選取的欄(移動與刪除則套用到每一個被選取的列),單一目標專屬的項目則自成一個獨立區段。Enum 定義試算表擁有與資料試算表相同的欄寬調整功能——拖曳、按兩下自動調整、精確寬度、自動調整欄寬、隱藏。超過 200 列後,網格只會渲染可視範圍(外加預先建置範圍),並以間隔元素撐出真正的捲動高度——與編輯器表格所用的門檻相同,因此在大型試算表上,兩者的體驗完全一致。 |
| 視覺數值 | Color、AnimationCurve 與 Gradient 儲存格會顯示一個填滿整個儲存格的預覽——一個色塊、一條曲線折線、一條漸層色帶——並在彈出視窗中開啟完整編輯器:顏色編輯器帶有 HSV 方形色域、色相與 Alpha 滑桿,以及一個十六進位欄位(瀏覽器原生的顏色輸入元件沒有 Alpha,因此並未採用);曲線編輯器帶有可縮放的網格、可拖曳的關鍵影格與切線控制點、切線模式(Free、Auto、Linear、Constant、ClampedAuto——在關鍵影格上按右鍵,或使用下拉選單),以及斷開與加權切換開關、數值欄位、前置/後置包裹,以及線性 / 漸入漸出 / 恆定這些預設集;漸層編輯器帶有可拖曳的色彩與 Alpha 關鍵影格(各至多 8 個)、一個模式下拉選單,以及一個色彩空間下拉選單。每一次變更都會經過 WebAssembly 核心往返——剖析、切線重新計算與取樣皆以 C# 完成,而非 JavaScript——已提交的文字與編輯器所寫入的完全是同一種標準形式,逐位元組相同。變更會在你做出的當下立即提交,與編輯器的原生欄位完全相同:編輯器開啟期間,儲存格、畫布與 Problems 都會同步跟進,一次編輯工作階段無論做出多少變更,都會合併為一個復原步驟,重新開啟編輯器則會開始新的一步。這裡沒有 Apply(套用)——唯一的按鈕是關閉(Esc 同樣可以關閉,且在顏色編輯器中 Esc 還會把數值還原成工作階段開始前的樣子);要復原則用 Ctrl+Z。開啟後未做任何變更就關閉,則不會暫存任何內容。選填欄在空白時會顯示 —,並在右鍵選單中提供清除(預設);三者的 List<> 則是一個晶片清單,其新增/移除/重新排序/編輯手勢,都各自是獨立的復原步驟。預覽色帶固定在標準的列高之內,如同編輯器表格一樣。畫布的數值列使用的是相同的元件。 |
| 結構編輯 | 新增/移除/移動欄、四欄位的 ✎ 欄位表單、分頁重新命名(包含互換與循環;xlsx 分頁會被封鎖)、試算表的建立/刪除,以及一個使用中設定的下拉選單——每一項都會以一個復原步驟暫存。Enum 定義試算表以相同的方式編寫——定義一個新的 enum、重新命名(每一個參照它的 @type 都會在同一批次中一併改寫)、刪除、重新排序欄、編輯基礎型別與說明——並遵循與編輯器相同的規則,因為判定的是同一段程式碼。 |
| 跨試算表搜尋 | 側邊欄的 All 項目會以部分符合的方式搜尋每一份試算表的 id 與欄位值,並列出試算表.鍵值.欄位.值,每頁 50 列——比對方式、排序與分頁筆數皆與編輯器相同。它讀取的是工作階段目前顯示的值,暫存編輯也包含在內,因此你剛變更的值會立即被找到。雙擊一筆結果——或選取該列後按下 Enter——該試算表就會開啟,並選取相符的儲存格;由於搜尋讀取的正是工作階段本身,每一筆結果都可以被跳轉過去。 |
| 在地化 | 在地化試算表在這裡就是普通試算表——包含編寫、驗證與逐語言涵蓋率。資料試算表的 LocRef 儲存格會內嵌顯示該條目的來源語言文字,並開啟其他參照共用的同一個鍵值選取器;在空白儲存格中輸入即可生成鍵值、其來源文字與參照,全都算一個復原步驟,與編輯器的行為完全相同。語言檢視鏡可切換可見的語言欄(僅供顯示),翻譯活頁簿會把選定的語言匯出成 xlsx,並把送回的檔案以「只有語言欄」的合併方式重新匯入。同步 Unity Localization StringTable 仍然留在編輯器中。 |
| 記錄畫布 | 一筆記錄的素材與使用端,會顯示為可透過拖曳連線來連結的卡片——畫布重複使用與編輯器完全相同的純版面配置、連線與編輯鏈程式碼,因此像素運算存在於 C# 中,而非某個 JS 圖形函式庫裡。卡片顯示的投影結果與表格相同:這一批次中已暫存的一欄,已經以標示為待處理的樣子呈現在卡片上,暫存的重新命名會在原始數值上方顯示新名稱,而暫存的刪除也會將該列從這裡移除。 |
| 輸出 | 逐試算表的 TSV/CSV 下載、一個**.xlsx 活頁簿下載**(將所有已選擇的試算表收進同一個檔案中,工作表命名規則無法承載的名稱會被調整並回報,絕不會被靜默重新命名),以及 Google 試算表的讀寫——每次推送後都會自動重新整理該試算表的資料驗證下拉選單(詳見下方)。 |
做到完全一致,而不僅是相似
這個網頁版 UI 是刻意對齊編輯器內建的 Data Studio 的,一路延伸到共用的邏輯本身。
- 共用的答案。 標頭判斷式(
pending/edited)、差異比對對話框,以及投影組合的順序,皆為共用的 C# 程式碼,因此兩個介面對同一個問題會給出相同的答案。 - 共用的句子。 當網頁版鏡射某個 Studio 畫面時,它使用的是 Studio 自己的字串鍵值,其數值則是在建置時從編輯器的語言表中產生,而非重新輸入一次。新增一句兩個介面都會顯示的句子,只需要在
Lang*.cs中新增一個鍵值;分歧在結構上就不可能發生,而不僅僅是不被鼓勵而已。有兩件事被刻意分開處理,並由一項建置時的防護機制強制維持這道邊界:- 真正僅限網頁使用的字串,留在網頁自己的對照表中;
- 診斷與報告則由 WebAssembly 核心渲染,絕不會在 UI 中重新措辭。
- 共用的外觀。 圖形與試算表會一同顯示在一個可調整大小的分割面板中,鏡射編輯器畫布的邊界夾制行為,且每一種顏色都來自編輯器
.aw-root這一組 token 作為唯一真實來源——沒有任何寫死的調色盤。 - 共用的元件套件。 這個 UI 是建構在一套自製的
aw套件之上,其類別名稱、token 與彈出視窗的放置位置,皆與編輯器的 USS 及標準 HTML 模型一對一對應。現在是一份模型同時餵給兩個埠——網頁應用與 UIToolkit 編輯器——而不是任由網頁版自行走偏。web/Docs/ui-parity.md記錄了當 Studio 變動時,網頁版是如何跟隨它調整的。 - 共用的儲存格元件。 一個儲存格會取得哪個元件,是由核心的儲存格元件提示所決定的——先查詢套件自己的註冊內容,再查詢內建對照表(
BuiltinCellEditorHints)——因此一個宣告了ColorPicker、CurveEditor或GradientEditor原型的外掛型別,在這裡開啟的會是與 Unity 中相同的編輯器,兩個主機絕不會為同一個型別名稱挑選出不同的元件。 - 畫布對等性。 拖放操作已達到與編輯器完全對等的程度:以滑鼠中鍵拖曳或 Alt 拖曳平移、在空白處開啟串聯選單、連線與節點檢閱器、拿起連線時的殘影效果,以及附確認對話框的終點刪除功能。縮放範圍與編輯器相同(25–200%),卡片的度量數據也來自核心,而非 JavaScript 中的第二份副本。
- 共用的型別清單。
@type下拉選單所提供的,正是剖析器登錄表實際知道的內容,分組方式也與編輯器完全相同:內建純量(包括Color、AnimationCurve與Gradient)、RecordId/IntId鍵值、RecordId@Tab與IntId@Tab參照、Enum<…>、AssetRef@Group,以及任何已載入外掛註冊的型別或 wrapper。因此,一個註冊新型別的外掛,不需要任何網頁端的變更就會出現在瀏覽器中。(在 WebAssembly 核心完成啟動之前,最初的第一次繪製會回退為四種內建純量型別。)
該用哪一個
- 想要隨處進行快速編寫、驗證與試算表編輯,或是給不會開啟 Unity 的隊友使用時,請用瀏覽器。
- 需要產生的 C# 類別與烘焙後的 ScriptableObject——也就是匯入、程式碼產生與烘焙這些步驟時,請用 Unity。
兩者都會寫入同一份試算表,因此在其中一邊所做的變更,會在另一邊下一次讀取時被取用。
相關頁面
- 試算表語法——瀏覽器核心所強制執行的規則,維持不變
- 在地化試算表 — 遊戲文字試算表,瀏覽器與編輯器皆可
- Web 外掛市集——在瀏覽器中安裝與側載外掛
- Web Google 試算表存取——從已部署的網站讀寫試算表
- Data Studio——這個網頁應用所鏡射的編輯器內建編寫介面