vizcore 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +66 -648
  3. data/docs/assets/playground-worker.js +373 -0
  4. data/docs/assets/playground.css +440 -0
  5. data/docs/assets/playground.js +652 -0
  6. data/docs/index.html +2 -1
  7. data/docs/playground.html +81 -0
  8. data/docs/shape_dsl.md +269 -0
  9. data/frontend/index.html +50 -2
  10. data/frontend/src/audio-inspector.js +9 -0
  11. data/frontend/src/custom-shape-param-controls.js +106 -0
  12. data/frontend/src/live-controls.js +219 -7
  13. data/frontend/src/main.js +703 -45
  14. data/frontend/src/mapping-target-selector.js +109 -0
  15. data/frontend/src/midi-learn.js +22 -2
  16. data/frontend/src/performance-monitor.js +137 -1
  17. data/frontend/src/renderer/engine.js +401 -11
  18. data/frontend/src/renderer/layer-manager.js +490 -75
  19. data/frontend/src/runtime-control-preset.js +44 -0
  20. data/frontend/src/scene-patches.js +159 -0
  21. data/frontend/src/shader-error-overlay.js +1 -0
  22. data/frontend/src/shape-editor-controls.js +157 -0
  23. data/frontend/src/visuals/geometry.js +425 -27
  24. data/frontend/src/visuals/image-renderer.js +19 -0
  25. data/frontend/src/visuals/particle-system.js +10 -0
  26. data/frontend/src/visuals/shape-renderer.js +488 -0
  27. data/frontend/src/visuals/spectrogram-renderer.js +14 -0
  28. data/frontend/src/visuals/svg-arc.js +104 -0
  29. data/frontend/src/visuals/text-renderer.js +13 -0
  30. data/frontend/src/websocket-client.js +6 -0
  31. data/lib/vizcore/analysis/adaptive_normalizer.rb +20 -2
  32. data/lib/vizcore/analysis/bpm_estimator.rb +18 -8
  33. data/lib/vizcore/analysis/feature_recorder.rb +117 -7
  34. data/lib/vizcore/analysis/feature_replay.rb +48 -9
  35. data/lib/vizcore/analysis/pipeline.rb +258 -9
  36. data/lib/vizcore/analysis/tap_tempo.rb +17 -2
  37. data/lib/vizcore/audio/calibration.rb +156 -0
  38. data/lib/vizcore/audio/file_input.rb +28 -0
  39. data/lib/vizcore/audio/input_manager.rb +36 -1
  40. data/lib/vizcore/audio/midi_input.rb +5 -0
  41. data/lib/vizcore/audio/ring_buffer.rb +22 -0
  42. data/lib/vizcore/audio.rb +1 -0
  43. data/lib/vizcore/cli/dsl_reference.rb +65 -9
  44. data/lib/vizcore/cli/plugin_checker.rb +93 -0
  45. data/lib/vizcore/cli/scene_diagnostics.rb +2 -2
  46. data/lib/vizcore/cli/scene_inspector.rb +35 -1
  47. data/lib/vizcore/cli/scene_validator.rb +573 -33
  48. data/lib/vizcore/cli/shader_template.rb +7 -2
  49. data/lib/vizcore/cli/shader_uniform_docs.rb +11 -0
  50. data/lib/vizcore/cli.rb +268 -15
  51. data/lib/vizcore/config.rb +40 -3
  52. data/lib/vizcore/control_preset.rb +29 -0
  53. data/lib/vizcore/deep_copy.rb +21 -0
  54. data/lib/vizcore/dsl/color_helpers.rb +155 -0
  55. data/lib/vizcore/dsl/engine.rb +219 -23
  56. data/lib/vizcore/dsl/layer_builder.rb +1072 -21
  57. data/lib/vizcore/dsl/layer_group_builder.rb +10 -12
  58. data/lib/vizcore/dsl/layout_helpers.rb +290 -0
  59. data/lib/vizcore/dsl/mapping_preset_builder.rb +41 -0
  60. data/lib/vizcore/dsl/mapping_resolver.rb +549 -13
  61. data/lib/vizcore/dsl/mapping_transform_builder.rb +50 -0
  62. data/lib/vizcore/dsl/midi_map_executor.rb +219 -23
  63. data/lib/vizcore/dsl/reaction_builder.rb +1 -0
  64. data/lib/vizcore/dsl/scene_builder.rb +83 -13
  65. data/lib/vizcore/dsl/shader_source_resolver.rb +1 -10
  66. data/lib/vizcore/dsl/style_builder.rb +3 -0
  67. data/lib/vizcore/dsl/timeline_builder.rb +91 -8
  68. data/lib/vizcore/dsl/transition_controller.rb +157 -18
  69. data/lib/vizcore/dsl.rb +2 -0
  70. data/lib/vizcore/layer_catalog.rb +5 -2
  71. data/lib/vizcore/plugin_asset_policy.rb +55 -0
  72. data/lib/vizcore/project_manifest.rb +12 -2
  73. data/lib/vizcore/renderer/render_sequence.rb +104 -13
  74. data/lib/vizcore/renderer/scene_frame_source.rb +190 -12
  75. data/lib/vizcore/renderer/scene_serializer.rb +38 -0
  76. data/lib/vizcore/renderer/snapshot.rb +4 -3
  77. data/lib/vizcore/renderer/snapshot_renderer.rb +641 -23
  78. data/lib/vizcore/scene_trust.rb +31 -0
  79. data/lib/vizcore/server/frame_broadcaster.rb +513 -18
  80. data/lib/vizcore/server/rack_app.rb +151 -4
  81. data/lib/vizcore/server/runner.rb +697 -82
  82. data/lib/vizcore/server/websocket_handler.rb +236 -14
  83. data/lib/vizcore/server.rb +21 -0
  84. data/lib/vizcore/shape.rb +742 -0
  85. data/lib/vizcore/sync/osc_message.rb +66 -9
  86. data/lib/vizcore/version.rb +1 -1
  87. data/lib/vizcore.rb +34 -0
  88. data/scripts/browser_capture.mjs +31 -2
  89. data/sig/vizcore.rbs +154 -4
  90. metadata +29 -3
