com.amanotes.gdk 0.2.86 → 0.2.88

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 (41) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/Editor/AmaGDKEditor.cs +3 -1
  3. package/Editor/Extra/GDKCIBuildCommand.cs +19 -2
  4. package/Editor/Extra/GDKLocalBuild.cs +25 -1
  5. package/Editor/Extra/GDKPostBuildAsset.cs +21 -3
  6. package/Editor/Utils/AmaGDKEditor.ExtractVersion.Max.cs +7 -0
  7. package/Extra/AmaGDKInstaller.unitypackage +0 -0
  8. package/Extra/AutoEventQC.unitypackage +0 -0
  9. package/Extra/CheckDiskSpace.unitypackage +0 -0
  10. package/Extra/Consent.unitypackage +0 -0
  11. package/Extra/CrashlyticHook.unitypackage +0 -0
  12. package/Extra/ForceUpdate.unitypackage +0 -0
  13. package/Extra/LegacyGDKUpdateHelper.unitypackage +0 -0
  14. package/Extra/PostProcessor.unitypackage +0 -0
  15. package/Packages/AmaGDKConfig.unitypackage +0 -0
  16. package/Packages/AmaGDKExample.unitypackage +0 -0
  17. package/Packages/AmaGDKTest.unitypackage +0 -0
  18. package/Packages/AppsFlyerAdapter.PurchaseConnector.unitypackage +0 -0
  19. package/Packages/AppsFlyerAdapter.unitypackage +0 -0
  20. package/Packages/FirebaseAnalyticsAdapter.unitypackage +0 -0
  21. package/Packages/FirebaseRemoteConfigAdapter.unitypackage +0 -0
  22. package/Packages/IronSourceAdapter.AdQuality.unitypackage +0 -0
  23. package/Packages/IronSourceAdapter.unitypackage +0 -0
  24. package/Packages/MaxAdNetworkAdapter.unitypackage +0 -0
  25. package/Packages/RevenueCatAdapter.unitypackage +0 -0
  26. package/Packages/SqliteAnalyticsAdapter.unitypackage +0 -0
  27. package/Runtime/Ad/AdLogic.cs +222 -147
  28. package/Runtime/AmaGDK.Analytics.cs +105 -65
  29. package/Runtime/AmaGDK.RemoteConfig.cs +50 -40
  30. package/Runtime/AmaGDK.cs +1 -1
  31. package/Runtime/AnalyticQualityAsset.cs +69 -38
  32. package/Runtime/AudioToolkit/Plugins/AudioDeviceDetector.cs +31 -17
  33. package/Runtime/Core/GDKSemVer.cs +23 -26
  34. package/Runtime/Fps/AmaFPSVisualizer.cs +48 -26
  35. package/Runtime/Internal/AmaGDK.Utils.cs +90 -46
  36. package/Runtime/Internal/ForceQuitMonitor.cs +43 -31
  37. package/Runtime/Klavar/Attributes/MinMaxAttribute.cs +12 -3
  38. package/Runtime/UI/ScrollView/GDKScrollView.cs +83 -48
  39. package/Runtime/Utils/GDKFileUtils.cs +2 -7
  40. package/Runtime/Utils/GDKUtils.cs +20 -8
  41. package/package.json +1 -1
@@ -124,40 +124,62 @@ namespace Amanotes.Core
124
124
  var stIndex = vCount <= RESOLUTION ? 0 : (vCount % RESOLUTION);
125
125
  var nVertex = vCount <= RESOLUTION ? vCount : RESOLUTION;
126
126
 
127
+ GenerateFPSVertices(vh, barW, barH, barX, stIndex, nVertex);
128
+ DrawReferenceLines(vh, rect.width, barH);
129
+ }
130
+
131
+ private void GenerateFPSVertices(VertexHelper vh, float barW, float barH, float barX, int stIndex, int nVertex)
132
+ {
127
133
  for (var i = 0; i < nVertex; i++)
128
134
  {
129
135
  var idx = (i + stIndex) % RESOLUTION;
130
136
  var fps = fpsHistory[idx];
131
- var h = fps <= lowerFPSBoundary ? 0 :
132
- fps >= upperFPSBoundary ? 1 : (fps - lowerFPSBoundary) / (upperFPSBoundary - lowerFPSBoundary);
133
-
134
- var v0 = new Vector3(barX, 0, 0);
135
- var v1 = new Vector3(barX, h * barH, 0);
136
- var c1 = colors[
137
- fps <= badFPS ? 0 :
138
- fps <= acceptableFPS ? 1 :
139
- fps <= goodFPS ? 2 : 3
140
- ];
141
- var c0 = c1;
142
- c0.a = 0;
143
-
144
- // Add 2 vertices
145
- vh.AddVert(v0, c0, Vector2.zero);
146
- vh.AddVert(v1, c1, Vector2.zero);
147
-
148
- if (i > 0)
149
- {
150
- var vIndex = vh.currentVertCount - 2;
151
- vh.AddTriangle(vIndex - 2, vIndex - 1, vIndex + 1);
152
- vh.AddTriangle(vIndex - 2, vIndex + 1, vIndex);
153
- }
137
+ var h = GetNormalizedHeight(fps);
154
138
 
139
+ AddFPSBar(vh, barX, h * barH, fps, i > 0);
155
140
  barX += barW;
156
141
  }
142
+ }
143
+
144
+ private void AddFPSBar(VertexHelper vh, float barX, float barHeight, float fps, bool connectToPrevious)
145
+ {
146
+ var v0 = new Vector3(barX, 0, 0);
147
+ var v1 = new Vector3(barX, barHeight, 0);
148
+ var c1 = GetFPSColor(fps);
149
+ var c0 = c1;
150
+ c0.a = 0;
151
+
152
+ vh.AddVert(v0, c0, Vector2.zero);
153
+ vh.AddVert(v1, c1, Vector2.zero);
154
+
155
+ if (connectToPrevious)
156
+ {
157
+ var vIndex = vh.currentVertCount - 2;
158
+ vh.AddTriangle(vIndex - 2, vIndex - 1, vIndex + 1);
159
+ vh.AddTriangle(vIndex - 2, vIndex + 1, vIndex);
160
+ }
161
+ }
162
+
163
+ private void DrawReferenceLines(VertexHelper vh, float width, float barH)
164
+ {
165
+ AddHorzLine(vh, width, barH * ((goodFPS-lowerFPSBoundary) / (float)(upperFPSBoundary-lowerFPSBoundary)), colors[2], 2f);
166
+ AddHorzLine(vh, width, barH * ((acceptableFPS-lowerFPSBoundary) / (float)(upperFPSBoundary-lowerFPSBoundary)), colors[1], 2f);
167
+ AddHorzLine(vh, width, barH * ((badFPS-lowerFPSBoundary) / (float)(upperFPSBoundary-lowerFPSBoundary)), colors[0], 2f);
168
+ }
157
169
 
158
- AddHorzLine(vh, rect.width, barH * ((goodFPS-lowerFPSBoundary) / (float)(upperFPSBoundary-lowerFPSBoundary)), colors[2], 2f);
159
- AddHorzLine(vh, rect.width, barH * ((acceptableFPS-lowerFPSBoundary) / (float)(upperFPSBoundary-lowerFPSBoundary)), colors[1], 2f);
160
- AddHorzLine(vh, rect.width, barH * ((badFPS-lowerFPSBoundary) / (float)(upperFPSBoundary-lowerFPSBoundary)), colors[0], 2f);
170
+ private float GetNormalizedHeight(float fps)
171
+ {
172
+ return fps <= lowerFPSBoundary ? 0 :
173
+ fps >= upperFPSBoundary ? 1 : (fps - lowerFPSBoundary) / (upperFPSBoundary - lowerFPSBoundary);
174
+ }
175
+
176
+ private Color GetFPSColor(float fps)
177
+ {
178
+ return colors[
179
+ fps <= badFPS ? 0 :
180
+ fps <= acceptableFPS ? 1 :
181
+ fps <= goodFPS ? 2 : 3
182
+ ];
161
183
  }
