tiny.rig.curve
Defined in tiny.rig.
Parameter curves: clips of plain values that drive shape and material parameters, with a mixer, a state machine, a blend space and notify tracks over them.
API (55)
Actions
Public operations.
BlendSpace1D.addSampleBlendSpace1D.deinitBlendSpace1D.evaluateSlotBlendSpace1D.initBlendSpace1D.sampleCountCatmullRomSpline.deinitCatmullRomSpline.evalCatmullRomSpline.initCubicHermiteSegment.evalNotifyTrack.addNotifyNotifyTrack.deinitNotifyTrack.initNotifyTrack.queryRangeParameterClip.addCurveParameterClip.deinitParameterClip.evalSlotParameterClip.initParameterClip.nameParameterMachine.addStateParameterMachine.addTransitionParameterMachine.currentStateParameterMachine.deinitParameterMachine.fireTriggerParameterMachine.initParameterMachine.isTransitioningParameterMachine.setInitialStateParameterMachine.updateParameterMixer.addLayerParameterMixer.advanceParameterMixer.blendSlotParameterMixer.deinitParameterMixer.initParameterMixer.removeLayerParameterState.namePeriodicSplineTransition.triggerangleSlerpinferBlendModescalarLerpvec3Lerp
Types and contracts
Public types and contracts.
BlendSampleBlendSpace1DCatmullRomSplineConditionFnCubicHermiteSegmentMixerLayerNotifyEventNotifyTrackParameterClipParameterMachineParameterMixerParameterStateSlotBlendModeSlotCurveTransition
Source
Source: fun/rig/src/curve/machine.zig:39
pub const ParameterMachine = struct { states: []ParameterState, state_count: usize, state_capacity: usize, transitions: []Transition, transition_count: usize, transition_capacity: usize, mixer: *ParameterMixer, current: ?usize = null, current_layer: ?usize = null, target: ?usize = null, target_layer: ?usize = null, blend_duration: f32 = 0, blend_elapsed: f32 = 0, pub fn init( allocator: Allocator, mixer: *ParameterMixer, max_states: usize, max_transitions: usize, ) !ParameterMachine { const states = try allocator.alloc(ParameterState, max_states); const transitions = try allocator.alloc(Transition, max_transitions); return .{ .states = states, .state_count = 0, .state_capacity = max_states, .transitions = transitions, .transition_count = 0, .transition_capacity = max_transitions, .mixer = mixer, }; } pub fn deinit(self: *ParameterMachine, allocator: Allocator) void { allocator.free(self.states); allocator.free(self.transitions); self.* = undefined; } pub fn addState(self: *ParameterMachine, clip: *const ParameterClip, state_name: []const u8, opts: struct { speed: f32 = 1.0, loop: bool = true, }) !usize { if (self.state_count >= self.state_capacity) return error.TooManyStates; const idx = self.state_count; var state = ParameterState{ .clip = clip, .speed = opts.speed, .loop = opts.loop, }; const copy_len = @min(state_name.len, 32); @memcpy(state.name_buf[0..copy_len], state_name[0..copy_len]); state.name_len = copy_len; self.states[idx] = state; self.state_count += 1; return idx; } pub fn setInitialState(self: *ParameterMachine, state_idx: usize) !void { if (state_idx >= self.state_count) return error.InvalidState; self.resetRuntimeState(); const st = &self.states[state_idx]; const layer = self.mixer.addLayer(st.clip, .{ .speed = st.speed, .loop = st.loop, }) catch return error.MixerFull; self.current = state_idx; self.current_layer = layer; } pub fn addTransition(self: *ParameterMachine, tr: Transition) !void { if (self.transition_count >= self.transition_capacity) return error.TooManyTransitions; self.transitions[self.transition_count] = tr; self.transition_count += 1; } pub fn isTransitioning(self: *const ParameterMachine) bool { return self.target != null; } pub fn currentState(self: *const ParameterMachine) ?usize { return self.current; } pub fn fireTrigger(self: *ParameterMachine, trigger_name: []const u8) void { const cur = self.current orelse return; if (self.isTransitioning()) return; for (self.transitions[0..self.transition_count]) |*tr| { if (tr.from_state != cur) continue; const tr_trigger = tr.trigger() orelse continue; if (!std.mem.eql(u8, tr_trigger, trigger_name)) continue; if (tr.condition) |cond| { if (!cond()) continue; } self.beginTransition(tr); return; } } pub fn update(self: *ParameterMachine, dt: f32) void { if (self.current == null) return; self.mixer.advance(dt); if (self.isTransitioning()) { self.advanceBlend(dt); } else { self.checkAutoTransitions(); self.checkConditionTransitions(); } } fn beginTransition(self: *ParameterMachine, tr: *const Transition) void { const st = &self.states[tr.to_state]; const target_layer = self.mixer.addLayer(st.clip, .{ .weight = 0.0, .speed = st.speed, .loop = st.loop, }) catch return; self.target = tr.to_state; self.blend_duration = tr.blend_duration; self.blend_elapsed = 0; self.target_layer = target_layer; } fn advanceBlend(self: *ParameterMachine, dt: f32) void { self.blend_elapsed += dt; if (self.blend_duration <= 0 or self.blend_elapsed >= self.blend_duration) { if (self.current_layer) |cl| self.mixer.removeLayer(cl); if (self.target_layer) |tl| { self.mixer.layers[tl].weight = 1.0; } self.current = self.target; self.current_layer = self.target_layer; self.target = null; self.target_layer = null; self.blend_duration = 0; self.blend_elapsed = 0; } else { const t = self.blend_elapsed / self.blend_duration; if (self.current_layer) |cl| { self.mixer.layers[cl].weight = 1.0 - t; } if (self.target_layer) |tl| { self.mixer.layers[tl].weight = t; } } } fn resetRuntimeState(self: *ParameterMachine) void { if (self.current_layer) |layer| { self.mixer.removeLayer(layer); } if (self.target_layer) |layer| { if (self.current_layer) |current_layer| { if (current_layer != layer) { self.mixer.removeLayer(layer); } } else { self.mixer.removeLayer(layer); } } self.current = null; self.current_layer = null; self.target = null; self.target_layer = null; self.blend_duration = 0; self.blend_elapsed = 0; } fn checkAutoTransitions(self: *ParameterMachine) void { const cur = self.current orelse return; const cl = self.current_layer orelse return; const layer = &self.mixer.layers[cl]; if (layer.loop or layer.time < layer.clip.duration) return; for (self.transitions[0..self.transition_count]) |*tr| { if (tr.from_state != cur) continue; if (tr.has_trigger or tr.condition != null) continue; self.beginTransition(tr); return; } } fn checkConditionTransitions(self: *ParameterMachine) void { const cur = self.current orelse return; for (self.transitions[0..self.transition_count]) |*tr| { if (tr.from_state != cur) continue; if (tr.has_trigger) continue; const cond = tr.condition orelse continue; if (cond()) { self.beginTransition(tr); return; } } }};Source: fun/rig/src/curve/machine.zig:27
pub const ParameterState = struct { name_buf: [32]u8 = undefined, name_len: usize = 0, clip: *const ParameterClip, speed: f32 = 1.0, loop: bool = true, pub fn name(self: *const ParameterState) []const u8 { return self.name_buf[0..self.name_len]; }};Source: fun/rig/src/curve/machine.zig:12
pub const Transition = struct { from_state: usize, to_state: usize, trigger_buf: [32]u8 = undefined, trigger_len: usize = 0, has_trigger: bool = false, blend_duration: f32 = 0.2, condition: ?ConditionFn = null, pub fn trigger(self: *const Transition) ?[]const u8 { if (self.has_trigger) return self.trigger_buf[0..self.trigger_len]; return null; }};Source: fun/rig/src/curve/mixer.zig:19
pub const MixerLayer = struct { clip: *const ParameterClip, weight: f32 = 1.0, time: f32 = 0.0, speed: f32 = 1.0, loop: bool = false, active: bool = true,};Source: fun/rig/src/curve/mixer.zig:28
pub const ParameterMixer = struct { layers: []MixerLayer, layer_count: usize, capacity: usize, pub fn init(allocator: Allocator, max_layers: usize) !ParameterMixer { const layers = try allocator.alloc(MixerLayer, max_layers); return .{ .layers = layers, .layer_count = 0, .capacity = max_layers }; } pub fn deinit(self: *ParameterMixer, allocator: Allocator) void { allocator.free(self.layers); self.* = undefined; } pub fn addLayer(self: *ParameterMixer, clip: *const ParameterClip, opts: struct { weight: f32 = 1.0, speed: f32 = 1.0, loop: bool = false, }) !usize { for (0..self.layer_count) |i| { if (!self.layers[i].active) { self.layers[i] = .{ .clip = clip, .weight = opts.weight, .speed = opts.speed, .loop = opts.loop, }; return i; } } if (self.layer_count >= self.capacity) return error.TooManyLayers; const idx = self.layer_count; self.layers[idx] = .{ .clip = clip, .weight = opts.weight, .speed = opts.speed, .loop = opts.loop, }; self.layer_count += 1; return idx; } pub fn removeLayer(self: *ParameterMixer, index: usize) void { if (index < self.layer_count) { self.layers[index].active = false; } } pub fn advance(self: *ParameterMixer, dt: f32) void { for (self.layers[0..self.layer_count]) |*layer| { if (!layer.active) continue; layer.time += dt * layer.speed; if (layer.loop and layer.clip.duration > 0) { layer.time = @mod(layer.time, layer.clip.duration); } } } pub fn blendSlot( self: *const ParameterMixer, slot_idx: usize, blend_mode: SlotBlendMode, out: []f32, tmp: []f32, ) void { const dim = out.len; for (out) |*v| v.* = 0; var weight_sum: f32 = 0; var first = true; for (self.layers[0..self.layer_count]) |*layer| { if (!layer.active or layer.weight <= 0) continue; if (slot_idx >= layer.clip.curve_count) continue; layer.clip.evalSlot(slot_idx, layer.time, tmp[0..dim]); weight_sum += layer.weight; if (dim == 1 and blend_mode == .slerp) { if (first) { out[0] = tmp[0]; first = false; } else { const t_blend = layer.weight / weight_sum; out[0] = angleSlerp(out[0], tmp[0], t_blend); } } else { for (0..dim) |d| { out[d] += layer.weight * tmp[d]; } } } if (blend_mode != .slerp or dim != 1) { if (weight_sum > 0) { for (0..dim) |d| { out[d] /= weight_sum; } } } }};Source: fun/rig/src/curve/mixer.zig:9
pub const SlotBlendMode = enum { lerp, slerp,};Source: fun/rig/src/curve/parameter.zig:15
pub const ParameterClip = struct { name_buf: [64]u8 = undefined, name_len: usize = 0, duration: f32, curves: []SlotCurve, curve_count: usize, capacity: usize, pub fn init(allocator: Allocator, clip_name: []const u8, duration: f32, max_curves: usize) !ParameterClip { const curves = try allocator.alloc(SlotCurve, max_curves); var clip = ParameterClip{ .duration = duration, .curves = curves, .curve_count = 0, .capacity = max_curves, }; const copy_len = @min(clip_name.len, 64); @memcpy(clip.name_buf[0..copy_len], clip_name[0..copy_len]); clip.name_len = copy_len; return clip; } pub fn deinit(self: *ParameterClip, allocator: Allocator) void { for (self.curves[0..self.curve_count]) |*c| { var spline = c.spline; spline.deinit(allocator); } allocator.free(self.curves); self.* = undefined; } pub fn name(self: *const ParameterClip) []const u8 { return self.name_buf[0..self.name_len]; } pub fn addCurve( self: *ParameterClip, allocator: Allocator, times: []const f32, values: []const f32, dim: usize, ) !usize { if (self.curve_count >= self.capacity) return error.TooManyCurves; const n_kf = times.len; if (n_kf < 2) return error.TooFewKeyframes; const spline = try CatmullRomSpline.init(allocator, values, dim); const n_seg = n_kf - 1; const t_span = times[n_kf - 1] - times[0]; const time_scale: f32 = if (t_span > 0) @as(f32, @floatFromInt(n_seg)) / t_span else 0.0; const idx = self.curve_count; self.curves[idx] = .{ .spline = spline, .time_scale = time_scale, .dim = dim }; self.curve_count += 1; return idx; } pub fn evalSlot(self: *const ParameterClip, slot_idx: usize, t: f32, out: []f32) void { const curve = &self.curves[slot_idx]; const clamped = clamp(t, 0.0, self.duration); const spline_t = clamped * curve.time_scale; curve.spline.eval(spline_t, out); }};Source: fun/rig/src/curve/parameter.zig:9
pub const SlotCurve = struct { spline: CatmullRomSpline, time_scale: f32, dim: usize,};Source: fun/rig/src/curve/space.zig:11
pub const BlendSample = struct { clip: *const ParameterClip, parameter: f32, speed: f32 = 1.0,};Source: fun/rig/src/curve/space.zig:27
pub const BlendSpace1D = struct { samples: std.ArrayListUnmanaged(BlendSample) = .empty, capacity: usize, pub fn init(capacity: usize) BlendSpace1D { return .{ .capacity = capacity }; } pub fn deinit(self: *BlendSpace1D, allocator: Allocator) void { self.samples.deinit(allocator); self.* = .{ .capacity = 0, }; } pub fn sampleCount(self: *const BlendSpace1D) u32 { return @intCast(self.samples.items.len); } pub fn addSample( self: *BlendSpace1D, allocator: Allocator, clip: *const ParameterClip, parameter: f32, speed: f32, ) !void { if (self.samples.items.len >= self.capacity) return error.TooManySamples; try self.samples.append(allocator, .{ .clip = clip, .parameter = parameter, .speed = speed, }); std.mem.sort(BlendSample, self.samples.items, {}, blendSampleLessThan); } pub fn evaluateSlot( self: *const BlendSpace1D, parameter: f32, slot_idx: usize, time: f32, blend_mode: SlotBlendMode, out: []f32, tmp: []f32, ) !void { if (self.samples.items.len == 0) return error.EmptyBlendSpace; if (out.len == 0 or tmp.len < out.len) return error.BufferTooSmall; const sample_pair = self.findPair(parameter); const left = sample_pair.left; const right = sample_pair.right; if (slot_idx >= left.clip.curve_count) return error.InvalidSlot; left.clip.evalSlot(slot_idx, time * left.speed, out); if (left.clip == right.clip and sample_pair.alpha == 0.0) return; if (slot_idx >= right.clip.curve_count) return error.InvalidSlot; right.clip.evalSlot(slot_idx, time * right.speed, tmp[0..out.len]); if (out.len == 1 and blend_mode == .slerp) { out[0] = angleSlerp(out[0], tmp[0], sample_pair.alpha); return; } for (out, tmp[0..out.len]) |*dst, src| { dst.* = (1.0 - sample_pair.alpha) * dst.* + sample_pair.alpha * src; } } fn findPair(self: *const BlendSpace1D, parameter: f32) BlendPair { const items = self.samples.items; if (items.len == 1 or parameter <= items[0].parameter) { return .{ .left = items[0], .right = items[0], .alpha = 0.0 }; } if (parameter >= items[items.len - 1].parameter) { const tail = items[items.len - 1]; return .{ .left = tail, .right = tail, .alpha = 0.0 }; } for (items[0 .. items.len - 1], items[1..]) |left, right| { if (parameter < left.parameter or parameter > right.parameter) continue; const span = right.parameter - left.parameter; const alpha = if (@abs(span) <= 1e-6) 0.0 else clamp01((parameter - left.parameter) / span); return .{ .left = left, .right = right, .alpha = alpha, }; } const tail = items[items.len - 1]; return .{ .left = tail, .right = tail, .alpha = 0.0 }; }};Source: fun/rig/src/curve/space.zig:123
pub const NotifyEvent = struct { id: u32, time: f32,};Source: fun/rig/src/curve/space.zig:132
pub const NotifyTrack = struct { events: std.ArrayListUnmanaged(NotifyEvent) = .empty, capacity: usize, pub fn init(capacity: usize) NotifyTrack { return .{ .capacity = capacity }; } pub fn deinit(self: *NotifyTrack, allocator: Allocator) void { self.events.deinit(allocator); self.* = .{ .capacity = 0, }; } pub fn addNotify( self: *NotifyTrack, allocator: Allocator, event_id: u32, time: f32, ) !void { if (self.events.items.len >= self.capacity) return error.TooManyEvents; try self.events.append(allocator, .{ .id = event_id, .time = time, }); std.mem.sort(NotifyEvent, self.events.items, {}, notifyEventLessThan); } pub fn queryRange( self: *const NotifyTrack, start_time: f32, end_time: f32, duration: f32, loop: bool, out_ids: []u32, out_times: []f32, ) !u32 { if (out_ids.len != out_times.len) return error.BufferTooSmall; if (loop and duration <= 0.0) return error.InvalidDuration; var count: usize = 0; if (!loop or end_time >= start_time) { try collectRange(self.events.items, start_time, end_time, out_ids, out_times, &count); return @intCast(count); } try collectRange(self.events.items, start_time, duration, out_ids, out_times, &count); try collectRange(self.events.items, 0.0, end_time, out_ids, out_times, &count); return @intCast(count); }};Source: fun/rig/src/curve/spline.zig:91
pub const CatmullRomSpline = struct { data: []f32, dim: usize, n_points: usize, pub fn init(allocator: Allocator, points: []const f32, dim: usize) !CatmullRomSpline { const n = points.len / dim; if (n < 2) return error.TooFewPoints; const total = n * dim * 2; const data = try allocator.alloc(f32, total); @memcpy(data[0 .. n * dim], points); const tangent_base = n * dim; for (0..n) |i| { const dst = data[tangent_base + i * dim ..][0..dim]; if (i == 0) { const p0 = data[0..dim]; const p1 = data[dim .. 2 * dim]; for (0..dim) |d| dst[d] = p1[d] - p0[d]; } else if (i == n - 1) { const pm = data[(n - 2) * dim ..][0..dim]; const pl = data[(n - 1) * dim ..][0..dim]; for (0..dim) |d| dst[d] = pl[d] - pm[d]; } else { const pp = data[(i - 1) * dim ..][0..dim]; const pn = data[(i + 1) * dim ..][0..dim]; for (0..dim) |d| dst[d] = 0.5 * (pn[d] - pp[d]); } } return .{ .data = data, .dim = dim, .n_points = n }; } pub fn deinit(self: *CatmullRomSpline, allocator: Allocator) void { allocator.free(self.data); self.* = undefined; } fn pointSlice(self: CatmullRomSpline, i: usize) []const f32 { return self.data[i * self.dim ..][0..self.dim]; } fn tangentSlice(self: CatmullRomSpline, i: usize) []const f32 { const base = self.n_points * self.dim; return self.data[base + i * self.dim ..][0..self.dim]; } fn segment(self: CatmullRomSpline, i: usize) CubicHermiteSegment { return .{ .p0 = self.pointSlice(i), .m0 = self.tangentSlice(i), .p1 = self.pointSlice(i + 1), .m1 = self.tangentSlice(i + 1), .dim = self.dim, }; } pub fn eval(self: CatmullRomSpline, t: f32, out: []f32) void { const n_seg = self.n_points - 1; const n_seg_f: f32 = @floatFromInt(n_seg); if (t <= 0.0) { @memcpy(out[0..self.dim], self.pointSlice(0)); return; } if (t >= n_seg_f) { @memcpy(out[0..self.dim], self.pointSlice(self.n_points - 1)); return; } var seg_idx: usize = @intFromFloat(t); if (seg_idx >= n_seg) seg_idx = n_seg - 1; const local_t = t - @as(f32, @floatFromInt(seg_idx)); self.segment(seg_idx).eval(local_t, out); }};Source: fun/rig/src/curve/spline.zig:71
pub const CubicHermiteSegment = struct { p0: []const f32, m0: []const f32, p1: []const f32, m1: []const f32, dim: usize, pub fn eval(self: CubicHermiteSegment, t: f32, out: []f32) void { const t2 = t * t; const t3 = t2 * t; const h00 = 2.0 * t3 - 3.0 * t2 + 1.0; const h10 = t3 - 2.0 * t2 + t; const h01 = -2.0 * t3 + 3.0 * t2; const h11 = t3 - t2; for (0..self.dim) |i| { out[i] = h00 * self.p0[i] + h10 * self.m0[i] + h01 * self.p1[i] + h11 * self.m1[i]; } }};Source: fun/rig/src/curve/machine.zig:10
pub const ConditionFn = *const fn () bool;Source: fun/rig/src/curve/mixer.zig:14
pub fn inferBlendMode(param_name: []const u8) SlotBlendMode { if (std.mem.eql(u8, param_name, "angle")) return .slerp; return .lerp;}Source: fun/rig/src/curve/spline.zig:30
pub fn PeriodicSpline(comptime point_count: usize, comptime dimension: usize) type { if (point_count < 4) @compileError("periodic splines require at least four points"); if (dimension == 0) @compileError("periodic splines require at least one dimension"); return struct { points: [point_count][dimension]f32, pub fn sample(self: @This(), phase: f32) [dimension]f32 { std.debug.assert(std.math.isFinite(phase)); const wrapped = phase - @floor(phase); const scaled = wrapped * @as(f32, @floatFromInt(point_count)); const segment: usize = @intFromFloat(scaled); const local = scaled - @as(f32, @floatFromInt(segment)); const p0 = self.points[(segment + point_count - 1) % point_count]; const p1 = self.points[segment]; const p2 = self.points[(segment + 1) % point_count]; const p3 = self.points[(segment + 2) % point_count]; const local2 = local * local; const local3 = local2 * local; var result: [dimension]f32 = undefined; for (0..dimension) |axis| { result[axis] = 0.5 * (2.0 * p1[axis] + (-p0[axis] + p2[axis]) * local + (2.0 * p0[axis] - 5.0 * p1[axis] + 4.0 * p2[axis] - p3[axis]) * local2 + (-p0[axis] + 3.0 * p1[axis] - 3.0 * p2[axis] + p3[axis]) * local3); } return result; } };}Source: fun/rig/src/curve/spline.zig:13
pub fn angleSlerp(a: f32, b: f32, t: f32) f32 { const two_pi: f32 = 2.0 * math.pi; var diff = @mod(b - a, two_pi); if (diff > math.pi) { diff -= two_pi; } return a + diff * t;}Source: fun/rig/src/curve/spline.zig:9
pub fn scalarLerp(a: f32, b: f32, t: f32) f32 { return a + (b - a) * t;}Source: fun/rig/src/curve/spline.zig:22
pub fn vec3Lerp(a: [3]f32, b: [3]f32, t: f32) [3]f32 { return .{ a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t, };}Source: fun/rig/src/curve/root.zig
//! Parameter curves: clips of plain values that drive shape and material//! parameters, with a mixer, a state machine, a blend space and notify//! tracks over them. Joint poses are `rig.JointClip`'s; these clips carry//! no joints.const machine = @import("machine.zig");const mixer = @import("mixer.zig");const parameter = @import("parameter.zig");const space = @import("space.zig");const spline = @import("spline.zig");pub const scalarLerp = spline.scalarLerp;pub const angleSlerp = spline.angleSlerp;pub const vec3Lerp = spline.vec3Lerp;pub const PeriodicSpline = spline.PeriodicSpline;pub const CubicHermiteSegment = spline.CubicHermiteSegment;pub const CatmullRomSpline = spline.CatmullRomSpline;pub const SlotCurve = parameter.SlotCurve;pub const ParameterClip = parameter.ParameterClip;pub const SlotBlendMode = mixer.SlotBlendMode;pub const inferBlendMode = mixer.inferBlendMode;pub const MixerLayer = mixer.MixerLayer;pub const ParameterMixer = mixer.ParameterMixer;pub const ConditionFn = machine.ConditionFn;pub const Transition = machine.Transition;pub const ParameterState = machine.ParameterState;pub const ParameterMachine = machine.ParameterMachine;pub const BlendSample = space.BlendSample;pub const BlendSpace1D = space.BlendSpace1D;pub const NotifyEvent = space.NotifyEvent;pub const NotifyTrack = space.NotifyTrack;Source: fun/rig/src/root.zig:23
pub const curve = @import("curve/root.zig");Complete caller list for curve.ParameterMixer.init
7 direct callers.
fun.rig.src.curve.machine.test_FSM_condition-based_transition[function] — test; no exact target atfun/rig/src/curve/machine.zig:287in nearest public ownerfun.rig.src.curve.machinefun.rig.src.curve.machine.test_FSM_state_transition_on_trigger[function] — test; no exact target atfun/rig/src/curve/machine.zig:241in nearest public ownerfun.rig.src.curve.machinefun.rig.src.curve.machine.test_mixer_reuses_inactive_slots_across_repeated_transitions[function] — test; no exact target atfun/rig/src/curve/machine.zig:330in nearest public ownerfun.rig.src.curve.machinefun.rig.src.curve.mixer.test_mixer_blending_two_clips_50/50[function] — test; no exact target atfun/rig/src/curve/mixer.zig:131in nearest public ownerfun.rig.src.curve.mixerfun.sdfii.src.animation.abi.sdfii_anim_mixer_create[function] — private; no exact target atfun/sdfii/src/animation/abi.zig:80in nearest public ownerfun.sdfii.src.animation.abifun.sdfii.src.animation.emission.test_FSM_slot_appends_proposal_through_mixer[function] — test; no exact target atfun/sdfii/src/animation/emission.zig:221in nearest public ownerfun.sdfii.src.animation.emissionfun.sdfii.src.animation.emission.test_mixer_slot_proposal_matches_direct_blend[function] — test; no exact target atfun/sdfii/src/animation/emission.zig:180in nearest public ownerfun.sdfii.src.animation.emission
Complete caller list for curve.ParameterClip.addCurve
10 direct callers.
fun.rig.src.curve.machine.test_FSM_condition-based_transition[function] — test; no exact target atfun/rig/src/curve/machine.zig:287in nearest public ownerfun.rig.src.curve.machinefun.rig.src.curve.machine.test_FSM_state_transition_on_trigger[function] — test; no exact target atfun/rig/src/curve/machine.zig:241in nearest public ownerfun.rig.src.curve.machinefun.rig.src.curve.machine.test_mixer_reuses_inactive_slots_across_repeated_transitions[function] — test; no exact target atfun/rig/src/curve/machine.zig:330in nearest public ownerfun.rig.src.curve.machinefun.rig.src.curve.mixer.test_mixer_blending_two_clips_50/50[function] — test; no exact target atfun/rig/src/curve/mixer.zig:131in nearest public ownerfun.rig.src.curve.mixerfun.rig.src.curve.parameter.test_cubic_curve_evaluation_at_midpoint[function] — test; no exact target atfun/rig/src/curve/parameter.zig:104in nearest public ownerfun.rig.src.curve.parameterfun.rig.src.curve.parameter.test_linear_interpolation_between_two_keyframes[function] — test; no exact target atfun/rig/src/curve/parameter.zig:82in nearest public ownerfun.rig.src.curve.parameterfun.rig.src.curve.space.test_blend_space_1d_interpolates_neighboring_clips[function] — test; no exact target atfun/rig/src/curve/space.zig:207in nearest public ownerfun.rig.src.curve.spacefun.sdfii.src.animation.emission.test_FSM_slot_appends_proposal_through_mixer[function] — test; no exact target atfun/sdfii/src/animation/emission.zig:221in nearest public ownerfun.sdfii.src.animation.emissionfun.sdfii.src.animation.emission.test_clip_slot_appends_vector_proposal[function] — test; no exact target atfun/sdfii/src/animation/emission.zig:151in nearest public ownerfun.sdfii.src.animation.emissionfun.sdfii.src.animation.emission.test_mixer_slot_proposal_matches_direct_blend[function] — test; no exact target atfun/sdfii/src/animation/emission.zig:180in nearest public ownerfun.sdfii.src.animation.emission
Complete caller list for curve.ParameterClip.deinit
10 direct callers.
fun.rig.src.curve.machine.test_FSM_condition-based_transition[function] — test; no exact target atfun/rig/src/curve/machine.zig:287in nearest public ownerfun.rig.src.curve.machinefun.rig.src.curve.machine.test_FSM_state_transition_on_trigger[function] — test; no exact target atfun/rig/src/curve/machine.zig:241in nearest public ownerfun.rig.src.curve.machinefun.rig.src.curve.machine.test_mixer_reuses_inactive_slots_across_repeated_transitions[function] — test; no exact target atfun/rig/src/curve/machine.zig:330in nearest public ownerfun.rig.src.curve.machinefun.rig.src.curve.mixer.test_mixer_blending_two_clips_50/50[function] — test; no exact target atfun/rig/src/curve/mixer.zig:131in nearest public ownerfun.rig.src.curve.mixerfun.rig.src.curve.parameter.test_cubic_curve_evaluation_at_midpoint[function] — test; no exact target atfun/rig/src/curve/parameter.zig:104in nearest public ownerfun.rig.src.curve.parameterfun.rig.src.curve.parameter.test_linear_interpolation_between_two_keyframes[function] — test; no exact target atfun/rig/src/curve/parameter.zig:82in nearest public ownerfun.rig.src.curve.parameterfun.rig.src.curve.space.test_blend_space_1d_interpolates_neighboring_clips[function] — test; no exact target atfun/rig/src/curve/space.zig:207in nearest public ownerfun.rig.src.curve.spacefun.sdfii.src.animation.emission.test_FSM_slot_appends_proposal_through_mixer[function] — test; no exact target atfun/sdfii/src/animation/emission.zig:221in nearest public ownerfun.sdfii.src.animation.emissionfun.sdfii.src.animation.emission.test_clip_slot_appends_vector_proposal[function] — test; no exact target atfun/sdfii/src/animation/emission.zig:151in nearest public ownerfun.sdfii.src.animation.emissionfun.sdfii.src.animation.emission.test_mixer_slot_proposal_matches_direct_blend[function] — test; no exact target atfun/sdfii/src/animation/emission.zig:180in nearest public ownerfun.sdfii.src.animation.emission
Complete caller list for curve.ParameterClip.init
11 direct callers.
fun.rig.src.curve.machine.test_FSM_condition-based_transition[function] — test; no exact target atfun/rig/src/curve/machine.zig:287in nearest public ownerfun.rig.src.curve.machinefun.rig.src.curve.machine.test_FSM_state_transition_on_trigger[function] — test; no exact target atfun/rig/src/curve/machine.zig:241in nearest public ownerfun.rig.src.curve.machinefun.rig.src.curve.machine.test_mixer_reuses_inactive_slots_across_repeated_transitions[function] — test; no exact target atfun/rig/src/curve/machine.zig:330in nearest public ownerfun.rig.src.curve.machinefun.rig.src.curve.mixer.test_mixer_blending_two_clips_50/50[function] — test; no exact target atfun/rig/src/curve/mixer.zig:131in nearest public ownerfun.rig.src.curve.mixerfun.rig.src.curve.parameter.test_cubic_curve_evaluation_at_midpoint[function] — test; no exact target atfun/rig/src/curve/parameter.zig:104in nearest public ownerfun.rig.src.curve.parameterfun.rig.src.curve.parameter.test_linear_interpolation_between_two_keyframes[function] — test; no exact target atfun/rig/src/curve/parameter.zig:82in nearest public ownerfun.rig.src.curve.parameterfun.rig.src.curve.space.test_blend_space_1d_interpolates_neighboring_clips[function] — test; no exact target atfun/rig/src/curve/space.zig:207in nearest public ownerfun.rig.src.curve.spacefun.sdfii.src.animation.abi.sdfii_anim_clip_create[function] — private; no exact target atfun/sdfii/src/animation/abi.zig:23in nearest public ownerfun.sdfii.src.animation.abifun.sdfii.src.animation.emission.test_FSM_slot_appends_proposal_through_mixer[function] — test; no exact target atfun/sdfii/src/animation/emission.zig:221in nearest public ownerfun.sdfii.src.animation.emissionfun.sdfii.src.animation.emission.test_clip_slot_appends_vector_proposal[function] — test; no exact target atfun/sdfii/src/animation/emission.zig:151in nearest public ownerfun.sdfii.src.animation.emissionfun.sdfii.src.animation.emission.test_mixer_slot_proposal_matches_direct_blend[function] — test; no exact target atfun/sdfii/src/animation/emission.zig:180in nearest public ownerfun.sdfii.src.animation.emission
Audit
| Definitions | 56 |
|---|---|
| Public names | 56 |
| Members | 62 |
| Version | 26.7.0 |
| Revision | daab053ee433 |