116 lines
2.0 KiB
Go
116 lines
2.0 KiB
Go
package play
|
|
|
|
import (
|
|
"reflect"
|
|
"time"
|
|
"unsafe"
|
|
|
|
"aego/platform/input"
|
|
)
|
|
|
|
const DefaultHistoryLimit = 256 << 20
|
|
|
|
const (
|
|
stepNone uint8 = iota
|
|
stepFixed
|
|
stepFrame
|
|
)
|
|
|
|
type frameRec struct {
|
|
dt float64
|
|
scale float64
|
|
tick uint64
|
|
input int32
|
|
brk int32
|
|
paused bool
|
|
step uint8
|
|
}
|
|
|
|
type recording struct {
|
|
data []byte
|
|
name string
|
|
frames []frameRec
|
|
inputs []input.State
|
|
bytes int
|
|
limit int
|
|
end int
|
|
why string
|
|
}
|
|
|
|
var (
|
|
frameSize = int(unsafe.Sizeof(frameRec{}))
|
|
inputSize = int(unsafe.Sizeof(input.State{}))
|
|
)
|
|
|
|
func newHistory(data []byte, name string, limit int) *recording {
|
|
if limit <= 0 {
|
|
limit = DefaultHistoryLimit
|
|
}
|
|
return &recording{data: data, name: name, limit: limit, end: -1, bytes: len(data)}
|
|
}
|
|
|
|
func (h *recording) usable() int {
|
|
if h.end >= 0 {
|
|
return h.end
|
|
}
|
|
return len(h.frames)
|
|
}
|
|
|
|
func (h *recording) cut(why string) {
|
|
h.cutAt(len(h.frames), why)
|
|
}
|
|
|
|
func (h *recording) cutAt(n int, why string) {
|
|
if h.end < 0 || n < h.end {
|
|
h.end, h.why = n, why
|
|
}
|
|
}
|
|
|
|
func (h *recording) truncate(n int) {
|
|
h.frames = h.frames[:n]
|
|
keep := 0
|
|
if n > 0 {
|
|
keep = int(h.frames[n-1].input) + 1
|
|
}
|
|
h.inputs = h.inputs[:keep]
|
|
if h.end > n {
|
|
h.end, h.why = -1, ""
|
|
}
|
|
h.bytes = len(h.data) + n*frameSize + keep*inputSize
|
|
}
|
|
|
|
func (h *recording) add(dt, scale float64, paused bool, step uint8, in *input.State) bool {
|
|
if h.end >= 0 {
|
|
return false
|
|
}
|
|
if h.bytes+frameSize+inputSize > h.limit {
|
|
h.cut("the history reached its memory limit")
|
|
return false
|
|
}
|
|
idx := len(h.inputs) - 1
|
|
if idx < 0 || !reflect.DeepEqual(&h.inputs[idx], in) {
|
|
h.inputs = append(h.inputs, *in)
|
|
idx++
|
|
h.bytes += inputSize
|
|
}
|
|
h.frames = append(h.frames, frameRec{dt: dt, scale: scale, paused: paused, step: step, input: int32(idx)})
|
|
h.bytes += frameSize
|
|
return true
|
|
}
|
|
|
|
type Timeline struct {
|
|
Frames int
|
|
Cursor int
|
|
Usable int
|
|
Floor int
|
|
Keys int
|
|
KeyBytes int
|
|
LastKey int
|
|
KeyTime time.Duration
|
|
Tick uint64
|
|
Why string
|
|
Blocked string
|
|
KeysOff string
|
|
Beyond bool
|
|
}
|