@@ -5098,129 +5098,65 @@ int Game_Interpreter::ManiacBitmask(int value, int mask) const {
5098
5098
5099
5099
return value;
5100
5100
}
5101
- std::vector<double > parseBezier (const std::string& bezierParams) {
5102
- std::vector<double > params;
5103
- std::string temp;
5104
- size_t startPos = bezierParams.find (" (" ) + 1 ;
5105
- size_t endPos = bezierParams.find (" )" );
5106
- std::string valuesString = bezierParams.substr (startPos, endPos - startPos);
5107
5101
5108
- size_t commaPos = valuesString.find (" ," );
5109
- while (commaPos != std::string::npos) {
5110
- temp = valuesString.substr (0 , commaPos);
5111
- params.push_back (std::stod (temp));
5112
- valuesString = valuesString.substr (commaPos + 1 );
5113
- commaPos = valuesString.find (" ," );
5114
- }
5115
- // Push the last value into the vector
5116
- params.push_back (std::stod (valuesString));
5117
-
5118
- return params;
5119
- }
5120
-
5121
- // FIXME: cubicBezier is completely Broken
5122
- // references to how it should work:
5102
+ // references for cubic bezier:
5123
5103
// https://matthewlein.com/tools/ceaser
5124
5104
// https://cubic-bezier.com/
5105
+ double cubicBezier (float t, const double & p0,const double & p1, const double & p2, const double & p3) {
5125
5106
5126
- double cubicBezier (double t, double p0, double p1, double p2, double p3) {
5127
- double u = 1 - t;
5128
- double tt = t * t;
5129
- double uu = u * u;
5130
- double uuu = uu * u;
5131
- double ttt = tt * t;
5107
+ float u = 1 - t;
5108
+ float tt = t * t;
5109
+ float uu = u * u;
5110
+ float uuu = uu * u;
5111
+ float ttt = tt * t;
5132
5112
5133
- double p = uuu * p0; // (1-t)^3
5134
- double q = 3 * uu * t * p1; // 3t(1-t)^2
5135
- double r = 3 * u * tt * p2; // 3(1-t)t^2
5136
- double s = ttt * p3; // t^3
5113
+ // Point2d p = {0,0};
5114
+ // p.x = uuu * 0 + 3 * uu * t * p0 + 3 * u * tt * p2 + ttt * 1;
5115
+ return uuu * 0 + 3 * uu * t * p1 + 3 * u * tt * p3 + ttt * 1 ;
5137
5116
5138
- return p + q + r + s ;
5117
+ // return p.y ;
5139
5118
}
5140
5119
5141
- double getEasedT (const std::string& easingType, double t, double b, double c, double d) {
5142
- if (easingType == " linear" ) {
5143
- return c * t / d + b;
5144
- }
5145
- else if (easingType == " quadIn" ) {
5146
- t /= d;
5147
- return c * t * t + b;
5148
- }
5149
- else if (easingType == " quadOut" ) {
5150
- t /= d;
5151
- return -c * t * (t - 2 ) + b;
5152
- }
5153
- else if (easingType == " quadInOut" ) {
5154
- t /= d / 2 ;
5155
- if (t < 1 ) {
5156
- return c / 2 * t * t + b;
5157
- }
5158
- else {
5159
- t -= 1 ;
5160
- return -c / 2 * (t * (t - 2 ) - 1 ) + b;
5161
- }
5162
- }
5163
- else if (easingType == " cubicIn" ) {
5164
- t /= d;
5165
- return c * t * t * t + b;
5166
- }
5167
- else if (easingType == " cubicOut" ) {
5168
- t = (t / d) - 1 ;
5169
- return c * (t * t * t + 1 ) + b;
5170
- }
5171
- else if (easingType == " cubicInOut" ) {
5172
- t /= d / 2 ;
5173
- if (t < 1 ) {
5174
- return c / 2 * t * t * t + b;
5175
- }
5176
- else {
5177
- t -= 2 ;
5178
- return c / 2 * (t * t * t + 2 ) + b;
5179
- }
5180
- }
5181
- else if (easingType == " sinIn" ) {
5182
- return -c * cos (t / d * (M_PI / 2 )) + c + b;
5183
- }
5184
- else if (easingType == " sinOut" ) {
5185
- return c * sin (t / d * (M_PI / 2 )) + b;
5186
- }
5187
- else if (easingType == " sinInOut" ) {
5188
- return -c / 2 * (cos (M_PI * t / d) - 1 ) + b;
5189
- }
5190
- else if (easingType == " expoIn" ) {
5191
- return c * pow (2 , 10 * (t / d - 1 )) + b;
5192
- }
5193
- else if (easingType == " expoOut" ) {
5194
- return c * (-pow (2 , -10 * t / d) + 1 ) + b;
5195
- }
5196
- else if (easingType == " expoInOut" ) {
5197
- t /= d / 2 ;
5198
- if (t < 1 ) {
5199
- return c / 2 * pow (2 , 10 * (t - 1 )) + b;
5200
- }
5201
- else {
5202
- t -= 1 ;
5203
- return c / 2 * (-pow (2 , -10 * t) + 2 ) + b;
5204
- }
5205
- }
5206
- else if (easingType == " circIn" ) {
5207
- t /= d;
5208
- return -c * (sqrt (1 - t * t) - 1 ) + b;
5209
- }
5210
- else if (easingType == " circOut" ) {
5211
- t = (t / d) - 1 ;
5212
- return c * sqrt (1 - t * t) + b;
5213
- }
5214
- else if (easingType == " circInOut" ) {
5215
- t /= d / 2 ;
5216
- if (t < 1 ) {
5217
- return -c / 2 * (sqrt (1 - t * t) - 1 ) + b;
5218
- }
5219
- else {
5220
- t -= 2 ;
5221
- return c / 2 * (sqrt (1 - t * t) + 1 ) + b;
5222
- }
5223
- }
5120
+ double getEasedTime (const std::string& easingType, double t, double b, double c, double d) {
5121
+ if (easingType == " linear" ) return cubicBezier (t, 0.250 , 0.250 , 0.750 , 0.750 );
5122
+
5123
+ else if (easingType == " ease" ) return cubicBezier (t, 0.250 , 0.100 , 0.250 , 1.000 );
5124
+ else if (easingType == " easeIn" ) return cubicBezier (t, 0.420 , 0.000 , 1.000 , 1.000 );
5125
+ else if (easingType == " easeOut" ) return cubicBezier (t, 0.000 , 0.000 , 0.580 , 1.000 );
5126
+ else if (easingType == " easeInOut" ) return cubicBezier (t, 0.420 , 0.000 , 0.580 , 1.000 );
5127
+
5128
+ else if (easingType == " quadIn" ) return cubicBezier (t, 0.550 , 0.085 , 0.680 , 0.530 );
5129
+ else if (easingType == " quadOut" ) return cubicBezier (t, 0.250 , 0.460 , 0.450 , 0.940 );
5130
+ else if (easingType == " quadInOut" ) return cubicBezier (t, 0.455 , 0.030 , 0.515 , 0.955 );
5131
+
5132
+ else if (easingType == " cubicIn" ) return cubicBezier (t, 0.550 , 0.055 , 0.675 , 0.190 );
5133
+ else if (easingType == " cubicOut" ) return cubicBezier (t, 0.215 , 0.610 , 0.355 , 1.000 );
5134
+ else if (easingType == " cubicInOut" ) return cubicBezier (t, 0.645 , 0.045 , 0.355 , 1.000 );
5135
+
5136
+ else if (easingType == " quartIn" ) return cubicBezier (t, 0.895 , 0.030 , 0.685 , 0.220 );
5137
+ else if (easingType == " quartOut" ) return cubicBezier (t, 0.165 , 0.840 , 0.440 , 1.000 );
5138
+ else if (easingType == " quartInOut" ) return cubicBezier (t, 0.770 , 0.000 , 0.175 , 1.000 );
5139
+
5140
+ else if (easingType == " quintIn" ) return cubicBezier (t, 0.755 , 0.050 , 0.855 , 0.060 );
5141
+ else if (easingType == " quintOut" ) return cubicBezier (t, 0.230 , 1.000 , 0.320 , 1.000 );
5142
+ else if (easingType == " quintInOut" ) return cubicBezier (t, 0.860 , 0.000 , 0.070 , 1.000 );
5143
+
5144
+ else if (easingType == " sineIn" ) return cubicBezier (t, 0.470 , 0.000 , 0.745 , 0.715 );
5145
+ else if (easingType == " sineOut" ) return cubicBezier (t, 0.390 , 0.575 , 0.565 , 1.000 );
5146
+ else if (easingType == " sineInOut" ) return cubicBezier (t, 0.445 , 0.050 , 0.550 , 0.950 );
5147
+
5148
+ else if (easingType == " ExpoIn" ) return cubicBezier (t, 0.950 , 0.050 , 0.795 , 0.035 );
5149
+ else if (easingType == " expoOut" ) return cubicBezier (t, 0.190 , 1.000 , 0.220 , 1.000 );
5150
+ else if (easingType == " expoInOut" ) return cubicBezier (t, 1.000 , 0.000 , 0.000 , 1.000 );
5151
+
5152
+ else if (easingType == " circIn" ) return cubicBezier (t, 0.600 , 0.040 , 0.980 , 0.335 );
5153
+ else if (easingType == " circOut" ) return cubicBezier (t, 0.075 , 0.820 , 0.165 , 1.000 );
5154
+ else if (easingType == " circInOut" ) return cubicBezier (t, 0.785 , 0.135 , 0.150 , 0.860 );
5155
+
5156
+ else if (easingType == " backIn" ) return cubicBezier (t, 0.600 , -0.280 , 0.735 , 0.045 );
5157
+ else if (easingType == " backOut" ) return cubicBezier (t, 0.175 , 0.885 , 0.320 , 1.275 );
5158
+ else if (easingType == " backInOut" ) return cubicBezier (t, 0.680 , -0.550 , 0.265 , 1.550 );
5159
+
5224
5160
else if (easingType == " elasticIn" ) {
5225
5161
if (t == 0 ) {
5226
5162
return b;
@@ -5270,8 +5206,9 @@ double getEasedT(const std::string& easingType, double t, double b, double c, do
5270
5206
double postFix = a * pow (2 , -10 * (t -= 1 )); // this is a fix, again, with post-increment operators
5271
5207
return postFix * sin ((t * d - s) * (2 * M_PI) / p) * 0.5 + c + b;
5272
5208
}
5209
+
5273
5210
else if (easingType == " bounceIn" ) {
5274
- return c - getEasedT (" bounceOut" , d - t, 0 , c, d) + b;
5211
+ return c - getEasedTime (" bounceOut" , d - t, 0 , c, d) + b;
5275
5212
}
5276
5213
else if (easingType == " bounceOut" ) {
5277
5214
if ((t /= d) < (1 / 2.75 )) {
@@ -5292,65 +5229,30 @@ double getEasedT(const std::string& easingType, double t, double b, double c, do
5292
5229
}
5293
5230
else if (easingType == " bounceInOut" ) {
5294
5231
if (t < d / 2 ) {
5295
- return getEasedT (" bounceIn" , t * 2 , 0 , c, d) * 0.5 + b;
5232
+ return getEasedTime (" bounceIn" , t * 2 , 0 , c, d) * 0.5 + b;
5296
5233
}
5297
5234
else {
5298
- return getEasedT (" bounceOut" , t * 2 - d, 0 , c, d) * 0.5 + c * 0.5 + b;
5299
- }
5300
- }
5301
- if (easingType.substr (0 , 6 ) == " bezier" ) {
5302
- std::vector < double > bezierParams = parseBezier (easingType.substr (7 ));
5303
- if (bezierParams.size () == 4 ) {
5304
- return cubicBezier (t / d, bezierParams[0 ], bezierParams[1 ], bezierParams[2 ], bezierParams[3 ]);
5235
+ return getEasedTime (" bounceOut" , t * 2 - d, 0 , c, d) * 0.5 + c * 0.5 + b;
5305
5236
}
5306
5237
}
5307
5238
5308
- return c * t / d + b; // Default to linear easing if the easing type is not recognized
5309
- }
5310
-
5311
- std::vector<double > interpolate (double start, double end, double duration, const std::string& easingTypeAtStart, const std::string& easingTypeAtEnd) {
5312
- std::vector<double > interpolatedValues;
5313
- interpolatedValues.push_back (start);
5239
+ if (easingType.substr (0 , 6 ) == " bezier" ) {
5240
+ std::vector<double > bezierParams;
5314
5241
5315
- // Calculate the number of steps based on the duration
5316
- int numSteps = static_cast < int >(duration); // Convert duration to an integer
5317
- double stepSize = 1.0 / numSteps ;
5242
+ size_t startPos = easingType. find ( " ( " ) + 1 ;
5243
+ size_t endPos = easingType. find ( " ) " );
5244
+ std::string valuesString = easingType. substr (startPos, endPos - startPos) ;
5318
5245
5319
- // Calculate the halfway point
5320
- double halfway = start + (end - start) * 0.5 ;
5246
+ std::istringstream iss (valuesString);
5247
+ double value ;
5321
5248
5322
- if (easingTypeAtEnd == " null" ) {
5323
- // Use easingTypeAtStart for the entire animation
5324
- for (int step = 1 ; step <= numSteps; ++step) {
5325
- double t = step * stepSize;
5326
- double easedT = getEasedT (easingTypeAtStart, t, 0 , 1 , 1 ); // Call getEasedT with appropriate parameters
5327
- double interpolatedValue = start + easedT * (end - start);
5328
- interpolatedValues.push_back (interpolatedValue);
5329
- }
5330
- }
5331
- else {
5332
- // Generate the first half of the interpolation
5333
- for (int step = 1 ; step <= numSteps / 2 ; ++step) {
5334
- double t = step * stepSize;
5335
- double normalizedT = t / 0.5 ; // Normalize the time for the first half
5336
- double easedT = getEasedT (easingTypeAtStart, normalizedT, 0 , 1 , 1 ); // Call getEasedT with appropriate parameters
5337
- double interpolatedValue = start + easedT * (halfway - start);
5338
- interpolatedValues.push_back (interpolatedValue);
5339
- }
5249
+ while (iss >> value) bezierParams.push_back (value), iss.ignore ();
5340
5250
5341
- // Generate the second half of the interpolation
5342
- for (int step = numSteps / 2 + 1 ; step <= numSteps; ++step) {
5343
- double t = step * stepSize;
5344
- double normalizedT = (t - 0.5 ) / 0.5 ; // Normalize the time for the second half
5345
- double easedT = getEasedT (easingTypeAtEnd, normalizedT, 0 , 1 , 1 ); // Call getEasedT with appropriate parameters
5346
- double interpolatedValue = halfway + easedT * (end - halfway);
5347
- interpolatedValues.push_back (interpolatedValue);
5348
- }
5251
+ if (bezierParams.size () == 4 )
5252
+ return cubicBezier (t, bezierParams[0 ], bezierParams[1 ], bezierParams[2 ], bezierParams[3 ]);
5349
5253
}
5350
5254
5351
- interpolatedValues.push_back (end);
5352
-
5353
- return interpolatedValues;
5255
+ return c * t / d + b; // Default to linear easing if the easing type is not recognized
5354
5256
}
5355
5257
5356
5258
bool Game_Interpreter::CommandEasyRpgAnimateVariable (lcf::rpg::EventCommand const & com) {
@@ -5361,42 +5263,67 @@ bool Game_Interpreter::CommandEasyRpgAnimateVariable(lcf::rpg::EventCommand cons
5361
5263
int32_t end = ValueOrVariable (com.parameters [4 ], com.parameters [5 ]);
5362
5264
int32_t duration = ValueOrVariable (com.parameters [6 ], com.parameters [7 ]);
5363
5265
5266
+ // Extract easing information
5267
+ std::string easingTypeAtStart = ToString (com.string );
5268
+ std::string easingTypeAtEnd = " null" ;
5269
+
5270
+ std::size_t pos = easingTypeAtStart.find (' /' );
5271
+
5272
+ if (pos != std::string::npos) {
5273
+ easingTypeAtEnd = easingTypeAtStart.substr (pos + 1 );
5274
+ easingTypeAtStart = easingTypeAtStart.substr (0 , pos);
5275
+ }
5276
+
5364
5277
// Prepare animation-related commands
5365
5278
lcf::rpg::EventCommand waitCom;
5366
5279
waitCom.code = int (Cmd::Wait);
5367
5280
5368
5281
lcf::rpg::EventCommand animatedCom;
5369
5282
animatedCom.code = int (Cmd::ControlVars);
5370
5283
std::vector<int32_t > animatedVarParams = { 0 , static_cast <int32_t >(target), 0 , 0 , 0 , static_cast <int32_t >(end) };
5371
- animatedCom.parameters = lcf::DBArray<int32_t >(animatedVarParams.begin (), animatedVarParams.end ());
5372
5284
5373
5285
std::vector<lcf::rpg::EventCommand> cmdList;
5374
5286
5375
- // Extract easing information
5376
- std::string easeStart = ToString (com.string );
5377
- std::string easeEnd = " null" ;
5287
+ int numSteps = static_cast <int >(duration);
5288
+ double stepSize = 1.0 / numSteps;
5378
5289
5379
- std::size_t pos = easeStart.find (' /' );
5290
+ for (int step = 1 ; step <= numSteps; ++step) {
5291
+ double normalizedTime;
5292
+ double currentTime = step * stepSize;
5293
+ double halfway;
5380
5294
5381
- if (pos != std::string::npos) {
5382
- easeEnd = easeStart.substr (pos + 1 );
5383
- easeStart = easeStart.substr (0 , pos);
5384
- }
5295
+ std::string easingType;
5296
+
5297
+ if (easingTypeAtEnd == " null" ) { // use a single interpolation.
5298
+ normalizedTime = currentTime;
5299
+ easingType = easingTypeAtStart;
5300
+ halfway = (step <= numSteps / 2 ) ? end : start;
5301
+ }
5302
+ else {
5303
+ if (step <= numSteps / 2 ) { // use 2 interpolations: start and end.
5304
+ normalizedTime = currentTime / 0.5 ;
5305
+ easingType = easingTypeAtStart;
5306
+ }
5307
+ else {
5308
+ normalizedTime = (currentTime - 0.5 ) / 0.5 ;
5309
+ easingType = easingTypeAtEnd;
5310
+ }
5311
+ halfway = start + 0.5 * (end - start);
5312
+ }
5313
+
5314
+ double easedTime = getEasedTime (easingType, normalizedTime, 0 , 1 , 1 );
5385
5315
5386
- // Insert animation commands
5387
- std::vector<double > interpolatedValues = interpolate (start, end, duration, easeStart, easeEnd);
5316
+ double startValue = (step <= numSteps / 2 ) ? start : halfway;
5317
+ double endValue = (step <= numSteps / 2 ) ? halfway : end;
5318
+ double interpolatedValue = startValue + easedTime * (endValue - startValue);
5388
5319
5389
- // Insert animatedCom and waitCom commands for each interpolated value
5390
- for (int value : interpolatedValues) {
5391
- animatedVarParams.back () = value;
5320
+ animatedVarParams.back () = interpolatedValue;
5392
5321
animatedCom.parameters = lcf::DBArray<int32_t >(animatedVarParams.begin (), animatedVarParams.end ());
5393
- animatedCom.indent = com.indent + 1 ;
5394
5322
5395
5323
cmdList.push_back (animatedCom);
5396
5324
cmdList.push_back (waitCom);
5397
5325
}
5398
5326
5399
- // Update current_command index and return true to indicate success
5400
5327
Push (cmdList, 0 , false );
5401
5328
return true ;
5402
5329
}
0 commit comments