
拖一個 .swf 就能跑Ruffle 桌面端從文件落到渲染的完整鏈路【免費下載鏈接】ruffleA Flash Player emulator written in Rust項目地址: https://gitcode.com/GitHub_Trending/ru/ruffle把鼠標指針按在任意一個.swf文件上拖到 Ruffle 窗口里松手——這是 Flash 模擬器 Ruffle 桌面版最省事的一個動作。它把「用戶手里一個路徑」變成「窗口里正在播放的一段動畫」中間沒有對話框、沒有格式確認。這篇文章就盯住這條鏈路事件從哪來數(shù)據(jù)穿過哪幾層畫面怎么落上去。桌面端三塊積木各自管什么整個桌面殼子大致分三塊。App/MainWindow負責(zé)接操作系統(tǒng)事件、維持一個 tokio 運行時GuiController管 wgpu 渲染目標和 egui 畫的那條菜單欄PlayerController則罩住真正的PlayerSWF 的解析、AVM 虛擬機、幀循環(huán)都躲在它后面。拖放這件事前兩塊各出一只手事件在MainWindow里被截獲創(chuàng)建動作交給GuiController而「能不能播」的判定其實落在第三塊的取流階段。從 DroppedFile 事件到 create_moviewinit 把操作系統(tǒng)層面的拖放壓平成一個事件沒有進入/懸停的中間態(tài)只有「文件已經(jīng)落地」這一個瞬間WindowEvent::DroppedFile(file) { if let Some(content_descriptor) ContentDescriptor::new_local(file, None) { self.gui.create_movie( mut self.player, LaunchOptions::from(self.preferences), content_descriptor, ); } }這一段在 app.rs 的window_event里。file是一個PathBufContentDescriptor::new_local做的事很輕——用Url::from_file_path把本地路徑包成file://URL同時留一個空的root_content_pathcontent.rs。注意這里沒有任何擴展名檢查拖進來是什么就包什么合法性判定被刻意推遲了。create_movie在 controller.rs 里先close_movie把舊播放器整個銷毀再MovieView::new造一個新的渲染目標然后調(diào)player.create。也就是說每次拖放都會把上一個播放的 SWF 從內(nèi)存里連根拔掉而不是疊加。SWF 頭如何反過來決定窗口尺寸player.create在 player.rs 里走 builder 模式把渲染器、導(dǎo)航器、UI 后端全掛上最后調(diào)fetch_root_movie并塞進去一個on_metadata回調(diào)。這個回調(diào)在 core 真正讀到 SWF 文件頭時觸發(fā)把HeaderExt含舞臺尺寸通過RuffleEvent::OnMetadata拋回事件循環(huán)。MainWindow::on_metadata收到它之后才做窗口布局拿stage_size()算出目標邏輯尺寸套上菜單欄高度Size::clamp到屏幕上限然后request_inner_size。如果 X11 上報的當(dāng)前尺寸還和請求值對不上狀態(tài)機就停在WaitingForResize等到下一次Resized事件確認到位才翻成Loaded。這個小小的三態(tài)枚舉Loading / WaitingForResize / Loaded保證了 SWF 里那些能觀察視口尺寸的代碼不會在窗口還沒定型時讀到錯的值。兩層畫面怎么合成到一塊屏幕真正上屏?xí)r一幀被拆成兩段 draw。GuiController::render先從 wgpu 拿到 surface 紋理開一個 render pass先調(diào)movie_view.render把 SWF 內(nèi)容從它的離屏紋理貼到屏幕上緊接著egui_renderer.render把菜單欄、按鈕那些 egui 三角形疊上去。SWF 自己渲染進的是MovieView持有的RenderTarget紋理egui 走的是另一套 tessellate 管線兩者互不干擾最后在同一個 pass 里前后合成。這就是為什么菜單可以被拖拽、縮放時獨立重繪而不會把下面的 SWF 畫面也一起重算。校驗為什么不做在拖放入口一個容易踩的坑是在DroppedFile那里就檢查.swf后綴、讀 magic 字節(jié)不合格直接彈錯。Ruffle 沒這么做。文件對話框那條路picker.rs確實按swf/spl/ruf分了過濾器可拖放這條路完全不過濾ContentDescriptor::new_local對任何路徑都返回Some。真正的合法性檢查下沉到了 core 取流時讀文件頭的那一步——magic 不對fetch_root_movie自然失敗錯誤沿通知通道彈回 UI。把信任邊界壓到最深處的好處是拖一個.txt進來不會 panic只是播不起來而且本地文件、bundle、遠程 URL 三條入口共享同一套判定不用在入口各寫一份。本地跑一條命令cargo run -p ruffle-desktop -- /path/to/movie.swf把文件當(dāng)參數(shù)傳進去或直接啟動后拖進去效果一致。拖放這條路目前只認單個本地文件多文件拖入、bundle 目錄拖入都還沒接上——這塊大概率是下一個要補的口子值得留意。【免費下載鏈接】ruffleA Flash Player emulator written in Rust項目地址: https://gitcode.com/GitHub_Trending/ru/ruffle創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考