UNPKG

skynovel

Version:
288 lines (257 loc) 9.57 kB
/* ***** BEGIN LICENSE BLOCK ***** Copyright (c) 2018-2020 Famibee (famibee.blog38.fc2.com) This software is released under the MIT License. http://opensource.org/licenses/mit-license.php ** ***** END LICENSE BLOCK ***** */ import { SysBase } from "./SysBase"; import {CmnLib} from './CmnLib'; import {IConfig, IHTag, IVariable, IMain, HArg, ITag, IFn2Path, IData4Vari} from './CmnInterface'; import {Main} from './Main'; const strLocal = require('store'); import {Application} from 'pixi.js'; import 'devtools-detect'; export class SysWeb extends SysBase { constructor(hPlg = {}, arg = {cur: 'prj/', crypto: false, dip: ''}) { super(hPlg, arg); const idxCur = arg.cur.lastIndexOf('/', arg.cur.length -2); this.def_prj = arg.cur.slice(idxCur +1, -1); // (idxCur == -1) // ? arg.cur.slice(0, -1) // : arg.cur.slice(idxCur +1, -1); window.onload = ()=> { for (const v of document.querySelectorAll('[data-prj]')) { v.addEventListener('click', ()=> { const elm = v.attributes.getNamedItem('data-prj'); if (! elm) return; const prj = elm.value; if (this.now_prj != prj) this.run(prj); }, {passive: true}); } for (const v of document.querySelectorAll('[data-reload]')) { v.addEventListener('click', ()=> this.run(this.now_prj), {passive: true}); } if (arg.dip) CmnLib.hDip = JSON.parse(arg.dip); const sp = new URLSearchParams(location.search); const dip = sp.get('dip'); // ディップスイッチ if (dip) CmnLib.hDip = {...CmnLib.hDip, ...JSON.parse(dip)}; if (! CmnLib.argChk_Boolean(CmnLib.hDip, 'oninit_run', true)) return; this.run(sp.get('cur') ?? ''); } if ('webkitFullscreenEnabled' in document) this.tgl_full_scr = o=> this.regEvt_FullScr( o, //Chrome15+, Safari5.1+, Opera15+ 'webkitRequestFullscreen', 'webkitCancelFullScreen', 'webkitFullscreenElement' ); else if ('mozFullScreenEnabled' in document) this.tgl_full_scr = o=> this.regEvt_FullScr( o, //FF10+ 'mozRequestFullScreen', 'mozCancelFullScreen', 'mozFullScreenElement' ); else if ('msFullscreenEnabled' in document) this.tgl_full_scr = o=> this.regEvt_FullScr( o, //IE11+ 'msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement' ); else if (document['fullscreenEnabled']) this.tgl_full_scr = o=> this.regEvt_FullScr( o, // HTML5 Fullscreen API仕様 'requestFullscreen', 'exitFullscreen', 'fullscreenElement' ); } private def_prj = 'prj'; readonly run = async (prj: string)=> { if (this.main) { const ms_late = 10; // NOTE: ギャラリーでのえもふり/Live 2D用・魔法数字 this.main.destroy(ms_late); await new Promise(r=> setTimeout(r, ms_late)); } this.now_prj = prj || this.def_prj; const idxEnd = this.arg.cur.lastIndexOf('/', this.arg.cur.length -2) +1; const idxStart = this.arg.cur.lastIndexOf('/', idxEnd -2) +1; this.arg.cur = location.href.slice(0, location.href.lastIndexOf('/') +1) + (idxEnd == 0 ?'' :this.arg.cur.slice(idxStart, idxEnd)) + this.now_prj +'/'; this.main = new Main(this); } stop() { if (! this.main) return; this.main.destroy(); this.main = null; } private now_prj = ':'; private main: Main | null; loadPathAndVal(hPathFn2Exts: IFn2Path, fncLoaded: ()=> void, cfg: IConfig): void { (async ()=> { const fn = this.arg.cur +'path.json'; const res = await fetch(fn); if (! res.ok) throw Error(res.statusText); const mes = await res.text(); const json = JSON.parse(await this.pre(fn, mes)); for (const nm in json) { const h = hPathFn2Exts[nm] = json[nm]; for (const ext in h) if (ext != ':cnt') h[ext] = this.arg.cur + h[ext]; } this.ns = cfg.getNs(); fncLoaded(); // ここでnew Variable、clearsysvar()、次にinitVal() })(); } private ns = ''; initVal(data: IData4Vari, hTmp: any, comp: (data: IData4Vari)=> void) { // システム情報 const hn = document.location.hostname; hTmp['const.sn.isDebugger'] = (hn == 'localhost' || hn == '127.0.0.1'); this.val.defTmp('const.sn.displayState', ()=> this.isFullScr()); this.flushSub = this.crypto ? ()=> { strLocal.set(this.ns +'sys_', String(this.enc(JSON.stringify(this.data.sys)))); strLocal.set(this.ns +'mark_', String(this.enc(JSON.stringify(this.data.mark)))); strLocal.set(this.ns +'kidoku_', String(this.enc(JSON.stringify(this.data.kidoku)))); } : ()=> { strLocal.set(this.ns +'sys', this.data.sys); strLocal.set(this.ns +'mark', this.data.mark); strLocal.set(this.ns +'kidoku', this.data.kidoku); }; if (strLocal.get(this.ns +(this.arg.crypto ?'sys_' :'sys')) == undefined) { hTmp['const.sn.isFirstBoot'] = true; this.data.sys = data['sys']; this.data.mark = data['mark']; this.data.kidoku = data['kidoku']; this.flush(); } else { hTmp['const.sn.isFirstBoot'] = false; if (this.crypto) { (async ()=> { let mes = ''; try { mes = 'sys'; // tst sys this.data.sys = JSON.parse( await this.pre('json', strLocal.get(this.ns +'sys_')) ); mes += Number(this.val.getVal('sys:TextLayer.Back.Alpha', 1)); mes = 'mark'; // tst mark this.data.mark = JSON.parse( await this.pre('json', strLocal.get(this.ns +'mark_')) ); mes = 'kidoku'; // tst kidoku this.data.kidoku = JSON.parse( await this.pre('json', strLocal.get(this.ns +'kidoku_')) ); this.val.saveKidoku(); } catch (e) { console.error(`セーブデータ(${mes})が壊れています。一度クリアする必要があります %o`, e); } comp(this.data); })(); return; } else { this.data.sys = strLocal.get(this.ns +'sys'); this.data.mark = strLocal.get(this.ns +'mark'); this.data.kidoku = strLocal.get(this.ns +'kidoku'); } } comp(this.data); } private flushSub = ()=> {}; flush() {this.flushSub();} init(cfg: IConfig, hTag: IHTag, appPixi: Application, val: IVariable, main: IMain): void { super.init(cfg, hTag, appPixi, val, main); if (! cfg.oCfg.debug.devtool) window.addEventListener('devtoolschange', e=> { if (! e.detail.isOpen) return; console.error(`DevToolは禁止されています。許可する場合は【プロジェクト設定】の【devtool】をONに。`); main.destroy(); }); } // URLを開く protected readonly navigate_to: ITag = hArg=> { const url = hArg.url; if (! url) throw '[navigate_to] urlは必須です'; // window.open(url); // 近年セキュリティ的に効かない window.open(url, '_blank'); // 効くがポップアップブロック // location.href = url; // これは効くがSKYNovelが終了してしまう return false; } // タイトル指定 protected readonly title: ITag = hArg=> { const text = hArg.text; if (! text) throw '[title] textは必須です'; document.title = text; for (const v of document.querySelectorAll('[data-title]')) v.textContent = text; return false; } // 全画面状態切替(タグではない手段で提供) private readonly isFullScr = ()=> ('mozFullScreen' in document) ? document['mozFullScreen'] : document.fullscreen; private regEvt_FullScr(hArg: HArg, go_fnc_name: string, exit_fnc_name: string, get_fnc_name: string): boolean { const elm: any = document.body; const doc: any = document; if (! hArg.key) { if (doc[get_fnc_name] != null) doc[exit_fnc_name](); else elm[go_fnc_name](); this.resizeFramesWork(); return false; } const key = hArg.key.toLowerCase(); doc.addEventListener('keydown', (e: KeyboardEvent)=> { const key2 = (e.altKey ?(e.key == 'Alt' ?'' :'alt+') :'') + (e.ctrlKey ?(e.key == 'Control' ?'' :'ctrl+') :'') + (e.shiftKey ?(e.key == 'Shift' ?'' :'shift+') :'') + e.key.toLowerCase(); if (key2 != key) return; e.stopPropagation(); if (doc[get_fnc_name] != null) doc[exit_fnc_name](); else elm[go_fnc_name](); this.resizeFramesWork(); }, {passive: true}); return false; } private resizeFramesWork() { const is_fs = this.isFullScr(); //this.reso4frame = is_fs ?screen.width /CmnLib.stageW :1; // 全画面を使う const ratioWidth = screen.width / CmnLib.stageW; const ratioHeight = screen.height / CmnLib.stageH; const ratio = (ratioWidth < ratioHeight) ?ratioWidth :ratioHeight; this.reso4frame = is_fs ?1 :ratio; // document.body.clientWidth が時々正しい値を返さないのでscreen.widthで this.ofsLeft4frm = is_fs ?0 :(screen.width -CmnLib.stageW *this.reso4frame *CmnLib.cvsScale) /2; this.ofsTop4frm = is_fs ?0 :(screen.height -CmnLib.stageH *this.reso4frame *CmnLib.cvsScale) /2; this.resizeFrames(); } readonly readFile = (path: string, callback: (err: NodeJS.ErrnoException | null, data: Buffer) => void)=> { try { (async ()=> { const res = await fetch(path); //fetch(path, {mode: 'same-origin'}) if (! res.ok) throw Error(res.statusText); callback(null, Buffer.from(await res.text())); })(); } catch (e) { console.error('Error:', e); } /* const FETCH_TIMEOUT = 5000; let didTimeOut = false; const timeout = setTimeout(function() { didTimeOut = true; //reject(new Error('Request timed out')); }, FETCH_TIMEOUT); // '⏰ Time Out' */ }; readonly savePic = (fn: string, data_url: string)=> { const anchor = document.createElement('a'); anchor.href = data_url; anchor.download = fn; const e = document.createEvent('MouseEvent'); e.initEvent('click'); anchor.dispatchEvent(e); if (CmnLib.debugLog) console.log('画像ファイルをダウンロードします'); }; }