162
184
 
163
185
  void AddHorzLine(VertexHelper vh, float w, float h, Color color, float thickness = 1f)
@@ -164,19 +164,32 @@ namespace Amanotes.Core.Internal
164
164
  return;
165
165
  }
166
166
 
167
+ Action<Action> nextAction = FindNextValidAction();
168
+ ExecuteActionOrComplete(nextAction);
169
+ }
170
+
171
+ private Action<Action> FindNextValidAction()
172
+ {
167
173
  Action<Action> nextAction = null;
168
174
  while (queue.Count > 0)
169
175
  {
170
176
  nextAction = queue.Dequeue();
171
- if (nextAction != null)
172
- {
173
- isProcessing = true;
174
- nextAction.Invoke(ActionCompleted);
175
- return;
176
- }
177
+ if (nextAction != null) break;
177
178
  }
179
+ return nextAction;
180
+ }
178
181
 
179
- if (nextAction == null) onComplete?.Invoke();
182
+ private void ExecuteActionOrComplete(Action<Action> nextAction)
183
+ {
184
+ if (nextAction != null)
185
+ {
186
+ isProcessing = true;
187
+ nextAction.Invoke(ActionCompleted);
188
+ }
189
+ else
190
+ {
191
+ onComplete?.Invoke();
192
+ }
180
193
  }
181
194
 
182
195
  public void StartQueue()
@@ -231,17 +244,9 @@ namespace Amanotes.Core.Internal
231
244
 
232
245
  foreach (DictionaryEntry entry in inputDict)
233
246
  {
234
- if (entry.Key == null || string.IsNullOrEmpty(entry.Key.ToString())) continue;
235
- string key = entry.Key.ToString();
236
- object value = entry.Value;
237
-
238
- if (isFirstElement)
239
- isFirstElement = false;
240
- else
241
- jsonSb.Append(",");
242
-
243
- jsonSb.AppendFormat("{0}\"{1}\":", format ? "\n" : "", key);
244
- AppendJsonValue(ref jsonSb, key, value, format, checkJsonInString);
247
+ if (!IsValidDictionaryEntry(entry)) continue;
248
+
249
+ AppendDictionaryEntry(ref jsonSb, entry, ref isFirstElement, format, checkJsonInString);
245
250
  }
246
251
 
247
252
  jsonSb.AppendFormat("{0}{1}", format ? "\n" : "", "}");
@@ -251,6 +256,25 @@ namespace Amanotes.Core.Internal
251
256
  return result;
252
257
  }
253
258
 
259
+ private static bool IsValidDictionaryEntry(DictionaryEntry entry)
260
+ {
261
+ return entry.Key != null && !string.IsNullOrEmpty(entry.Key.ToString());
262
+ }
263
+
264
+ private static void AppendDictionaryEntry(ref StringBuilder jsonSb, DictionaryEntry entry, ref bool isFirstElement, bool format, bool checkJsonInString)
265
+ {
266
+ string key = entry.Key.ToString();
267
+ object value = entry.Value;
268
+
269
+ if (isFirstElement)
270
+ isFirstElement = false;
271
+ else
272
+ jsonSb.Append(",");
273
+
274
+ jsonSb.AppendFormat("{0}\"{1}\":", format ? "\n" : "", key);
275
+ AppendJsonValue(ref jsonSb, key, value, format, checkJsonInString);
276
+ }
277
+
254
278
  private static void GetJsonIListValue(ref StringBuilder jsonSb, string key, IList list, bool format)
