@next2d/builder 0.1.7 → 0.1.10
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/dist/cli.d.ts +59 -0
- package/dist/cli.js +141 -0
- package/dist/constants.d.ts +53 -0
- package/dist/constants.js +64 -0
- package/dist/context.d.ts +29 -0
- package/dist/context.js +19 -0
- package/dist/electron.d.ts +10 -0
- package/dist/electron.js +142 -0
- package/dist/index.js +18 -754
- package/dist/native.d.ts +27 -0
- package/dist/native.js +123 -0
- package/dist/utils.d.ts +27 -0
- package/dist/utils.js +40 -0
- package/dist/web.d.ts +18 -0
- package/dist/web.js +70 -0
- package/dist/xbox.d.ts +62 -0
- package/dist/xbox.js +426 -0
- package/package.json +12 -9
- package/templates/xbox/CMakeLists.txt +116 -11
- package/templates/xbox/README.md +34 -8
- package/templates/xbox/cmake/FetchDawn.cmake +47 -6
- package/templates/xbox/cmake/FindV8.cmake +15 -0
- package/templates/xbox/js/bootstrap.js +151 -28
- package/templates/xbox/js/selftest.js +740 -90
- package/templates/xbox/src/AssetLoader.cpp +115 -12
- package/templates/xbox/src/AssetLoader.h +4 -0
- package/templates/xbox/src/EmbeddedAssets.cpp +149 -0
- package/templates/xbox/src/EmbeddedAssets.h +60 -0
- package/templates/xbox/src/EventLoop.cpp +13 -1
- package/templates/xbox/src/EventLoop.h +12 -0
- package/templates/xbox/src/bindings/Audio.cpp +211 -31
- package/templates/xbox/src/bindings/Bindings.h +10 -0
- package/templates/xbox/src/bindings/Canvas.cpp +77 -2
- package/templates/xbox/src/bindings/Canvas2D.cpp +496 -43
- package/templates/xbox/src/bindings/Console.cpp +6 -1
- package/templates/xbox/src/bindings/DomShims.cpp +143 -0
- package/templates/xbox/src/bindings/EventTarget.cpp +11 -0
- package/templates/xbox/src/bindings/Fetch.cpp +2 -8
- package/templates/xbox/src/bindings/Image.cpp +243 -15
- package/templates/xbox/src/bindings/Polyfills.cpp +1226 -0
- package/templates/xbox/src/bindings/RasterCore.h +105 -1
- package/templates/xbox/src/bindings/Video.cpp +153 -10
- package/templates/xbox/src/bindings/webgpu/WebGPU.cpp +844 -18
- package/templates/xbox/src/bindings/webgpu/WebGPUCommon.h +7 -9
- package/templates/xbox/src/bindings/webgpu/WebGPUEnums.h +32 -0
- package/templates/xbox/src/gpu/DawnContext.cpp +245 -7
- package/templates/xbox/src/gpu/DawnContext.h +18 -0
- package/templates/xbox/src/main.cpp +459 -8
- package/templates/xbox/src/platform/AudioDecoder.cpp +121 -0
- package/templates/xbox/src/platform/AudioDecoder.h +18 -0
- package/templates/xbox/src/platform/AudioEngine.cpp +37 -6
- package/templates/xbox/src/platform/DecodeQueue.cpp +136 -0
- package/templates/xbox/src/platform/DecodeQueue.h +27 -0
- package/templates/xbox/src/platform/ImageDecoder.cpp +44 -0
- package/templates/xbox/src/platform/ImageDecoder.h +18 -0
- package/templates/xbox/src/platform/StbTextRasterizer.cpp +324 -0
- package/templates/xbox/src/platform/StbTextRasterizer.h +37 -0
- package/templates/xbox/src/platform/TextRasterizer.cpp +32 -0
- package/templates/xbox/src/platform/WicDecoder.cpp +19 -0
- package/templates/xbox/src/v8/CodeCache.h +223 -0
- package/templates/xbox/src/v8/V8Runtime.cpp +76 -11
- package/templates/xbox/src/v8/V8Util.h +79 -0
- package/templates/xbox/src/v8/WeakHandle.h +45 -0
- package/templates/xbox/src/worker/WorkerRuntime.cpp +432 -48
- package/templates/xbox/src/worker/WorkerRuntime.h +43 -13
- package/templates/xbox/tests/check_local.sh +7 -2
- package/templates/xbox/tests/gamecore_api_probe.cpp +172 -0
- package/templates/xbox/tests/raster_test.cpp +50 -0
- package/templates/xbox/tests/windows_platform_test.cpp +75 -3
- package/templates/xbox/third_party/LICENSES.md +14 -0
- package/templates/xbox/third_party/dr_mp3.h +5412 -0
- package/templates/xbox/third_party/dr_wav.h +9131 -0
- package/templates/xbox/third_party/stb_image.h +7988 -0
- package/templates/xbox/third_party/stb_truetype.h +5079 -0
- package/templates/xbox/third_party/stb_vorbis.c +5584 -0
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include <cctype>
|
|
8
8
|
#include <cmath>
|
|
9
9
|
#include <cstdint>
|
|
10
|
+
#include <memory>
|
|
10
11
|
#include <string>
|
|
11
12
|
#include <utility>
|
|
12
13
|
#include <vector>
|
|
@@ -26,10 +27,18 @@ struct SubPath {
|
|
|
26
27
|
|
|
27
28
|
struct RGBA { uint8_t r=0,g=0,b=0,a=255; };
|
|
28
29
|
|
|
29
|
-
//
|
|
30
|
+
// クリップ領域 (デバイス座標)。
|
|
31
|
+
// active=false … 無制限
|
|
32
|
+
// active=true, mask=null … 矩形クリップ [x0,x1) x [y0,y1) (厳密)
|
|
33
|
+
// mask!=null … 任意形状クリップ。x0..y1 は外接矩形 (高速リジェクト用)、
|
|
34
|
+
// mask は surface と同寸のカバレッジ (1=内側/0=外側)。
|
|
35
|
+
// mask は shared_ptr のため save()/restore() の state コピーで安価に共有される
|
|
36
|
+
// (clip() は既存 mask を破壊せず新しい mask を割り当てるので復元が壊れない)。
|
|
30
37
|
struct ClipRect {
|
|
31
38
|
bool active = false;
|
|
32
39
|
double x0 = 0, y0 = 0, x1 = 0, y1 = 0;
|
|
40
|
+
std::shared_ptr<const std::vector<uint8_t>> mask;
|
|
41
|
+
int mask_w = 0, mask_h = 0;
|
|
33
42
|
};
|
|
34
43
|
|
|
35
44
|
// RGBA8 のピクセルバッファ。
|
|
@@ -101,6 +110,9 @@ inline void Blend(Surface& s, const ClipRect& clip, int x, int y, const RGBA& co
|
|
|
101
110
|
{
|
|
102
111
|
if (x < 0 || y < 0 || x >= s.width || y >= s.height) return;
|
|
103
112
|
if (clip.active && (x < clip.x0 || x >= clip.x1 || y < clip.y0 || y >= clip.y1)) return;
|
|
113
|
+
// 任意形状クリップ: マスクの外なら書き込まない。
|
|
114
|
+
if (clip.mask && (x >= clip.mask_w || y >= clip.mask_h ||
|
|
115
|
+
(*clip.mask)[static_cast<size_t>(y) * clip.mask_w + x] == 0)) return;
|
|
104
116
|
size_t i = (static_cast<size_t>(y) * s.width + x) * 4;
|
|
105
117
|
double a = (col.a / 255.0) * alpha;
|
|
106
118
|
s.pixels[i+0] = static_cast<uint8_t>(col.r * a + s.pixels[i+0] * (1 - a));
|
|
@@ -215,6 +227,98 @@ inline void IntersectClip(ClipRect& clip, double nx0, double ny0, double nx1, do
|
|
|
215
227
|
}
|
|
216
228
|
}
|
|
217
229
|
|
|
230
|
+
// パスが単一の軸並行矩形か判定する (矩形なら外接矩形クリップで厳密に足りる)。
|
|
231
|
+
// beginPath→rect() は 4 or 5 点 (閉路点重複) の矩形サブパスになる。
|
|
232
|
+
inline bool IsAxisAlignedRect(const std::vector<SubPath>& path)
|
|
233
|
+
{
|
|
234
|
+
if (path.size() != 1) return false;
|
|
235
|
+
const std::vector<Point>& p = path[0].pts;
|
|
236
|
+
// 末尾が始点と重複する 5 点表現も許容する
|
|
237
|
+
size_t n = p.size();
|
|
238
|
+
if (n == 5 && std::abs(p[4].x - p[0].x) < 1e-6 && std::abs(p[4].y - p[0].y) < 1e-6) {
|
|
239
|
+
n = 4;
|
|
240
|
+
}
|
|
241
|
+
if (n != 4) return false;
|
|
242
|
+
// 各辺が水平または垂直であること
|
|
243
|
+
for (size_t i = 0; i < 4; ++i) {
|
|
244
|
+
const Point& a = p[i];
|
|
245
|
+
const Point& b = p[(i + 1) % 4];
|
|
246
|
+
const bool horizontal = std::abs(a.y - b.y) < 1e-6;
|
|
247
|
+
const bool vertical = std::abs(a.x - b.x) < 1e-6;
|
|
248
|
+
if (!horizontal && !vertical) return false;
|
|
249
|
+
}
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// パスを nonzero winding でカバレッジマスク (surface 同寸, 1=内側) にラスタライズする。
|
|
254
|
+
// スキャンライン規約は FillPath と一致させる (塗りと同じ形にクリップされる)。
|
|
255
|
+
inline std::shared_ptr<std::vector<uint8_t>> RasterizePathMask(
|
|
256
|
+
const std::vector<SubPath>& path, int width, int height)
|
|
257
|
+
{
|
|
258
|
+
auto mask = std::make_shared<std::vector<uint8_t>>(
|
|
259
|
+
static_cast<size_t>(width) * height, 0);
|
|
260
|
+
if (width <= 0 || height <= 0) return mask;
|
|
261
|
+
|
|
262
|
+
double miny = 1e18, maxy = -1e18;
|
|
263
|
+
for (auto& sp : path) for (auto& p : sp.pts) { miny = std::min(miny,p.y); maxy = std::max(maxy,p.y); }
|
|
264
|
+
if (maxy < miny) return mask;
|
|
265
|
+
int y0 = std::max(0, static_cast<int>(std::floor(miny)));
|
|
266
|
+
int y1 = std::min(height - 1, static_cast<int>(std::ceil(maxy)));
|
|
267
|
+
for (int y = y0; y <= y1; ++y) {
|
|
268
|
+
double sy = y + 0.5;
|
|
269
|
+
std::vector<std::pair<double,int>> xs;
|
|
270
|
+
for (auto& sp : path) {
|
|
271
|
+
size_t n = sp.pts.size();
|
|
272
|
+
if (n < 2) continue;
|
|
273
|
+
for (size_t i = 0; i < n; ++i) {
|
|
274
|
+
Point a = sp.pts[i];
|
|
275
|
+
Point b = sp.pts[(i+1) % n];
|
|
276
|
+
if ((a.y <= sy && b.y > sy) || (b.y <= sy && a.y > sy)) {
|
|
277
|
+
double t = (sy - a.y) / (b.y - a.y);
|
|
278
|
+
xs.push_back({a.x + t * (b.x - a.x), a.y < b.y ? 1 : -1});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
std::sort(xs.begin(), xs.end());
|
|
283
|
+
int wind = 0;
|
|
284
|
+
for (size_t i = 0; i + 1 < xs.size(); ++i) {
|
|
285
|
+
wind += xs[i].second;
|
|
286
|
+
if (wind != 0) {
|
|
287
|
+
int xa = std::max(0, static_cast<int>(std::floor(xs[i].first)));
|
|
288
|
+
int xb = std::min(width - 1, static_cast<int>(std::ceil(xs[i+1].first)));
|
|
289
|
+
for (int x = xa; x <= xb; ++x) {
|
|
290
|
+
(*mask)[static_cast<size_t>(y) * width + x] = 1;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return mask;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// 任意形状パスをクリップへ積集合で反映する (非矩形 clip() の実体)。
|
|
299
|
+
// 外接矩形 (高速リジェクト) も同時に反映し、既存 mask があれば AND を取って
|
|
300
|
+
// 新しい mask を割り当てる (save/restore 安全)。
|
|
301
|
+
inline void IntersectClipMask(ClipRect& clip, const std::vector<SubPath>& path,
|
|
302
|
+
int width, int height)
|
|
303
|
+
{
|
|
304
|
+
double minx, miny, maxx, maxy;
|
|
305
|
+
if (PathBounds(path, &minx, &miny, &maxx, &maxy)) {
|
|
306
|
+
IntersectClip(clip, std::floor(minx), std::floor(miny),
|
|
307
|
+
std::ceil(maxx), std::ceil(maxy));
|
|
308
|
+
}
|
|
309
|
+
auto next = RasterizePathMask(path, width, height);
|
|
310
|
+
if (clip.mask) {
|
|
311
|
+
const std::vector<uint8_t>& prev = *clip.mask;
|
|
312
|
+
const size_t n = std::min(next->size(), prev.size());
|
|
313
|
+
for (size_t i = 0; i < n; ++i) {
|
|
314
|
+
if (prev[i] == 0) { (*next)[i] = 0; }
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
clip.mask = next;
|
|
318
|
+
clip.mask_w = width;
|
|
319
|
+
clip.mask_h = height;
|
|
320
|
+
}
|
|
321
|
+
|
|
218
322
|
// 3次ベジェを現在サブパスへフラット化して追記する。p0 は変換済みの直前点。
|
|
219
323
|
inline void FlattenCubic(std::vector<Point>& out,
|
|
220
324
|
Point p0, Point p1, Point p2, Point p3, int steps = 16)
|
|
@@ -13,6 +13,15 @@
|
|
|
13
13
|
#include "ImageSource.h"
|
|
14
14
|
#include "EventTarget.h"
|
|
15
15
|
#include "v8/V8Util.h"
|
|
16
|
+
#include "v8/WeakHandle.h"
|
|
17
|
+
|
|
18
|
+
#include <string>
|
|
19
|
+
#include <vector>
|
|
20
|
+
|
|
21
|
+
// Media Foundation はコンソール (Game Core OS) に無いデスクトップ専用 API。
|
|
22
|
+
// コンソールでは動画デコード未対応 (末尾の «CONSOLE» スタブ)。
|
|
23
|
+
// 実機での動画対応は devkit 段階の課題。
|
|
24
|
+
#if !NEXT2D_XBOX_CONSOLE
|
|
16
25
|
|
|
17
26
|
#include <mfapi.h>
|
|
18
27
|
#include <mfidl.h>
|
|
@@ -20,9 +29,6 @@
|
|
|
20
29
|
#include <shlwapi.h>
|
|
21
30
|
#include <wrl/client.h>
|
|
22
31
|
|
|
23
|
-
#include <string>
|
|
24
|
-
#include <vector>
|
|
25
|
-
|
|
26
32
|
#pragma comment(lib, "mfplat.lib")
|
|
27
33
|
#pragma comment(lib, "mfreadwrite.lib")
|
|
28
34
|
#pragma comment(lib, "mfuuid.lib")
|
|
@@ -47,6 +53,24 @@ struct VideoDecoder {
|
|
|
47
53
|
bool playing = false;
|
|
48
54
|
bool ended = false;
|
|
49
55
|
double duration = 0.0;
|
|
56
|
+
double position = 0.0; // 現在位置 (秒, サンプルタイムスタンプ由来)
|
|
57
|
+
|
|
58
|
+
// 先頭 (または指定秒) へシークする。loop 再生と currentTime 設定で使用。
|
|
59
|
+
bool Seek(double seconds)
|
|
60
|
+
{
|
|
61
|
+
if (!reader) return false;
|
|
62
|
+
PROPVARIANT var;
|
|
63
|
+
PropVariantInit(&var);
|
|
64
|
+
var.vt = VT_I8;
|
|
65
|
+
var.hVal.QuadPart = static_cast<LONGLONG>(seconds * 1e7); // s -> 100ns
|
|
66
|
+
const bool ok = SUCCEEDED(reader->SetCurrentPosition(GUID_NULL, var));
|
|
67
|
+
PropVariantClear(&var);
|
|
68
|
+
if (ok) {
|
|
69
|
+
ended = false;
|
|
70
|
+
position = seconds;
|
|
71
|
+
}
|
|
72
|
+
return ok;
|
|
73
|
+
}
|
|
50
74
|
|
|
51
75
|
bool Open(const std::vector<uint8_t>& bytes)
|
|
52
76
|
{
|
|
@@ -87,13 +111,15 @@ struct VideoDecoder {
|
|
|
87
111
|
{
|
|
88
112
|
if (!reader) return false;
|
|
89
113
|
DWORD flags = 0;
|
|
114
|
+
LONGLONG timestamp = 0;
|
|
90
115
|
ComPtr<IMFSample> sample;
|
|
91
116
|
if (FAILED(reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0,
|
|
92
|
-
nullptr, &flags,
|
|
117
|
+
nullptr, &flags, ×tamp, &sample))) {
|
|
93
118
|
return false;
|
|
94
119
|
}
|
|
95
120
|
if (flags & MF_SOURCE_READERF_ENDOFSTREAM) { ended = true; return false; }
|
|
96
121
|
if (!sample) return false;
|
|
122
|
+
position = static_cast<double>(timestamp) / 1e7; // 100ns -> s
|
|
97
123
|
|
|
98
124
|
ComPtr<IMFMediaBuffer> buffer;
|
|
99
125
|
sample->ConvertToContiguousBuffer(&buffer);
|
|
@@ -112,8 +138,6 @@ struct VideoDecoder {
|
|
|
112
138
|
}
|
|
113
139
|
};
|
|
114
140
|
|
|
115
|
-
void ReleaseVideo(const v8::WeakCallbackInfo<VideoDecoder>& info) { delete info.GetParameter(); }
|
|
116
|
-
|
|
117
141
|
VideoDecoder* Decoder(v8::Local<v8::Object> obj)
|
|
118
142
|
{
|
|
119
143
|
return static_cast<VideoDecoder*>(obj->GetInternalField(0).As<v8::External>()->Value());
|
|
@@ -144,7 +168,10 @@ void LoadVideo(v8::Isolate* isolate, v8::Local<v8::Object> self, const std::stri
|
|
|
144
168
|
SetValue(isolate, self, "videoHeight", v8::Integer::NewFromUnsigned(isolate, dec->height));
|
|
145
169
|
SetValue(isolate, self, "duration", v8::Number::New(isolate, dec->duration));
|
|
146
170
|
SetValue(isolate, self, "readyState", v8::Integer::New(isolate, 4));
|
|
171
|
+
// player は loadedmetadata / progress / canplaythrough を購読する
|
|
172
|
+
// (VideoRegisterEventUseCase)。ローカル読み込みは即完了のため順に発火する。
|
|
147
173
|
FireVideoEvent(isolate, self, "loadedmetadata");
|
|
174
|
+
FireVideoEvent(isolate, self, "progress");
|
|
148
175
|
FireVideoEvent(isolate, self, "canplaythrough");
|
|
149
176
|
} else {
|
|
150
177
|
FireVideoEvent(isolate, self, "error");
|
|
@@ -162,7 +189,20 @@ bool GetVideoFramePixels(v8::Isolate* isolate, v8::Local<v8::Object> obj,
|
|
|
162
189
|
if (dec->playing && !dec->ended) {
|
|
163
190
|
dec->ReadNextFrame(); // 描画のたびに次フレームへ進める(簡易フレーム進行)
|
|
164
191
|
if (dec->ended) {
|
|
165
|
-
|
|
192
|
+
// loop 指定時は先頭へ戻して継続、そうでなければ ended を通知
|
|
193
|
+
v8::Local<v8::Value> loop_v;
|
|
194
|
+
const bool loop =
|
|
195
|
+
obj->Get(isolate->GetCurrentContext(),
|
|
196
|
+
v8util::Str(isolate, "loop")).ToLocal(&loop_v) &&
|
|
197
|
+
loop_v->BooleanValue(isolate);
|
|
198
|
+
if (loop && dec->Seek(0.0)) {
|
|
199
|
+
dec->ReadNextFrame();
|
|
200
|
+
} else {
|
|
201
|
+
dec->playing = false;
|
|
202
|
+
SetValue(isolate, obj, "ended", v8::Boolean::New(isolate, true));
|
|
203
|
+
SetValue(isolate, obj, "paused", v8::Boolean::New(isolate, true));
|
|
204
|
+
FireVideoEvent(isolate, obj, "ended");
|
|
205
|
+
}
|
|
166
206
|
}
|
|
167
207
|
}
|
|
168
208
|
*out_rgba = dec->frame.data();
|
|
@@ -180,19 +220,69 @@ v8::Local<v8::Object> CreateVideoElement(v8::Isolate* isolate, HostContext* /*ho
|
|
|
180
220
|
|
|
181
221
|
auto* dec = new VideoDecoder();
|
|
182
222
|
self->SetInternalField(0, v8::External::New(isolate, dec));
|
|
183
|
-
|
|
184
|
-
handle->SetWeak(dec, ReleaseVideo, v8::WeakCallbackType::kParameter);
|
|
223
|
+
v8util::AttachWeak(isolate, self, dec);
|
|
185
224
|
|
|
186
225
|
SetValue(isolate, self, "__isVideoElement", v8::Boolean::New(isolate, true));
|
|
187
226
|
SetValue(isolate, self, "tagName", Str(isolate, "VIDEO"));
|
|
188
227
|
SetValue(isolate, self, "videoWidth", v8::Integer::New(isolate, 0));
|
|
189
228
|
SetValue(isolate, self, "videoHeight", v8::Integer::New(isolate, 0));
|
|
190
|
-
SetValue(isolate, self, "currentTime", v8::Number::New(isolate, 0));
|
|
191
229
|
SetValue(isolate, self, "readyState", v8::Integer::New(isolate, 0));
|
|
192
230
|
SetValue(isolate, self, "loop", v8::Boolean::New(isolate, false));
|
|
231
|
+
SetValue(isolate, self, "paused", v8::Boolean::New(isolate, true));
|
|
232
|
+
SetValue(isolate, self, "ended", v8::Boolean::New(isolate, false));
|
|
233
|
+
SetValue(isolate, self, "muted", v8::Boolean::New(isolate, false));
|
|
234
|
+
SetValue(isolate, self, "volume", v8::Number::New(isolate, 1.0));
|
|
235
|
+
SetValue(isolate, self, "autoplay", v8::Boolean::New(isolate, false));
|
|
193
236
|
SetValue(isolate, self, "style", v8::Object::New(isolate));
|
|
194
237
|
InstallEventTarget(isolate, self);
|
|
195
238
|
|
|
239
|
+
// currentTime: 取得はデコーダの現在位置、設定はシーク
|
|
240
|
+
self->SetNativeDataProperty(ctx, Str(isolate, "currentTime"),
|
|
241
|
+
[](v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
242
|
+
VideoDecoder* d = Decoder(info.This());
|
|
243
|
+
info.GetReturnValue().Set(
|
|
244
|
+
v8::Number::New(info.GetIsolate(), d ? d->position : 0.0));
|
|
245
|
+
},
|
|
246
|
+
[](v8::Local<v8::Name>, v8::Local<v8::Value> value,
|
|
247
|
+
const v8::PropertyCallbackInfo<void>& info) {
|
|
248
|
+
if (!value->IsNumber()) return;
|
|
249
|
+
VideoDecoder* d = Decoder(info.This());
|
|
250
|
+
if (d) {
|
|
251
|
+
d->Seek(value.As<v8::Number>()->Value());
|
|
252
|
+
}
|
|
253
|
+
}).Check();
|
|
254
|
+
|
|
255
|
+
// setAttribute / getAttribute (player は playsinline を設定する)
|
|
256
|
+
SetMethod(isolate, self, "setAttribute",
|
|
257
|
+
[](const v8::FunctionCallbackInfo<v8::Value>& a) {
|
|
258
|
+
if (a.Length() < 2) return;
|
|
259
|
+
v8::Isolate* iso = a.GetIsolate();
|
|
260
|
+
v8::Local<v8::Context> c = iso->GetCurrentContext();
|
|
261
|
+
v8::Local<v8::Value> attrs;
|
|
262
|
+
v8::Local<v8::Object> store;
|
|
263
|
+
if (a.This()->Get(c, v8util::Str(iso, "__attrs")).ToLocal(&attrs) && attrs->IsObject()) {
|
|
264
|
+
store = attrs.As<v8::Object>();
|
|
265
|
+
} else {
|
|
266
|
+
store = v8::Object::New(iso);
|
|
267
|
+
SetValue(iso, a.This(), "__attrs", store);
|
|
268
|
+
}
|
|
269
|
+
store->Set(c, a[0], a[1]).Check();
|
|
270
|
+
});
|
|
271
|
+
SetMethod(isolate, self, "getAttribute",
|
|
272
|
+
[](const v8::FunctionCallbackInfo<v8::Value>& a) {
|
|
273
|
+
a.GetReturnValue().SetNull();
|
|
274
|
+
if (a.Length() < 1) return;
|
|
275
|
+
v8::Isolate* iso = a.GetIsolate();
|
|
276
|
+
v8::Local<v8::Context> c = iso->GetCurrentContext();
|
|
277
|
+
v8::Local<v8::Value> attrs;
|
|
278
|
+
if (a.This()->Get(c, v8util::Str(iso, "__attrs")).ToLocal(&attrs) && attrs->IsObject()) {
|
|
279
|
+
v8::Local<v8::Value> v;
|
|
280
|
+
if (attrs.As<v8::Object>()->Get(c, a[0]).ToLocal(&v) && !v->IsUndefined()) {
|
|
281
|
+
a.GetReturnValue().Set(v);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
196
286
|
// src セッター: 代入で読み込み開始
|
|
197
287
|
self->SetNativeDataProperty(ctx, Str(isolate, "src"),
|
|
198
288
|
[](v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
@@ -218,12 +308,16 @@ v8::Local<v8::Object> CreateVideoElement(v8::Isolate* isolate, HostContext* /*ho
|
|
|
218
308
|
SetMethod(isolate, self, "play", [](const v8::FunctionCallbackInfo<v8::Value>& a) {
|
|
219
309
|
v8::Isolate* iso = a.GetIsolate();
|
|
220
310
|
Decoder(a.This())->playing = true;
|
|
311
|
+
SetValue(iso, a.This(), "paused", v8::Boolean::New(iso, false));
|
|
312
|
+
SetValue(iso, a.This(), "ended", v8::Boolean::New(iso, false));
|
|
221
313
|
auto r = v8::Promise::Resolver::New(iso->GetCurrentContext()).ToLocalChecked();
|
|
222
314
|
r->Resolve(iso->GetCurrentContext(), v8::Undefined(iso)).Check();
|
|
223
315
|
a.GetReturnValue().Set(r->GetPromise());
|
|
224
316
|
});
|
|
225
317
|
SetMethod(isolate, self, "pause", [](const v8::FunctionCallbackInfo<v8::Value>& a) {
|
|
318
|
+
v8::Isolate* iso = a.GetIsolate();
|
|
226
319
|
Decoder(a.This())->playing = false;
|
|
320
|
+
SetValue(iso, a.This(), "paused", v8::Boolean::New(iso, true));
|
|
227
321
|
});
|
|
228
322
|
SetMethod(isolate, self, "canPlayType", [](const v8::FunctionCallbackInfo<v8::Value>& a) {
|
|
229
323
|
a.GetReturnValue().Set(Str(a.GetIsolate(), "maybe"));
|
|
@@ -233,3 +327,52 @@ v8::Local<v8::Object> CreateVideoElement(v8::Isolate* isolate, HostContext* /*ho
|
|
|
233
327
|
}
|
|
234
328
|
|
|
235
329
|
} // namespace next2d
|
|
330
|
+
|
|
331
|
+
#else // NEXT2D_XBOX_CONSOLE
|
|
332
|
+
|
|
333
|
+
// «CONSOLE» 動画デコード未対応スタブ。
|
|
334
|
+
// createElement('video') がクラッシュしないよう API 形状だけ提供する
|
|
335
|
+
// (フレーム取得は常に false、canPlayType は空 = 非対応を正しく通知)。
|
|
336
|
+
namespace next2d {
|
|
337
|
+
|
|
338
|
+
using v8util::Str;
|
|
339
|
+
using v8util::SetMethod;
|
|
340
|
+
using v8util::SetValue;
|
|
341
|
+
|
|
342
|
+
bool GetVideoFramePixels(v8::Isolate*, v8::Local<v8::Object>,
|
|
343
|
+
const uint8_t** out_rgba, uint32_t* out_width, uint32_t* out_height)
|
|
344
|
+
{
|
|
345
|
+
*out_rgba = nullptr;
|
|
346
|
+
*out_width = 0;
|
|
347
|
+
*out_height = 0;
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
v8::Local<v8::Object> CreateVideoElement(v8::Isolate* isolate, HostContext* /*host*/)
|
|
352
|
+
{
|
|
353
|
+
v8::Local<v8::Object> self = v8::Object::New(isolate);
|
|
354
|
+
SetValue(isolate, self, "__isVideoElement", v8::Boolean::New(isolate, true));
|
|
355
|
+
SetValue(isolate, self, "tagName", Str(isolate, "VIDEO"));
|
|
356
|
+
SetValue(isolate, self, "localName", Str(isolate, "video"));
|
|
357
|
+
SetValue(isolate, self, "videoWidth", v8::Integer::New(isolate, 0));
|
|
358
|
+
SetValue(isolate, self, "videoHeight", v8::Integer::New(isolate, 0));
|
|
359
|
+
SetValue(isolate, self, "paused", v8::Boolean::New(isolate, true));
|
|
360
|
+
SetValue(isolate, self, "ended", v8::Boolean::New(isolate, false));
|
|
361
|
+
InstallEventTarget(isolate, self);
|
|
362
|
+
SetMethod(isolate, self, "load", [](const v8::FunctionCallbackInfo<v8::Value>&) {});
|
|
363
|
+
SetMethod(isolate, self, "play", [](const v8::FunctionCallbackInfo<v8::Value>& a) {
|
|
364
|
+
v8::Isolate* iso = a.GetIsolate();
|
|
365
|
+
auto r = v8::Promise::Resolver::New(iso->GetCurrentContext()).ToLocalChecked();
|
|
366
|
+
r->Resolve(iso->GetCurrentContext(), v8::Undefined(iso)).Check();
|
|
367
|
+
a.GetReturnValue().Set(r->GetPromise());
|
|
368
|
+
});
|
|
369
|
+
SetMethod(isolate, self, "pause", [](const v8::FunctionCallbackInfo<v8::Value>&) {});
|
|
370
|
+
SetMethod(isolate, self, "canPlayType", [](const v8::FunctionCallbackInfo<v8::Value>& a) {
|
|
371
|
+
a.GetReturnValue().Set(Str(a.GetIsolate(), ""));
|
|
372
|
+
});
|
|
373
|
+
return self;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
} // namespace next2d
|
|
377
|
+
|
|
378
|
+
#endif // !NEXT2D_XBOX_CONSOLE
|