com.amanotes.gdk 0.2.86 → 0.2.87
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.
- package/CHANGELOG.md +22 -0
- package/Editor/Extra/GDKCIBuildCommand.cs +19 -2
- package/Editor/Extra/GDKLocalBuild.cs +25 -1
- package/Editor/Utils/AmaGDKEditor.ExtractVersion.Max.cs +7 -0
- package/Extra/AmaGDKInstaller.unitypackage +0 -0
- package/Extra/AutoEventQC.unitypackage +0 -0
- package/Extra/CheckDiskSpace.unitypackage +0 -0
- package/Extra/Consent.unitypackage +0 -0
- package/Extra/CrashlyticHook.unitypackage +0 -0
- package/Extra/ForceUpdate.unitypackage +0 -0
- package/Extra/LegacyGDKUpdateHelper.unitypackage +0 -0
- package/Extra/PostProcessor.unitypackage +0 -0
- package/Packages/AmaGDKConfig.unitypackage +0 -0
- package/Packages/AmaGDKExample.unitypackage +0 -0
- package/Packages/AmaGDKTest.unitypackage +0 -0
- package/Packages/AppsFlyerAdapter.PurchaseConnector.unitypackage +0 -0
- package/Packages/AppsFlyerAdapter.unitypackage +0 -0
- package/Packages/FirebaseAnalyticsAdapter.unitypackage +0 -0
- package/Packages/FirebaseRemoteConfigAdapter.unitypackage +0 -0
- package/Packages/IronSourceAdapter.AdQuality.unitypackage +0 -0
- package/Packages/IronSourceAdapter.unitypackage +0 -0
- package/Packages/MaxAdNetworkAdapter.unitypackage +0 -0
- package/Packages/RevenueCatAdapter.unitypackage +0 -0
- package/Packages/SqliteAnalyticsAdapter.unitypackage +0 -0
- package/Runtime/Ad/AdLogic.cs +222 -147
- package/Runtime/AmaGDK.Analytics.cs +105 -65
- package/Runtime/AmaGDK.RemoteConfig.cs +50 -40
- package/Runtime/AmaGDK.cs +1 -1
- package/Runtime/AnalyticQualityAsset.cs +69 -38
- package/Runtime/AudioToolkit/Plugins/AudioDeviceDetector.cs +31 -17
- package/Runtime/Core/GDKSemVer.cs +23 -26
- package/Runtime/Fps/AmaFPSVisualizer.cs +48 -26
- package/Runtime/Internal/AmaGDK.Utils.cs +90 -46
- package/Runtime/Internal/ForceQuitMonitor.cs +43 -31
- package/Runtime/Klavar/Attributes/MinMaxAttribute.cs +12 -3
- package/Runtime/UI/ScrollView/GDKScrollView.cs +83 -48
- package/Runtime/Utils/GDKFileUtils.cs +2 -7
- package/Runtime/Utils/GDKUtils.cs +20 -8
- 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
|
|
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
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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
|
-
|
|
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 (
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 <=
|
|
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
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
itemWithRect.rectDirty = true;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
348
|
+
HandleDataCountChange(newDataCount, keepOldItems);
|
|
349
|
+
}
|
|
350
|
+
else
|
|
351
|
+
{
|
|
352
|
+
HandleSameDataCount(keepOldItems);
|
|
353
|
+
}
|
|
340
354
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
390
|
+
if (i < newDataCount)
|
|
374
391
|
{
|
|
375
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|