255
279
  {
256
280
  jsonSb.Append("[");
@@ -258,12 +282,7 @@ namespace Amanotes.Core.Internal
258
282
 
259
283
  foreach (object item in list)
260
284
  {
261
- if (isFirstElement)
262
- isFirstElement = false;
263
- else
264
- jsonSb.Append(",");
265
-
266
- if (format) jsonSb.AppendLine();
285
+ AppendListSeparator(ref jsonSb, ref isFirstElement, format);
267
286
  AppendJsonValue(ref jsonSb, key, item, format, false);
268
287
  }
269
288
 
@@ -271,6 +290,16 @@ namespace Amanotes.Core.Internal
271
290
  jsonSb.Append("]");
272
291
  }
273
292
 
293
+ private static void AppendListSeparator(ref StringBuilder jsonSb, ref bool isFirstElement, bool format)
294
+ {
295
+ if (isFirstElement)
296
+ isFirstElement = false;
297
+ else
298
+ jsonSb.Append(",");
299
+
300
+ if (format) jsonSb.AppendLine();
301
+ }
302
+
274
303
  private static void AppendJsonValue(ref StringBuilder jsonSb, string key, object value, bool format, bool checkJsonInString)
275
304
  {
276
305
  if (value == null)
@@ -281,31 +310,11 @@ namespace Amanotes.Core.Internal
281
310
 
282
311
  if (value is string)
283
312
  {
284
- var s = value.ToString();
285
- if (checkJsonInString)
286
- {
287
- if (s.StartsWith("{") && s.EndsWith("}"))
288
- {
289
- jsonSb.Append(s);
290
- return;
291
- }
292
- if (s.StartsWith("[") && s.EndsWith("]"))
293
- {
294
- jsonSb.Append(s);
295
- return;
296
- }
297
- }
298
- jsonSb.Append($"\"");
299
- AppendEscapeJsonString(jsonSb, s);
300
- jsonSb.Append($"\"");
313
+ AppendStringValue(ref jsonSb, value.ToString(), checkJsonInString);
301
314
  return;
302
315
  }
303
316
 
304
- if (value is int || value is float || value is double || value is long)
305
- {
306
- jsonSb.Append($"{value}");
307
- return;
308
- }
317
+ if (AppendNumericValue(ref jsonSb, value)) return;
309
318
 
310
319
  if (value is bool b)
311
320
  {
@@ -313,6 +322,11 @@ namespace Amanotes.Core.Internal
313
322
  return;
314
323
  }
315
324
 
325
+ AppendComplexValue(ref jsonSb, key, value, format);
326
+ }
327
+
328
+ private static void AppendComplexValue(ref StringBuilder jsonSb, string key, object value, bool format)
329
+ {
316
330
  if (value is IDictionary dictionary)
317
331
  {
318
332
  jsonSb.Append($"{DictionaryToJson(dictionary, format)}");
@@ -328,6 +342,36 @@ namespace Amanotes.Core.Internal
328
342
  jsonSb.Append($"{JsonUtility.ToJson(value, format)}");
329
343
  }
330
344
 
345
+ private static void AppendStringValue(ref StringBuilder jsonSb, string s, bool checkJsonInString)
346
+ {
347
+ if (checkJsonInString && IsJsonLikeString(s))
348
+ {
349
+ jsonSb.Append(s);
350
+ return;
351
+ }
352
+
353
+ jsonSb.Append($"\"");
354
+ AppendEscapeJsonString(jsonSb, s);
355
+ jsonSb.Append($"\"");
356
+ }
357
+
358
+ private static bool IsJsonLikeString(string s)
359
+ {
360
+ return (s.StartsWith("{") && s.EndsWith("}"))
361
+ || (s.StartsWith("[") && s.EndsWith("]"));
362
+ }
363
+
364
+ private static bool AppendNumericValue(ref StringBuilder jsonSb, object value)
365
+ {
366
+ if (value.IsNumeric())
367
+ {
368
+ jsonSb.Append($"{value}");
369
+ return true;
370
+ }
371
+
372
+ return false;
373
+ }
374
+
331
375
  /// <summary>
332
376
  /// Escapes a string for inclusion in a JSON document according to RFC 8259.
333
377
  /// For more details, see <a href="https://www.rfc-editor.org/rfc/rfc8259.txt">RFC 8259</a>.
@@ -40,10 +40,22 @@ namespace Amanotes.Core.Internal
40
40
  }
