Skip to content

Instantly share code, notes, and snippets.

@voidproc
Created August 26, 2023 12:55
Show Gist options
  • Save voidproc/58300ad9f589eaf03270c6c8f5dfe6d9 to your computer and use it in GitHub Desktop.
Save voidproc/58300ad9f589eaf03270c6c8f5dfe6d9 to your computer and use it in GitHub Desktop.
mergeInto(LibraryManager.library, {
$siv3dInputElement: null,
$siv3dDialogFileReader: null,
$siv3dDownloadLink: null,
siv3dInitDialog: function() {
siv3dInputElement = document.createElement("input");
siv3dInputElement.type = "file";
siv3dDialogFileReader = new FileReader();
siv3dDownloadLink = document.createElement("a");
},
siv3dInitDialog__sig: "v",
siv3dInitDialog__deps: [ "$siv3dInputElement", "$siv3dDialogFileReader", "$siv3dDownloadLink" ],
siv3dOpenDialogAsync: function(filterStr, callback, futurePtr, acceptMuilitple) {
siv3dInputElement.accept = UTF8ToString(filterStr);
siv3dInputElement.multiple = !!acceptMuilitple;
function cancelHandler(e) {
{{{ makeDynCall('viii', 'callback') }}}(0, 0, futurePtr);
_siv3dMaybeAwake();
}
// addEventListener を使用する形だと Firefox でも動作する
// once オプションにより、イベントが発生すればハンドラは自動的に削除される
siv3dInputElement.addEventListener('cancel', cancelHandler, { once: true });
siv3dInputElement.oninput = async function(e) {
// cancel イベントが発生しない場合はイベントハンドラを削除する
siv3dInputElement.removeEventListener('cancel', cancelHandler);
// 次回、同じファイルが選択されてもイベントが発火するようにするワークアラウンドのため
// ファイルリストをコピーしておく
const files = [...e.target.files];
e.target.value = '';
if (files.length < 1) {
{{{ makeDynCall('viii', 'callback') }}}(0, 0, futurePtr);
_siv3dMaybeAwake();
return;
}
let filePathes = [];
const sp = stackSave();
for (let file of files) {
await new Promise((resolve) => {
const filePath = "/tmp/" + file.name;
siv3dDialogFileReader.addEventListener("load", function onLoaded() {
FS.writeFile(filePath, new Uint8Array(siv3dDialogFileReader.result));
const namePtr = allocate(intArrayFromString(filePath), ALLOC_STACK);
filePathes.push(namePtr);
siv3dDialogFileReader.removeEventListener("load", onLoaded);
resolve();
});
siv3dDialogFileReader.readAsArrayBuffer(file);
});
}
const filePathesPtr = stackAlloc(filePathes.length * {{{ POINTER_SIZE }}});
for (let i = 0; i < filePathes.length; i++) {
setValue(filePathesPtr + i * {{{ POINTER_SIZE }}}, filePathes[i], "i32");
}
{{{ makeDynCall('viii', 'callback') }}}(filePathesPtr, filePathes.length, futurePtr);
stackRestore(sp);
_siv3dMaybeAwake();
};
siv3dRegisterUserAction(function() {
siv3dInputElement.click();
});
},
siv3dOpenDialogAsync__sig: "vii",
siv3dOpenDialogAsync__deps: [ "$siv3dInputElement", "$siv3dDialogFileReader", "$siv3dRegisterUserAction", "$FS", "siv3dMaybeAwake" ],
$siv3dSaveFileBuffer: null,
$siv3dSaveFileBufferWritePos: 0,
$siv3dDefaultSaveFileName: null,
siv3dDownloadFile: function(filePathPtr, fileNamePtr, mimeTypePtr) {
const filePath = UTF8ToString(filePathPtr);
const fileName = UTF8ToString(fileNamePtr);
const mimeType = mimeTypePtr ? UTF8ToString(mimeTypePtr) : "application/octet-stream";
const fileData = FS.readFile(filePath);
const blob = new Blob([ fileData ], { type: mimeType });
siv3dDownloadLink.href = URL.createObjectURL(blob);
siv3dDownloadLink.download = fileName;
siv3dRegisterUserAction(function() {
siv3dDownloadLink.click();
});
},
siv3dDownloadFile__sig: "viii",
siv3dDownloadFile__deps: [ "$siv3dRegisterUserAction" ],
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment