rngine 0.8.2 → 0.8.3
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/android/kls_database.db +0 -0
- package/android/src/main/java/com/margelo/nitro/rngine/ImageLoaderHelper.kt +56 -0
- package/lib/module/GameMethods.js +3 -3
- package/lib/module/GameMethods.js.map +1 -1
- package/lib/typescript/src/GameMethods.nitro.d.ts +1 -1
- package/lib/typescript/src/GameMethods.nitro.d.ts.map +1 -1
- package/nitrogen/generated/shared/c++/HybridGameMethodsSpec.cpp +1 -1
- package/nitrogen/generated/shared/c++/HybridGameMethodsSpec.hpp +1 -1
- package/package.json +1 -1
- package/shared/GameMethods.cpp +71 -37
- package/shared/GameMethods.hpp +2 -2
- package/shared/GameRenderer.cpp +89 -38
- package/shared/GameRenderer.hpp +6 -3
- package/src/GameMethods.nitro.ts +1 -1
- package/src/GameMethods.ts +3 -3
- package/android/src/main/java/com/margelo/nitro/rngine/SvgLoaderHelper.kt +0 -24
package/android/kls_database.db
CHANGED
|
Binary file
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package com.margelo.nitro.rngine
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import androidx.annotation.Keep
|
|
5
|
+
import com.margelo.nitro.NitroModules
|
|
6
|
+
import java.io.IOException
|
|
7
|
+
import java.net.URL
|
|
8
|
+
|
|
9
|
+
@Keep
|
|
10
|
+
object ImageLoaderHelper {
|
|
11
|
+
@JvmStatic
|
|
12
|
+
fun loadFromUrl(uri: String): ByteArray {
|
|
13
|
+
Log.d("ImageLoaderHelper", "loadFromUrl: fetching $uri")
|
|
14
|
+
return try {
|
|
15
|
+
val bytes = URL(uri).openStream().use { it.readBytes() }
|
|
16
|
+
Log.d("ImageLoaderHelper", "loadFromUrl: success, ${bytes.size} bytes for $uri")
|
|
17
|
+
bytes
|
|
18
|
+
} catch (e: IOException) {
|
|
19
|
+
Log.e("ImageLoaderHelper", "loadFromUrl: network/IO failure for $uri", e)
|
|
20
|
+
throw e
|
|
21
|
+
} catch (e: Exception) {
|
|
22
|
+
Log.e("ImageLoaderHelper", "loadFromUrl: unexpected failure for $uri", e)
|
|
23
|
+
throw e
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@JvmStatic
|
|
28
|
+
fun loadFromResource(uri: String): ByteArray {
|
|
29
|
+
Log.d("ImageLoaderHelper", "loadFromResource: resolving resource for '$uri'")
|
|
30
|
+
val context = NitroModules.applicationContext
|
|
31
|
+
if (context == null) {
|
|
32
|
+
Log.e(
|
|
33
|
+
"ImageLoaderHelper",
|
|
34
|
+
"loadFromResource: applicationContext is null, NitroModules not initialized?"
|
|
35
|
+
)
|
|
36
|
+
throw IllegalStateException("No Context available!")
|
|
37
|
+
}
|
|
38
|
+
var resId = context.resources.getIdentifier(uri, "raw", context.packageName)
|
|
39
|
+
if (resId == 0) {
|
|
40
|
+
resId = context.resources.getIdentifier(uri, "drawable", context.packageName)
|
|
41
|
+
}
|
|
42
|
+
if (resId == 0) {
|
|
43
|
+
Log.e("ImageLoaderHelper", "loadFromResource: no resource found for '$uri'")
|
|
44
|
+
throw IllegalStateException("Could not resolve raw resource for asset: $uri")
|
|
45
|
+
}
|
|
46
|
+
Log.d("ImageLoaderHelper", "loadFromResource: resolved '$uri' -> resId=$resId")
|
|
47
|
+
return try {
|
|
48
|
+
val bytes = context.resources.openRawResource(resId).use { it.readBytes() }
|
|
49
|
+
Log.d("ImageLoaderHelper", "loadFromResource: success, ${bytes.size} bytes for '$uri'")
|
|
50
|
+
bytes
|
|
51
|
+
} catch (e: Exception) {
|
|
52
|
+
Log.e("ImageLoaderHelper", "loadFromResource: failed reading resId=$resId for '$uri'", e)
|
|
53
|
+
throw e
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -81,9 +81,9 @@ const loadAsset = async asset => {
|
|
|
81
81
|
if (!assetUri) {
|
|
82
82
|
throw new Error(`loadAssets: could not resolve asset URI for ${asset}`);
|
|
83
83
|
}
|
|
84
|
-
const
|
|
85
|
-
if (!
|
|
86
|
-
throw new Error('loadAssets: Failed to load
|
|
84
|
+
const isLoaded = await gameMethods.loadImage(asset, assetUri);
|
|
85
|
+
if (!isLoaded) {
|
|
86
|
+
throw new Error('loadAssets: Failed to load image asset');
|
|
87
87
|
}
|
|
88
88
|
return asset;
|
|
89
89
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["gameMethods","Image","configure","world","screen","entities","systems","paused","nativeSystems","system","push","collisions","onTick","e","c","start","Date","now","finish","setWorld","setScreen","setEntities","setSystems","pause","resume","spawn","entityArray","Array","isArray","despawn","id","update","updates","entityUpdateArray","assetCache","WeakMap","nextId","loadAsset","asset","Error","has","get","assetId","set","isLottieLoaded","loadLottie","JSON","stringify","isAssetLoaded","assetUri","resolveAssetSource","uri","
|
|
1
|
+
{"version":3,"names":["gameMethods","Image","configure","world","screen","entities","systems","paused","nativeSystems","system","push","collisions","onTick","e","c","start","Date","now","finish","setWorld","setScreen","setEntities","setSystems","pause","resume","spawn","entityArray","Array","isArray","despawn","id","update","updates","entityUpdateArray","assetCache","WeakMap","nextId","loadAsset","asset","Error","has","get","assetId","set","isLottieLoaded","loadLottie","JSON","stringify","isAssetLoaded","assetUri","resolveAssetSource","uri","isLoaded","loadImage","loadAssets","assets","keys","Object","result","key"],"sourceRoot":"../../src","sources":["GameMethods.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -15,7 +15,7 @@ interface GameMethods extends HybridObject<{
|
|
|
15
15
|
update(updates: EntityUpdate[]): void;
|
|
16
16
|
isAssetLoaded(id: number): boolean;
|
|
17
17
|
loadLottie(id: number, jsonStr: string): Promise<boolean>;
|
|
18
|
-
|
|
18
|
+
loadImage(id: number, imageUri: string): Promise<boolean>;
|
|
19
19
|
}
|
|
20
20
|
export declare const gameMethods: GameMethods;
|
|
21
21
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameMethods.nitro.d.ts","sourceRoot":"","sources":["../../../src/GameMethods.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EACZ,MAAM,EACN,MAAM,EACN,KAAK,EACN,MAAM,eAAe,CAAC;AAGvB,UAAU,WAAY,SAAQ,YAAY,CAAC;IACzC,GAAG,EAAE,KAAK,CAAC;IACX,OAAO,EAAE,KAAK,CAAC;CAChB,CAAC;IACA,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACtC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAEtC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,
|
|
1
|
+
{"version":3,"file":"GameMethods.nitro.d.ts","sourceRoot":"","sources":["../../../src/GameMethods.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EACZ,MAAM,EACN,MAAM,EACN,KAAK,EACN,MAAM,eAAe,CAAC;AAGvB,UAAU,WAAY,SAAQ,YAAY,CAAC;IACzC,GAAG,EAAE,KAAK,CAAC;IACX,OAAO,EAAE,KAAK,CAAC;CAChB,CAAC;IACA,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACtC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAEtC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3D;AAED,eAAO,MAAM,WAAW,aACqC,CAAC"}
|
|
@@ -25,7 +25,7 @@ namespace margelo::nitro::rngine {
|
|
|
25
25
|
prototype.registerHybridMethod("update", &HybridGameMethodsSpec::update);
|
|
26
26
|
prototype.registerHybridMethod("isAssetLoaded", &HybridGameMethodsSpec::isAssetLoaded);
|
|
27
27
|
prototype.registerHybridMethod("loadLottie", &HybridGameMethodsSpec::loadLottie);
|
|
28
|
-
prototype.registerHybridMethod("
|
|
28
|
+
prototype.registerHybridMethod("loadImage", &HybridGameMethodsSpec::loadImage);
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -75,7 +75,7 @@ namespace margelo::nitro::rngine {
|
|
|
75
75
|
virtual void update(const std::vector<EntityUpdate>& updates) = 0;
|
|
76
76
|
virtual bool isAssetLoaded(double id) = 0;
|
|
77
77
|
virtual std::shared_ptr<Promise<bool>> loadLottie(double id, const std::string& jsonStr) = 0;
|
|
78
|
-
virtual std::shared_ptr<Promise<bool>>
|
|
78
|
+
virtual std::shared_ptr<Promise<bool>> loadImage(double id, const std::string& imageUri) = 0;
|
|
79
79
|
|
|
80
80
|
protected:
|
|
81
81
|
// Hybrid Setup
|
package/package.json
CHANGED
package/shared/GameMethods.cpp
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#include "EntityUpdate.hpp"
|
|
3
3
|
#include "GameLoop.hpp"
|
|
4
4
|
#include "GameRenderer.hpp"
|
|
5
|
+
#include "include/core/SkImage.h"
|
|
5
6
|
#include "include/core/SkStream.h"
|
|
6
7
|
#include <android/log.h>
|
|
7
8
|
#include <fbjni/fbjni.h>
|
|
@@ -176,9 +177,9 @@ bool GameMethods::isAssetLoaded(double id) {
|
|
|
176
177
|
auto &gameRenderer = GameRenderer::getInstance();
|
|
177
178
|
|
|
178
179
|
if (id > 0) {
|
|
179
|
-
auto &
|
|
180
|
-
auto it =
|
|
181
|
-
return it !=
|
|
180
|
+
auto &imageCache = gameRenderer.getImageCacheInternal();
|
|
181
|
+
auto it = imageCache.find(id);
|
|
182
|
+
return it != imageCache.end();
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
if (id < 0) {
|
|
@@ -213,53 +214,86 @@ GameMethods::loadLottie(double id, const std::string &jsonStr) {
|
|
|
213
214
|
});
|
|
214
215
|
};
|
|
215
216
|
|
|
216
|
-
std::shared_ptr<Promise<bool>>
|
|
217
|
-
|
|
217
|
+
std::shared_ptr<Promise<bool>>
|
|
218
|
+
GameMethods::loadImage(double id, const std::string &imageUri) {
|
|
218
219
|
return Promise<bool>::async([=]() -> bool {
|
|
219
|
-
|
|
220
|
+
__android_log_print(ANDROID_LOG_DEBUG, "GameMethods",
|
|
221
|
+
"loadImage: start id=%.0f uri=%s", id,
|
|
222
|
+
imageUri.c_str());
|
|
223
|
+
std::string imageStr;
|
|
220
224
|
|
|
221
225
|
using namespace facebook::jni;
|
|
222
226
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
227
|
+
try {
|
|
228
|
+
ThreadScope::WithClassLoader([&] {
|
|
229
|
+
static const auto helperClass =
|
|
230
|
+
findClassStatic("com/margelo/nitro/rngine/ImageLoaderHelper");
|
|
231
|
+
|
|
232
|
+
local_ref<JArrayByte> byteArray;
|
|
233
|
+
|
|
234
|
+
if (imageUri.rfind("http://", 0) == 0 ||
|
|
235
|
+
imageUri.rfind("https://", 0) == 0) {
|
|
236
|
+
static const auto method =
|
|
237
|
+
helperClass->getStaticMethod<JArrayByte(local_ref<JString>)>(
|
|
238
|
+
"loadFromUrl");
|
|
239
|
+
byteArray = method(helperClass, make_jstring(imageUri));
|
|
240
|
+
} else {
|
|
241
|
+
static const auto method =
|
|
242
|
+
helperClass->getStaticMethod<JArrayByte(local_ref<JString>)>(
|
|
243
|
+
"loadFromResource");
|
|
244
|
+
byteArray = method(helperClass, make_jstring(imageUri));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (!byteArray) {
|
|
248
|
+
throw std::runtime_error("Failed to load image bytes for: " +
|
|
249
|
+
imageUri);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
size_t len = byteArray->size();
|
|
253
|
+
imageStr.resize(len);
|
|
254
|
+
byteArray->getRegion(0, len,
|
|
255
|
+
reinterpret_cast<int8_t *>(imageStr.data()));
|
|
256
|
+
});
|
|
257
|
+
} catch (const std::exception &e) {
|
|
258
|
+
__android_log_print(ANDROID_LOG_ERROR, "GameMethods",
|
|
259
|
+
"loadImage: JNI fetch failed id=%.0f: %s", id,
|
|
260
|
+
e.what());
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
240
263
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
264
|
+
__android_log_print(ANDROID_LOG_DEBUG, "GameMethods",
|
|
265
|
+
"loadImage: fetched %zu bytes id=%.0f", imageStr.size(),
|
|
266
|
+
id);
|
|
244
267
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
byteArray->getRegion(0, len, reinterpret_cast<int8_t *>(svgStr.data()));
|
|
248
|
-
});
|
|
268
|
+
auto &gameRenderer = GameRenderer::getInstance();
|
|
269
|
+
auto &imageCache = gameRenderer.getImageCacheInternal();
|
|
249
270
|
|
|
250
|
-
auto stream = SkMemoryStream::MakeDirect(
|
|
271
|
+
auto stream = SkMemoryStream::MakeDirect(imageStr.data(), imageStr.size());
|
|
251
272
|
auto svgDom = SkSVGDOM::MakeFromStream(*stream);
|
|
252
273
|
|
|
253
|
-
if (
|
|
254
|
-
|
|
274
|
+
if (svgDom) {
|
|
275
|
+
__android_log_print(ANDROID_LOG_DEBUG, "GameMethods",
|
|
276
|
+
"loadImage: parsed as SVG id=%.0f", id);
|
|
277
|
+
imageCache[id] = std::move(svgDom);
|
|
278
|
+
return true;
|
|
255
279
|
}
|
|
256
280
|
|
|
257
|
-
auto
|
|
258
|
-
auto
|
|
281
|
+
auto data = SkData::MakeWithCopy(imageStr.data(), imageStr.size());
|
|
282
|
+
auto raster = SkImages::DeferredFromEncodedData(std::move(data));
|
|
259
283
|
|
|
260
|
-
|
|
284
|
+
if (raster) {
|
|
285
|
+
__android_log_print(ANDROID_LOG_DEBUG, "GameMethods",
|
|
286
|
+
"loadImage: parsed as raster id=%.0f", id);
|
|
287
|
+
imageCache[id] = std::move(raster);
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
261
290
|
|
|
262
|
-
|
|
291
|
+
__android_log_print(ANDROID_LOG_ERROR, "GameMethods",
|
|
292
|
+
"loadImage: both SVG parse and raster decode failed "
|
|
293
|
+
"id=%.0f",
|
|
294
|
+
id);
|
|
295
|
+
|
|
296
|
+
return false;
|
|
263
297
|
});
|
|
264
298
|
};
|
|
265
299
|
} // namespace margelo::nitro::rngine
|
package/shared/GameMethods.hpp
CHANGED
|
@@ -31,7 +31,7 @@ public:
|
|
|
31
31
|
std::shared_ptr<Promise<bool>>
|
|
32
32
|
loadLottie(double id, const std::string &jsonStr) override;
|
|
33
33
|
|
|
34
|
-
std::shared_ptr<Promise<bool>>
|
|
35
|
-
|
|
34
|
+
std::shared_ptr<Promise<bool>> loadImage(double id,
|
|
35
|
+
const std::string &svgUri) override;
|
|
36
36
|
};
|
|
37
37
|
} // namespace margelo::nitro::rngine
|
package/shared/GameRenderer.cpp
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#include "include/core/SkColorSpace.h"
|
|
11
11
|
#include "include/core/SkPaint.h"
|
|
12
12
|
#include "include/core/SkRect.h"
|
|
13
|
+
#include "include/core/SkRefCnt.h"
|
|
13
14
|
#include "include/core/SkSurface.h"
|
|
14
15
|
|
|
15
16
|
#include "include/gpu/ganesh/GrBackendSurface.h"
|
|
@@ -19,6 +20,7 @@
|
|
|
19
20
|
|
|
20
21
|
#include "include/gpu/ganesh/gl/GrGLDirectContext.h"
|
|
21
22
|
#include "include/gpu/ganesh/gl/GrGLInterface.h"
|
|
23
|
+
#include "modules/svg/include/SkSVGDOM.h"
|
|
22
24
|
|
|
23
25
|
#include <EGL/egl.h>
|
|
24
26
|
#include <GLES3/gl3.h>
|
|
@@ -151,29 +153,58 @@ void GameRenderer::render(const Screen &screen,
|
|
|
151
153
|
if (screen.asset.has_value() && screen.asset.value() != 0) {
|
|
152
154
|
double assetId = screen.asset.value();
|
|
153
155
|
|
|
154
|
-
auto
|
|
155
|
-
if (
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
156
|
+
auto imageIt = _imageCache.find(assetId);
|
|
157
|
+
if (imageIt != _imageCache.end()) {
|
|
158
|
+
std::visit(
|
|
159
|
+
[&](const auto image) {
|
|
160
|
+
using T = std::decay_t<decltype(image)>;
|
|
161
|
+
if constexpr (std::is_same_v<T, sk_sp<SkSVGDOM>>) {
|
|
162
|
+
SkSize intrinsicSize = image->containerSize();
|
|
163
|
+
|
|
164
|
+
if (intrinsicSize.isEmpty()) {
|
|
165
|
+
image->setContainerSize(
|
|
166
|
+
SkSize::Make(virtualWidth, virtualHeight));
|
|
167
|
+
intrinsicSize = SkSize::Make(virtualWidth, virtualHeight);
|
|
168
|
+
}
|
|
163
169
|
|
|
164
|
-
|
|
165
|
-
|
|
170
|
+
float scaleX = virtualWidth / intrinsicSize.width();
|
|
171
|
+
float scaleY = virtualHeight / intrinsicSize.height();
|
|
166
172
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
173
|
+
canvas->save();
|
|
174
|
+
if (screen.flipH.has_value() || screen.flipV.has_value()) {
|
|
175
|
+
canvas->translate(virtualWidth / 2.f, virtualHeight / 2.f);
|
|
176
|
+
canvas->scale(screen.flipH.value_or(false) ? -1.f : 1.f,
|
|
177
|
+
screen.flipV.value_or(false) ? -1.f : 1.f);
|
|
178
|
+
canvas->translate(-virtualWidth / 2.f, -virtualHeight / 2.f);
|
|
179
|
+
}
|
|
180
|
+
canvas->scale(scaleX, scaleY);
|
|
181
|
+
image->render(canvas);
|
|
182
|
+
canvas->restore();
|
|
183
|
+
} else {
|
|
184
|
+
float intrinsicW = static_cast<float>(image->width());
|
|
185
|
+
float intrinsicH = static_cast<float>(image->height());
|
|
186
|
+
if (intrinsicW <= 0.f || intrinsicH <= 0.f)
|
|
187
|
+
return;
|
|
188
|
+
|
|
189
|
+
float scaleX = virtualWidth / intrinsicW;
|
|
190
|
+
float scaleY = virtualHeight / intrinsicH;
|
|
191
|
+
|
|
192
|
+
canvas->save();
|
|
193
|
+
if (screen.flipH.has_value() || screen.flipV.has_value()) {
|
|
194
|
+
canvas->translate(virtualWidth / 2.f, virtualHeight / 2.f);
|
|
195
|
+
canvas->scale(screen.flipH.value_or(false) ? -1.f : 1.f,
|
|
196
|
+
screen.flipV.value_or(false) ? -1.f : 1.f);
|
|
197
|
+
canvas->translate(-virtualWidth / 2.f, -virtualHeight / 2.f);
|
|
198
|
+
}
|
|
199
|
+
canvas->scale(scaleX, scaleY);
|
|
200
|
+
|
|
201
|
+
SkSamplingOptions sampling(SkFilterMode::kLinear,
|
|
202
|
+
SkMipmapMode::kLinear);
|
|
203
|
+
canvas->drawImage(image, 0.f, 0.f, sampling);
|
|
204
|
+
canvas->restore();
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
imageIt->second);
|
|
177
208
|
} else {
|
|
178
209
|
auto lottieIt = _lottieCache.find(assetId);
|
|
179
210
|
if (lottieIt != _lottieCache.end() && lottieIt->second) {
|
|
@@ -246,23 +277,43 @@ void GameRenderer::render(const Screen &screen,
|
|
|
246
277
|
canvas->translate(-width / 2.f, -height / 2.f);
|
|
247
278
|
}
|
|
248
279
|
|
|
249
|
-
auto
|
|
250
|
-
if (
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
280
|
+
auto imageIt = _imageCache.find(assetId);
|
|
281
|
+
if (imageIt != _imageCache.end()) {
|
|
282
|
+
std::visit(
|
|
283
|
+
[&](const auto image) {
|
|
284
|
+
using T = std::decay_t<decltype(image)>;
|
|
285
|
+
if constexpr (std::is_same_v<T, sk_sp<SkSVGDOM>>) {
|
|
286
|
+
SkSize intrinsicSize = image->containerSize();
|
|
287
|
+
if (intrinsicSize.isEmpty()) {
|
|
288
|
+
image->setContainerSize(SkSize::Make(width, height));
|
|
289
|
+
intrinsicSize = SkSize::Make(width, height);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
float scaleX = width / intrinsicSize.width();
|
|
293
|
+
float scaleY = height / intrinsicSize.height();
|
|
294
|
+
|
|
295
|
+
canvas->save();
|
|
296
|
+
canvas->scale(scaleX, scaleY);
|
|
297
|
+
image->render(canvas);
|
|
298
|
+
canvas->restore();
|
|
299
|
+
} else {
|
|
300
|
+
float intrinsicW = static_cast<float>(image->width());
|
|
301
|
+
float intrinsicH = static_cast<float>(image->height());
|
|
302
|
+
if (intrinsicW <= 0.f || intrinsicH <= 0.f)
|
|
303
|
+
return;
|
|
304
|
+
|
|
305
|
+
float scaleX = width / intrinsicW;
|
|
306
|
+
float scaleY = height / intrinsicH;
|
|
307
|
+
|
|
308
|
+
canvas->save();
|
|
309
|
+
canvas->scale(scaleX, scaleY);
|
|
310
|
+
SkSamplingOptions sampling(SkFilterMode::kLinear,
|
|
311
|
+
SkMipmapMode::kLinear);
|
|
312
|
+
canvas->drawImage(image, 0.f, 0.f, sampling);
|
|
313
|
+
canvas->restore();
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
imageIt->second);
|
|
266
317
|
} else {
|
|
267
318
|
auto lottieIt = _lottieCache.find(assetId);
|
|
268
319
|
if (lottieIt != _lottieCache.end() && lottieIt->second) {
|
package/shared/GameRenderer.hpp
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
#include "Entity.hpp"
|
|
3
3
|
#include "Screen.hpp"
|
|
4
|
+
#include "include/core/SkImage.h"
|
|
4
5
|
#include "include/core/SkSurface.h"
|
|
5
6
|
#include "include/gpu/ganesh/GrDirectContext.h"
|
|
6
7
|
#include "modules/skottie/include/Skottie.h"
|
|
@@ -21,9 +22,11 @@ public:
|
|
|
21
22
|
|
|
22
23
|
~GameRenderer();
|
|
23
24
|
|
|
24
|
-
std::map<double, sk_sp<SkSVGDOM
|
|
25
|
-
|
|
25
|
+
std::map<double, std::variant<sk_sp<SkSVGDOM>, sk_sp<SkImage>>> &
|
|
26
|
+
getImageCacheInternal() {
|
|
27
|
+
return _imageCache;
|
|
26
28
|
};
|
|
29
|
+
|
|
27
30
|
std::map<double, sk_sp<skottie::Animation>> &getLottieCacheInternal() {
|
|
28
31
|
return _lottieCache;
|
|
29
32
|
};
|
|
@@ -52,8 +55,8 @@ private:
|
|
|
52
55
|
int _height{0};
|
|
53
56
|
bool _initialized{false};
|
|
54
57
|
|
|
55
|
-
std::map<double, sk_sp<SkSVGDOM>> _svgCache;
|
|
56
58
|
std::map<double, sk_sp<skottie::Animation>> _lottieCache;
|
|
59
|
+
std::map<double, std::variant<sk_sp<SkSVGDOM>, sk_sp<SkImage>>> _imageCache;
|
|
57
60
|
|
|
58
61
|
bool isEntityVisible(const Entity &entity, float screenWidth,
|
|
59
62
|
float screenHeight);
|
package/src/GameMethods.nitro.ts
CHANGED
|
@@ -24,7 +24,7 @@ interface GameMethods extends HybridObject<{
|
|
|
24
24
|
|
|
25
25
|
isAssetLoaded(id: number): boolean;
|
|
26
26
|
loadLottie(id: number, jsonStr: string): Promise<boolean>;
|
|
27
|
-
|
|
27
|
+
loadImage(id: number, imageUri: string): Promise<boolean>;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export const gameMethods =
|
package/src/GameMethods.ts
CHANGED
|
@@ -89,9 +89,9 @@ const loadAsset = async (asset: unknown) => {
|
|
|
89
89
|
if (!assetUri) {
|
|
90
90
|
throw new Error(`loadAssets: could not resolve asset URI for ${asset}`);
|
|
91
91
|
}
|
|
92
|
-
const
|
|
93
|
-
if (!
|
|
94
|
-
throw new Error('loadAssets: Failed to load
|
|
92
|
+
const isLoaded = await gameMethods.loadImage(asset, assetUri);
|
|
93
|
+
if (!isLoaded) {
|
|
94
|
+
throw new Error('loadAssets: Failed to load image asset');
|
|
95
95
|
}
|
|
96
96
|
return asset;
|
|
97
97
|
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
package com.margelo.nitro.rngine
|
|
2
|
-
|
|
3
|
-
import androidx.annotation.Keep
|
|
4
|
-
import com.margelo.nitro.NitroModules
|
|
5
|
-
import java.net.URL
|
|
6
|
-
|
|
7
|
-
@Keep
|
|
8
|
-
object SvgLoaderHelper {
|
|
9
|
-
@JvmStatic
|
|
10
|
-
fun loadFromUrl(uri: String): ByteArray {
|
|
11
|
-
return URL(uri).openStream().use { it.readBytes() }
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
@JvmStatic
|
|
15
|
-
fun loadFromResource(uri: String): ByteArray {
|
|
16
|
-
val context = NitroModules.applicationContext
|
|
17
|
-
?: throw IllegalStateException("No Context available!")
|
|
18
|
-
val resId = context.resources.getIdentifier(uri, "raw", context.packageName)
|
|
19
|
-
if (resId == 0) {
|
|
20
|
-
throw IllegalStateException("Could not resolve raw resource for asset: $uri")
|
|
21
|
-
}
|
|
22
|
-
return context.resources.openRawResource(resId).use { it.readBytes() }
|
|
23
|
-
}
|
|
24
|
-
}
|