41
41
  private readonly Lazy<ForceQuitData> _localData = new Lazy<ForceQuitData>(() => new ForceQuitData());
42
42
  private ForceQuitData localData => _localData.Value;
43
+
44
+ private readonly Dictionary<string, System.Action<Dictionary<string, object>>> _eventHandlers;
43
45
 
44
46
  public ForceQuitMonitor()
45
47
  {
46
48
  AmaGDK.Analytics.OnEventSent += OnLogEvent;
49
+ _eventHandlers = new Dictionary<string, System.Action<Dictionary<string, object>>>
50
+ {
51
+ { "videoads_show_called", _ => HandleAdsShowCalled("watch_videoads") },
52
+ { "fullads_show_called", _ => HandleAdsShowCalled("watch_fullads") },
53
+ { "ad_impression", HandleAdImpression },
54
+ { "videoads_show_notready", _ => HandleAdsEnd() },
55
+ { "videoads_finish", _ => HandleAdsEnd() },
56
+ { "fullads_show_notready", _ => HandleAdsEnd() },
57
+ { "fullads_finish", _ => HandleAdsEnd() }
58
+ };
47
59
  }
48
60
 
49
61
  private string GetStringValueOrDefault(Dictionary<string, object> dict, string key, string defaultValue = "")
@@ -55,41 +67,41 @@ namespace Amanotes.Core.Internal
55
67
 
56
68
  public void OnLogEvent(string eventNameToSend, Dictionary<string, object> parameters)
57
69
  {
58
- switch (eventNameToSend)
70
+ if (_eventHandlers.TryGetValue(eventNameToSend, out var handler))
71
+ {
72
+ handler(parameters);
73
+ }
74
+ }
75
+
76
+ private void HandleAdsShowCalled(string reason)
77
+ {
78
+ localData.adsEvent = new AdsEvent { reason = reason };
79
+ localData.isDirty = true;
80
+ }
81
+
82
+ private void HandleAdImpression(Dictionary<string, object> parameters)
83
+ {
84
+ string adFormat = GetStringValueOrDefault(parameters, "ad_format");
85
+ if (adFormat == "rewarded_video" || adFormat == "interstitial") return;
86
+
87
+ if (localData.adsEvent != null)
59
88
  {
60
- case "videoads_show_called":
61
- localData.adsEvent = new AdsEvent { reason = "watch_videoads" };
62
- localData.isDirty = true;
63
- break;
64
- case "fullads_show_called":
65
- localData.adsEvent = new AdsEvent { reason = "watch_fullads" };
66
- localData.isDirty = true;
67
- break;
68
- case "ad_impression":
69
- string adFormat = GetStringValueOrDefault(parameters, "ad_format");
70
- if (adFormat == "rewarded_video" || adFormat == "interstitial") break;
71
-
72
- if (localData.adsEvent != null)
73
- {
74
- var detailParams = new Dictionary<string, object>
75
- {
76
- ["ad_source"] = GetStringValueOrDefault(parameters, "ad_source"),
77
- ["ad_unit_name"] = GetStringValueOrDefault(parameters, "ad_unit_name")
78
- };
79
- localData.adsEvent.detail = JsonUtils.DictionaryToJson(detailParams);
80
- localData.SaveIfDirty(true);
81
- }
82
- break;
83
- case "videoads_show_notready":
84
- case "videoads_finish":
85
- case "fullads_show_notready":
86
- case "fullads_finish":
87
- localData.adsEvent = null;
88
- localData.isDirty = true;
89
- break;
89
+ var detailParams = new Dictionary<string, object>
90
+ {
91
+ ["ad_source"] = GetStringValueOrDefault(parameters, "ad_source"),
92
+ ["ad_unit_name"] = GetStringValueOrDefault(parameters, "ad_unit_name")
93
+ };
94
+ localData.adsEvent.detail = JsonUtils.DictionaryToJson(detailParams);
95
+ localData.SaveIfDirty(true);
90
96
  }
91
97
  }