@@ -4,37 +4,46 @@ module Vizcore
4
4
  module Sync
5
5
  # Minimal OSC 1.0 message parser for control sync.
6
6
  class OscMessage
7
- attr_reader :address, :arguments
7
+ attr_reader :address, :arguments, :timetag
8
8
 
9
9
  # @param data [String]
10
- # @return [Vizcore::Sync::OscMessage, nil]
10
+ # @return [Vizcore::Sync::OscMessage, Array<Vizcore::Sync::OscMessage>, nil]
11
11
  def self.parse(data)
12
12
  parser = Parser.new(data)
13
- address = parser.read_string
14
- return nil unless address&.start_with?("/")
15
-
16
- tags = parser.read_string
17
- arguments = parser.read_arguments(tags)
18
- new(address: address, arguments: arguments)
13
+ parser.parse_packet
19
14
  rescue StandardError
20
15
  nil
21
16
  end
22
17
 
23
18
  # @param address [String]
24
19
  # @param arguments [Array]
25
- def initialize(address:, arguments: [])
20
+ # @param timetag [Float, nil]
21
+ def initialize(address:, arguments: [], timetag: nil)
26
22
  @address = address
27
23
  @arguments = Array(arguments)
24
+ @timetag = timetag
28
25
  end
29
26
 
30
27
  # @api private
31
28
  class Parser
29
+ BUNDLE_SIGNATURE = "#bundle"
30
+ NTP_TO_UNIX_OFFSET = 2_208_988_800
31
+
32
32
  # @param data [String]
33
33
  def initialize(data)
34
34
  @data = data.to_s.b
35
35
  @offset = 0
36
36
  end
37
37
 
38
+ # @return [Vizcore::Sync::OscMessage, Array<Vizcore::Sync::OscMessage>, nil]
39
+ def parse_packet(default_timetag: nil)
40
+ signature_or_address = read_string
41
+ return nil unless signature_or_address
42
+
43
+ return parse_bundle if signature_or_address == BUNDLE_SIGNATURE
44
+ parse_message(signature_or_address, timetag: default_timetag)
45
+ end
46
+
38
47
  # @return [String, nil]
39
48
  def read_string
40
49
  start = @offset
@@ -47,6 +56,42 @@ module Vizcore
47
56
  value
48
57
  end
49
58
 
59
+ def parse_bundle
60
+ bundle_timetag = parse_timetag(read_uint64)
61
+ messages = []
62
+
63
+ until @offset >= @data.bytesize
64
+ break if @offset + 4 > @data.bytesize
65
+
66
+ begin
67
+ message_size = read_int32
68
+ rescue StandardError
69
+ break
70
+ end
71
+
72
+ break if message_size <= 0
73
+
74
+ begin
75
+ message_data = read_bytes(message_size)
76
+ rescue StandardError
77
+ break
78
+ end
79
+
80
+ parsed = Parser.new(message_data).parse_packet(default_timetag: bundle_timetag)
81
+ messages.concat(Array(parsed))
82
+ end
83
+
84
+ messages
85
+ end
86
+
87
+ def parse_message(address, timetag: nil)
88
+ return nil unless address&.start_with?("/")
89
+
90
+ tags = read_string
91
+ arguments = read_arguments(tags)
92
+ OscMessage.new(address: address, arguments: arguments, timetag: timetag)
93
+ end
94
+
50
95
  # @param tags [String, nil]
