From 5ed031cb6a07cbb8ee144daa3b88056816b9f726 Mon Sep 17 00:00:00 2001 From: firebingo Date: Sat, 21 Apr 2018 12:53:55 -0700 Subject: [PATCH] Language selection. Gulpfile --- .gitignore | 1 + Css/main.css | 27 +++++++++++++++++--- Js/Main.js | 62 +++++++++++++++++++++++++++++++++++---------- Js/Player.js | 2 +- Js/TextFunctions.js | 11 +++++++- Js/UtageParse.js | 30 ++++++++++++++++------ Js/XduPlayer.min.js | 1 + Player.html | 9 ++++--- gulpfile.js | 24 ++++++++++++++++++ 9 files changed, 135 insertions(+), 32 deletions(-) create mode 100644 Js/XduPlayer.min.js create mode 100644 gulpfile.js diff --git a/.gitignore b/.gitignore index c4b39bc..8c3896e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ / web.config /Js/Typed +/node_modules diff --git a/Css/main.css b/Css/main.css index a618643..813b0f8 100644 --- a/Css/main.css +++ b/Css/main.css @@ -39,6 +39,19 @@ src: url(../Fonts/SourceCodePro-Regular.woff2) format('woff'); } +@-webkit-keyframes smallbounce { + from { transform: translate(0, 5px); } + to { transform: translate(0, -5px); } +} +@-moz-keyframes smallbounce { + from { transform: translate(0, 5px); } + to { transform: translate(0, -5px); } +} +@keyframes smallbounce { + from { transform: translate(0, 5px); } + to { transform: translate(0, -5px); } +} + .centered { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; } .hidden { opacity: 0; } @@ -75,7 +88,7 @@ #dialog #dialog-controls { position: fixed; right: 0; display: flex; height: 135px; align-items: center; } -#dialog-controls #dialog-next { margin-right: 37px; } +#dialog-controls #dialog-next { margin-right: 37px; animation: smallbounce 0.5s ease-in-out 0s infinite alternate; } #dialog-next img { height: 80px; } @@ -85,10 +98,16 @@ #dialog-scroll img { height: 35px; } -#other-controls-container { display: flex; width: 100; justify-content: center; } +#other-controls-container { display: flex; width: 550px; justify-content: center; } -#select-mission { max-width: 300px; } +#select-mission { min-width: 0; } + +#select-language { margin-left: 10px; } #volume-control { display: flex; margin-right: 10px; } -#volume-control #mute-button { cursor: pointer; } \ No newline at end of file +#volume-control #mute-button { cursor: pointer; } + +@media screen and (max-width: 550px) { + #other-controls-container { width: 100vw; } +} \ No newline at end of file diff --git a/Js/Main.js b/Js/Main.js index 6d45bfc..acc8c92 100644 --- a/Js/Main.js +++ b/Js/Main.js @@ -14,6 +14,7 @@ const languages = ["eng", "jpn"]; let bodyLoaded = false; let utageLoaded = false; let selectedLang = "eng"; +let currentMission = undefined; let screenw = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); let screenh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); let screenSizeTimeout = undefined; @@ -40,19 +41,7 @@ function onBodyLoaded() { (function checkIsLoaded() { if(bodyLoaded) { document.getElementById('loading-font').style.cssText = "display: none;"; - volume = localStorage.getItem('volume') || 0.5; - volume = Number(volume); - audio.changeVolume(volume); - document.getElementById('volume-range').value = volume * 100; - isMuted = localStorage.getItem('ismuted') || false; - if(isMuted === "false") { isMuted = false; } - else if(isMuted === "true") { isMuted = true; } - audio.mute(isMuted); - if(isMuted) { - document.getElementById('mute-button').innerText = "πŸ”‡"; - } else { - document.getElementById('mute-button').innerText = "πŸ”Š"; - } + loadLocalStorage(); } if(utageLoaded) { document.getElementById('loading-utage').style.cssText = "display: none;"; @@ -68,6 +57,7 @@ function onBodyLoaded() { function onAllLoaded(success) { textFunc.findTextElements(); buildMissionSelectList(); + buildLanguageList(); let appContainer = document.getElementById('app-container'); appContainer.appendChild(pixiApp.app.view); setTimeout(() => { @@ -77,6 +67,28 @@ function onAllLoaded(success) { }, 0); } +function loadLocalStorage() { + //audio + volume = localStorage.getItem('volume') || 0.5; + volume = Number(volume); + audio.changeVolume(volume); + document.getElementById('volume-range').value = volume * 100; + isMuted = localStorage.getItem('ismuted') || false; + if(isMuted === "false") { isMuted = false; } + else if(isMuted === "true") { isMuted = true; } + audio.mute(isMuted); + if(isMuted) { + document.getElementById('mute-button').innerText = "πŸ”‡"; + } else { + document.getElementById('mute-button').innerText = "πŸ”Š"; + } + //language + let lang = localStorage.getItem('language') || "eng"; + if(languages.includes(lang)) { + selectedLang = lang; + } +} + function buildMissionSelectList() { let selectBox = document.getElementById('select-mission'); selectBox.innerHTML = ''; @@ -97,13 +109,26 @@ function buildMissionSelectList() { } } +function buildLanguageList() { + let selectBox = document.getElementById('select-language'); + selectBox.innerHTML = ''; + for(let i = 0; i < languages.length; ++i) { + let opt = document.createElement('option'); + opt.setAttribute('value', languages[i]); + opt.innerText = languages[i]; + selectBox.appendChild(opt); + } + selectBox.value = selectedLang; +} + function missionChanged(event) { if(!event || !event.currentTarget || !event.currentTarget.value || event.currentTarget.value === '{Select}') { return; } let newMission = utage.availableMissions[event.currentTarget.value.split('|')[0]]; + currentMission = newMission; let promises = [ utage.parseMissionFile(`${utage.rootDirectory}XDUData/${newMission.Path.replace('Asset/', '').replace('.utage', '').replace('.tsv', '_t.tsv')}`), - utage.loadMissionTranslation(`${utage.rootDirectory}XDUData/${newMission.Path.replace('Asset/', '').replace('.utage', '').replace('.tsv', `_translations_${selectedLang}.json`)}`), + utage.loadMissionTranslation(`${utage.rootDirectory}XDUData/${newMission.Path.replace('Asset/', '').replace('.utage', '').replace('.tsv', `_translations_${selectedLang}.json`)}`, selectedLang), player.resetAll() ]; @@ -112,16 +137,25 @@ function missionChanged(event) { let res = player.playFile() .then((success) => { player.resetAll(); + currentMission = undefined; debugger; }, (failure) => { debugger; + currentMission = undefined; console.log(failure); }); }, (failure) => { + currentMission = undefined; console.log(failure); }); } +function languageChanged(event) { + if(!event || !event.currentTarget || !event.currentTarget.value || event.currentTarget.value === '{Select}' || !languages.includes(event.currentTarget.value)) { return; } + selectedLang = event.currentTarget.value; + utage.loadMissionTranslation(`${utage.rootDirectory}XDUData/${currentMission.Path.replace('Asset/', '').replace('.utage', '').replace('.tsv', `_translations_${selectedLang}.json`)}`, selectedLang); +} + function onMainClick(event) { player.onMainClick(event); } diff --git a/Js/Player.js b/Js/Player.js index 55e5b0c..87bc6a9 100644 --- a/Js/Player.js +++ b/Js/Player.js @@ -284,7 +284,6 @@ class Player { default: { let newValue = commonFunctions.lerp(l.initV, l.finalV, pos, inter); let split = l.type.split("."); - if(split[0] == 'scale') { debugger; } switch(split.length) { case 1: l.object[split[0]] = newValue; @@ -805,6 +804,7 @@ class Player { this.playingVoice = undefined; this.text.resetAll(); this.audio.resetAll(); + this.utage.resetTranslations(); resolve(); } catch (error) { reject(error); diff --git a/Js/TextFunctions.js b/Js/TextFunctions.js index 36f5a87..860b16a 100644 --- a/Js/TextFunctions.js +++ b/Js/TextFunctions.js @@ -8,12 +8,13 @@ class TextFunctions { this.dialogBox = undefined; this.character = undefined; this.dialog = undefined; + this.textScrollSpeedMs = 35; this.scrollControls = undefined; this.nextIndicator = undefined; this.dialogToDisplay = {timeout: undefined, fullText: "", text: "", curPos: 0}; - this.textScrollSpeedMs = 40; this.scrollingText = false; this.lineHeight = -1; + this.textHistory = []; } findTextElements() { @@ -67,6 +68,7 @@ class TextFunctions { } else { this.dialogToDisplay.text = text; this.dialogToDisplay.fullText = text; + this.textHistory.push({ character: this.character.innerHTML, text: text }); this.dialogToDisplay.curPos = 0; this.dialogInner.innerHTML = ""; //this.dialogInner.innerHTML = this.dialogToDisplay.text[0]; @@ -180,5 +182,12 @@ class TextFunctions { this.dialogBox.classList.add('hidden'); this.scrollControls.classList.add('hidden'); this.nextIndicator.classList.add('hidden'); + this.textHistory.length = 0; + if(this.dialogToDisplay.timeout) { + clearTimeout(this.dialogToDisplay.timeout); + } + this.dialogToDisplay = {timeout: undefined, fullText: "", text: "", curPos: 0}; + this.scrollingText = false; + this.lineHeight = -1; } } \ No newline at end of file diff --git a/Js/UtageParse.js b/Js/UtageParse.js index 9261bee..8b622b8 100644 --- a/Js/UtageParse.js +++ b/Js/UtageParse.js @@ -13,6 +13,7 @@ class UtageInfo { this.paramInfo = {}; this.soundInfo = {}; this.textureInfo = {}; + this.translations = {}; this.currentTranslation = {}; this.bgmLoopData = {}; } @@ -77,16 +78,24 @@ class UtageInfo { }); } - loadMissionTranslation(file) { + loadMissionTranslation(file, key) { return new Promise((resolve, reject) => { - commonFunctions.getFileJson(file) - .then((success) => { - this.currentTranslation = success; + if(this.translations[key]) { + debugger; + this.currentTranslation = this.translations[key]; resolve(); - }, (failure) => { - this.currentTranslation = {}; - resolve(); - }); + } else { + commonFunctions.getFileJson(file) + .then((success) => { + debugger; + this.translations[key] = success; + this.currentTranslation = success; + resolve(); + }, (failure) => { + this.currentTranslation = {}; + resolve(); + }); + } }); } @@ -229,4 +238,9 @@ class UtageInfo { } } } + + resetTranslations() { + this.translations = {}; + this.currentTranslation = {}; + } } \ No newline at end of file diff --git a/Js/XduPlayer.min.js b/Js/XduPlayer.min.js new file mode 100644 index 0000000..11194a3 --- /dev/null +++ b/Js/XduPlayer.min.js @@ -0,0 +1 @@ +"use strict";let rootUrl=`${window.location.protocol}//${window.location.host}/`;const screenRatio=9/16;class commonFunctions{static getFileText(e){return new Promise((t,i)=>{try{fetch(e).then(e=>{200===e.status?e.text().then(e=>{t(e)}):i(e)},e=>{i(e)})}catch(e){i(e)}})}static getFileJson(e){return new Promise((t,i)=>{try{fetch(e).then(e=>{200===e.status?e.json().then(e=>{t(e)}):i(e)},e=>{i(e)})}catch(e){i(e)}})}static readLine(e,t){if(e.startsWith("//"))return{comment:e};if(e){let i=e.split("\t"),s={};for(let e=0;e|<\/speed>/g,"")).replace(/\\n/g,"
")).match(//g);if(t)for(let i=0;i"===s[e]&&(r=!1,n=!0),r&&(a+=s[e]),"="===s[e]&&(r=!0);e=e.replace(s,`${o}${a}`)}return e}static getNewResolution(e,t,i,s){let a={width:0,height:0};if(t>=i){let o=(i-(s||0))/e.height;a.height=e.height*o,a.width=e.width*o,a.width>t&&(o=t/e.width,a.height=e.height*o,a.width=e.width*o)}else if(i>t){let i=t/e.width;a.height=e.height*i,a.width=e.width*i}return a}static getAnchorFromCharPivot(e){let t=.5,i=.5,s=e.split(" ");for(let e of s)e.startsWith("x=")?t=Number(e.substring(2)):e.startsWith("y=")&&(i=1-(i=Number(e.substring(2))));return{x:t,y:i}}static getPropertiesFromTweenCommand(e,t=!0){var i={};let s=e.indexOf("x=");if(-1!==s){i.x="";for(let t=s+2;tt+5&&(this.dialog.scrollTop=this.dialogInner.offsetHeight-t,this.showScrollControls(!0))}this.dialogToDisplay.timeout=setTimeout(e.bind(this),this.textScrollSpeedMs)}.bind(this),this.textScrollSpeedMs))),this.mainUi.classList.toggle("hidden",!e),this.dialogBox.classList.toggle("hidden",!e)}showDialogFullText(){this.dialogToDisplay.timeout&&(clearTimeout(this.dialogToDisplay.timeout),this.dialogToDisplay.timeout=void 0),this.dialogInner.innerHTML=this.dialogToDisplay.fullText;let e=2*this.lineHeight;this.dialogInner.offsetHeight>e+5&&(this.dialog.scrollTop=this.dialogInner.offsetHeight-e,this.showScrollControls(!0)),this.showNextIndicator(!0),this.scrollingText=!1}typeHtmlChars(e,t){const i=e.substr(t).charAt(0);if("<"===i||"&"===i){let s="";for(s="<"===i?">":";";e.substr(t+1).charAt(0)!==s&&!(++t+1>e.length););t++}return t}showScrollControls(e){this.scrollControls.classList.toggle("hidden",!e)}scrollTextUp(){let e=2*this.lineHeight,t=this.dialog.scrollTop-e;t<0&&(t=0),this.dialog.scrollTop=t}scrollTextDown(){let e=2*this.lineHeight,t=this.dialog.scrollTop+e;t>this.dialogInner.offsetHeight-e&&(t=this.dialogInner.offsetHeight-e),this.dialog.scrollTop=t}showNextIndicator(e){this.nextIndicator.classList.toggle("hidden",!e)}hideUi(e){this.mainUi.classList.toggle("hidden",!e),this.dialogBox.classList.toggle("hidden",!e),this.character.classList.toggle("hidden",!e)}resetAll(){this.title.innerHTML="",this.diva.innerHTML="",this.character.innerHTML="",this.dialogInner.innerHTML="",this.title.classList.add("hidden"),this.diva.classList.add("hidden"),this.mainUi.classList.add("hidden"),this.character.classList.add("hidden"),this.dialogBox.classList.add("hidden"),this.scrollControls.classList.add("hidden"),this.nextIndicator.classList.add("hidden"),this.textHistory.length=0,this.dialogToDisplay.timeout&&clearTimeout(this.dialogToDisplay.timeout),this.dialogToDisplay={timeout:void 0,fullText:"",text:"",curPos:0},this.scrollingText=!1,this.lineHeight=-1}}class UtageInfo{constructor(){this.currentPlayingFile=[],this.rootDirectory=`${rootUrl}XDUPlayer/`,this.availableMissions={},this.missionsList=[],this.characterInfo={},this.layerInfo={},this.localizeInfo={},this.paramInfo={},this.soundInfo={},this.textureInfo={},this.translations={},this.currentTranslation={},this.bgmLoopData={}}loadUtageSettings(e,t){return new Promise((e,t)=>{let i=[commonFunctions.getFileJson(`${this.rootDirectory}Js/XduMissions.json`),commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Character.tsv`),commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Layer.tsv`),commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Localize.tsv`),commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Param.tsv`),commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Sound.tsv`),commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Texture.tsv`),commonFunctions.getFileJson(`${this.rootDirectory}Js/bgmLoop.json`)];Promise.all(i).then(t=>{this.availableMissions=t[0],this.missionsList=Object.keys(this.availableMissions).map(e=>`${this.availableMissions[e].Id}|${this.availableMissions[e].Name}`),this.missionsList.sort(),this.parseCharacterInfo(t[1]),this.parseLayerInfo(t[2]),this.parseLocalizeInfo(t[3]),this.parseParamInfo(t[4]),this.parseSoundInfo(t[5]),this.parseTextureInfo(t[6]),this.bgmLoopData=t[7],e()},e=>{t(e)})})}parseMissionFile(e){return new Promise((t,i)=>{commonFunctions.getFileText(e).then(e=>{let i=e.split("\n"),s=[];for(let e=0;e{i(e)})})}loadMissionTranslation(e,t){return new Promise((i,s)=>{this.translations[t]?(this.currentTranslation=this.translations[t],i()):commonFunctions.getFileJson(e).then(e=>{this.translations[t]=e,this.currentTranslation=e,i()},e=>{this.currentTranslation={},i()})})}parseCharacterInfo(e){let t=e.split("\n"),i=[],s="",a="";for(let e=0;e{try{fetch(e).then(a=>{if(200!==a.status)return this.onloadUpdate&&this.onloadUpdate(++this.loadCount/this.soundMap.length*100),void s(a);a.arrayBuffer().then(a=>{this.context.decodeAudioData(a,a=>{a||s("error decoding file data: "+e),this.bufferList[t]=a,this.onloadUpdate&&this.onloadUpdate(++this.loadCount/this.soundMap.length*100),i(`${this.loadCount}|${this.soundMap.length}`)},function(i){console.log(i),console.log(`url: ${e}, name: ${t}`),this.onloadUpdate&&this.onloadUpdate(++this.loadCount/this.soundMap.length*100),s(i)})})},e=>{console.log(e),s(e)})}catch(e){console.log(e),s(e)}})}resetAll(){this.bufferList={}}}class audioController{constructor(e){this.utage=e,this.volume=1,this.muted=!1,this.audioCtx=new(window.AudioContext||window.webkitAudioContext),this.gainNode=this.audioCtx.createGain(),this.gainNode.connect(this.audioCtx.destination),this.loader=void 0,this.sources={}}playSound(e,t){if(!this.loader.bufferList[e])return;let i=this.audioCtx.createBufferSource();if(this.sources[e]=i,i.buffer=this.loader.bufferList[e],i.loop=!1,"bgm"===t&&this.utage.bgmLoopData[this.utage.soundInfo[e].origFileName]){let t=this.utage.bgmLoopData[this.utage.soundInfo[e].origFileName];i.loopStart=t.loop_start.seconds,i.loopEnd=t.loop_end.seconds,i.loop=!0}i.connect(this.gainNode),i.onended=(()=>{this.sources[e]&&(this.sources[e].disconnect(this.gainNode),this.sources[e]=void 0)}),i.start(0)}stopSound(e){if("bgm"===e)for(let e of Object.keys(this.sources))try{if(!e.startsWith("bgm"))continue;let t=this.sources[e];t.stop(),t.disconnect(this.gainNode),t=void 0}catch(e){}else{if(!this.sources[e])return;this.sources[e].stop(),this.sources[e].disconnect(this.gainNode),this.sources[e]=void 0}}changeVolume(e){this.volume=(Math.exp(e)-1)/(Math.E-1),this.muted||this.gainNode.gain.setValueAtTime(this.volume,this.audioCtx.currentTime)}mute(e){this.muted=void 0!=e?e:!this.muted,this.muted?this.gainNode.gain.setValueAtTime(0,this.audioCtx.currentTime):this.gainNode.gain.setValueAtTime(this.volume,this.audioCtx.currentTime)}loadSounds(e,t){this.loader=new bufferLoader(this.audioCtx,e,e=>{t&&t(e)}),this.loader.load()}resetAll(){this.loader&&(this.loader.resetAll(),this.loader=void 0);for(let e of Object.keys(this.sources)){let t=this.sources[e];try{t.stop(),t.disconnect(this.gainNode),t=void 0}catch(e){}}this.sources={}}}const baseDimensions={width:1334,height:750};class Player{constructor(e,t,i,s){this.pixi=e,this.loader=e.loader,this.utage=t,this.text=i,this.audio=s,this.resolutionScale=1,this.baseFps=60,this.bgLayerName="θƒŒζ™―",this.defaultCharPattern="すまし",this.backCharTint=8421504,this.titleWaitTime=1,this.blackBackSp=void 0,this.currentCharacters={},this.lastCharOffLayer=void 0,this.layers={},this.sprites={},this.currentCommand=void 0,this.runEvent=!1,this.secondTicker=1e3,this.waitTime=0,this.lerpTargets=[],this.manualNext=!1,this.hasMoreText=!1,this.uiHidden=!1,this.center={x:baseDimensions.width/2*this.resolutionScale,y:baseDimensions.height/2*this.resolutionScale},this.assetLoadPercent=0,this.audioLoadPercent=0,this.playingVoice=void 0}playFile(){let e=new Promise((e,t)=>{this.resolve=e,this.reject=t});return this.preCheckFilesToGet().then(e=>{this.pixi.app.ticker.add(this.onPixiTick,this)},e=>{console.log(e)}),e}preCheckFilesToGet(){return new Promise((e,t)=>{let i={},s={};for(let e=0;e"!=e?this.loader.resources[`char|${t.Arg1}|${e}`]||this.loader.add(`char|${t.Arg1}|${e}`,this.utage.characterInfo[t.Arg1][e].FileName):!t.Arg1||!e||""==e||this.utage.characterInfo[t.Arg1]&&this.utage.characterInfo[t.Arg1][e]||console.log(`Failed to get Character: ${t.Arg1}|${e}`),t.Voice){let e=t.Voice;if(e.includes(",")){let t=e.split(",");e=`${t[0].split("_").join("/")}/${t[1]}`}e=`${this.utage.rootDirectory}XDUData/Voice/${e}.opus`,s[t.Voice]||(s[t.Voice]={Label:t.Voice,FileName:e})}break;case"bgm":this.utage.soundInfo[t.Arg1]?i[t.Arg1]||(i[t.Arg1]=this.utage.soundInfo[t.Arg1]):console.log(`Failed to get BGM: ${t.Arg1}`);break;case"se":this.utage.soundInfo[t.Arg1]?s[t.Arg1]||(s[t.Arg1]=this.utage.soundInfo[t.Arg1]):console.log(`Failed to get SE: ${t.Arg1}`)}}catch(e){console.log(e);continue}let a=[];for(let e of Object.keys(i))a.push(i[e]);for(let e of Object.keys(s))a.push(s[e]);this.audio.loadSounds(a,e=>{this.onAudioProgress(e)}),this.loader.add("bg|whiteFade",`${this.utage.rootDirectory}Images/white.png`),this.loader.on("progress",(e,t)=>{this.onPixiProgress(e,t)}).load(()=>{this.onPixiLoad(e,t)})})}buildLayerContainers(){let e=[];for(let t of Object.keys(this.utage.layerInfo))e.push(this.utage.layerInfo[t]);e.sort(function(e,t){return e.Order-t.Order});let t=new PIXI.Container;t.position.set(this.center.x,this.center.y),t.pivot.set(this.center.x,this.center.y),this.pixi.app.stage.addChild(t),this.layers["bg|mainparent"]={container:t};for(let i of e){this.layers[i.LayerName]={info:i};let e=new PIXI.Container;this.layers[i.LayerName].container=e,t.addChild(e);let s=(baseDimensions.width/2+Number(i.X))*this.resolutionScale,a=(baseDimensions.height/2-Number(i.Y))*this.resolutionScale;e.position.set(s,a),e.visible=!1}let i=new PIXI.Container,s=new PIXI.Sprite(this.loader.resources["bg|whiteFade"].texture);s.height=baseDimensions.height*this.resolutionScale,s.width=baseDimensions.width*this.resolutionScale,this.layers["bg|whiteFade"]={info:void 0,sprite:s,container:i},s.alpha=0,i.addChild(s),this.pixi.app.stage.addChild(i)}onPixiProgress(e,t){this.assetLoadPercent=e.progress,this.text.titleText(!0,`Loading Assets... ${e.progress.toFixed(0)}%`),this.onLoadProgressUpdate()}onAudioProgress(e){this.audioLoadPercent=e,this.onLoadProgressUpdate()}onLoadProgressUpdate(){let e=this.audioLoadPercent/2+this.assetLoadPercent/2;this.text.titleText(!0,`Loading Assets... ${e.toFixed(0)}%`)}onPixiLoad(e,t){100===this.audioLoadPercent?(this.text.titleText(!1,""),setTimeout(()=>{this.runEvent=!0,this.buildLayerContainers(),e()},1e3)):setTimeout(()=>{this.onPixiLoad(e,t)},100)}onPixiTick(e){try{if(!this.runEvent)return;let t=1e3/this.baseFps*e;this.secondTicker-=t,this.waitTime>=0&&(this.waitTime-=t),this.loopHandleLerps(t),this.currentCommand&&this.waitTime<=0&&!this.manualNext&&this.processEndCommand(e),this.currentCommand||this.getNextCommand(),this.currentCommand&&!this.manualNext&&this.waitTime<=0&&this.processCommand(e),this.secondTicker<0&&(this.secondTicker=1e3)}catch(e){console.log(e)}}loopHandleLerps(e){try{let t=[];for(let i=0;i=1&&(o=1,t.push(i),"destroy"===s.post)){s.object.destroy();continue}switch(s.type){case"shake":if(1===o)s.object instanceof HTMLElement?s.object.style="":s.object.position.set(s.initV.x,s.initV.y);else{let e=Math.floor(Math.random()*(s.finalV.x*(1-o))),t=Math.floor(Math.random()*(s.finalV.y*(1-o)));s.object instanceof HTMLElement?s.object.style=`transform: translate(${e}px, ${t}px);`:s.object.position.set(e,t)}break;default:{let e=commonFunctions.lerp(s.initV,s.finalV,o,a),t=s.type.split(".");switch(t.length){case 1:s.object[t[0]]=e;break;case 2:s.object[t[0]][t[1]]=e;break;default:continue}break}}}catch(e){t.push(i)}for(let e=t.length-1;e>-1;--e)this.lerpTargets.splice(t[e],1)}catch(e){console.log(e)}}processCommand(e){try{let i=this.currentCommand;switch((i.Command||"").toLowerCase()){case"scenetitle01":this.waitTime=1e3*this.titleWaitTime;var t=i.English&&utage.currentTranslation[i.English]||i.Text;this.text.titleText(!0,t);break;case"divaeffect":this.waitTime=1e3;t=i.English&&utage.currentTranslation[i.English]||i.Text;this.text.divaText(!0,t);break;case"fadeout":this.text.dialogText(!1,""),this.text.characterName(!1,""),this.waitTime=1e3*Number(i.Arg6),this.layers["bg|whiteFade"].sprite.tint=commonFunctions.getColorFromName(i.Arg1),this.lerpTargets.push({type:"alpha",object:this.layers["bg|whiteFade"].sprite,curTime:0,time:this.waitTime,finalV:1,initV:0});break;case"fadein":this.waitTime=1e3*Number(i.Arg6),this.layers["bg|whiteFade"].sprite.tint=commonFunctions.getColorFromName(i.Arg1),this.lerpTargets.push({type:"alpha",object:this.layers["bg|whiteFade"].sprite,curTime:0,time:this.waitTime,finalV:0,initV:1});break;case"bg":{let e=this.utage.textureInfo[i.Arg1],t=this.layers[this.bgLayerName].container;if(i.Arg6)this.lerpTargets.push({type:"alpha",object:t.children[0],curTime:0,time:1e3*Number(i.Arg6),finalV:0,initV:1,post:"destroy"});else for(let e=0;e"===e.Arg2.toLowerCase())this.text.characterName(!0,e.Arg1),this.text.dialogText(!0,commonFunctions.convertUtageTextTags(t));else{let i=!1;for(let s of Object.keys(this.currentCharacters))this.currentCharacters[s]&&(this.currentCharacters[s].charName!==e.Arg1?this.currentCharacters[s].sprite&&(this.currentCharacters[s].sprite.tint=this.backCharTint):(this.text.characterName(!0,this.currentCharacters[s].character.NameText),this.text.dialogText(!0,t),this.currentCharacters[s].sprite.tint=16777215,i=!0));i||(this.text.characterName(!0,e.Arg1),this.text.dialogText(!0,t))}this.manualNext=!0}else if(!e.Command&&""===e.Arg2.toLowerCase()&&e.Text){t=e.English&&utage.currentTranslation[e.English]||e.Text;this.text.characterName(!0,""),this.text.dialogText(!0,commonFunctions.convertUtageTextTags(t)),this.manualNext=!0}e.Voice&&(this.playingVoice=e.Voice,this.audio.playSound(e.Voice))}processTween(e,t){this.text.dialogText(!1,""),this.text.characterName(!1,"");let i=void 0;for(let e of Object.keys(this.currentCharacters))this.currentCharacters[e]&&(this.currentCharacters[e].charName!==t.Arg1?this.currentCharacters[e].sprite&&(this.currentCharacters[e].sprite.tint=this.backCharTint):(i=this.currentCharacters[e],this.currentCharacters[e].sprite.tint=16777215));if(i)switch(t.Arg2.toLowerCase()){case"moveto":{let e=commonFunctions.getPropertiesFromTweenCommand(t.Arg3);t.Arg6&&"NoWait"===t.Arg6||(this.waitTime=e.time+(e.delay||0)),e.x&&(e.time?this.lerpTargets.push({type:"position.x",object:i.sprite,curTime:0-(e.delay||0),time:e.time,finalV:i.sprite.position.x+e.x,initV:i.sprite.position.x,inter:"exp"}):i.sprite.position.x=i.sprite.position.x+e.x),e.y&&(e.time?this.lerpTargets.push({type:"position.y",object:i.sprite,curTime:0-(e.delay||0),time:e.time,finalV:i.sprite.position.y+e.y,initV:i.sprite.position.y,inter:"exp"}):i.sprite.position.y=i.sprite.position.y+e.y);break}case"punchposition":{let e=commonFunctions.getPropertiesFromTweenCommand(t.Arg3);e.time||(e.time=500),t.Arg6&&"NoWait"===t.Arg6||(this.waitTime=e.time+(e.delay||0)),e.x&&this.lerpTargets.push({type:"position.x",object:i.sprite,curTime:0-(e.delay||0),time:e.time,finalV:i.sprite.position.x+e.x,initV:i.sprite.position.x,inter:"dampsin"}),e.y&&this.lerpTargets.push({type:"position.y",object:i.sprite,curTime:0-(e.delay||0),time:e.time,finalV:i.sprite.position.y+e.y,initV:i.sprite.position.y,inter:"dampsin"});break}case"scaleto":{let e=commonFunctions.getPropertiesFromTweenCommand(t.Arg3,!1);e.time||(e.time=500),e.speed&&(e.time=1e3*e.speed),t.Arg6&&"NoWait"===t.Arg6||(this.waitTime=e.time+(e.delay||0)),e.x&&this.lerpTargets.push({type:"scale.x",object:i.sprite,curTime:0-(e.delay||0),time:e.time,finalV:i.sprite.scale.x*e.x,initV:i.sprite.scale.x}),e.y&&this.lerpTargets.push({type:"scale.y",object:i.sprite,curTime:0-(e.delay||0),time:e.time,finalV:i.sprite.scale.y*e.y,initV:i.sprite.scale.y})}case"colorto":{let e=commonFunctions.getPropertiesFromTweenCommand(t.Arg3);e.alpha&&(e.time?this.lerpTargets.push({type:"alpha",object:i.sprite,curTime:0-(e.delay||0),time:e.time,finalV:e.alpha,initV:i.sprite.alpha}):i.sprite.alpha=0)}}}processShake(e,t){switch(t.Arg1.toLowerCase()){case"camera":{let e=commonFunctions.getPropertiesFromTweenCommand(t.Arg3);e.time||(e.time=1e3),t.Arg6&&"NoWait"===t.Arg6||(this.waitTime=e.time+(e.delay||0)),e.x||(e.x=30),e.y||(e.y=30);let i=this.pixi.app.stage.position;this.lerpTargets.push({type:"shake",object:this.pixi.app.stage,curTime:0-(e.delay||0),time:e.time,finalV:{x:e.x+i.x,y:e.y+i.y},initV:{x:i.x,y:i.y}});break}case"messagewindow":{let e=commonFunctions.getPropertiesFromTweenCommand(t.Arg3);e.time||(e.time=1e3),t.Arg6&&"NoWait"===t.Arg6||(this.waitTime=e.time+(e.delay||0)),e.x||(e.x=30),e.y||(e.y=30),this.lerpTargets.push({type:"shake",object:document.getElementById("dialog-box"),curTime:0-(e.delay||0),time:e.time,finalV:{x:e.x,y:e.y},initV:{x:0,y:0}});break}}}processEndCommand(e){switch(this.currentCommand.Command){case"SceneTitle01":this.text.titleText(!1,"");break;case"DivaEffect":this.text.divaText(!1,"")}this.currentCommand=void 0}checkIfAllOff(){for(let e of Object.keys(this.currentCharacters))if(this.currentCharacters[e])return!1;return!0}onMainClick(e){this.runEvent&&(e.preventDefault(),e.stopPropagation(),this.manualNext&&!this.uiHidden?this.text.scrollingText?this.text.scrollingText&&this.text.showDialogFullText():(this.manualNext=!1,this.waitTime=0):this.uiHidden&&(this.text.hideUi(!0),this.uiHidden=!1))}hideUiClicked(e){this.runEvent&&(e.preventDefault(),e.stopPropagation(),this.uiHidden=!0,this.text.hideUi(!1))}onEndFile(){this.resolve()}getNextCommand(){let e=utage.currentPlayingFile.pop();utage.currentPlayingFile&&0!==utage.currentPlayingFile.length?e&&!e.comment&&(e.Command||e.Arg1||e.Arg2||e.Arg3||e.Arg4||e.Arg5||e.Arg6)?this.currentCommand=e:this.getNextCommand():this.onEndFile()}updateResolution(e){let t=e.height/baseDimensions.height;this.pixi.app.stage.scale.set(t,t),this.pixi.app.renderer.resize(e.width,e.height),document.getElementById("text-container").style.cssText=`transform: scale(${t})`}resetAll(){return new Promise((e,t)=>{try{this.pixi.app.ticker.remove(this.onPixiTick,this),this.pixi.app.stage.children.forEach(function(e){e.destroy(!0,!0,!0)});for(let e of Object.keys(PIXI.utils.TextureCache))PIXI.utils.TextureCache[e]&&PIXI.utils.TextureCache[e].destroy(!0);this.loader.reset(),this.currentCharacters={},this.lastCharOffLayer=void 0,this.layers={},this.sprites={},this.blackBackSp=void 0,this.currentCommand=void 0,this.runEvent=!1,this.secondTicker=1e3,this.waitTime=0,this.lerpTargets=[],this.manualNext=!1,this.hasMoreText=!1,this.audioLoadPercent=0,this.assetLoadPercent=0,this.playingVoice=void 0,this.text.resetAll(),this.audio.resetAll(),this.utage.resetTranslations(),e()}catch(e){t(e)}})}}const pixiApp={app:new PIXI.Application(baseDimensions),loader:PIXI.loader},utage=new UtageInfo,textFunc=new TextFunctions,audio=new audioController(utage),player=new Player(pixiApp,utage,textFunc,audio),context=new(window.AudioContext||window.webkitAudioContext),languages=["eng","jpn"];let bodyLoaded=!1,utageLoaded=!1,selectedLang="eng",currentMission=void 0,screenw=Math.max(document.documentElement.clientWidth,window.innerWidth||0),screenh=Math.max(document.documentElement.clientHeight,window.innerHeight||0),screenSizeTimeout=void 0,isMuted=!1,volume=.5;function onBodyLoaded(){bodyLoaded=!0}function onAllLoaded(e){textFunc.findTextElements(),buildMissionSelectList(),buildLanguageList(),document.getElementById("app-container").appendChild(pixiApp.app.view),setTimeout(()=>{document.getElementById("parent-container").style.cssText="opacity: 1;",onWindowResize(),window.addEventListener("resize",onWindowResize)},0)}function loadLocalStorage(){volume=localStorage.getItem("volume")||.5,volume=Number(volume),audio.changeVolume(volume),document.getElementById("volume-range").value=100*volume,"false"===(isMuted=localStorage.getItem("ismuted")||!1)?isMuted=!1:"true"===isMuted&&(isMuted=!0),audio.mute(isMuted),document.getElementById("mute-button").innerText=isMuted?"πŸ”‡":"πŸ”Š";let e=localStorage.getItem("language")||"eng";languages.includes(e)&&(selectedLang=e)}function buildMissionSelectList(){let e=document.getElementById("select-mission");e.innerHTML="";for(let t=-1;t{player.playFile().then(e=>{player.resetAll(),currentMission=void 0},e=>{currentMission=void 0,console.log(e)})},e=>{currentMission=void 0,console.log(e)})}function languageChanged(e){e&&e.currentTarget&&e.currentTarget.value&&"{Select}"!==e.currentTarget.value&&languages.includes(e.currentTarget.value)&&(selectedLang=e.currentTarget.value,utage.loadMissionTranslation(`${utage.rootDirectory}XDUData/${currentMission.Path.replace("Asset/","").replace(".utage","").replace(".tsv",`_translations_${selectedLang}.json`)}`,selectedLang))}function onMainClick(e){player.onMainClick(e)}function hideUiClicked(e){player.hideUiClicked(e)}function dialogScrollUp(e){e.preventDefault(),e.stopPropagation(),textFunc.scrollTextUp()}function dialogScrollDown(e){e.preventDefault(),e.stopPropagation(),textFunc.scrollTextDown()}function toggleMute(e){isMuted=!isMuted,audio.mute(isMuted),localStorage.setItem("ismuted",isMuted),document.getElementById("mute-button").innerText=isMuted?"πŸ”‡":"πŸ”Š"}function onVolumeChange(e){let t=e.currentTarget.value/100;audio.changeVolume(t),localStorage.setItem("volume",t)}function onWindowResize(e){screenSizeTimeout&&(clearTimeout(screenSizeTimeout),screenSizeTimeout=void 0),screenSizeTimeout=setTimeout(()=>{screenw=Math.max(document.documentElement.clientWidth,window.innerWidth||0),screenh=Math.max(document.documentElement.clientHeight,window.innerHeight||0);let e=document.getElementById("other-controls-container").offsetHeight+6,t=commonFunctions.getNewResolution(baseDimensions,screenw,screenh,e);player.updateResolution(t),document.getElementById("app-container").style.cssText=`width: ${t.width}px; height: ${t.height}px;`},400)}!function(){let e=[utage.loadUtageSettings()];Promise.all(e).then(e=>{utageLoaded=!0},e=>{console.log(e)})}(),function e(){bodyLoaded&&(document.getElementById("loading-font").style.cssText="display: none;",loadLocalStorage()),utageLoaded&&(document.getElementById("loading-utage").style.cssText="display: none;"),bodyLoaded&&utageLoaded?(document.getElementById("loading-container").style.cssText="opacity: 0;",onAllLoaded()):setTimeout(e,300)}(); \ No newline at end of file diff --git a/Player.html b/Player.html index e36c672..8fb2dc6 100644 --- a/Player.html +++ b/Player.html @@ -6,15 +6,15 @@ - - + - + +

Loading Utage Data...

Loading Fonts...

@@ -26,6 +26,7 @@
+ diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..f4f6450 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,24 @@ +const gulp = require('gulp'); +const concat = require('gulp-concat'); +const rename = require('gulp-rename'); +const uglify = require('gulp-uglify-es').default; + + +const jsFiles = [ +"Js/Common.js", +"Js/TextFunctions.js", +"Js/UtageParse.js", +"Js/Audio.js", +"Js/Player.js", +"Js/Main.js" +]; +const jsDest = "Js"; +gulp.task('minify', function() { + // place code for your default task here + return gulp.src(jsFiles) + .pipe(concat('XduPlayer.js')) + .pipe(gulp.dest(jsDest)) + .pipe(rename('XduPlayer.min.js')) + .pipe(uglify()) + .pipe(gulp.dest(jsDest)); +}); \ No newline at end of file