92
98
 
99
+ private void HandleAdsEnd()
100
+ {
101
+ localData.adsEvent = null;
102
+ localData.isDirty = true;
103
+ }
104
+
93
105
  public void Init()
94
106
  {
95
107
  GDKUtils.AddUnityCallbacks(this);
@@ -47,17 +47,26 @@ namespace Amanotes.Core
47
47
  return;
48
48
  }
49
49
 
50
+ ValidateRange(parent, fieldInfo, param);
51
+ }
52
+
53
+ private void ValidateRange(object parent, FieldInfo fieldInfo, object param)
54
+ {
50
55
  double val = Convert.ToDouble(param);
51
56
  bool isMinValid = inclusiveMin ? val >= min : val > min;
52
57
  bool isMaxValid = inclusiveMax ? val <= max : val < max;
53
58
 
54
59
  if (isMinValid && isMaxValid) return;
55
60
 
61
+ string rangeDescription = GetRangeDescription();
62
+ KlavarException.ThrowErrorOnField(parent, fieldInfo, $"Field '{fieldInfo.Name}' must be in the {rangeDescription}. Current value: {param}");
63
+ }
64
+
65
+ private string GetRangeDescription()
66
+ {
56
67
  string minBracket = inclusiveMin ? "[" : "(";
57
68
  string maxBracket = inclusiveMax ? "]" : ")";
58
- string rangeDescription = $"{minBracket}{min}, {max}{maxBracket}";
59
-
60
- KlavarException.ThrowErrorOnField(parent, fieldInfo, $"Field '{fieldInfo.Name}' must be in the {rangeDescription}. Current value: {param}");
69
+ return $"{minBracket}{min}, {max}{maxBracket}";
61
70
  }
62
71
  }
63
72
 
@@ -179,11 +179,16 @@ namespace Amanotes.Core.Internal
179
179
 
180
180
  private void EnsureItemRect(int index)
181
181
  {
182
- if (!_managedItems[index].rectDirty)
183
- {
184
- return;
185
- }
182
+ if (!_managedItems[index].rectDirty) return;
183
+
184
+ EnsureFirstItemRect();
185
+ int nearestClean = FindNearestCleanItem(index);
186
+ CalculateItemRects(nearestClean, index);
187
+ UpdateContentSize(index);
188
+ }
186
189
 
190
+ private void EnsureFirstItemRect()
191
+ {
187
192
  var firstItem = _managedItems[0];
188
193
  if (firstItem.rectDirty)
189
194
  {
@@ -191,29 +196,42 @@ namespace Amanotes.Core.Internal
191
196
  firstItem.rect = CreateWithLeftTopAndSize(Vector2.zero, firstSize);
192
197
  firstItem.rectDirty = false;
193
198
  }
199
+ }
194
200
 
201
+ private int FindNearestCleanItem(int index)
202
+ {
195
203
  var nearestClean = 0;
196
204
  for (var i = index; i >= 0; --i)
197
205
  {
198
- if (_managedItems[i].rectDirty)
199
- continue;
206
+ if (_managedItems[i].rectDirty) continue;
200
207
  nearestClean = i;
201
208
  break;
202
209
  }
210
+ return nearestClean;
211
+ }
203
212
 