51
96
  # @return [Array]
52
97
  def read_arguments(tags)
@@ -86,6 +131,10 @@ module Vizcore
86
131
  read_bytes(4).unpack1("g")
87
132
  end
88
133
 
134
+ def read_uint64
135
+ read_bytes(8).unpack1("Q>")
136
+ end
137
+
89
138
  def read_bytes(length)
90
139
  raise ArgumentError, "OSC payload truncated" if @offset + length > @data.bytesize
91
140
 
@@ -94,6 +143,14 @@ module Vizcore
94
143
  end
95
144
  end
96
145
 
146
+ def parse_timetag(raw)
147
+ return nil if raw == 0
148
+
149
+ seconds = (raw >> 32) - NTP_TO_UNIX_OFFSET
150
+ fraction = raw & 0xFFFF_FFFF
151
+ seconds + (fraction / 4_294_967_296.0)
152
+ end
153
+
97
154
  def align_offset
98
155
  @offset += 1 while (@offset % 4).positive?
99
156
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Vizcore
4
4
  # Current gem version.
5
- VERSION = "1.0.0"
5
+ VERSION = "1.2.0"
6
6
  end
data/lib/vizcore.rb CHANGED
@@ -1,9 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "vizcore/version"
4
+ require_relative "vizcore/deep_copy"
4
5
  require_relative "vizcore/errors"
5
6
  require_relative "vizcore/layer_catalog"
7
+ require_relative "vizcore/plugin_asset_policy"
8
+ require_relative "vizcore/scene_trust"
9
+ require_relative "vizcore/shape"
6
10
  require_relative "vizcore/dsl"
11
+ require_relative "vizcore/analysis"
12
+ require_relative "vizcore/audio"
7
13
  require "pathname"
8
14
 
9
15
  # Main namespace for the Vizcore runtime and DSL entrypoints.
@@ -28,6 +34,19 @@ module Vizcore
28
34
  root.join("lib", "vizcore", "templates")
29
35
  end
30
36
 
37
+ # @param command_available [#call, nil] optional command lookup for tests
38
+ # @return [Hash<Symbol, Boolean>] optional runtime feature availability
39
+ def self.features(command_available: nil)
40
+ command_available ||= method(:command_available?)
41
+ {
42
+ mic: feature_available? { Audio::PortAudioFFI.available? },
43
+ midi: feature_available? { Audio::MidiInput.available? },
44
+ ffmpeg: command_available.call("ffmpeg"),
45
+ browser_capture: root.join("scripts", "browser_capture.mjs").file? && command_available.call("node"),
46
+ fftw: feature_available? { Analysis::FFTProcessor.fftw_available? }
47
+ }
48
+ end
49
+
31
50
  # Evaluate a Vizcore DSL definition block.
32
51
  #
33
52
  # @yield DSL configuration block (`audio`, `scene`, `midi_map`, etc.)
@@ -61,4 +80,19 @@ module Vizcore
61
80
  description: description
62
81
  )
63
82
  end
83
+
84
+ def self.feature_available?
85
+ !!yield
86
+ rescue StandardError
87
+ false
88
+ end
89
+ private_class_method :feature_available?
90
+
91
+ def self.command_available?(command)
92
+ ENV.fetch("PATH", "").split(File::PATH_SEPARATOR).any? do |directory|
93
+ path = File.join(directory, command)
94
+ File.file?(path) && File.executable?(path)
95
+ end
96
+ end
97
+ private_class_method :command_available?
64
98
  end
@@ -4,7 +4,7 @@ import path from "node:path";
4
4
  const options = parseArgs(process.argv.slice(2));
5
5
 
6
6
  if (!options.url) {
7
- console.error("Usage: node scripts/browser_capture.mjs URL --out browser-capture.png [--selector #vizcore-canvas] [--wait 1000]");
7
+ console.error("Usage: node scripts/browser_capture.mjs URL --out browser-capture.png [--selector #vizcore-canvas] [--wait 1000] [--wait-for-frame]");
8
8
  process.exit(1);
9
9
  }
10
10
 
@@ -24,8 +24,11 @@ try {
24
24
  await page.waitForTimeout(options.wait);
25
25
  }
26
26
 
27
- const element = page.locator(options.selector).first();
27
+ const element = await resolveCaptureLocator(page, options.selector);
28
28
  await element.waitFor({ state: "visible", timeout: 10000 });
29
+ if (options.waitForFrame) {
30
+ await waitForVizcoreFrame(page, options.frameTimeout);
31
+ }
29
32
  await fs.mkdir(path.dirname(options.out), { recursive: true });
30
33
  await element.screenshot({ path: options.out });
31
34
  console.log(`Browser capture written: ${options.out}`);
@@ -33,6 +36,25 @@ try {
33
36
  await browser.close();
34
37
  }
35
38
 
