Compare commits

...

46 Commits

Author SHA1 Message Date
62e702b9fa Merge pull request 'feature/czechlang' (#9) from feature/czechlang into master 2021-02-16 10:14:42 -05:00
428ea1d660 changed czech font to PTSans 2021-02-15 20:00:30 +01:00
0def56d476 added czech 2021-02-15 19:48:57 +01:00
85f2815b6a added player support for new scene images 2020-10-21 23:54:33 +02:00
7b43a86b99
master tracks master
we're just going to rebuild beta off the most recently pushed branch
2020-09-12 16:39:42 -04:00
1dc54f8590
master branch tracks beta translations 2020-09-12 03:03:52 -04:00
d6ac86ed8c
load name variants
global stinx
2020-08-11 12:32:41 -04:00
afd850fbca
make sure translation is supplied when propagating enables 2020-08-11 11:55:19 -04:00
bdc076b664
fixed player supporting global 2020-08-11 11:55:17 -04:00
47e250ba89 support for global languages 2020-05-16 15:39:41 +02:00
14efed32e3 Merge branch 'master' of https://git.poweris.moe/yttt-xdu/XDUPlayer 2020-04-17 14:26:49 -07:00
90236c665d Since we dont have battles we use "divaeffectcontinue" as a fade out but they also sometimes call "fadeout" so set a flag so we don't do fade out again if we are already doing it. 2020-04-17 14:26:12 -07:00
89a93407f1 Update repository links for submodules and player info 2020-02-18 18:18:02 -05:00
2ca5a9e704 js: move bgmloop to data folder
Having xdu-specific data in this repo doesn't make much sense when most of the
data is fairly general to the engine, plus now I don't have to make a commit
every time I want to update the data.
2019-11-12 18:58:42 -05:00
c6c9c99c31 json: update bgmloop 2019-10-25 17:56:09 -04:00
ae90fd1c37 Updated pixi again with fork because im clearly still doing something wrong and still need the sprite hack. 2019-09-29 11:53:12 -07:00
5ca0935ac6 Updated to Pixi v5.
This also fixes a chrome video preload spec change.
2019-09-29 11:19:51 -07:00
0c039b6ed4 1.3.1 version bump 2019-06-09 21:36:52 -04:00
a93978f39d Fix movecamera since its a macro now. 2019-06-01 14:38:39 -07:00
b6821d4157 fix broken links 2019-05-24 10:00:38 -04:00
d8a5d4d177 changelog: 1.3.0 2019-05-24 04:49:54 -04:00
022250c4c4 fonts: re-enable russian font
idk why bingo disabled this
2019-05-24 04:22:04 -04:00
3101868b30 Merge branch 'quest-json' of https://git.poweris.moe/xduplayer into quest-json 2019-05-21 20:56:42 -07:00
bb409c45a1 Fixes for colorTo and tint not being kept during dialogue. 2019-05-21 20:56:37 -07:00
4716b5e8e8 divamovie: respect volume controls 2019-05-21 22:42:52 -04:00
9dc0c8f9cf enable-guard play all 2019-05-17 18:53:17 -04:00
0d522b55c5 fix urlparams play
single value, questscenemstid
2019-05-17 13:00:05 -04:00
f289381955 Merge branch 'quest-json' of git.poweris.moe:xduplayer into quest-json 2019-05-17 12:59:21 -04:00
c1c6cbfd99 demagicify custom namespace 2019-05-17 12:44:14 -04:00
90625d82b6 css for follow links instead of table. 2019-05-17 09:38:16 -07:00
5dba520155 continue playing scene after selecting specific part 2019-05-17 12:31:44 -04:00
0e9f6f8d70 custom doesn't matter for part select
it's decided by the current scene
2019-05-17 12:05:42 -04:00
8786c54200 bgmloop: update
why is this in this repo
2019-05-17 06:37:26 -04:00
25f7d90951 metadata changes and quest selector 2019-05-17 05:20:02 -04:00
526d0a51cc copy macros
macros were being edited in-place and affecting later uses
2019-05-13 20:22:17 -04:00
737b13da42 custom macros
dug out an old copy of the Macros file from the wedding gears
event and set up the player to merge removed macros
2019-05-13 17:41:01 -04:00
269592c3d6 Merge branch 'master' of https://git.poweris.moe/xduplayer 2019-05-13 13:16:45 -07:00
d4e96c66a8 Removed webpack for gulp again because its simpler for a project this size. 2019-05-13 13:16:40 -07:00
effb55871f utage: divamovie support
this is used for skillmovies that play during some missions
they must first be converted into webm format
2019-05-13 16:13:01 -04:00
77fc6e4d69 Merge branch 'master' of git.poweris.moe:xduplayer 2019-05-13 03:42:32 -04:00
bf11050984 utage macro support
xdu ships with a Macro.tsv, and loading commands
out of there instead of defining them manually
saves a lot of trouble

bingo didn't know about it

there's probably some regressions, needs further testing
2019-05-13 03:31:42 -04:00
1d469d4f3e webpack, eslint
javascript didn't have proper modules until es6 what the fuck

bingo's code scares me so i hope i didn't break it when fixing
the linting errors
2019-05-12 20:59:45 -04:00
e3b7233b20 remove emoji strings
replaced with html entities/creation from unicode code-point where applicable
my editor doesn't render emoji
2019-05-11 23:36:58 -04:00
rdh
d233bf77ce Merge branch 'master' of file:///mnt/bigstuff/source/xduplayer 2018-12-29 12:53:06 -05:00
42e37585d6 urlparams: rewrite 2018-12-29 12:53:03 -05:00
9ca49d25cc urlparams: rewrite 2018-12-29 12:45:27 -05:00
21 changed files with 9831 additions and 7672 deletions

1
.eslintignore Normal file
View File

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

29
.eslintrc.json Normal file
View File

@ -0,0 +1,29 @@
{
"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,6 +3,8 @@
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
@ -10,3 +12,4 @@ 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/xdutranslations.git url = https://git.poweris.moe/yttt-xdu/xdutranslations.git
branch = . branch = master
[submodule "CustomData"] [submodule "CustomData"]
path = CustomData path = CustomData
url = https://git.poweris.moe/customdata.git url = https://git.poweris.moe/yttt-xdu/customdata.git
branch = . branch = .

View File

@ -26,3 +26,25 @@ Fix translation fallback
Add language url parameter Add language url parameter
Fix noise\_disappearance commands 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,6 +84,8 @@ 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; }
@ -122,9 +124,11 @@ body { margin: 0; height: 100%; }
#title-container { padding: 2px 0; } #title-container { padding: 2px 0; }
#other-controls-container { padding-bottom: 4px; display: flex; width: 550px; justify-content: center; align-items: center; z-index: 10; } #other-controls-container { padding-bottom: 4px; display: flex; width: 100%; justify-content: center; align-items: center; z-index: 10; }
#select-mission { min-width: 0; } #select-quest { min-width: 0; width: 25% }
#select-scene { min-width: 0; width: 25% }
#select-language { margin-left: 10px; } #select-language { margin-left: 10px; }
@ -154,6 +158,12 @@ 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 e45642773aa255babfde41b770ce1e4c78ca5251 Subproject commit e92af8f0d0c0d4246e44dd0b63508f9e460fe3a8

View File

@ -1,5 +1,4 @@
//(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) {
@ -182,4 +181,4 @@ class audioController {
} }
this.sources = {}; this.sources = {};
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,11 @@ 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) => {
@ -334,8 +339,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 loader: PIXI.Loader.shared
}; };
const utage = new UtageInfo(); const utage = new UtageInfo();
@ -10,16 +10,17 @@ 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"]; const languages = ["eng", "jpn", "rus", "cze", "enm", "kor", "zho"];
const version = "YameteTomete XDUPlayer V1.2.2"; const version = "YameteTomete XDUPlayer V1.5.0";
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 currentMission = undefined; let currentScene = {};
let currentMissionMst = 0; let currentSceneId = "";
let currentMissionIndex = 0; let scenePlaylist = [];
let currentMissionList = []; let currentPart = "";
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);
@ -27,7 +28,14 @@ let screenSizeTimeout = undefined;
let isMuted = false; let isMuted = false;
let volume = 0.5; let volume = 0.5;
let fullScreen = false; let fullScreen = false;
let prevMission = '{Select}'; let prevScene = '{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;
@ -54,6 +62,7 @@ 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) {
@ -69,7 +78,8 @@ function onBodyLoaded() {
function onAllLoaded(success) { function onAllLoaded(success) {
textFunc.findTextElements(); textFunc.findTextElements();
buildMissionSelectList(); buildQuestSelectList();
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);
@ -83,7 +93,6 @@ function onAllLoaded(success) {
function loadLocalStorage() { function loadLocalStorage() {
try { try {
urlParams = commonFunctions.readQueryParameters();
//audio //audio
volume = localStorage.getItem('volume') || 0.5; volume = localStorage.getItem('volume') || 0.5;
volume = Number(volume); volume = Number(volume);
@ -96,9 +105,9 @@ function loadLocalStorage() {
audio.mute(isMuted); audio.mute(isMuted);
} }
if(isMuted) { if(isMuted) {
document.getElementById('mute-button').innerText = "🔇"; document.getElementById('mute-button').innerText = emoji.Mute;
} else { } else {
document.getElementById('mute-button').innerText = "🔊"; document.getElementById('mute-button').innerText = emoji.LoudSound;
} }
//language //language
let lang = urlParams['lang'] || localStorage.getItem('language') || "eng"; let lang = urlParams['lang'] || localStorage.getItem('language') || "eng";
@ -118,27 +127,79 @@ function loadLocalStorage() {
} }
} }
function buildMissionSelectList() { function buildQuestSelectList() {
let selectBox = document.getElementById('select-mission'); let questBox = document.getElementById('select-quest');
selectBox.innerHTML = ''; questBox.innerHTML = '';
for(let i = -1; i < utage.missionsList.length; ++i) { for (let i = -1; i < utage.questList.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 Mission'; opt.innerText = 'Select Event';
} else { } else {
let m = utage.missionsList[i]; let q = utage.questList[i];
if(!Object.keys(utage.groupedMissions[m.MstId].Missions).some((mis) => { return utage.groupedMissions[m.MstId].Missions[mis].Enabled === true })) { let cust = q.IsCustom ? CUSTOM.custom : CUSTOM.stock;
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;
} }
opt.setAttribute('value', m.MstId); if (!tl_key.Enabled && !utage.quests[cust][q.QuestMstId].Scenes.some((s) => { return utage.sceneTranslations[cust][s].Enabled === true })) {
let name = m.Name; continue;
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;
} }
selectBox.appendChild(opt); questBox.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);
} }
} }
@ -156,29 +217,85 @@ function buildLanguageList() {
function checkQueryParameters() { function checkQueryParameters() {
urlParams = commonFunctions.readQueryParameters(); urlParams = commonFunctions.readQueryParameters();
if(urlParams['mstid'] && urlParams['id'] && utage.groupedMissions[urlParams['mstid']] && utage.groupedMissions[urlParams['mstid']].Missions[urlParams['id']]) { if (languagesLoaded) {
document.getElementById('play-from-query').style.cssText = "position: fixed; z-index: 15; text-align: center; top: 50%; left: 50%; display: block;"; 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;";
}
} }
} }
function playFromQuery(event) { function playFromQuery(event) {
missionChanged(urlParams['mstid'], urlParams['id']); let cust;
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 missionDropDownChanged(event) { function questDropDownChanged(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 mis = utage.groupedMissions[misId]; let cust = event.currentTarget.value.split("|")[0];
if(!mis) { console.log(`Mission ${misId} not found`); return; } let questSceneMstId = event.currentTarget.value.split("|")[1];
let name = mis.Name;
let summary = mis.SummaryText; let scene = utage.scenes[cust][questSceneMstId];
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 = "";
if(utage.missionTranslations[mis.MstId]) { let tl_key = utage.sceneTranslations[cust][questSceneMstId];
name = utage.missionTranslations[mis.MstId].Name || name;
summary = utage.missionTranslations[mis.MstId].SummaryText || summary; if(tl_key) {
credits = utage.missionTranslations[mis.MstId].Credits || credits; name = tl_key.Name || name;
summary = tl_key.SummaryText || summary;
credits = tl_key.Credits || credits;
} }
if(!credits) { if(!credits) {
if(selectedLang === "eng") { if(selectedLang === "eng") {
@ -187,15 +304,15 @@ function missionDropDownChanged(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">';
for(let k of Object.keys(mis.Missions)) { chapterSelect += `<option value="{All}">Play All</option>`
var m = mis.Missions[k]; for (const p of scene.Parts) {
if(m.Enabled) { chapterSelect += `<option value="${p}">${p}</option>`
chapterSelect += `<option value="${m.Id}">${m.Id}</option>`
}
} }
let detailSrc = `${utage.rootDirectory}${(mis.IsCustom ? "CustomData" : "XDUData")}/Asset/Image/Quest/Snap/Detail/${mis.MstId}.png`;
let iconSrc = `${utage.rootDirectory}${(mis.IsCustom ? "CustomData" : "XDUData")}/Asset/Image/Quest/Snap/Icon/${mis.MstId}.png`; let detailSrc = `${utage.rootDirectory}${(scene.IsCustom ? "CustomData" : "XDUData")}/Asset/Image/Quest/Snap/Detail/${image}.png`;
let iconSrc = `${utage.rootDirectory}${(scene.IsCustom ? "CustomData" : "XDUData")}/Asset/Image/Quest/Snap/Icon/${image}.png`;
chapterSelect += '</select></div>'; chapterSelect += '</select></div>';
cont.innerHTML = ` cont.innerHTML = `
<div id="mission-modal" class="modal"> <div id="mission-modal" class="modal">
@ -210,8 +327,8 @@ function missionDropDownChanged(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: ${mis.MstId}</span> <span>MstId: ${questSceneMstId}</span>
<button onclick="missionChanged(${mis.MstId})">Play</button> <button onclick="sceneSet('${questSceneMstId}', '${cust}')">Play</button>
</div> </div>
</div>`; </div>`;
document.getElementById("click-catcher").style.cssText = 'display: flex;'; document.getElementById("click-catcher").style.cssText = 'display: flex;';
@ -220,10 +337,18 @@ function missionDropDownChanged(event) {
function closeMissionModal(event, wasStarted) { function closeMissionModal(event, wasStarted) {
if(!wasStarted) { if(!wasStarted) {
document.getElementById('select-mission').value = prevMission; document.getElementById('select-scene').value = prevScene;
document.getElementById('select-quest').value = prevQuest;
} else { } else {
prevMission = document.getElementById('select-mission').value; prevScene = document.getElementById('select-scene').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);
} }
@ -234,67 +359,85 @@ function closeModal(event) {
cont.innerHTML = ''; cont.innerHTML = '';
} }
function missionChanged(mstId, value) { function sceneSet(questSceneMstId, cust) {
let mst = utage.groupedMissions[mstId]; resetPlaylist();
let name = mst.Name; let part = document.getElementById('ChapterSelect');
if(utage.missionTranslations[mstId]) { utage.scenes[cust][questSceneMstId]['QuestSceneMstId'] = questSceneMstId;
name = utage.missionTranslations[mstId].Name || name; if (!part || part.value === '{All}') {
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) => {
let newMission = mst.Missions[value]; if (scenePlaylist.length || partPlaylist.length) {
checkMissionList(mst.Missions, value); document.getElementById("skip-button").style.cssText = "display: inline-block;";
currentMission = newMission; } else {
currentMissionMst = mstId; document.getElementById("skip-button").style.cssText = "display: none;";
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(newMission.IsCustom) { if(currentScene.IsCustom) {
promises.push(utage.parseMissionFile(`${utage.rootDirectory}CustomData/${newMission.Path.replace('Asset/', '').replace('.utage', '').replace('.tsv', '_t.tsv')}`)); promises.push(utage.parseMissionFile(`${utage.rootDirectory}CustomData/Utage/${currentScene.Folder}/Scenario/${part}_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/${newMission.Path.replace('Asset/', '').replace('.utage', '').replace('.tsv', '_t.tsv')}`)); promises.push(utage.parseMissionFile(`${utage.rootDirectory}XDUData/Utage/${currentScene.Folder}/Scenario/${part}_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} (${value})`; document.getElementById("playing-title").innerText = `${name} (${part})`;
document.getElementById("title-tag").innerText = name; document.getElementById("title-tag").innerText = name;
currentPart = part;
player.playFile() player.playFile()
.then((success) => { .then((success) => {
if(currentMissionIndex !== currentMissionList.length - 1) { playNext();
missionChanged(currentMissionMst, mst.Missions[currentMissionList[currentMissionIndex+1]].Id);
} else {
player.resetAll();
resetMissions();
}
}, (failure) => { }, (failure) => {
player.resetAll(); player.resetAll();
resetMissions(); resetPlaylist();
console.log(failure); console.log(failure);
}); });
}, (failure) => { }, (failure) => {
resetMissions(); resetPlaylist();
console.log(failure); console.log(failure);
}); });
}, (failure) => { }, (failure) => {
@ -306,43 +449,32 @@ 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(currentMission) { if(currentPart) {
missionPath = `${utage.rootDirectory}Js/Translations/Missions/${currentMission.Path.replace('Asset/Utage/', '').replace('Scenario/', '').replace('.utage', '').replace('.tsv', `_translations_${selectedLang}.json`)}`; if (currentScene.IsCustom) {
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;
buildMissionSelectList(); buildQuestSelectList();
buildSceneSelectList();
localStorage.setItem('language', selectedLang); localStorage.setItem('language', selectedLang);
}); });
} }
function checkMissionList(missions, currentvalue) { function resetPlaylist() {
currentMissionList = []; currentScene = {};
let i = 0; scenePlaylist = [];
for(var m of Object.keys(missions)) { currentPart = "";
currentMissionList.push(m); partPlaylist = [];
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-mission').value = '{Select}'; document.getElementById("select-quest").value = '{Select}';
buildSceneSelectList();
} }
function onMainClick(event) { function onMainClick(event) {
@ -356,20 +488,10 @@ 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 && currentMissionIndex !== currentMissionList.length - 1) { } else if(player.runEvent) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
//Find the next enabled mission playNext();
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();
} }
} }
@ -415,11 +537,17 @@ function openHelpModal(event) {
iOS: 11+, no audio<br/> iOS: 11+, no audio<br/>
</div> </div>
</div> </div>
<a style="margin-top: auto; text-align: center; "href="https://discord.gg/fpQZQ8g">YameteTomete Discord</a> <div class="follow-links">
<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/xduplayer.git/" target="_blank">Source</a> <a href="https://git.poweris.moe/yttt-xdu/XDUPlayer" target="_blank">Source</a>
</div> </div>
</div>`; </div>`;
document.getElementById("click-catcher").style.cssText = 'display: flex;'; document.getElementById("click-catcher").style.cssText = 'display: flex;';
@ -433,9 +561,9 @@ function toggleMute(event) {
} }
localStorage.setItem('ismuted', isMuted); localStorage.setItem('ismuted', isMuted);
if(isMuted) { if(isMuted) {
document.getElementById('mute-button').innerText = "🔇"; document.getElementById('mute-button').innerText = emoji.Mute;
} else { } else {
document.getElementById('mute-button').innerText = "🔊"; document.getElementById('mute-button').innerText = emoji.LoudSound;
} }
} }
@ -474,7 +602,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 = ""; document.getElementById('fullscreen-button').innerText = emoji.HeavyPlusSign;
} }
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,25 +1,20 @@
//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 vec2 dimensions; uniform vec4 inputPixel;
uniform vec4 filterArea; uniform highp vec4 outputFrame;
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; vec2 uv = vTextureCoord * inputPixel.xy / outputFrame.zw;
vec2 mappedCoord = mapCoord(uv) / dimensions; vec2 mappedCoord = uv;
float step2 = time; float step2 = time;
float step3 = time + 0.2; float step3 = time + 0.2;
@ -35,21 +30,16 @@ class Shaders {
this.rightToLeftFadeShader = ` this.rightToLeftFadeShader = `
precision mediump float; precision mediump float;
varying vec2 vTextureCoord; varying vec2 vTextureCoord;
uniform vec2 dimensions; uniform vec4 inputPixel;
uniform vec4 filterArea; uniform highp vec4 outputFrame;
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; vec2 uv = vTextureCoord * inputPixel.xy / outputFrame.zw;
vec2 mappedCoord = mapCoord(uv) / dimensions; vec2 mappedCoord = uv;
float step2 = (1.0 - time); float step2 = (1.0 - time);
float step3 = (1.0 - time) - 0.2; float step3 = (1.0 - time) - 0.2;
@ -65,22 +55,16 @@ class Shaders {
this.downToUpFadeShader = ` this.downToUpFadeShader = `
precision mediump float; precision mediump float;
varying vec2 vTextureCoord; varying vec2 vTextureCoord;
uniform vec2 dimensions; uniform vec4 inputPixel;
uniform vec4 filterArea; uniform highp vec4 outputFrame;
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; vec2 uv = vTextureCoord * inputPixel.xy / outputFrame.zw;
vec2 mappedCoord = mapCoord(uv) / dimensions; vec2 mappedCoord = uv;
float step2 = (1.0 - time); float step2 = (1.0 - time);
float step3 = (1.0 - time) - 0.2; float step3 = (1.0 - time) - 0.2;
@ -96,22 +80,16 @@ class Shaders {
this.uptoDownFadeShader = ` this.uptoDownFadeShader = `
precision mediump float; precision mediump float;
varying vec2 vTextureCoord; varying vec2 vTextureCoord;
uniform vec2 dimensions; uniform vec4 inputPixel;
uniform vec4 filterArea; uniform highp vec4 outputFrame;
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; vec2 uv = vTextureCoord * inputPixel.xy / outputFrame.zw;
vec2 mappedCoord = mapCoord(uv) / dimensions; vec2 mappedCoord = uv;
float step2 = time; float step2 = time;
float step3 = time + 0.2; float step3 = time + 0.2;
@ -128,7 +106,6 @@ 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 )
@ -149,10 +126,11 @@ 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] }
}); });
@ -161,7 +139,6 @@ 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] }
}); });
@ -170,7 +147,6 @@ 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] }
}); });
@ -179,7 +155,6 @@ 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] }
}); });
@ -187,16 +162,13 @@ 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,7 +84,6 @@ 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;
@ -191,4 +190,4 @@ class TextFunctions {
this.scrollingText = false; this.scrollingText = false;
this.lineHeight = -1; this.lineHeight = -1;
} }
} }

