aboutsummaryrefslogtreecommitdiffstats
path: root/build/4coder_byp/custom/4coder_delta_rule.cpp
blob: ff598ca07dbf409ae22dda8c06f3570b414c7d24 (plain) (blame)
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*
4coder_delta_rule.cpp - Built in delta rules and delta rule helpers.
*/

// TOP

function u64
delta_ctx_size(u64 base_size){
  return(base_size + sizeof(Delta_Context_Header));
}

function Delta_Context_Header*
delta_ctx_get_header(String_Const_u8 delta_ctx){
  return((Delta_Context_Header*)delta_ctx.str);
}

function void*
delta_ctx_get_user_data(String_Const_u8 delta_ctx){
  Delta_Context_Header *ctx = (Delta_Context_Header*)delta_ctx.str;
  return(ctx + 1);
}

function Buffer_Point_Delta_Result
delta_apply(Application_Links *app, View_ID view,
            Delta_Rule_Function *func, String_Const_u8 delta_ctx,
            f32 dt, Buffer_Point position, Buffer_Point target){
  Buffer_Point_Delta_Result result = {};
  Vec2_f32 pending = view_point_difference(app, view, target, position);
  if (!near_zero(pending, 0.5f)){
    Delta_Context_Header *ctx = delta_ctx_get_header(delta_ctx);
    b32 is_new_target = false;
    if (!block_match_struct(&ctx->point, &target)){
      block_copy_struct(&ctx->point, &target);
      is_new_target = true;
    }
    void *rule_data = delta_ctx_get_user_data(delta_ctx);
    Vec2_f32 partial = func(pending, is_new_target, dt, rule_data);

    // NOTE(allen): clamp partial into the box from the origin
    // to the pending delta.
    Range_f32 x = If32(pending.x, 0.f);
    Range_f32 y = If32(pending.y, 0.f);
    partial.x = clamp_range(x, partial.x);
    partial.y = clamp_range(y, partial.y);

    result.point = view_move_buffer_point(app, view, position, partial);
    result.still_animating = true;
  }
  else{
    result.point = target;
  }
  return(result);
}

function Buffer_Point_Delta_Result
delta_apply(Application_Links *app, View_ID view,
            Delta_Rule_Function *func, String_Const_u8 delta_ctx,
            f32 dt, Buffer_Scroll scroll){
  return(delta_apply(app, view, func, delta_ctx,
                     dt, scroll.position, scroll.target));
}

function Buffer_Point_Delta_Result
delta_apply(Application_Links *app, View_ID view,
            f32 dt, Buffer_Point position, Buffer_Point target){
  View_Context ctx = view_current_context(app, view);
  String_Const_u8 delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule);
  return(delta_apply(app, view, ctx.delta_rule, delta_ctx,
                     dt, position, target));
}

function Buffer_Point_Delta_Result
delta_apply(Application_Links *app, View_ID view,
            f32 dt, Buffer_Scroll scroll){
  View_Context ctx = view_current_context(app, view);
  String_Const_u8 delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule);
  return(delta_apply(app, view, ctx.delta_rule, delta_ctx,
                     dt, scroll.position, scroll.target));
}

function Vec2_f32_Delta_Result
delta_apply(Application_Links *app, View_ID view,
            Delta_Rule_Function *func, String_Const_u8 delta_ctx,
            f32 dt, Vec2_f32 position, Vec2_f32 target){
  Vec2_f32_Delta_Result result = {};
  Vec2_f32 pending = target - position;
  if (!near_zero(pending, 0.5f)){
    Delta_Context_Header *ctx = delta_ctx_get_header(delta_ctx);
    b32 is_new_target = false;
    if (!near_zero(ctx->p - target, 0.1f)){
      block_copy_struct(&ctx->p, &target);
      is_new_target = true;
    }
    void *rule_data = delta_ctx_get_user_data(delta_ctx);
    Vec2_f32 partial = func(pending, is_new_target, dt, rule_data);

    // NOTE(allen): clamp partial into the box from the origin
    // to the pending delta.
    Range_f32 x = If32(pending.x, 0.f);
    Range_f32 y = If32(pending.y, 0.f);
    partial.x = clamp_range(x, partial.x);
    partial.y = clamp_range(y, partial.y);

    result.p = position + partial;
    result.still_animating = true;
  }
  else{
    result.p = target;
  }
  return(result);
}