39
+ async function resolveCaptureLocator(page, selector) {
40
+ const candidates = [...new Set([selector, "#vizcore-canvas", "canvas"].filter(Boolean))];
41
+ for (const candidate of candidates) {
42
+ const locator = page.locator(candidate).first();
43
+ if (await locator.count().catch(() => 0) > 0) {
44
+ return locator;
45
+ }
46
+ }
47
+ return page.locator(selector).first();
48
+ }
49
+
50
+ async function waitForVizcoreFrame(page, timeout) {
51
+ await page.waitForFunction(
52
+ () => Number(document.body?.dataset?.vizcoreFrameCount || 0) > 0,
53
+ null,
54
+ { timeout }
55
+ );
56
+ }
57
+
36
58
  function parseArgs(args) {
37
59
  const parsed = {
38
60
  url: null,
@@ -41,6 +63,8 @@ function parseArgs(args) {
41
63
  wait: 1000,
42
64
  width: 1280,
43
65
  height: 720,
66
+ waitForFrame: false,
67
+ frameTimeout: 10000,
44
68
  };
45
69
 
46
70
  for (let index = 0; index < args.length; index += 1) {
@@ -60,6 +84,11 @@ function parseArgs(args) {
60
84
  } else if (value === "--height") {
61
85
  parsed.height = finiteNumber(args[index + 1], parsed.height);
62
86
  index += 1;
87
+ } else if (value === "--wait-for-frame") {
88
+ parsed.waitForFrame = true;
89
+ } else if (value === "--frame-timeout") {
90
+ parsed.frameTimeout = finiteNumber(args[index + 1], parsed.frameTimeout);
91
+ index += 1;
63
92
  } else if (!parsed.url) {
64
93
  parsed.url = value;
65
94
  }
data/sig/vizcore.rbs CHANGED
@@ -4,8 +4,12 @@ module Vizcore
4
4
  def self.root: () -> Pathname
5
5
  def self.frontend_root: () -> Pathname
6
6
  def self.templates_root: () -> Pathname
7
+ def self.features: (?command_available: untyped? command_available) -> Hash[Symbol, bool]
7
8
  def self.define: () { () -> void } -> Hash[Symbol, untyped]
8
9
  def self.plugin: (String | Symbol name) -> bool
10
+ def self.register_shape: (Symbol | String name, untyped renderer) -> Vizcore::Shape::Definition
11
+ | (Symbol | String name) { (Vizcore::Shape::DrawContext) -> untyped } -> Vizcore::Shape::Definition
12
+ def self.resolve_shape: (Symbol | String name) -> Vizcore::Shape::Definition?
9
13
  def self.register_layer_capability: (
10
14
  type: Symbol | String,
11
15
  ?aliases: Array[Symbol | String] aliases,
@@ -15,6 +19,94 @@ module Vizcore
15
19
  ) -> Vizcore::LayerCatalog::Capability
16
20
  end
17
21
 
22
+ module Vizcore::Shape
23
+ SUPPORTED_PRIMITIVES: Array[Symbol]
24
+
25
+ def self.normalize_primitives: (untyped value, shape_name: untyped) -> Array[Hash[Symbol, untyped]]
26
+ def self.expand_custom_shape: (
27
+ untyped renderer,
28
+ params: Hash[Symbol | String, untyped],
29
+ ?shape_id: Symbol | String? shape_id,
30
+ ?layer_name: Symbol? layer_name,
31
+ ?palette: Array[untyped] palette,
32
+ ?audio: Hash[untyped, untyped] audio,
33
+ ?time: Numeric time,
34
+ ?frame: Integer frame,
35
+ ?resolution: Array[untyped] resolution,
36
+ ?globals: Hash[untyped, untyped] globals,
37
+ ?shape_name: untyped shape_name
38
+ ) -> Array[Hash[Symbol, untyped]]
39
+ def self.param_schema_for: (untyped renderer) -> Hash[Symbol, Hash[Symbol, untyped]]
40
+
41
+ class Definition < Struct[untyped]
42
+ attr_accessor name: Symbol?
43
+ attr_accessor renderer: untyped
44
+ end
45
+
46
+ module ClassMethods
47
+ def param: (
48
+ Symbol | String name,
49
+ ?default: untyped default,
50
+ ?range: Range[Numeric]? | [Numeric, Numeric]? range,
51
+ ?min: Numeric? min,
52
+ ?max: Numeric? max,
53
+ ?step: Numeric? step
54
+ ) -> Hash[Symbol, untyped]
55
+ def shape_param_schema: () -> Hash[Symbol, Hash[Symbol, untyped]]
56
+ end
57
+
58
+ class DrawContext
59
+ attr_reader params: Hash[Symbol, untyped]
60
+ attr_reader shape_id: Symbol?
61
+ attr_reader layer_name: Symbol?
62
+ attr_reader palette: Array[untyped]
63
+ attr_reader audio: AudioContext
64
+ attr_reader time: Float
65
+ attr_reader frame: Integer
66
+ attr_reader resolution: Array[untyped]
67
+ attr_reader globals: Hash[Symbol, untyped]
68
+
69
+ def initialize: (
70
+ params: Hash[Symbol | String, untyped],
71
+ ?param_schema: Hash[Symbol, Hash[Symbol, untyped]] param_schema,
72
+ ?shape_id: Symbol | String? shape_id,
73
+ ?layer_name: Symbol? layer_name,
74
+ ?palette: Array[untyped] palette,
75
+ ?audio: Hash[untyped, untyped] audio,
76
+ ?time: Numeric time,
77
+ ?frame: Integer frame,
78
+ ?resolution: Array[untyped] resolution,
79
+ ?globals: Hash[untyped, untyped] globals
80
+ ) -> void
81
+ def param: (Symbol | String name, ?untyped default) -> untyped
82
+ def width: () -> untyped
83
+ def height: () -> untyped
84
+ def draw: () { () -> void } -> Array[Hash[Symbol, untyped]]
85
+ def shapes: () -> Array[Hash[Symbol, untyped]]
86
+ end
87
+
88
+ class AudioContext
89
+ def amplitude: () -> Float
90
+ def bass: () -> Float
91
+ def bass_peak: () -> Float
92
+ def mid: () -> Float
93
+ def mid_peak: () -> Float
94
+ def high: () -> Float
95
+ def high_peak: () -> Float
96
+ def fft: () -> Array[untyped]
97
+ def beat?: () -> bool
98
+ def beat_pulse: () -> Float
99
+ def beat_phase: () -> Float
100
+ def bar_phase: () -> Float
101
+ def bar_count: () -> Integer
102
+ def phrase_count: () -> Integer
103
+ def kick: () -> Float
104
+ def snare: () -> Float
105
+ def hihat: () -> Float
106
+ def bpm: () -> Float
107
+ end
108
+ end
109
+
18
110
  module Vizcore::LayerCatalog
19
111
  class Capability < Struct[untyped]
20
112
  attr_accessor type: Symbol
@@ -117,10 +209,14 @@ module Vizcore::Analysis
117
209
 
118
210
  class FeatureReplay
119
211
  attr_reader metadata: Hash[Symbol, untyped]
212
+ attr_reader cursor: Integer
120
213
 
121
214
  def initialize: (path: String | Pathname path) -> void
122
215
  def call: (?Array[Float]? samples) -> Hash[Symbol, untyped]
123
216
  def frame_count: () -> Integer
217
+ def seek: (Integer index) -> FeatureReplay
218
+ def seek_seconds: (Numeric seconds) -> FeatureReplay
219
+ def frame: (Integer index) -> Hash[Symbol, untyped]
124
220
  end
125
221
  end
126
222
 
@@ -155,7 +251,8 @@ module Vizcore::DSL
155
251
  type scene = { name: Symbol, layers: Array[layer], ?theme: Symbol }
156
252
  type style = { name: Symbol, params: Hash[Symbol, untyped] }
157
253
  type theme = { name: Symbol, params: Hash[Symbol, untyped] }
158
- type timeline_entry = { at: Float, unit: Symbol, scene: Symbol }
254
+ type mapping_preset = { name: Symbol, mappings: Array[mapping] }
255
+ type timeline_entry = { at: Float, unit: Symbol, scene: Symbol, ?cue: Symbol }
159
256
  type key_action = { type: Symbol, ?scene: String, ?control: Symbol }
160
257
  type key_mapping = { key: String, action: key_action }
161
258
 
@@ -167,18 +264,28 @@ module Vizcore::DSL
167
264
  def audio: (Symbol | String name, **untyped options) -> Array[Hash[Symbol, untyped]]
168
265
  def style: (Symbol | String name) { () -> void } -> void
169
266
  def theme: (Symbol | String name) { () -> void } -> void
267
+ def mapping: (Symbol | String name) { () -> void } -> void
170
268
  def midi: (Symbol | String name, **untyped options) -> Array[Hash[Symbol, untyped]]
171
269
  def audio_normalize: (?mode: Symbol | String mode, **untyped options) -> Hash[Symbol, untyped]
270
+ def audio_analysis: (**untyped options) -> Hash[Symbol, untyped]
172
271
  def bpm: (Numeric value) -> Float
173
272
  def bpm_lock: () -> bool
174
273
  | (bool value) -> bool
175
274
  def tap_tempo: (?key: Symbol | String key) -> Hash[Symbol, untyped]
176
275
  def key: (Symbol | String value) { () -> void } -> void
177
276
  def scene: (Symbol | String name, ?extends: Symbol | String? extends) { () -> void } -> void
178
- def section: (Symbol | String name, bars: Integer bars, ?beats_per_bar: Integer beats_per_bar) { () -> void } -> void
277
+ def section: (Symbol | String name, bars: Integer bars, ?beats_per_bar: Integer beats_per_bar, ?loop: bool loop, ?hold: Numeric hold, ?outro: bool outro) { () -> void } -> void
179
278
  def timeline: (?beats_per_bar: Integer beats_per_bar) { () -> void } -> void
180
279
  def transition: (from: Symbol | String, to: Symbol | String) { () -> void } -> void
181
- def midi_map: (?note: Integer? note, ?cc: Integer? cc, ?pc: Integer? pc) { (*untyped) -> void } -> void
280
+ def midi_map: (
281
+ ?note: Integer? note,
282
+ ?cc: Integer? cc,
283
+ ?pc: Integer? pc,
284
+ ?channel: Integer? channel,
285
+ ?relative: bool relative,
286
+ ?deadband: Numeric? deadband,
287
+ ?smooth: Numeric | bool | nil smooth
288
+ ) { (*untyped) -> void } -> void
182
289
  def set: (Symbol | String key, untyped value) -> untyped
183
290
  def to_h: () -> Hash[Symbol, untyped]
184
291
  end
@@ -224,6 +331,7 @@ module Vizcore::DSL
224
331
  name: Symbol | String name,
225
332
  ?styles: Hash[Symbol, Hash[Symbol, untyped]] styles,
226
333
  ?themes: Hash[Symbol, Hash[Symbol, untyped]] themes,
334
+ ?mapping_presets: Hash[Symbol, Array[mapping]] mapping_presets,
227
335
  ?layers: Array[layer] layers
228
336
  ) -> void
229
337
  def evaluate: () ?{ () -> void } -> SceneBuilder
@@ -237,6 +345,7 @@ module Vizcore::DSL
237
345
  def initialize: (
238
346
  name: Symbol | String name,
239
347
  ?styles: Hash[Symbol, Hash[Symbol, untyped]] styles,
348
+ ?mapping_presets: Hash[Symbol, Array[mapping]] mapping_presets,
240
349
  ?defaults: Hash[Symbol, untyped] defaults
241
350
  ) -> void
242
351
  def evaluate: () ?{ () -> void } -> LayerGroupBuilder
@@ -267,6 +376,7 @@ module Vizcore::DSL
267
376
  def initialize: (
268
377
  name: Symbol | String name,
269
378
  ?styles: Hash[Symbol, Hash[Symbol, untyped]] styles,
379
+ ?mapping_presets: Hash[Symbol, Array[mapping]] mapping_presets,
270
380
  ?defaults: Hash[Symbol, untyped] defaults
271
381
  ) -> void
272
382
  def evaluate: () ?{ () -> void } -> LayerBuilder
@@ -276,6 +386,14 @@ module Vizcore::DSL
276
386
  def file: (String | Pathname path) -> String
277
387
  def circle: (**untyped options) ?{ () -> void } -> Hash[Symbol, untyped]
278
388
  def line: (**untyped options) ?{ () -> void } -> Hash[Symbol, untyped]
389
+ def rect: (*untyped args, **untyped options) ?{ () -> void } -> Hash[Symbol, untyped]
390
+ def polygon: (*untyped args, **untyped options) ?{ () -> void } -> Hash[Symbol, untyped]
391
+ def polyline: (*untyped args, **untyped options) ?{ () -> void } -> Hash[Symbol, untyped]
392
+ def path: (*untyped args, **untyped options) ?{ () -> void } -> Hash[Symbol, untyped]
393
+ def bezier: (*untyped args, **untyped options) ?{ () -> void } -> Hash[Symbol, untyped]
394
+ def star: (*untyped args, **untyped options) ?{ () -> void } -> Hash[Symbol, untyped]
395
+ def custom_shape: (untyped renderer, **untyped options) ?{ () -> void } -> (Array[Hash[Symbol, untyped]] | Hash[Symbol, untyped])
396
+ def group: (*untyped args, **untyped attrs) { () -> void } -> Array[Hash[Symbol, untyped]]
279
397
  def draw: () { () -> void } -> Array[Hash[Symbol, untyped]]
280
398
  def source: (Symbol | String value, **untyped options) -> (Symbol | source)
281
399
  def count: (Integer value) -> Integer
@@ -299,6 +417,7 @@ module Vizcore::DSL
299
417
  def color_shift: (Numeric value) -> Float
300
418
  def palette: (*untyped colors) -> Array[String]
301
419
  def use_style: (Symbol | String name) -> Hash[Symbol, untyped]
420
+ def use_mapping: (Symbol | String name) -> void
302
421
  def param: (
303
422
  Symbol | String name,
304
423
  ?default: Numeric? default,
@@ -311,12 +430,19 @@ module Vizcore::DSL
311
430
  def react_to: (Hash[Symbol, untyped] | Symbol | String source_value) { () -> void } -> void
312
431
  def amplitude: () -> source
313
432
  def frequency_band: (Symbol | String name) -> source
433
+ def frequency_band_peak: (Symbol | String name) -> source
314
434
  def sub: () -> source
435
+ def sub_peak: () -> source
315
436
  def low: () -> source
437
+ def low_peak: () -> source
316
438
  def bass: () -> source
439
+ def bass_peak: () -> source
317
440
  def mid: () -> source
441
+ def mid_peak: () -> source
318
442
  def high: () -> source
443
+ def high_peak: () -> source
319
444
  def treble: () -> source
445
+ def treble_peak: () -> source
320
446
  def fft_spectrum: () -> source
321
447
  def onset: () -> source
322
448
  | (Symbol | String band) -> source
@@ -331,6 +457,15 @@ module Vizcore::DSL
331
457
  def beat_confidence: () -> source
332
458
  def beat_pulse: () -> source
333
459
  def beat_count: () -> source
460
+ def beat_phase: () -> source
461
+ def beat_2: () -> source
462
+ def beat_4: () -> source
463
+ def beat_8: () -> source
464
+ def beat_triplet: () -> source
465
+ def triplet: () -> source
466
+ def bar_phase: () -> source
467
+ def bar_count: () -> source
468
+ def phrase_count: () -> source
334
469
  def bpm: () -> source
335
470
  def to_h: () -> layer
336
471
  end
@@ -355,8 +490,23 @@ module Vizcore::DSL
355
490
  def to_h: () -> Hash[Symbol, untyped]
356
491
  end
357
492
 
493
+ class MappingPresetBuilder
494
+ def initialize: (name: Symbol | String name, ?strict: bool strict) -> void
495
+ def evaluate: () ?{ () -> void } -> MappingPresetBuilder
496
+ def to_h: () -> mapping_preset
497
+ end
498
+
358
499
  class MappingResolver
359
500
  def initialize: () -> void
360
- def resolve_layers: (scene_layers: Array[Hash[Symbol, untyped]], audio: Hash[Symbol, untyped]) -> Array[Hash[Symbol, untyped]]
501
+ def resolve_layers: (
502
+ scene_layers: Array[Hash[Symbol, untyped]],
503
+ audio: Hash[Symbol, untyped],
504
+ ?time: Numeric time,
505
+ ?frame: Integer frame,
506
+ ?resolution: Array[untyped] resolution,
507
+ ?globals: Hash[untyped, untyped] globals,
508
+ ?custom_shape_overrides: Hash[untyped, untyped] custom_shape_overrides,
509
+ ?layer_param_overrides: Hash[untyped, untyped] layer_param_overrides
510
+ ) -> Array[Hash[Symbol, untyped]]
361
511
  end
362
512
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vizcore
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yudai Takada
@@ -13,16 +13,22 @@ dependencies:
13
13
  name: faye-websocket
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - "~>"
16
+ - - ">="
17
17
  - !ruby/object:Gem::Version
18
18
  version: '0.11'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '0.13'
19
22
  type: :runtime
20
23
  prerelease: false
21
24
  version_requirements: !ruby/object:Gem::Requirement
22
25
  requirements:
23
- - - "~>"
26
+ - - ">="
24
27
  - !ruby/object:Gem::Version
25
28
  version: '0.11'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '0.13'
26
32
  - !ruby/object:Gem::Dependency
27
33
  name: ffi
28
34
  requirement: !ruby/object:Gem::Requirement
@@ -91,11 +97,16 @@ files:
91
97
  - LICENSE.txt
92
98
  - README.md
93
99
  - docs/.nojekyll
100
+ - docs/assets/playground-worker.js
101
+ - docs/assets/playground.css
102
+ - docs/assets/playground.js
94
103
  - docs/assets/site.css
95
104
  - docs/assets/vizcore-demo.gif
96
105
  - docs/assets/vizcore-poster.png
97
106
  - docs/assets/vj-tunnel.js
98
107
  - docs/index.html
108
+ - docs/playground.html
109
+ - docs/shape_dsl.md
99
110
  - examples/README.md
100
111
  - examples/assets/README.md
101
112
  - examples/assets/complex_demo_loop.wav
@@ -129,8 +140,10 @@ files:
129
140
  - exe/vizcore
130
141
  - frontend/index.html
131
142
  - frontend/src/audio-inspector.js
143
+ - frontend/src/custom-shape-param-controls.js
132
144
  - frontend/src/live-controls.js
133
145
  - frontend/src/main.js
146
+ - frontend/src/mapping-target-selector.js
134
147
  - frontend/src/midi-learn.js
135
148
  - frontend/src/performance-monitor.js
136
149
  - frontend/src/plugin-runtime.js
@@ -139,16 +152,20 @@ files:
139
152
  - frontend/src/renderer/layer-manager.js
140
153
  - frontend/src/renderer/shader-manager.js
141
154
  - frontend/src/runtime-control-preset.js
155
+ - frontend/src/scene-patches.js
142
156
  - frontend/src/shader-error-overlay.js
143
157
  - frontend/src/shader-param-controls.js
144
158
  - frontend/src/shaders/builtins.js
145
159
  - frontend/src/shaders/post-effects.js
160
+ - frontend/src/shape-editor-controls.js
146
161
  - frontend/src/visual-regression.js
147
162
  - frontend/src/visual-settings-preset.js
148
163
  - frontend/src/visuals/geometry.js
149
164
  - frontend/src/visuals/image-renderer.js
150
165
  - frontend/src/visuals/particle-system.js
166
+ - frontend/src/visuals/shape-renderer.js
151
167
  - frontend/src/visuals/spectrogram-renderer.js
168
+ - frontend/src/visuals/svg-arc.js
152
169
  - frontend/src/visuals/text-renderer.js
153
170
  - frontend/src/visuals/vj-effects.js
154
171
  - frontend/src/websocket-client.js
@@ -167,6 +184,7 @@ files:
167
184
  - lib/vizcore/analysis/tap_tempo.rb
168
185
  - lib/vizcore/audio.rb
169
186
  - lib/vizcore/audio/base_input.rb
187
+ - lib/vizcore/audio/calibration.rb
170
188
  - lib/vizcore/audio/dummy_sine_input.rb
171
189
  - lib/vizcore/audio/file_input.rb
172
190
  - lib/vizcore/audio/fixture_input.rb
@@ -179,6 +197,7 @@ files:
179
197
  - lib/vizcore/cli/doctor.rb
180
198
  - lib/vizcore/cli/dsl_reference.rb
181
199
  - lib/vizcore/cli/layer_docs.rb
200
+ - lib/vizcore/cli/plugin_checker.rb
182
201
  - lib/vizcore/cli/scene_diagnostics.rb
183
202
  - lib/vizcore/cli/scene_inspector.rb
184
203
  - lib/vizcore/cli/scene_validator.rb
@@ -186,11 +205,15 @@ files:
186
205
  - lib/vizcore/cli/shader_uniform_docs.rb
187
206
  - lib/vizcore/config.rb
188
207
  - lib/vizcore/control_preset.rb
208
+ - lib/vizcore/deep_copy.rb
189
209
  - lib/vizcore/dsl.rb
210
+ - lib/vizcore/dsl/color_helpers.rb
190
211
  - lib/vizcore/dsl/engine.rb
191
212
  - lib/vizcore/dsl/file_watcher.rb
192
213
  - lib/vizcore/dsl/layer_builder.rb
193
214
  - lib/vizcore/dsl/layer_group_builder.rb
215
+ - lib/vizcore/dsl/layout_helpers.rb
216
+ - lib/vizcore/dsl/mapping_preset_builder.rb
194
217
  - lib/vizcore/dsl/mapping_resolver.rb
195
218
  - lib/vizcore/dsl/mapping_transform_builder.rb
196
219
  - lib/vizcore/dsl/midi_map_executor.rb
@@ -202,6 +225,7 @@ files:
202
225
  - lib/vizcore/dsl/transition_controller.rb
203
226
  - lib/vizcore/errors.rb
204
227
  - lib/vizcore/layer_catalog.rb
228
+ - lib/vizcore/plugin_asset_policy.rb
205
229
  - lib/vizcore/project_manifest.rb
206
230
  - lib/vizcore/renderer.rb
207
231
  - lib/vizcore/renderer/frame_scheduler.rb
@@ -211,6 +235,7 @@ files:
211
235
  - lib/vizcore/renderer/scene_serializer.rb
212
236
  - lib/vizcore/renderer/snapshot.rb
213
237
  - lib/vizcore/renderer/snapshot_renderer.rb
238
+ - lib/vizcore/scene_trust.rb
214
239
  - lib/vizcore/server.rb
215
240
  - lib/vizcore/server/frame_broadcaster.rb
216
241
  - lib/vizcore/server/gallery_app.rb
@@ -220,6 +245,7 @@ files:
220
245
  - lib/vizcore/server/runner.rb
221
246
  - lib/vizcore/server/scene_dependency_watcher.rb
222
247
  - lib/vizcore/server/websocket_handler.rb
248
+ - lib/vizcore/shape.rb
223
249
  - lib/vizcore/sync.rb
224
250
  - lib/vizcore/sync/osc_message.rb
225
251
  - lib/vizcore/sync/osc_receiver.rb