213
+ private void CalculateItemRects(int nearestClean, int targetIndex)
214
+ {
204
215
  Rect nearestCleanRect = _managedItems[nearestClean].rect;
205
216
  Vector2 curPos = GetLeftTop(nearestCleanRect);
206
217
  Vector2 size = nearestCleanRect.size;
207
218
  MovePos(ref curPos, size);
208
219
 
209
- for (var i = nearestClean + 1; i <= index; i++)
220
+ for (var i = nearestClean + 1; i <= targetIndex; i++)
210
221
  {
211
222
  size = GetItemSize(i);
212
223
  _managedItems[i].rect = CreateWithLeftTopAndSize(curPos, size);
213
224
  _managedItems[i].rectDirty = false;
214
225
  MovePos(ref curPos, size);
215
226
  }
227
+ }
216
228
 
229
+ private void UpdateContentSize(int index)
230
+ {
231
+ var lastRect = _managedItems[index].rect;
232
+ Vector2 curPos = GetLeftTop(lastRect);
233
+ Vector2 size = lastRect.size;
234
+
217
235
  var range = new Vector2(Mathf.Abs(curPos.x), Mathf.Abs(curPos.y));
218
236
  switch (layoutType)
219
237
  {
@@ -227,7 +245,6 @@ namespace Amanotes.Core.Internal
227
245
  {
228
246
  range.y += size.y;
229
247
  }
230
-
231
248
  break;
232
249
  }
233
250
 
@@ -328,58 +345,76 @@ namespace Amanotes.Core.Internal
328
345
 
329
346
  if (newDataCount != _managedItems.Count)
330
347
  {
331
- if (_managedItems.Count < newDataCount)
332
- {
333
- if (!keepOldItems)
334
- {
335
- foreach (var itemWithRect in _managedItems)
336
- {
337
- itemWithRect.rectDirty = true;
338
- }
339
- }
348
+ HandleDataCountChange(newDataCount, keepOldItems);
349
+ }
350
+ else
351
+ {
352
+ HandleSameDataCount(keepOldItems);
353
+ }
340
354
 
341
- while (_managedItems.Count < newDataCount)
342
- {
343
- _managedItems.Add(new ScrollItemWithRect());
344
- }
345
- }
346
- else
355
+ _dataCount = newDataCount;
356
+ }
357
+
358
+ private void HandleDataCountChange(int newDataCount, bool keepOldItems)
359
+ {
360
+ if (_managedItems.Count < newDataCount)
361
+ {
362
+ HandleDataCountIncrease(newDataCount, keepOldItems);
363
+ }
364
+ else
365
+ {
366
+ HandleDataCountDecrease(newDataCount, keepOldItems);
367
+ }
368
+ }
369
+
370
+ private void HandleDataCountIncrease(int newDataCount, bool keepOldItems)
371
+ {
372
+ if (!keepOldItems)
373
+ {
374
+ foreach (var itemWithRect in _managedItems)
347
375
  {
348
- for (int i = 0, count = _managedItems.Count; i < count; ++i)
349
- {
350
- if (i < newDataCount)
351
- {
352
- if (!keepOldItems)
353
- {
354
- _managedItems[i].rectDirty = true;
355
- }
356
-
357
- if (i == newDataCount - 1)
358
- {
359
- _managedItems[i].rectDirty = true;
360
- }
361
- }
362
-
363
- if (i < newDataCount) continue;
364
- _managedItems[i].rectDirty = true;
365
- if (_managedItems[i].item == null) continue;
366
- RecycleOldItem(_managedItems[i].item);
367
- _managedItems[i].item = null;
368
- }
376
+ itemWithRect.rectDirty = true;
369
377
  }
370
378
  }
371
- else
379
+
380
+ while (_managedItems.Count < newDataCount)
381
+ {
382
+ _managedItems.Add(new ScrollItemWithRect());
383
+ }
384
+ }
385
+
386
+ private void HandleDataCountDecrease(int newDataCount, bool keepOldItems)
387
+ {
388
+ for (int i = 0, count = _managedItems.Count; i < count; ++i)
372
389
  {
373
- if (!keepOldItems)
390
+ if (i < newDataCount)
374
391
  {
375
- for (int i = 0, count = _managedItems.Count; i < count; ++i)
392
+ if (!keepOldItems)
393
+ {
394
+ _managedItems[i].rectDirty = true;
395
+ }
396
+
397
+ if (i == newDataCount - 1)
376
398
  {
377
399
  _managedItems[i].rectDirty = true;
378
400
  }
379
401
  }
402
+
403
+ if (i < newDataCount) continue;
404
+ _managedItems[i].rectDirty = true;
405
+ if (_managedItems[i].item == null) continue;
406
+ RecycleOldItem(_managedItems[i].item);
407
+ _managedItems[i].item = null;
380
408
  }
409
+ }
381
410
 
