71 lines
2.3 KiB
Go
71 lines
2.3 KiB
Go
// Pseudo-code / toolkit-agnostic example.
|
|
// Goal: never render more than one frame concurrently, and always render the latest params.
|
|
//
|
|
// Это не “асинхронная работа в фоне”, а чистый паттерн управления вызовами Render.
|
|
// Он работает в любом UI, где у тебя есть loop и возможность запускать отрисовку
|
|
// (например, через requestAnimationFrame-аналог или таски).
|
|
//
|
|
// Как это сочетается с CoalesceUpdates
|
|
// - Если params.Options.Incremental.CoalesceUpdates == true, UI использует этот scheduler.
|
|
// - Если false, UI может пытаться рендерить каждое событие (но это обычно хуже).
|
|
//
|
|
// # Важный момент
|
|
//
|
|
// Это не делает рендер асинхронным в смысле “рендерить в фоне” — в реальном UI ты должен
|
|
// выполнять w.Render строго в UI thread. Я показал go только как “планировщик”
|
|
// (в твоём GUI заменишь на invokeOnMainThread/PostTask/RunOnUI).
|
|
package world
|
|
|
|
import "sync"
|
|
|
|
type RenderScheduler struct {
|
|
w *World
|
|
drawer PrimitiveDrawer
|
|
|
|
// Protects fields below.
|
|
mu sync.Mutex
|
|
|
|
inFlight bool
|
|
pending bool
|
|
latest RenderParams
|
|
}
|
|
|
|
// RequestRender stores the latest params and schedules rendering.
|
|
// If a render is already in progress, it coalesces (drops intermediate requests).
|
|
func (s *RenderScheduler) RequestRender(params RenderParams) {
|
|
s.mu.Lock()
|
|
s.latest = params
|
|
if s.inFlight {
|
|
s.pending = true
|
|
s.mu.Unlock()
|
|
return
|
|
}
|
|
s.inFlight = true
|
|
s.mu.Unlock()
|
|
|
|
// Schedule on the UI thread/event loop. Replace this with your toolkit method.
|
|
go s.runOnUIThread()
|
|
}
|
|
|
|
// runOnUIThread should execute on the UI thread.
|
|
// Replace the body with actual UI scheduling primitives.
|
|
func (s *RenderScheduler) runOnUIThread() {
|
|
for {
|
|
s.mu.Lock()
|
|
params := s.latest
|
|
s.mu.Unlock()
|
|
|
|
_ = s.w.Render(s.drawer, params) // handle error in real code
|
|
|
|
s.mu.Lock()
|
|
if !s.pending {
|
|
s.inFlight = false
|
|
s.mu.Unlock()
|
|
return
|
|
}
|
|
// There was a newer request while we were rendering. Loop and render latest.
|
|
s.pending = false
|
|
s.mu.Unlock()
|
|
}
|
|
}
|