Compare commits

..

No commits in common. "master" and "v1.2.1" have entirely different histories.

21 changed files with 7687 additions and 9853 deletions

View File

@ -1 +0,0 @@
Js/Pixi.min.js

View File

@ -1,29 +0,0 @@
{
"env": {
"browser": true,
"es6": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly",
"PIXI": "readonly",
"UtageInfo": "readonly",
"TextFunctions": "readonly",
"Player": "readonly",
"Shaders": "readonly",
"baseDimensions": "readonly",
"commonFunctions": "readonly",
"audioController": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"rules": {
"no-console": "off",
"no-unused-vars": [2, { "vars": "local", "argsIgnorePattern": "^(success|event|resource|delta|reject)$"}],
"no-empty": ["error", { "allowEmptyCatch": true }],
"no-mixed-spaces-and-tabs": "off"
}
}

3
.gitignore vendored
View File

@ -3,8 +3,6 @@
web.config web.config
/Js/Typed /Js/Typed
/Js/[Pp]ixi.js /Js/[Pp]ixi.js
/Js/[Pp]ixi.js.map
/Js/[Pp]ixi.min.js.map
/node_modules /node_modules
/Js/XduPlayer.js /Js/XduPlayer.js
/Js/XduPlayer.min.js.map /Js/XduPlayer.min.js.map
@ -12,4 +10,3 @@ web.config
/Dist /Dist
/Css/main.min.css /Css/main.min.css
/Js/XduPlayer.min.js /Js/XduPlayer.min.js
/**/.*.swp

6
.gitmodules vendored
View File

@ -1,8 +1,8 @@
[submodule "Js/Translations"] [submodule "Js/Translations"]
path = Js/Translations path = Js/Translations
url = https://git.poweris.moe/yttt-xdu/xdutranslations.git url = https://git.poweris.moe/xdutranslations.git
branch = master branch = .
[submodule "CustomData"] [submodule "CustomData"]
path = CustomData path = CustomData
url = https://git.poweris.moe/yttt-xdu/customdata.git url = https://git.poweris.moe/customdata.git
branch = . branch = .

View File

@ -15,36 +15,3 @@ DPI is now taken into account when resizing.
Added credits to mission modal. Added credits to mission modal.
Added ability to go fullscreen. Added ability to go fullscreen.
Missions JSON moved to translations submodule so missions can be added/enabled without disturbing main project. Missions JSON moved to translations submodule so missions can be added/enabled without disturbing main project.
## V1.2.1 (2018-12-29)
Custom asset support
Russian language support
Fix translation fallback
## V1.2.2 (2019-01-20)
Add language url parameter
Fix noise\_disappearance commands
## V1.3.0 (2019-05-13)
Macro support
DivaMovie
Changed metadata to include quests
Per-language quest enabling
Sort scenes into quests to reduce clutter
Preserve ColorTo tinting properly
urlparam: questSceneMstId
## V1.3.1 (2019-06-09)
Fix MoveCamera macro
## V1.4.0 (2019-09-29)
Updated Pixi.js to v5
## V1.5.0 (2020-07-31)
XDU Global support

View File

@ -84,8 +84,6 @@ body { margin: 0; height: 100%; }
#text-container.rus { font-family: 'PTSans'; } #text-container.rus { font-family: 'PTSans'; }
#text-container.cze { font-family: 'PTSans'; }
#text-container #fullscreen-button { position: absolute; top: 0.5rem; left: 0.5rem; font-size: 30px; line-height: 30px; opacity: 0.35; z-index: 11; } #text-container #fullscreen-button { position: absolute; top: 0.5rem; left: 0.5rem; font-size: 30px; line-height: 30px; opacity: 0.35; z-index: 11; }
#text-container #title { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; font-size: 20px; transition: opacity 0.3s; cursor: default; user-select: none; } #text-container #title { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; font-size: 20px; transition: opacity 0.3s; cursor: default; user-select: none; }
@ -124,11 +122,9 @@ body { margin: 0; height: 100%; }
#title-container { padding: 2px 0; } #title-container { padding: 2px 0; }
#other-controls-container { padding-bottom: 4px; display: flex; width: 100%; justify-content: center; align-items: center; z-index: 10; } #other-controls-container { padding-bottom: 4px; display: flex; width: 550px; justify-content: center; align-items: center; z-index: 10; }
#select-quest { min-width: 0; width: 25% } #select-mission { min-width: 0; }
#select-scene { min-width: 0; width: 25% }
#select-language { margin-left: 10px; } #select-language { margin-left: 10px; }
@ -158,12 +154,6 @@ body { margin: 0; height: 100%; }
#modal-buttons { bottom: 0; margin-top: auto; width: 100%; display: flex; justify-content: space-between; min-height: 21px; } #modal-buttons { bottom: 0; margin-top: auto; width: 100%; display: flex; justify-content: space-between; min-height: 21px; }
#mission-modal .follow-links { margin-top: auto; display: flex; flex-direction: column; text-align: center; width:100%; }
#mission-modal .follow-links .follow-links-header { font-weight: bold; }
#mission-modal .follow-links .follow-links-links { display: flex; flex-direction: row; justify-content: space-around; margin-top: 5px; }
@media screen and (max-width: 812px) { @media screen and (max-width: 812px) {
#modal-container { top: 0; bottom: 0; left: 0; right: 0; transform: none; } #modal-container { top: 0; bottom: 0; left: 0; right: 0; transform: none; }
.modal { width: 100%; height: 100%; border-radius: 0; } .modal { width: 100%; height: 100%; border-radius: 0; }

@ -1 +1 @@
Subproject commit e92af8f0d0c0d4246e44dd0b63508f9e460fe3a8 Subproject commit e45642773aa255babfde41b770ce1e4c78ca5251

View File

@ -1,4 +1,5 @@
//(Math.exp(x)-1)/(Math.E-1) //(Math.exp(x)-1)/(Math.E-1)
//🔊
class bufferLoader { class bufferLoader {
constructor(context, soundMap, callback) { constructor(context, soundMap, callback) {

1263
Js/BgmLoop.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,11 +4,6 @@ let rootUrl = `${window.location.protocol}//${window.location.host}/`;
const baseDimensions = {width: 1334, height: 750}; const baseDimensions = {width: 1334, height: 750};
const screenRatio = 9/16; const screenRatio = 9/16;
const CUSTOM = {
custom: 'Custom',
stock: 'Stock'
}
class commonFunctions { class commonFunctions {
static getFileText(file) { static getFileText(file) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -339,6 +334,7 @@ class commonFunctions {
if(props[i] == " ") { break; } if(props[i] == " ") { break; }
retval.color += props[i]; retval.color += props[i];
} }
retval.color = retval.color;
} }
return retval; return retval;
} }

View File

@ -2,7 +2,7 @@
const pixiApp = { const pixiApp = {
app: new PIXI.Application(baseDimensions), app: new PIXI.Application(baseDimensions),
loader: PIXI.Loader.shared loader: PIXI.loader
}; };
const utage = new UtageInfo(); const utage = new UtageInfo();
@ -10,17 +10,16 @@ const shaders = new Shaders();
const textFunc = new TextFunctions(); const textFunc = new TextFunctions();
let audio = undefined; //Cant create a audio context without user input. let audio = undefined; //Cant create a audio context without user input.
const player = new Player(pixiApp, utage, textFunc, audio, shaders); const player = new Player(pixiApp, utage, textFunc, audio, shaders);
const languages = ["eng", "jpn", "rus", "cze", "enm", "kor", "zho"]; const languages = ["eng", "jpn", "rus"];
const version = "YameteTomete XDUPlayer V1.5.0"; const version = "YameteTomete XDUPlayer V1.2.1";
let bodyLoaded = false; let bodyLoaded = false;
let utageLoaded = false; let utageLoaded = false;
let languagesLoaded = false; let languagesLoaded = false;
let selectedLang = "eng"; let selectedLang = "eng";
let currentScene = {}; let currentMission = undefined;
let currentSceneId = ""; let currentMissionMst = 0;
let scenePlaylist = []; let currentMissionIndex = 0;
let currentPart = ""; let currentMissionList = [];
let partPlaylist = [];
let urlParams = {}; let urlParams = {};
let screenw = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); let screenw = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
let screenh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); let screenh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
@ -28,14 +27,7 @@ let screenSizeTimeout = undefined;
let isMuted = false; let isMuted = false;
let volume = 0.5; let volume = 0.5;
let fullScreen = false; let fullScreen = false;
let prevScene = '{Select}'; let prevMission = '{Select}';
let prevQuest = '{Select}';
const emoji = {
LoudSound: String.fromCodePoint(0x1f50a),
Mute: String.fromCodePoint(0x1f507),
HeavyPlusSign: String.fromCodePoint(0x2795)
};
function onBodyLoaded() { function onBodyLoaded() {
bodyLoaded = true; bodyLoaded = true;
@ -62,7 +54,6 @@ function onBodyLoaded() {
(function checkIsLoaded() { (function checkIsLoaded() {
if(bodyLoaded) { if(bodyLoaded) {
document.getElementById('loading-font').style.cssText = "display: none;"; document.getElementById('loading-font').style.cssText = "display: none;";
checkQueryParameters();
loadLocalStorage(); loadLocalStorage();
} }
if(utageLoaded && languagesLoaded) { if(utageLoaded && languagesLoaded) {
@ -78,8 +69,7 @@ function onBodyLoaded() {
function onAllLoaded(success) { function onAllLoaded(success) {
textFunc.findTextElements(); textFunc.findTextElements();
buildQuestSelectList(); buildMissionSelectList();
buildSceneSelectList();
buildLanguageList(); buildLanguageList();
let appContainer = document.getElementById('app-container'); let appContainer = document.getElementById('app-container');
appContainer.appendChild(pixiApp.app.view); appContainer.appendChild(pixiApp.app.view);
@ -105,12 +95,12 @@ function loadLocalStorage() {
audio.mute(isMuted); audio.mute(isMuted);
} }
if(isMuted) { if(isMuted) {
document.getElementById('mute-button').innerText = emoji.Mute; document.getElementById('mute-button').innerText = "🔇";
} else { } else {
document.getElementById('mute-button').innerText = emoji.LoudSound; document.getElementById('mute-button').innerText = "🔊";
} }
//language //language
let lang = urlParams['lang'] || localStorage.getItem('language') || "eng"; let lang = localStorage.getItem('language') || "eng";
if(languages.includes(lang)) { if(languages.includes(lang)) {
selectedLang = lang; selectedLang = lang;
} }
@ -127,79 +117,27 @@ function loadLocalStorage() {
} }
} }
function buildQuestSelectList() { function buildMissionSelectList() {
let questBox = document.getElementById('select-quest'); let selectBox = document.getElementById('select-mission');
questBox.innerHTML = ''; selectBox.innerHTML = '';
for (let i = -1; i < utage.questList.length; ++i) { for(let i = -1; i < utage.missionsList.length; ++i) {
let opt = document.createElement('option') let opt = document.createElement('option');
if(i === -1) { if(i === -1) {
opt.setAttribute('value', '{Select}'); opt.setAttribute('value', '{Select}');
opt.innerText = 'Select Event'; opt.innerText = 'Select Mission';
} else { } else {
let q = utage.questList[i]; let m = utage.missionsList[i];
let cust = q.IsCustom ? CUSTOM.custom : CUSTOM.stock; if(!Object.keys(utage.groupedMissions[m.MstId].Missions).some((mis) => { return utage.groupedMissions[m.MstId].Missions[mis].Enabled === true })) {
let name = q.Name;
let tl_key = utage.questTranslations[cust][q.QuestMstId];
if (!tl_key) {
console.log("Failed to build quest list: missing translations");
continue; continue;
} }
if (!tl_key.Enabled && !utage.quests[cust][q.QuestMstId].Scenes.some((s) => { return utage.sceneTranslations[cust][s].Enabled === true })) { opt.setAttribute('value', m.MstId);
continue; let name = m.Name;
if(utage.missionTranslations[m.MstId]) {
name = utage.missionTranslations[m.MstId].Name || name;
} }
name = tl_key.Name || name;
opt.setAttribute('value', `${cust}|${q.QuestMstId}`);
opt.innerText = name; opt.innerText = name;
} }
questBox.appendChild(opt); selectBox.appendChild(opt);
}
}
function buildSceneSelectList() {
let sceneBox = document.getElementById('select-scene');
let questBox = document.getElementById('select-quest');
sceneBox.innerHTML = '';
let opt = document.createElement('option');
opt.setAttribute('value', '{Select}');
opt.innerText = "Select Scene";
if (questBox.value === '{Select}') {
sceneBox.appendChild(opt);
sceneBox.setAttribute("disabled", "true");
return;
} else {
sceneBox.removeAttribute("disabled");
}
let cust = questBox.value.split("|")[0];
let questMstId = questBox.value.split("|")[1];
for (let i = -2; i < utage.quests[cust][questMstId].Scenes.length; ++i) {
let opt = document.createElement('option');
if (i === -2) {
opt.setAttribute('value', '{Select}');
opt.innerText = 'Select Scene';
} else if (i === -1) {
opt.setAttribute('value', '{All}');
opt.innerText = 'Play All';
} else {
let questSceneMstId = utage.quests[cust][questMstId].Scenes[i];
let s = utage.scenes[cust][questSceneMstId];
opt.setAttribute('value', `${cust}|${questSceneMstId}`);
let name = s.Name;
let tl_key = utage.sceneTranslations[cust][questSceneMstId];
if (!tl_key) {
console.log("Failed to build scene list: missing translations");
continue;
}
if (!tl_key.Enabled) {
continue;
}
name = tl_key.Name || name;
opt.innerText = name;
}
sceneBox.appendChild(opt);
} }
} }
@ -217,85 +155,29 @@ function buildLanguageList() {
function checkQueryParameters() { function checkQueryParameters() {
urlParams = commonFunctions.readQueryParameters(); urlParams = commonFunctions.readQueryParameters();
if (languagesLoaded) { if(urlParams['mstid'] && urlParams['id'] && utage.groupedMissions[urlParams['mstid']] && utage.groupedMissions[urlParams['mstid']].Missions[urlParams['id']]) {
let cust;
if (urlParams['custom'] && urlParams['custom'] === "1") {
cust = CUSTOM.custom;
} else {
cust = CUSTOM.stock;
}
let playable = (urlParams['questscenemstid'] &&
utage.scenes[cust][urlParams['questscenemstid']] &&
utage.sceneTranslations[cust][urlParams['questscenemstid']] &&
utage.sceneTranslations[cust][urlParams['questscenemstid']].Enabled);
if(playable) {
document.getElementById('play-from-query').style.cssText = "position: fixed; z-index: 15; text-align: center; top: 50%; left: 50%; display: block;"; document.getElementById('play-from-query').style.cssText = "position: fixed; z-index: 15; text-align: center; top: 50%; left: 50%; display: block;";
} }
} }
}
function playFromQuery(event) { function playFromQuery(event) {
let cust; missionChanged(urlParams['mstid'], urlParams['id']);
if (urlParams['custom'] && urlParams['custom'] === "1") {
cust = CUSTOM.custom;
} else {
cust = CUSTOM.stock;
}
sceneSet(urlParams['questscenemstid'], cust);
document.getElementById('play-from-query').style.cssText = "display: none;"; document.getElementById('play-from-query').style.cssText = "display: none;";
} }
function questDropDownChanged(event) { function missionDropDownChanged(event) {
if(!event || !event.currentTarget || !event.currentTarget.value) { return; }
buildSceneSelectList();
}
function sceneDropDownChanged(event) {
if(!event || !event.currentTarget || !event.currentTarget.value || event.currentTarget.value === '{Select}') { return; } if(!event || !event.currentTarget || !event.currentTarget.value || event.currentTarget.value === '{Select}') { return; }
if (event.currentTarget.value === '{All}') {
let quest = document.getElementById("select-quest");
let cust = quest.value.split("|")[0];
let questMstId = quest.value.split("|")[1];
let scene = utage.quests[cust][questMstId].Scenes;
resetPlaylist();
for (const s of scene) {
let tl_key = utage.sceneTranslations[cust][s];
if (tl_key) {
if (utage.sceneTranslations[cust][s].Enabled) {
utage.scenes[cust][s]['QuestSceneMstId'] = s;
scenePlaylist.push(utage.scenes[cust][s]);
}
}
}
playNext();
return;
}
let cont = document.getElementById("modal-container"); let cont = document.getElementById("modal-container");
let misId = event.currentTarget.value;
let cust = event.currentTarget.value.split("|")[0]; let mis = utage.groupedMissions[misId];
let questSceneMstId = event.currentTarget.value.split("|")[1]; if(!mis) { console.log(`Mission ${misId} not found`); return; }
let name = mis.Name;
let scene = utage.scenes[cust][questSceneMstId]; let summary = mis.SummaryText;
if(!scene) { console.log(`Scene ${questSceneMstId} not found`); return; }
let name = scene.Name;
let summary = scene.SummaryText;
let image = questSceneMstId;
if ("Image" in scene) {
image = scene.Image;
}
let credits = ""; let credits = "";
let tl_key = utage.sceneTranslations[cust][questSceneMstId]; if(utage.missionTranslations[mis.MstId]) {
name = utage.missionTranslations[mis.MstId].Name || name;
if(tl_key) { summary = utage.missionTranslations[mis.MstId].SummaryText || summary;
name = tl_key.Name || name; credits = utage.missionTranslations[mis.MstId].Credits || credits;
summary = tl_key.SummaryText || summary;
credits = tl_key.Credits || credits;
} }
if(!credits) { if(!credits) {
if(selectedLang === "eng") { if(selectedLang === "eng") {
@ -304,15 +186,15 @@ function sceneDropDownChanged(event) {
credits = "None"; credits = "None";
} }
} }
let chapterSelect = '<div><span>Chapter Select:</span><select id="ChapterSelect">'; let chapterSelect = '<div><span>Chapter Select:</span><select id="ChapterSelect">';
chapterSelect += `<option value="{All}">Play All</option>` for(let k of Object.keys(mis.Missions)) {
for (const p of scene.Parts) { var m = mis.Missions[k];
chapterSelect += `<option value="${p}">${p}</option>` if(m.Enabled) {
chapterSelect += `<option value="${m.Id}">${m.Id}</option>`
} }
}
let detailSrc = `${utage.rootDirectory}${(scene.IsCustom ? "CustomData" : "XDUData")}/Asset/Image/Quest/Snap/Detail/${image}.png`; let detailSrc = `${utage.rootDirectory}${(mis.IsCustom ? "CustomData" : "XDUData")}/Asset/Image/Quest/Snap/Detail/${mis.MstId}.png`;
let iconSrc = `${utage.rootDirectory}${(scene.IsCustom ? "CustomData" : "XDUData")}/Asset/Image/Quest/Snap/Icon/${image}.png`; let iconSrc = `${utage.rootDirectory}${(mis.IsCustom ? "CustomData" : "XDUData")}/Asset/Image/Quest/Snap/Icon/${mis.MstId}.png`;
chapterSelect += '</select></div>'; chapterSelect += '</select></div>';
cont.innerHTML = ` cont.innerHTML = `
<div id="mission-modal" class="modal"> <div id="mission-modal" class="modal">
@ -327,8 +209,8 @@ function sceneDropDownChanged(event) {
</div> </div>
<div id="modal-buttons"> <div id="modal-buttons">
<button onclick="closeMissionModal(event, false)">Close</button> <button onclick="closeMissionModal(event, false)">Close</button>
<span>MstId: ${questSceneMstId}</span> <span>MstId: ${mis.MstId}</span>
<button onclick="sceneSet('${questSceneMstId}', '${cust}')">Play</button> <button onclick="missionChanged(${mis.MstId})">Play</button>
</div> </div>
</div>`; </div>`;
document.getElementById("click-catcher").style.cssText = 'display: flex;'; document.getElementById("click-catcher").style.cssText = 'display: flex;';
@ -337,18 +219,10 @@ function sceneDropDownChanged(event) {
function closeMissionModal(event, wasStarted) { function closeMissionModal(event, wasStarted) {
if(!wasStarted) { if(!wasStarted) {
document.getElementById('select-scene').value = prevScene; document.getElementById('select-mission').value = prevMission;
document.getElementById('select-quest').value = prevQuest;
} else { } else {
prevScene = document.getElementById('select-scene').value; prevMission = document.getElementById('select-mission').value;
prevQuest = document.getElementById('select-quest').value;
} }
if (prevScene === '{Select}') {
document.getElementById('select-scene').setAttribute("disabled", "true");
} else {
document.getElementById('select-scene').removeAttribute("disabled");
}
closeModal(event); closeModal(event);
} }
@ -359,85 +233,67 @@ function closeModal(event) {
cont.innerHTML = ''; cont.innerHTML = '';
} }
function sceneSet(questSceneMstId, cust) { function missionChanged(mstId, value) {
resetPlaylist(); let mst = utage.groupedMissions[mstId];
let part = document.getElementById('ChapterSelect'); let name = mst.Name;
utage.scenes[cust][questSceneMstId]['QuestSceneMstId'] = questSceneMstId; if(utage.missionTranslations[mstId]) {
if (!part || part.value === '{All}') { name = utage.missionTranslations[mstId].Name || name;
scenePlaylist.push(utage.scenes[cust][questSceneMstId]);
} else {
currentScene = utage.scenes[cust][questSceneMstId];
try {
partPlaylist.push.apply(partPlaylist, currentScene.Parts.slice(currentScene.Parts.indexOf(part.value)));
} catch (error) {
console.log(error);
return;
} }
if(!value) {
value = document.getElementById("ChapterSelect").value;
} }
playNext();
}
function playNext() {
if (!partPlaylist.length) {
if (!scenePlaylist.length) {
resetPlaylist();
return; // we're probably done
}
currentScene = scenePlaylist.shift();
partPlaylist = currentScene.Parts.slice();
}
partChanged(partPlaylist.shift());
}
function partChanged(part) {
let cust = currentScene.IsCustom ? CUSTOM.custom : CUSTOM.stock;
let name = currentScene.Name;
let tl_key = utage.sceneTranslations[cust][currentScene.QuestSceneMstId];
if(tl_key) {
name = tl_key.Name || name;
}
if(!audio) { if(!audio) {
audio = new audioController(utage); audio = new audioController(utage);
audio.changeVolume(volume); audio.changeVolume(volume);
audio.mute(isMuted); audio.mute(isMuted);
player.audio = audio; player.audio = audio;
} }
player.resetAll() player.resetAll()
.then((success) => { .then((success) => {
if (scenePlaylist.length || partPlaylist.length) { let newMission = mst.Missions[value];
document.getElementById("skip-button").style.cssText = "display: inline-block;"; checkMissionList(mst.Missions, value);
} else { currentMission = newMission;
document.getElementById("skip-button").style.cssText = "display: none;"; currentMissionMst = mstId;
if(!currentMission.Enabled) {
//Check for the next enabled mission. If there are none just reset.
for(let i = currentMissionIndex + 1; i < currentMissionList.length; ++i) {
const mis = mst.Missions[currentMissionList[i]];
if(mis && mis.Enabled) {
missionChanged(currentMissionMst, mis.Id);
return;
}
}
//If we got through the loop there are no more enabled so just end
resetMissions();
return;
} }
let promises = []; let promises = [];
if(currentScene.IsCustom) { if(newMission.IsCustom) {
promises.push(utage.parseMissionFile(`${utage.rootDirectory}CustomData/Utage/${currentScene.Folder}/Scenario/${part}_t.tsv`)); promises.push(utage.parseMissionFile(`${utage.rootDirectory}CustomData/${newMission.Path.replace('Asset/', '').replace('.utage', '').replace('.tsv', '_t.tsv')}`));
promises.push(utage.loadMissionTranslation(`${utage.rootDirectory}Js/Translations/MissionsCustom/${currentScene.Folder}/${part}_translations_${selectedLang}.json`));
} else { } else {
promises.push(utage.parseMissionFile(`${utage.rootDirectory}XDUData/Utage/${currentScene.Folder}/Scenario/${part}_t.tsv`)); promises.push(utage.parseMissionFile(`${utage.rootDirectory}XDUData/${newMission.Path.replace('Asset/', '').replace('.utage', '').replace('.tsv', '_t.tsv')}`));
promises.push(utage.loadMissionTranslation(`${utage.rootDirectory}Js/Translations/Missions/${currentScene.Folder}/${part}_translations_${selectedLang}.json`));
} }
promises.push(utage.loadMissionTranslation(`${utage.rootDirectory}Js/Translations/Missions/${currentMission.Path.replace('Asset/Utage/', '').replace('Scenario/', '').replace('.utage', '').replace('.tsv', `_translations_${selectedLang}.json`)}`))
closeMissionModal(undefined, true); closeMissionModal(undefined, true);
Promise.all(promises) Promise.all(promises)
.then((success) => { .then((success) => {
document.getElementById("playing-title").innerText = `${name} (${part})`; document.getElementById("playing-title").innerText = `${name} (${value})`;
document.getElementById("title-tag").innerText = name; document.getElementById("title-tag").innerText = name;
currentPart = part;
player.playFile() player.playFile()
.then((success) => { .then((success) => {
playNext(); if(currentMissionIndex !== currentMissionList.length - 1) {
missionChanged(currentMissionMst, mst.Missions[currentMissionList[currentMissionIndex+1]].Id);
} else {
player.resetAll();
resetMissions();
}
}, (failure) => { }, (failure) => {
player.resetAll(); player.resetAll();
resetPlaylist(); resetMissions();
console.log(failure); console.log(failure);
}); });
}, (failure) => { }, (failure) => {
resetPlaylist(); resetMissions();
console.log(failure); console.log(failure);
}); });
}, (failure) => { }, (failure) => {
@ -449,32 +305,43 @@ function languageChanged(event) {
if(!event || !event.currentTarget || !event.currentTarget.value || event.currentTarget.value === '{Select}' || !languages.includes(event.currentTarget.value)) { return; } if(!event || !event.currentTarget || !event.currentTarget.value || event.currentTarget.value === '{Select}' || !languages.includes(event.currentTarget.value)) { return; }
selectedLang = event.currentTarget.value; selectedLang = event.currentTarget.value;
let missionPath = ''; let missionPath = '';
if(currentPart) { if(currentMission) {
if (currentScene.IsCustom) { missionPath = `${utage.rootDirectory}Js/Translations/Missions/${currentMission.Path.replace('Asset/Utage/', '').replace('Scenario/', '').replace('.utage', '').replace('.tsv', `_translations_${selectedLang}.json`)}`;
missionPath = `${utage.rootDirectory}Js/Translations/CustomMissions/${currentScene.Folder}/${currentPart}_translations_${selectedLang}.json`;
} else {
missionPath = `${utage.rootDirectory}Js/Translations/Missions/${currentScene.Folder}/${currentPart}_translations_${selectedLang}.json`;
}
} }
utage.setTranslationLanguage(selectedLang, missionPath) utage.setTranslationLanguage(selectedLang, missionPath)
.then((success) => { .then((success) => {
document.getElementById('text-container').className = selectedLang; document.getElementById('text-container').className = selectedLang;
buildQuestSelectList(); buildMissionSelectList();
buildSceneSelectList();
localStorage.setItem('language', selectedLang); localStorage.setItem('language', selectedLang);
}); });
} }
function resetPlaylist() { function checkMissionList(missions, currentvalue) {
currentScene = {}; currentMissionList = [];
scenePlaylist = []; let i = 0;
currentPart = ""; for(var m of Object.keys(missions)) {
partPlaylist = []; currentMissionList.push(m);
if(m === currentvalue) {
currentMissionIndex = i;
}
++i;
}
if(currentMissionIndex + 1 === currentMissionList.length) {
document.getElementById("skip-button").style.cssText = "display: none;";
} else {
document.getElementById("skip-button").style.cssText = "display: inline-block;";
}
}
function resetMissions() {
currentMissionIndex = 0;
currentMissionList = [];
currentMission = undefined;
currentMissionMst = 0;
document.getElementById("skip-button").style.cssText = "display: inline-block;"; document.getElementById("skip-button").style.cssText = "display: inline-block;";
document.getElementById("playing-title").innerText = 'None'; document.getElementById("playing-title").innerText = 'None';
document.getElementById("title-tag").innerText = version; document.getElementById("title-tag").innerText = version;
document.getElementById("select-quest").value = '{Select}'; document.getElementById('select-mission').value = '{Select}';
buildSceneSelectList();
} }
function onMainClick(event) { function onMainClick(event) {
@ -488,10 +355,20 @@ function hideUiClicked(event) {
function skipClicked(event) { function skipClicked(event) {
if(player.uiHidden) { if(player.uiHidden) {
player.hideUiClicked(event); player.hideUiClicked(event);
} else if(player.runEvent) { } else if(player.runEvent && currentMissionIndex !== currentMissionList.length - 1) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
playNext(); //Find the next enabled mission
for(let i = currentMissionIndex + 1; i < currentMissionList.length; ++i) {
const mis = utage.groupedMissions[currentMissionMst].Missions[currentMissionList[i]];
if(mis && mis.Enabled) {
//missionChanged(currentMissionMst, utage.groupedMissions[currentMissionMst].Missions[currentMissionList[currentMissionIndex+1]].Id);
missionChanged(currentMissionMst, mis.Id);
return;
}
}
//If we got through the loop there are no more enabled so just end
resetMissions();
} }
} }
@ -537,17 +414,11 @@ function openHelpModal(event) {
iOS: 11+, no audio<br/> iOS: 11+, no audio<br/>
</div> </div>
</div> </div>
<div class="follow-links"> <a style="margin-top: auto; text-align: center; "href="https://discord.gg/fpQZQ8g">YameteTomete Discord</a>
<div class="follow-links-header">Follow YameteTomete</div>
<div class="follow-links-links">
<a href="https://discord.gg/fpQZQ8g" target="_blank" >Discord</a>
<a href="https://twitter.com/YameteTomete" target="_blank">Twitter</a>
</div>
</div>
<div style="margin-top: auto; text-align: center;">All Symphogear content belongs to its respective owners</div> <div style="margin-top: auto; text-align: center;">All Symphogear content belongs to its respective owners</div>
<div id="modal-buttons"> <div id="modal-buttons">
<button onclick="closeModal(event)">Close</button> <button onclick="closeModal(event)">Close</button>
<a href="https://git.poweris.moe/yttt-xdu/XDUPlayer" target="_blank">Source</a> <a href="https://git.poweris.moe/xduplayer.git/" target="_blank">Source</a>
</div> </div>
</div>`; </div>`;
document.getElementById("click-catcher").style.cssText = 'display: flex;'; document.getElementById("click-catcher").style.cssText = 'display: flex;';
@ -561,9 +432,9 @@ function toggleMute(event) {
} }
localStorage.setItem('ismuted', isMuted); localStorage.setItem('ismuted', isMuted);
if(isMuted) { if(isMuted) {
document.getElementById('mute-button').innerText = emoji.Mute; document.getElementById('mute-button').innerText = "🔇";
} else { } else {
document.getElementById('mute-button').innerText = emoji.LoudSound; document.getElementById('mute-button').innerText = "🔊";
} }
} }
@ -602,7 +473,7 @@ function onFullScreenChange(event) {
} else { } else {
document.getElementById('other-controls-container').style.cssText = ""; document.getElementById('other-controls-container').style.cssText = "";
document.getElementById('title-container').style.cssText = ""; document.getElementById('title-container').style.cssText = "";
document.getElementById('fullscreen-button').innerText = emoji.HeavyPlusSign; document.getElementById('fullscreen-button').innerText = "";
} }
onWindowResize(event, 0); onWindowResize(event, 0);
} }

19
Js/Pixi.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,25 @@
//http://glslsandbox.com/e#39992.0 //http://glslsandbox.com/e#39992.0
class Shaders { class Shaders {
constructor() { constructor() {
this.leftToRightFadeShader = ` this.leftToRightFadeShader = `
precision mediump float; precision mediump float;
varying vec2 vTextureCoord; varying vec2 vTextureCoord;
uniform vec4 inputPixel; uniform vec2 dimensions;
uniform highp vec4 outputFrame; uniform vec4 filterArea;
uniform float time; uniform float time;
uniform vec4 fadeincolor; uniform vec4 fadeincolor;
uniform vec4 fadeoutcolor; uniform vec4 fadeoutcolor;
vec2 mapCoord( vec2 coord ) {
coord *= filterArea.xy;
coord += filterArea.zw;
return coord;
}
void main( void ) { void main( void ) {
vec2 uv = vTextureCoord * inputPixel.xy / outputFrame.zw; vec2 uv = vTextureCoord;
vec2 mappedCoord = uv; vec2 mappedCoord = mapCoord(uv) / dimensions;
float step2 = time; float step2 = time;
float step3 = time + 0.2; float step3 = time + 0.2;
@ -30,16 +35,21 @@ class Shaders {
this.rightToLeftFadeShader = ` this.rightToLeftFadeShader = `
precision mediump float; precision mediump float;
varying vec2 vTextureCoord; varying vec2 vTextureCoord;
uniform vec4 inputPixel; uniform vec2 dimensions;
uniform highp vec4 outputFrame; uniform vec4 filterArea;
uniform float time; uniform float time;
uniform vec4 fadeincolor; uniform vec4 fadeincolor;
uniform vec4 fadeoutcolor; uniform vec4 fadeoutcolor;
vec2 mapCoord( vec2 coord ) {
coord *= filterArea.xy;
return coord;
}
void main( void ) { void main( void ) {
vec2 uv = vTextureCoord * inputPixel.xy / outputFrame.zw; vec2 uv = vTextureCoord;
vec2 mappedCoord = uv; vec2 mappedCoord = mapCoord(uv) / dimensions;
float step2 = (1.0 - time); float step2 = (1.0 - time);
float step3 = (1.0 - time) - 0.2; float step3 = (1.0 - time) - 0.2;
@ -55,16 +65,22 @@ class Shaders {
this.downToUpFadeShader = ` this.downToUpFadeShader = `
precision mediump float; precision mediump float;
varying vec2 vTextureCoord; varying vec2 vTextureCoord;
uniform vec4 inputPixel; uniform vec2 dimensions;
uniform highp vec4 outputFrame; uniform vec4 filterArea;
uniform float time; uniform float time;
uniform vec4 fadeincolor; uniform vec4 fadeincolor;
uniform vec4 fadeoutcolor; uniform vec4 fadeoutcolor;
vec2 mapCoord( vec2 coord ) {
coord *= filterArea.xy;
coord += filterArea.zw;
return coord;
}
void main( void ) { void main( void ) {
vec2 uv = vTextureCoord * inputPixel.xy / outputFrame.zw; vec2 uv = vTextureCoord;
vec2 mappedCoord = uv; vec2 mappedCoord = mapCoord(uv) / dimensions;
float step2 = (1.0 - time); float step2 = (1.0 - time);
float step3 = (1.0 - time) - 0.2; float step3 = (1.0 - time) - 0.2;
@ -80,16 +96,22 @@ class Shaders {
this.uptoDownFadeShader = ` this.uptoDownFadeShader = `
precision mediump float; precision mediump float;
varying vec2 vTextureCoord; varying vec2 vTextureCoord;
uniform vec4 inputPixel; uniform vec2 dimensions;
uniform highp vec4 outputFrame; uniform vec4 filterArea;
uniform float time; uniform float time;
uniform vec4 fadeincolor; uniform vec4 fadeincolor;
uniform vec4 fadeoutcolor; uniform vec4 fadeoutcolor;
vec2 mapCoord( vec2 coord ) {
coord *= filterArea.xy;
coord += filterArea.zw;
return coord;
}
void main( void ) { void main( void ) {
vec2 uv = vTextureCoord * inputPixel.xy / outputFrame.zw; vec2 uv = vTextureCoord;
vec2 mappedCoord = uv; vec2 mappedCoord = mapCoord(uv) / dimensions;
float step2 = time; float step2 = time;
float step3 = time + 0.2; float step3 = time + 0.2;
@ -106,6 +128,7 @@ class Shaders {
precision mediump float; precision mediump float;
varying vec2 vTextureCoord; varying vec2 vTextureCoord;
uniform sampler2D uSampler; uniform sampler2D uSampler;
uniform vec2 dimensions;
uniform float factor; uniform float factor;
vec4 Sepia( in vec4 color ) vec4 Sepia( in vec4 color )
@ -126,11 +149,10 @@ class Shaders {
} }
//https://jsfiddle.net/60e5pp8d/1/ //https://jsfiddle.net/60e5pp8d/1/
//v5 changes to shaders, https://github.com/pixijs/pixi.js/wiki/v5-Creating-filters
// https://www.html5gamedevs.com/topic/42235-how-to-get-correct-fragment-shader-uv-in-pixi-50-rc0/
buildShaders() { buildShaders() {
let divalefttorightfade = new PIXI.Filter(null, this.leftToRightFadeShader, { let divalefttorightfade = new PIXI.Filter(null, this.leftToRightFadeShader, {
time: { type: 'f', value: 0 }, time: { type: 'f', value: 0 },
dimensions: { type: 'v2', value: [baseDimensions.width, baseDimensions.height] },
fadeincolor: { type: 'v4', value: [0.0,0.0,0.0,1.0] }, fadeincolor: { type: 'v4', value: [0.0,0.0,0.0,1.0] },
fadeoutcolor: { type: 'v4', value: [0.0,0.0,0.0,0.0] } fadeoutcolor: { type: 'v4', value: [0.0,0.0,0.0,0.0] }
}); });
@ -139,6 +161,7 @@ class Shaders {
let divarighttoleftfade = new PIXI.Filter(null, this.rightToLeftFadeShader, { let divarighttoleftfade = new PIXI.Filter(null, this.rightToLeftFadeShader, {
time: { type: 'f', value: 0 }, time: { type: 'f', value: 0 },
dimensions: { type: 'v2', value: [baseDimensions.width, baseDimensions.height] },
fadeincolor: { type: 'v4', value: [0.0,0.0,0.0,1.0] }, fadeincolor: { type: 'v4', value: [0.0,0.0,0.0,1.0] },
fadeoutcolor: { type: 'v4', value: [0.0,0.0,0.0,0.0] } fadeoutcolor: { type: 'v4', value: [0.0,0.0,0.0,0.0] }
}); });
@ -147,6 +170,7 @@ class Shaders {
let divauptodownfade = new PIXI.Filter(null, this.uptoDownFadeShader, { let divauptodownfade = new PIXI.Filter(null, this.uptoDownFadeShader, {
time: { type: 'f', value: 0 }, time: { type: 'f', value: 0 },
dimensions: { type: 'v2', value: [baseDimensions.width, baseDimensions.height] },
fadeincolor: { type: 'v4', value: [0.0,0.0,0.0,1.0] }, fadeincolor: { type: 'v4', value: [0.0,0.0,0.0,1.0] },
fadeoutcolor: { type: 'v4', value: [0.0,0.0,0.0,0.0] } fadeoutcolor: { type: 'v4', value: [0.0,0.0,0.0,0.0] }
}); });
@ -155,6 +179,7 @@ class Shaders {
let divadowntoupfade = new PIXI.Filter(null, this.downToUpFadeShader, { let divadowntoupfade = new PIXI.Filter(null, this.downToUpFadeShader, {
time: { type: 'f', value: 0 }, time: { type: 'f', value: 0 },
dimensions: { type: 'v2', value: [baseDimensions.width, baseDimensions.height] },
fadeincolor: { type: 'v4', value: [0.0,0.0,0.0,1.0] }, fadeincolor: { type: 'v4', value: [0.0,0.0,0.0,1.0] },
fadeoutcolor: { type: 'v4', value: [0.0,0.0,0.0,0.0] } fadeoutcolor: { type: 'v4', value: [0.0,0.0,0.0,0.0] }
}); });
@ -162,12 +187,15 @@ class Shaders {
this.shaders['divadowntoupfade'] = divadowntoupfade; this.shaders['divadowntoupfade'] = divadowntoupfade;
let sepia = new PIXI.Filter(null, this.sepiaShader, { let sepia = new PIXI.Filter(null, this.sepiaShader, {
factor: { type: 'f', value: 0.5 } factor: { type: 'f', value: 0.5 },
dimensions: { type: 'v2', value: [baseDimensions.width, baseDimensions.height] }
}); });
sepia.apply = baseShaderApply; sepia.apply = baseShaderApply;
this.shaders['sepia'] = sepia; this.shaders['sepia'] = sepia;
function baseShaderApply(filterManager, input, output) { function baseShaderApply(filterManager, input, output) {
this.uniforms.dimensions[0] = input.sourceFrame.width;
this.uniforms.dimensions[1] = input.sourceFrame.height;
filterManager.applyFilter(this, input, output); filterManager.applyFilter(this, input, output);
} }
} }

View File

@ -84,6 +84,7 @@ class TextFunctions {
function putText() { function putText() {
// skip over any HTML chars // skip over any HTML chars
this.dialogToDisplay.curPos = this.typeHtmlChars(this.dialogToDisplay.text, this.dialogToDisplay.curPos); this.dialogToDisplay.curPos = this.typeHtmlChars(this.dialogToDisplay.text, this.dialogToDisplay.curPos);
let substr = this.dialogToDisplay.text.substr(this.dialogToDisplay.curPos);
if (this.dialogToDisplay.curPos === this.dialogToDisplay.text.length) { if (this.dialogToDisplay.curPos === this.dialogToDisplay.text.length) {
this.showNextIndicator(true); this.showNextIndicator(true);
this.scrollingText = false; this.scrollingText = false;

@ -1 +1 @@
Subproject commit ac0bfbd699431e9befdd843379e7c91ad1014cec Subproject commit 533c48371ed01ed7265b6b5f052d1b2c3fce940f

View File

@ -6,9 +6,7 @@ class UtageInfo {
this.currentPlayingFile = []; this.currentPlayingFile = [];
this.rootDirectory = ``; this.rootDirectory = ``;
this.groupedMissions = {}; this.groupedMissions = {};
this.quests = {}; this.missionsList = [];
this.questList = [];
this.scenes = {};
this.characterInfo = {}; this.characterInfo = {};
this.layerInfo = {}; this.layerInfo = {};
this.localizeInfo = {}; this.localizeInfo = {};
@ -18,64 +16,44 @@ class UtageInfo {
this.currentTranslation = 'eng'; this.currentTranslation = 'eng';
this.translationsInner = {}; this.translationsInner = {};
this.charTranslationsInner = {}; this.charTranslationsInner = {};
this.questTranslationsInner = {}; this.missionTranslationsInner = {};
this.sceneTranslationsInner = {};
this.bgmLoopData = {}; this.bgmLoopData = {};
this.macros = {};
} }
loadUtageSettings() { loadUtageSettings() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let promises = [ let promises = [
commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduQuest.json`), //0 commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduMissions.json`), //0
commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduScene.json`), //1 commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Character.tsv`), //1
commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Character.tsv`), //2 commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Layer.tsv`), //2
commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Layer.tsv`), //3 commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Localize.tsv`), //3
commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Localize.tsv`), //4
//commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Param.tsv`), //commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Param.tsv`),
//commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Scenario.tsv`), //commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Scenario.tsv`),
commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Sound.tsv`), //5 commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Sound.tsv`), //4
commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Texture.tsv`), //6 commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Texture.tsv`), //5
commonFunctions.getFileJson(`${this.rootDirectory}XDUData/Bgm/BgmLoop.json`), //7 commonFunctions.getFileJson(`${this.rootDirectory}Js/BgmLoop.json`), //6
commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduQuestCustom.json`), //8 commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduMissionsCustom.json`), //7
commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduSceneCustom.json`), //9 commonFunctions.getFileText(`${this.rootDirectory}CustomData/Utage/Diva/Settings/CustomCharacter.tsv`), //8
commonFunctions.getFileText(`${this.rootDirectory}CustomData/Utage/Diva/Settings/CustomCharacter.tsv`), //10 commonFunctions.getFileText(`${this.rootDirectory}CustomData/Utage/Diva/Settings/CustomSound.tsv`), //9
commonFunctions.getFileText(`${this.rootDirectory}CustomData/Utage/Diva/Settings/CustomSound.tsv`), //11 commonFunctions.getFileText(`${this.rootDirectory}CustomData/Utage/Diva/Settings/CustomTexture.tsv`), //10
commonFunctions.getFileText(`${this.rootDirectory}CustomData/Utage/Diva/Settings/CustomTexture.tsv`), //12
commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Scenario/Macro.tsv`), //13
commonFunctions.getFileText(`${this.rootDirectory}CustomData/Utage/Diva/Settings/CustomMacro.tsv`), //14
]; ];
Promise.all(promises) Promise.all(promises)
.then((success) => { .then((success) => {
this.quests[CUSTOM.stock] = success[0]; this.groupMissions(success[0], success[7]);
this.questList = Object.keys(this.quests[CUSTOM.stock]).map((k) => { this.missionsList = Object.keys(this.groupedMissions).map((k) => {
return {QuestMstId: k, Name: this.quests[CUSTOM.stock][k].Name, IsCustom: false}; return {Name: this.groupedMissions[k].Name, MstId: this.groupedMissions[k].MstId};
}); });
this.quests[CUSTOM.custom] = success[8]; this.missionsList.sort();
for (const k of Object.keys(this.quests[CUSTOM.custom])) { this.parseCharacterInfo(success[1]);
this.questList.push({QuestMstId: k, Name: this.quests[CUSTOM.custom][k].Name, IsCustom: true}); this.parseLayerInfo(success[2]);
} this.parseLocalizeInfo(success[3]);
this.questList.sort((a, b) => { return a.QuestMstId - b.QuestMstId });
this.scenes[CUSTOM.stock] = success[1];
for (const k of Object.keys(this.scenes[CUSTOM.stock])) {
this.scenes[CUSTOM.stock][k]['IsCustom'] = false;
}
this.parseCharacterInfo(success[2]);
this.parseLayerInfo(success[3]);
this.parseLocalizeInfo(success[4]);
//this.parseParamInfo(success[4]); //this.parseParamInfo(success[4]);
this.parseSoundInfo(success[5]); this.parseSoundInfo(success[4]);
this.parseTextureInfo(success[6]); this.parseTextureInfo(success[5]);
this.bgmLoopData = success[7]; this.bgmLoopData = success[6];
this.scenes[CUSTOM.custom] = success[9]; this.parseCharacterInfo(success[8], true);
for (const k of Object.keys(this.scenes[CUSTOM.custom])) { this.parseSoundInfo(success[9], true);
this.scenes[CUSTOM.custom][k]['IsCustom'] = true; this.parseTextureInfo(success[10], true);
}
this.parseCharacterInfo(success[10], true);
this.parseSoundInfo(success[11], true);
this.parseTextureInfo(success[12], true);
this.parseMacroFile(success[13]);
this.parseMacroFile(success[14]);
resolve(); resolve();
}, (failure) => { }, (failure) => {
reject(failure); reject(failure);
@ -109,6 +87,40 @@ class UtageInfo {
}); });
} }
groupMissions(missions, customMissions) {
for(let key of Object.keys(missions)) {
let mis = missions[key];
if(!this.groupedMissions[mis.MstId]) {
this.groupedMissions[mis.MstId] = {
Name: mis.Name,
SummaryText: mis.SummaryText,
MstId: mis.MstId,
Missions: {}
}
this.groupedMissions[mis.MstId].Missions[mis.Id] = { Id: mis.Id, Path: mis.Path, Enabled: mis.Enabled };
} else {
this.groupedMissions[mis.MstId].Missions[mis.Id] = { Id: mis.Id, Path: mis.Path, Enabled: mis.Enabled };
}
}
for(let key of Object.keys(customMissions)) {
let mis = customMissions[key];
mis.IsCustom = true;
if(!this.groupedMissions[mis.MstId]) {
this.groupedMissions[mis.MstId] = {
IsCustom: true,
Name: mis.Name,
SummaryText: mis.SummaryText,
MstId: mis.MstId,
Missions: {}
}
this.groupedMissions[mis.MstId].Missions[mis.Id] = { Id: mis.Id, Path: mis.Path, Enabled: mis.Enabled, IsCustom: true };
} else {
this.groupedMissions[mis.MstId].Missions[mis.Id] = { Id: mis.Id, Path: mis.Path, Enabled: mis.Enabled, IsCustom: true };
}
}
}
get translations() { get translations() {
return this.translationsInner[this.currentTranslation]; return this.translationsInner[this.currentTranslation];
} }
@ -117,40 +129,20 @@ class UtageInfo {
return this.charTranslationsInner[this.currentTranslation]; return this.charTranslationsInner[this.currentTranslation];
} }
get questTranslations() { get missionTranslations() {
return this.questTranslationsInner[this.currentTranslation]; return this.missionTranslationsInner[this.currentTranslation];
}
get sceneTranslations() {
return this.sceneTranslationsInner[this.currentTranslation];
} }
setTranslationLanguage(key, missionPath) { setTranslationLanguage(key, missionPath) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.currentTranslation = key; this.currentTranslation = key;
let promises = [this.loadCharacterTranslations(key), let promises = [this.loadCharacterTranslations(key),
this.loadQuestNamesTranslations(key), this.loadMissionNamesTranslations(key)];
this.loadSceneNamesTranslations(key)];
if(missionPath) { if(missionPath) {
promises.push(this.loadMissionTranslation(missionPath, key)); promises.push(this.loadMissionTranslation(missionPath, key));
} }
Promise.all(promises) Promise.all(promises)
.then((success) => { .then((success) => {
// propagate language-based enables downwards from quests to scenes
for (const c of [CUSTOM.custom, CUSTOM.stock]) {
for (const k of Object.keys(this.questTranslationsInner[this.currentTranslation][c])) {
if (this.questTranslationsInner[this.currentTranslation][c][k].Enabled) {
for (const s of this.quests[c][k].Scenes) {
// only propagate if exists in translation file (THANKS GLOBAL) and translated name is supplied
if (c in this.sceneTranslationsInner[this.currentTranslation]
&& s in this.sceneTranslationsInner[this.currentTranslation][c]
&& this.sceneTranslationsInner[this.currentTranslation][c][s].Name != "") {
this.sceneTranslationsInner[this.currentTranslation][c][s].Enabled = true;
}
}
}
}
}
resolve(); resolve();
}, (failure) => { }, (failure) => {
console.log(failure); console.log(failure);
@ -181,7 +173,7 @@ class UtageInfo {
if(this.charTranslationsInner[this.currentTranslation]) { if(this.charTranslationsInner[this.currentTranslation]) {
resolve(); resolve();
} else { } else {
commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/nametranslations_${this.currentTranslation}.json`) commonFunctions.getFileJson(`${utage.rootDirectory}Js/Translations/nametranslations_${this.currentTranslation}.json`)
.then((success) => { .then((success) => {
this.charTranslationsInner[this.currentTranslation] = success; this.charTranslationsInner[this.currentTranslation] = success;
resolve(); resolve();
@ -193,20 +185,21 @@ class UtageInfo {
}); });
} }
loadQuestNamesTranslations() { loadMissionNamesTranslations() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if(this.questTranslationsInner[this.currentTranslation]) { if(this.missionTranslationsInner[this.currentTranslation]) {
resolve(); resolve();
} else { } else {
var promises = [ var promises = [
commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduQuestNames_${this.currentTranslation}.json`), commonFunctions.getFileJson(`${utage.rootDirectory}Js/Translations/XduMissionsNames_${this.currentTranslation}.json`),
commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduQuestNamesCustom_${this.currentTranslation}.json`) commonFunctions.getFileJson(`${utage.rootDirectory}Js/Translations/XduMissionsNamesCustom_${this.currentTranslation}.json`)
]; ];
Promise.all(promises) Promise.all(promises)
.then((success) => { .then((success) => {
this.questTranslationsInner[this.currentTranslation] = {}; for(let m of Object.keys(success[1])) {
this.questTranslationsInner[this.currentTranslation][CUSTOM.stock] = success[0]; success[0][m] = success[1][m];
this.questTranslationsInner[this.currentTranslation][CUSTOM.custom] = success[1]; }
this.missionTranslationsInner[this.currentTranslation] = success[0];
resolve(); resolve();
}, (failure) => { }, (failure) => {
console.log(failure); console.log(failure);
@ -216,59 +209,6 @@ class UtageInfo {
}); });
} }
loadSceneNamesTranslations() {
return new Promise((resolve, reject) => {
if(this.sceneTranslationsInner[this.currentTranslation]) {
resolve();
} else {
var promises = [
commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduSceneNames_${this.currentTranslation}.json`),
commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduSceneNamesCustom_${this.currentTranslation}.json`)
];
Promise.all(promises)
.then((success) => {
this.sceneTranslationsInner[this.currentTranslation] = {};
this.sceneTranslationsInner[this.currentTranslation][CUSTOM.stock] = success[0];
this.sceneTranslationsInner[this.currentTranslation][CUSTOM.custom] = success[1];
resolve();
}, (failure) => {
console.log(failure);
resolve();
});
}
});
}
parseMacroFile(file) {
let lines = file.split('\n');
let header = lines[0].split('\t');
let macro = false;
let name = "";
for (let i = 1; i < lines.length; ++i) {
let line = commonFunctions.readLine(lines[i], header);
if (line && !line.comment) {
if (macro === false) {
if (line.Command[0] === '*') {
name = line.Command.slice(1);
if (!(name in this.macros)) {
macro = true;
this.macros[name] = [];
}
}
} else {
if (line.Command === "EndMacro") {
macro = false;
continue;
}
if (!line.Command && !line.Arg1 && !line.Arg2 && !line.Arg3 && !line.Arg4 && !line.Arg5 && !line.Arg6) {
continue;
}
this.macros[name].push(line);
}
}
}
}
//http://madnesslabo.net/utage/?page_id=4521&lang=en //http://madnesslabo.net/utage/?page_id=4521&lang=en
parseCharacterInfo(text, custom = false) { parseCharacterInfo(text, custom = false) {
let lines = text.split("\n"); let lines = text.split("\n");

View File

@ -15,9 +15,10 @@
<script src="Js/TextFunctions.js"></script> <script src="Js/TextFunctions.js"></script>
<script src="Js/UtageParse.js"></script> <script src="Js/UtageParse.js"></script>
<script src="Js/Audio.js"></script> <script src="Js/Audio.js"></script>
<script src="Js/Player.js"></script>--> <script src="Js/Player.js"></script>
<script src="Js/Main.js"></script> -->
<script src="Js/XduPlayer.min.js"></script> <script src="Js/XduPlayer.min.js"></script>
<div id="loading-container" class="centered" style="z-index: 20;"> <div id="loading-container" class="centered">
<h2 id="loading-utage">Loading Utage Data...</h2> <h2 id="loading-utage">Loading Utage Data...</h2>
<h2 id="loading-font">Loading Page Data...</h2> <h2 id="loading-font">Loading Page Data...</h2>
</div> </div>
@ -25,11 +26,10 @@
<div id="title-container"><span>Now Playing: </span><span id="playing-title">None</span></div> <div id="title-container"><span>Now Playing: </span><span id="playing-title">None</span></div>
<div id="other-controls-container"> <div id="other-controls-container">
<div id="volume-control"> <div id="volume-control">
<span onclick="toggleMute(event)" id="mute-button">&#128266;</span> <!-- loud_sound --> <span onclick="toggleMute(event)" id="mute-button">🔊</span>
<input onchange="onVolumeChange(event)" id="volume-range" value="50" type="range" min="0" max="100" step="1"/> <input onchange="onVolumeChange(event)" id="volume-range" value="50" type="range" min="0" max="100" step="1"/>
</div> </div>
<select id="select-quest" onchange="questDropDownChanged(event);"></select> <select id="select-mission" onchange="missionDropDownChanged(event);"></select>
<select id="select-scene" disabled="true" onchange="sceneDropDownChanged(event);"></select>
<select id="select-language" onchange="languageChanged(event);"></select> <select id="select-language" onchange="languageChanged(event);"></select>
<a style="font-size: 20px; margin-left: 5px;" title="info/help" onclick="openHelpModal(event)">?</a> <a style="font-size: 20px; margin-left: 5px;" title="info/help" onclick="openHelpModal(event)">?</a>
</div> </div>
@ -37,7 +37,7 @@
The canvas then resizes as the canvas does and the text-container uses transform scale based off this resolution --> The canvas then resizes as the canvas does and the text-container uses transform scale based off this resolution -->
<div id="app-container" onclick="onMainClick(event);"> <div id="app-container" onclick="onMainClick(event);">
<div id="text-container"> <div id="text-container">
<div id="fullscreen-button" onclick="toggleFullscreen(event)">&#10133;</div> <!-- heavy_plus_sign --> <div id="fullscreen-button" onclick="toggleFullscreen(event)"></div>
<img id="main-ui-img" class="hidden" src="Images/newui_main.png"/> <img id="main-ui-img" class="hidden" src="Images/newui_main.png"/>
<button id="play-from-query" onclick="playFromQuery(event)" style="display: none;">Play</button> <button id="play-from-query" onclick="playFromQuery(event)" style="display: none;">Play</button>
<div id="title" class="hidden">Title Text</div> <div id="title" class="hidden">Title Text</div>

View File

@ -26,6 +26,9 @@ const cssToCopy = [
"Css/main.min.css", "Css/main.min.css",
"Css/generic.min.css" "Css/generic.min.css"
]; ];
const jsonFiles = [
"Js/BgmLoop.json",
];
const translations = [ const translations = [
"Js/Translations/**" "Js/Translations/**"
]; ];
@ -47,6 +50,7 @@ gulp.task('dist', gulp.series(
buildCss, buildCss,
copyCss copyCss
), ),
buildJson,
buildJsonTranslations, buildJsonTranslations,
copyHtml, copyHtml,
copyImages, copyImages,
@ -113,6 +117,12 @@ function copyCustomData() {
.pipe(gulp.dest('Dist/CustomData')); .pipe(gulp.dest('Dist/CustomData'));
} }
function buildJson() {
return gulp.src(jsonFiles)
.pipe(jsonmin())
.pipe(gulp.dest('Dist/Js'));
}
function buildJsonTranslations() { function buildJsonTranslations() {
return gulp.src(translations) return gulp.src(translations)
.pipe(jsonmin()) .pipe(jsonmin())

8557
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,16 @@
{ {
"name": "XduPlayer", "name": "XduPlayer",
"version": "1.3.0", "version": "1.0.0",
"private": true, "private": true,
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"gulp": "~4.0.2", "gulp": "github:gulpjs/gulp#4.0",
"gulp-concat": "~2.6.1", "gulp-concat": "~2.6.1",
"gulp-cssmin": "~0.2.0", "gulp-cssmin": "~0.2.0",
"gulp-jsonminify": "^1.1.0", "gulp-jsonminify": "^1.1.0",
"gulp-rename": "~1.2.2", "gulp-rename": "~1.2.2",
"gulp-sourcemaps": "~2.6.4", "gulp-sourcemaps": "~2.6.4",
"gulp-uglify": "~3.0.0", "gulp-uglify": "~3.0.0",
"gulp-uglify-es": "~1.0.1", "gulp-uglify-es": "~1.0.1"
"npm": "^6.9.0",
"eslint": "^5.16.0"
} }
} }