382
- _dataCount = newDataCount;
411
+ private void HandleSameDataCount(bool keepOldItems)
412
+ {
413
+ if (keepOldItems) return;
414
+ for (int i = 0, count = _managedItems.Count; i < count; ++i)
415
+ {
416
+ _managedItems[i].rectDirty = true;
417
+ }
383
418
  }
384
419
 
385
420
  private void ResetCriticalItems()
@@ -254,14 +254,9 @@ namespace Amanotes.Core.Internal
254
254
  try
255
255
  {
256
256
  var operation = request.SendWebRequest();
257
- while (!operation.isDone)
258
- {
259
- await Task.Yield();
260
- }
257
+ while (!operation.isDone) await Task.Yield();
261
258
 
262
- return request.result != UnityWebRequest.Result.Success
263
- ? null
264
- : request.downloadHandler.text;
259
+ return request.result != UnityWebRequest.Result.Success ? null : request.downloadHandler.text;
265
260
  } catch (Exception ex)
266
261
  {
267
262
  LogError($"[GDKFileUtils] StreamingAssets load error: {ex.Message}");
@@ -105,6 +105,12 @@ namespace Amanotes.Core.Internal
105
105
  yield return new WaitForSecondsRealtime(duration);
106
106
  yield break;
107
107
  }
108
+
109
+ yield return WaitForSecondsWithFocusHandling(duration);
110
+ }
111
+
112
+ private static IEnumerator WaitForSecondsWithFocusHandling(float duration)
113
+ {
108
114
  float elapsedTime = 0f;
109
115
  float lastTimeStamp = Time.realtimeSinceStartup;
110
116
  bool focusChangedSinceLastFrame = false;
@@ -115,19 +121,25 @@ namespace Amanotes.Core.Internal
115
121
  {
116
122
  if (Application.isFocused)
117
123
  {
118
- if (focusChangedSinceLastFrame)
119
- {
120
- lastTimeStamp = Time.realtimeSinceStartup;
121
- focusChangedSinceLastFrame = false;
122
- }
123
-
124
- elapsedTime += Time.realtimeSinceStartup - lastTimeStamp;
125
- lastTimeStamp = Time.realtimeSinceStartup;
124
+ elapsedTime = UpdateElapsedTime(elapsedTime, ref lastTimeStamp, ref focusChangedSinceLastFrame);
126
125
  }
127
126
 
128
127
  yield return null;
129
128
  }
130
129
  Application.focusChanged -= onApplicationFocusCallback;
131
130
  }
131
+
132
+ private static float UpdateElapsedTime(float elapsedTime, ref float lastTimeStamp, ref bool focusChangedSinceLastFrame)
133
+ {
134
+ if (focusChangedSinceLastFrame)
135
+ {
136
+ lastTimeStamp = Time.realtimeSinceStartup;
137
+ focusChangedSinceLastFrame = false;
138
+ }
139
+
140
+ elapsedTime += Time.realtimeSinceStartup - lastTimeStamp;
141
+ lastTimeStamp = Time.realtimeSinceStartup;
142
+ return elapsedTime;
143
+ }
132
144
  }
133
145
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.amanotes.gdk",
3
- "version": "0.2.86",
3
+ "version": "0.2.88",
4
4
  "displayName": "AmaGDK",
5
5
  "description": "Amanotes Game Development Kit",
6
6
  "unity": "2020.3",