function Vec2_f32_Delta_Result
delta_apply(Application_Links *app, View_ID view,
            Delta_Rule_Function *func, String_Const_u8 delta_ctx,
            f32 dt, Basic_Scroll scroll){
  return(delta_apply(app, view, func, delta_ctx,
                     dt, scroll.position, scroll.target));
}

function Vec2_f32_Delta_Result
delta_apply(Application_Links *app, View_ID view,
            f32 dt, Vec2_f32 position, Vec2_f32 target){
  View_Context ctx = view_current_context(app, view);
  String_Const_u8 delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule);
  return(delta_apply(app, view, ctx.delta_rule, delta_ctx,
                     dt, position, target));
}

function Vec2_f32_Delta_Result
delta_apply(Application_Links *app, View_ID view,
            f32 dt, Basic_Scroll scroll){
  View_Context ctx = view_current_context(app, view);
  String_Const_u8 delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule);
  return(delta_apply(app, view, ctx.delta_rule, delta_ctx,
                     dt, scroll.position, scroll.target));
}

////////////////////////////////

internal Smooth_Step
smooth_camera_step(f32 target, f32 v, f32 S, f32 T){
  Smooth_Step step = {};
  step.v = v;
  if (step.p != target){
    if (step.p > target - .1f && step.p < target + .1f){
      step.p = target;
      step.v = 1.f;
    }
    else{
      f32 L = step.p + T*(target - step.p);
      i32 sign = (target > step.p) - (target < step.p);
      f32 V = step.p + sign*step.v;
      if (sign > 0){
        step.p = (L<V)?(L):(V);
      }
      else{
        step.p = (L>V)?(L):(V);
      }
      if (step.p == V){
        step.v *= S;
      }
    }
  }
  return(step);
}
DELTA_RULE_SIG(original_delta){
  Vec2_f32 *velocity = (Vec2_f32*)data;
  if (velocity->x == 0.f){
    velocity->x = 1.f;
    velocity->y = 1.f;
  }
  Smooth_Step step_x = smooth_camera_step(pending.x, velocity->x, 80.f, 1.f/2.f);
  Smooth_Step step_y = smooth_camera_step(pending.y, velocity->y, 80.f, 1.f/2.f);
  *velocity = V2f32(step_x.v, step_y.v);
  return(V2f32(step_x.p, step_y.p));
}
global_const u64 original_delta_memory_size = sizeof(Vec2_f32);

DELTA_RULE_SIG(snap_delta){
  return(pending);
}
global_const u64 snap_delta_memory_size = 0;

function f32
cubic_reinterpolate(f32 t){
  f32 t2 = t*t;
  f32 t3 = t2*t;
  return(3*t2 - 2*t3);
}
DELTA_RULE_SIG(fixed_time_cubic_delta){
  local_const f32 duration_in_seconds = (1.f/8.f);
  local_const f32 dt_multiplier = 1.f/duration_in_seconds;
  f32 step = dt*dt_multiplier;
  f32 *t = (f32*)data;
  *t = clamp(0.f, *t, 1.f);
  f32 prev_t = *t;
  if (is_new_target){
    prev_t = 0.f;
    *t = step;
  }
  else{
    *t += step;
  }
  *t = clamp(0.f, *t, 1.f);
  Vec2_f32 result = pending;
  if (*t < 1.f){
    f32 prev_x = cubic_reinterpolate(prev_t);
    f32 x = cubic_reinterpolate(*t);
    f32 portion = ((x - prev_x)/(1.f - prev_x));
    result *= portion;
  }
  return(result);
}
global_const u64 fixed_time_cubic_delta_memory_size = sizeof(f32);

// BOTTOM