automated snapshot

This commit is contained in:
sumi
2025-12-22 01:43:35 -06:00
parent 922c8bb2f6
commit 2f10e026a0
3 changed files with 73 additions and 20 deletions

28
main.go
View File

@@ -15,21 +15,21 @@ import (
const ( const (
targetWidth = 1000 targetWidth = 1000
targetHeight = 1000 targetHeight = 1000
sourceScale = 8 sourceScale = 2
snapshotsDir = "snapshots" snapshotsDir = "snapshots"
) )
type TextureCam struct { type TextureCam struct {
SourceWidth int SourceWidth int32
SourceHeight int SourceHeight int32
LookAt rl.Vector2 LookAt rl.Vector2
Zoom float32 Zoom float32
} }
func main() { func main() {
sourceWidth := sourceScale * targetWidth sourceWidth := int32(sourceScale * targetWidth)
sourceHeight := sourceScale * targetHeight sourceHeight := int32(sourceScale * targetHeight)
os.MkdirAll(snapshotsDir, 0755) os.MkdirAll(snapshotsDir, 0755)
log := log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile) log := log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile)
@@ -64,7 +64,7 @@ func main() {
x: -float32(sourceWidth / 2.0), x: -float32(sourceWidth / 2.0),
y: -float32(sourceHeight / 2.0), y: -float32(sourceHeight / 2.0),
field: &ScaleField{ field: &ScaleField{
scale: 5.0, scale: 1.0,
field: &imageField, field: &imageField,
}, },
} }
@@ -72,7 +72,7 @@ func main() {
contourLayer := NewContourLayer(rng, &field, sourceWidth, sourceHeight) contourLayer := NewContourLayer(rng, &field, sourceWidth, sourceHeight)
sketch := NewSketch() sketch := NewSketch(sourceWidth, sourceHeight)
//sketch.CreateLayer("testPattern", &TestPattern{}, int32(sourceWidth), int32(sourceHeight)) //sketch.CreateLayer("testPattern", &TestPattern{}, int32(sourceWidth), int32(sourceHeight))
//sketch.CreateLayer("actors", &contourLayer, int32(sourceWidth), int32(sourceHeight)) //sketch.CreateLayer("actors", &contourLayer, int32(sourceWidth), int32(sourceHeight))
//sketch.CreateLayer("field", &FieldLayer{field: &field, dirty: true}, int32(sourceWidth), int32(sourceHeight)) //sketch.CreateLayer("field", &FieldLayer{field: &field, dirty: true}, int32(sourceWidth), int32(sourceHeight))
@@ -112,7 +112,9 @@ func main() {
sketch.Draw(renderCtx) sketch.Draw(renderCtx)
if rl.IsKeyDown(rl.KeySpace) { if rl.IsKeyDown(rl.KeySpace) {
if _, err := storage.Save(); err != nil { capture := sketch.Capture()
if _, err := storage.Save(capture); err != nil {
log.Printf("Error saving snapshot: %v\n", err) log.Printf("Error saving snapshot: %v\n", err)
} }
} }
@@ -172,11 +174,11 @@ type ContourLayer struct {
field Field field Field
actors []*Actor actors []*Actor
rng *rand.Rand rng *rand.Rand
sourceWidth int sourceWidth int32
sourceHeight int sourceHeight int32
} }
func NewContourLayer(rng *rand.Rand, field Field, sourceWidth int, sourceHeight int) ContourLayer { func NewContourLayer(rng *rand.Rand, field Field, sourceWidth int32, sourceHeight int32) ContourLayer {
actors := make([]*Actor, 0) actors := make([]*Actor, 0)
@@ -195,8 +197,8 @@ func NewContourLayer(rng *rand.Rand, field Field, sourceWidth int, sourceHeight
func (s *ContourLayer) AddActors(n int) { func (s *ContourLayer) AddActors(n int) {
for range n { for range n {
x := s.rng.Int() % s.sourceWidth x := s.rng.Int31() % s.sourceWidth
y := s.rng.Int() % s.sourceHeight y := s.rng.Int31() % s.sourceHeight
newActor := newActor :=
&Actor { &Actor {
position: rl.Vector2{X: float32(x), Y: float32(y)}, position: rl.Vector2{X: float32(x), Y: float32(y)},

View File

@@ -6,14 +6,20 @@ import (
) )
type Sketch struct { type Sketch struct {
sourceWidth int32
sourceHeight int32
layerTools map[string]LayerTools layerTools map[string]LayerTools
layerToolsOrdered []LayerTools layerToolsOrdered []LayerTools
composite rl.RenderTexture2D
} }
func NewSketch() Sketch { func NewSketch(sourceWidth, sourceHeight int32) Sketch {
return Sketch{ return Sketch {
sourceWidth: sourceWidth,
sourceHeight: sourceHeight,
layerTools: make(map[string]LayerTools), layerTools: make(map[string]LayerTools),
layerToolsOrdered: []LayerTools {}, layerToolsOrdered: []LayerTools {},
composite: rl.LoadRenderTexture(sourceWidth, sourceHeight),
} }
} }
@@ -49,12 +55,28 @@ func (s *Sketch) Draw(ctx *RenderCtx) {
Height: float32(ctx.TargetHeight), Height: float32(ctx.TargetHeight),
} }
viewport := s.CalcViewport(ctx) // copy from full texture for compositing, with vertical flipping
src := rl.Rectangle {
for _, instance := range s.layerToolsOrdered { X: 0, Y: 0,
rl.DrawTexturePro(instance.texture.Texture, viewport, screen, rl.Vector2{}, 0, rl.White) Width: float32(ctx.SourceWidth),
Height: -float32(ctx.SourceHeight),
}
dst := rl.Rectangle {
X: 0, Y: 0,
Width: float32(ctx.SourceWidth),
Height: float32(ctx.SourceHeight),
} }
viewport := s.CalcViewport(ctx)
rl.BeginTextureMode(s.composite)
rl.ClearBackground(rl.Black)
for _, instance := range s.layerToolsOrdered {
rl.DrawTexturePro(instance.texture.Texture, src, dst, rl.Vector2{}, 0, rl.White)
}
rl.EndTextureMode()
rl.DrawTexturePro(s.composite.Texture, viewport, screen, rl.Vector2{}, 0, rl.White)
} }
func (s *Sketch) CalcViewport(ctx *RenderCtx) rl.Rectangle { func (s *Sketch) CalcViewport(ctx *RenderCtx) rl.Rectangle {
@@ -98,6 +120,24 @@ func (s *Sketch) Update(ctx *RenderCtx) {
} }
type SketchCapture struct {
compositeImage *rl.Image
layerImages []*rl.Image
}
func (s *Sketch) Capture() *SketchCapture {
composite := rl.LoadImageFromTexture(s.composite.Texture)
layerImages := make([]*rl.Image, len(s.layerToolsOrdered))
for i, layerTool := range s.layerToolsOrdered {
layerImages[i] = rl.LoadImageFromTexture(layerTool.texture.Texture)
}
return &SketchCapture {
compositeImage: composite,
layerImages: layerImages,
}
}
type LayerTools struct { type LayerTools struct {
name string name string
layer Layer layer Layer

View File

@@ -85,18 +85,29 @@ func initSchema(db *sql.DB) error {
return tx.Commit() return tx.Commit()
} }
func (s *Storage) Save() (string, error) { func (s *Storage) Save(capture *SketchCapture) (string, error) {
id, _ := s.gen.Next() id, _ := s.gen.Next()
kid := ids.Base62Encode(id) kid := ids.Base62Encode(id)
path := filepath.Join(s.snapshotsDir, kid) path := filepath.Join(s.snapshotsDir, kid)
os.MkdirAll(path, 0755) os.MkdirAll(path, 0755)
// wysiwyg at screen res
img := rl.LoadImageFromScreen() img := rl.LoadImageFromScreen()
defer rl.UnloadImage(img) defer rl.UnloadImage(img)
snapshotPng := filepath.Join(path, fmt.Sprintf("%s.png", kid)) snapshotPng := filepath.Join(path, fmt.Sprintf("%s.png", kid))
rl.ExportImage(*img, snapshotPng) rl.ExportImage(*img, snapshotPng)
// capture full res compsite
compositePng := filepath.Join(path, fmt.Sprintf("%s-composite.png", kid))
rl.ExportImage(*capture.compositeImage, compositePng)
// capture full res layer
for i, layerImage := range capture.layerImages {
layerPng := filepath.Join(path, fmt.Sprintf("%s-%3d.png", kid, i))
rl.ExportImage(*layerImage, layerPng)
}
s.log.Printf("Checking git status...\n") s.log.Printf("Checking git status...\n")
hash, branch, committed, err := CommitAllIfDirty(s.repoRoot, "automated snapshot", s.log) hash, branch, committed, err := CommitAllIfDirty(s.repoRoot, "automated snapshot", s.log)