blob: b43dcb364cad5b3a511032b29f82b321e2fe4157 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
# tools/screenshot_mode.rb — OPTIONAL in-script screenshot helpers.
#
# The PRIMARY, generic capture path is the env hook in Rl.while_window_open
# (gated by JAMSTACK_SCREENSHOT=<path>) + the bin/screenshot wrapper. That works
# on ANY game script with zero changes — see tools/SCREENSHOT.md.
#
# This file is for the case where you want MANUAL control over WHEN the frame is
# captured: e.g. capture at a specific game-state event (after a physics step
# settles, when a shader parameter hits a value, N frames after input). Require
# it from your game script and call Jamstack::Screenshot.capture(path) inside
# your Rl.while_window_open block at the moment you choose:
#
# require_relative "../tools/screenshot_mode"
# ...
# Rl.while_window_open do
# ... draw ...
# Jamstack::Screenshot.capture("/tmp/scene.png") if some_condition
# end
#
# capture() is a no-op unless JAMSTACK_SCREENSHOT_MANUAL=1 is set, so it is safe
# to leave committed in a game script — it only fires when you opt in. This keeps
# the env hook (auto-exit) and manual capture from both running.
#
# NOTE: take_screenshot reads the framebuffer AFTER the current frame's drawing
# is complete, so call capture() at the END of your block (after Rl.draw {}).
# On desktop the PNG is written synchronously by raylib. Do NOT commit PNGs.
module Jamstack
module Screenshot
class << self
# True only when manual screenshot mode is opted in via the env var.
# Keeps committed `capture` calls inert in normal runs.
def enabled? = !::Jamstack.getenv('JAMSTACK_SCREENSHOT_MANUAL').nil?
# Write a pixel-exact PNG of the current framebuffer to +path+.
# No-op unless JAMSTACK_SCREENSHOT_MANUAL=1. Returns true if written.
def capture(path)
return false unless enabled?
::Rl.take_screenshot(path)
::Jamstack::Log.info("screenshot(manual) -> #{path}") rescue nil
true
end
# Count frames and capture once +path+ after +frames+ frames have elapsed
# since the first call. Useful inside the loop: pass the same path each
# frame; it fires exactly once then stops. Returns true on the capturing
# frame, nil otherwise. No-op unless enabled?.
def capture_after(frames, path)
return nil unless enabled?
@counters ||= {}
n = (@counters[path] ||= 0) + 1
@counters[path] = n
if n == frames
capture(path)
else
nil
end
end
# Reset the per-path frame counter (e.g. to re-capture the same path).
def reset(path = nil)
if path
@counters&.delete(path)
else
@counters = {}
end
end
end
end
end
|