@ -1 +1 @@
Subproject commit dc15df970a33c34dd53654fb77ce775ee9e3f051 Subproject commit ac0bfbd699431e9befdd843379e7c91ad1014cec

View File

@ -6,7 +6,9 @@ class UtageInfo {
this.currentPlayingFile = []; this.currentPlayingFile = [];
this.rootDirectory = ``; this.rootDirectory = ``;
this.groupedMissions = {}; this.groupedMissions = {};
this.missionsList = []; this.quests = {};
this.questList = [];
this.scenes = {};
this.characterInfo = {}; this.characterInfo = {};
this.layerInfo = {}; this.layerInfo = {};
this.localizeInfo = {}; this.localizeInfo = {};
@ -16,51 +18,71 @@ class UtageInfo {
this.currentTranslation = 'eng'; this.currentTranslation = 'eng';
this.translationsInner = {}; this.translationsInner = {};
this.charTranslationsInner = {}; this.charTranslationsInner = {};
this.missionTranslationsInner = {}; this.questTranslationsInner = {};
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/XduMissions.json`), //0 commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduQuest.json`), //0
commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Character.tsv`), //1 commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduScene.json`), //1
commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Layer.tsv`), //2 commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Character.tsv`), //2
commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Localize.tsv`), //3 commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Layer.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`), //4 commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Sound.tsv`), //5
commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Texture.tsv`), //5 commonFunctions.getFileText(`${this.rootDirectory}XDUData/Utage/Diva/Settings/Texture.tsv`), //6
commonFunctions.getFileJson(`${this.rootDirectory}Js/BgmLoop.json`), //6 commonFunctions.getFileJson(`${this.rootDirectory}XDUData/Bgm/BgmLoop.json`), //7
commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduMissionsCustom.json`), //7 commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduQuestCustom.json`), //8
commonFunctions.getFileText(`${this.rootDirectory}CustomData/Utage/Diva/Settings/CustomCharacter.tsv`), //8 commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduSceneCustom.json`), //9
commonFunctions.getFileText(`${this.rootDirectory}CustomData/Utage/Diva/Settings/CustomSound.tsv`), //9 commonFunctions.getFileText(`${this.rootDirectory}CustomData/Utage/Diva/Settings/CustomCharacter.tsv`), //10
commonFunctions.getFileText(`${this.rootDirectory}CustomData/Utage/Diva/Settings/CustomTexture.tsv`), //10 commonFunctions.getFileText(`${this.rootDirectory}CustomData/Utage/Diva/Settings/CustomSound.tsv`), //11
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.groupMissions(success[0], success[7]); this.quests[CUSTOM.stock] = success[0];
this.missionsList = Object.keys(this.groupedMissions).map((k) => { this.questList = Object.keys(this.quests[CUSTOM.stock]).map((k) => {
return {Name: this.groupedMissions[k].Name, MstId: this.groupedMissions[k].MstId}; return {QuestMstId: k, Name: this.quests[CUSTOM.stock][k].Name, IsCustom: false};
}); });
this.missionsList.sort(); this.quests[CUSTOM.custom] = success[8];
this.parseCharacterInfo(success[1]); for (const k of Object.keys(this.quests[CUSTOM.custom])) {
this.parseLayerInfo(success[2]); this.questList.push({QuestMstId: k, Name: this.quests[CUSTOM.custom][k].Name, IsCustom: true});
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[4]); this.parseSoundInfo(success[5]);
this.parseTextureInfo(success[5]); this.parseTextureInfo(success[6]);
this.bgmLoopData = success[6]; this.bgmLoopData = success[7];
this.parseCharacterInfo(success[8], true); this.scenes[CUSTOM.custom] = success[9];
this.parseSoundInfo(success[9], true); for (const k of Object.keys(this.scenes[CUSTOM.custom])) {
this.parseTextureInfo(success[10], true); this.scenes[CUSTOM.custom][k]['IsCustom'] = 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);
}); });
}); });
} }
parseMissionFile(file) { parseMissionFile(file) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
commonFunctions.getFileText(file) commonFunctions.getFileText(file)
@ -86,41 +108,7 @@ 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];
} }
@ -129,20 +117,40 @@ class UtageInfo {
return this.charTranslationsInner[this.currentTranslation]; return this.charTranslationsInner[this.currentTranslation];
} }
get missionTranslations() { get questTranslations() {
return this.missionTranslationsInner[this.currentTranslation]; return this.questTranslationsInner[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.loadMissionNamesTranslations(key)]; this.loadQuestNamesTranslations(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);
@ -173,7 +181,7 @@ class UtageInfo {
if(this.charTranslationsInner[this.currentTranslation]) { if(this.charTranslationsInner[this.currentTranslation]) {
resolve(); resolve();
} else { } else {
commonFunctions.getFileJson(`${utage.rootDirectory}Js/Translations/nametranslations_${this.currentTranslation}.json`) commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/nametranslations_${this.currentTranslation}.json`)
.then((success) => { .then((success) => {
this.charTranslationsInner[this.currentTranslation] = success; this.charTranslationsInner[this.currentTranslation] = success;
resolve(); resolve();
@ -185,21 +193,20 @@ class UtageInfo {
}); });
} }
loadMissionNamesTranslations() { loadQuestNamesTranslations() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if(this.missionTranslationsInner[this.currentTranslation]) { if(this.questTranslationsInner[this.currentTranslation]) {
resolve(); resolve();
} else { } else {
var promises = [ var promises = [
commonFunctions.getFileJson(`${utage.rootDirectory}Js/Translations/XduMissionsNames_${this.currentTranslation}.json`), commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduQuestNames_${this.currentTranslation}.json`),
commonFunctions.getFileJson(`${utage.rootDirectory}Js/Translations/XduMissionsNamesCustom_${this.currentTranslation}.json`) commonFunctions.getFileJson(`${this.rootDirectory}Js/Translations/XduQuestNamesCustom_${this.currentTranslation}.json`)
]; ];
Promise.all(promises) Promise.all(promises)
.then((success) => { .then((success) => {
for(let m of Object.keys(success[1])) { this.questTranslationsInner[this.currentTranslation] = {};
success[0][m] = success[1][m]; this.questTranslationsInner[this.currentTranslation][CUSTOM.stock] = success[0];
} this.questTranslationsInner[this.currentTranslation][CUSTOM.custom] = success[1];
this.missionTranslationsInner[this.currentTranslation] = success[0];
resolve(); resolve();
}, (failure) => { }, (failure) => {
console.log(failure); console.log(failure);
@ -208,6 +215,59 @@ 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) {
@ -362,4 +422,4 @@ class UtageInfo {
resetTranslations() { resetTranslations() {
this.translationsInner = {}; this.translationsInner = {};
} }
} }

View File

@ -15,10 +15,9 @@
<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"> <div id="loading-container" class="centered" style="z-index: 20;">
<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>
@ -26,10 +25,11 @@
<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">🔊</span> <span onclick="toggleMute(event)" id="mute-button">&#128266;</span> <!-- loud_sound -->
<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-mission" onchange="missionDropDownChanged(event);"></select> <select id="select-quest" onchange="questDropDownChanged(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)"></div> <div id="fullscreen-button" onclick="toggleFullscreen(event)">&#10133;</div> <!-- heavy_plus_sign -->
<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>
@ -78,4 +78,4 @@
<span style="font-family: 'SourceCodePro-Regular'">test</span> --> <span style="font-family: 'SourceCodePro-Regular'">test</span> -->
</div> </div>
</body> </body>
</html> </html>

View File

@ -26,9 +26,6 @@ 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/**"
]; ];
@ -50,7 +47,6 @@ gulp.task('dist', gulp.series(
buildCss, buildCss,
copyCss copyCss
), ),
buildJson,
buildJsonTranslations, buildJsonTranslations,
copyHtml, copyHtml,
copyImages, copyImages,
@ -117,12 +113,6 @@ 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())

14467
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,18 @@
{ {
"name": "XduPlayer", "name": "XduPlayer",
"version": "1.0.0", "version": "1.3.0",
"private": true, "private": true,
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"gulp": "github:gulpjs/gulp#4.0", "gulp": "~4.0.2",
"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"
} }
} }