Added mission select modal.
Changed file structure so images called like file:// can be loaded properly. Some commenting.
This commit is contained in:
parent
7a5c02d736
commit
57ddeb08f4
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,3 +8,4 @@ web.config
|
||||
/Fonts
|
||||
/Dist
|
||||
/Css/main.min.css
|
||||
/Js/XduPlayer.min.js
|
||||
|
29
Css/main.css
29
Css/main.css
@ -108,6 +108,33 @@
|
||||
|
||||
#volume-control #mute-button { cursor: pointer; }
|
||||
|
||||
@media screen and (max-width: 550px) {
|
||||
#click-catcher { background-color: #000000; opacity: 0.7; position: fixed; z-index: 15; top: 0; bottom: 0; left: 0; right: 0; }
|
||||
|
||||
#modal-container { position: fixed; z-index: 16; top: 50%; left: 50%; transform: translate(-50%, -50%); }
|
||||
|
||||
.modal { background-color: #393939; color: #F0F0F0; height: 400px; width: 350px; position: relative; margin: auto; display: flex; flex-direction: column; align-items: center; box-shadow: 0px 0px 20px 3px #070707; border-radius: 7px; box-sizing: border-box; padding: 10px; }
|
||||
|
||||
#mission-modal { }
|
||||
|
||||
#mission-modal #mission-detail { display: block; width: 100%; margin: 10px 0 10px 0; object-fit: contain; }
|
||||
|
||||
#mission-modal #mission-icon { display: none; margin: 10px 0 10px 0; object-fit: contain; }
|
||||
|
||||
#mission-modal span { max-width: 100%; word-break: break-word; max-height: 120px; overflow: auto;}
|
||||
|
||||
#mission-modal .mission-title { text-align: center; }
|
||||
|
||||
#mission-modal #mission-ids { margin-top: auto; width: 100%; display: flex; justify-content: space-around; }
|
||||
|
||||
#modal-buttons { bottom: 0; margin-top: 10px; width: 100%; display: flex; justify-content: space-between; }
|
||||
|
||||
@media screen and (max-width: 812px) {
|
||||
#modal-container { top: 0; bottom: 0; left: 0; right: 0; transform: none; }
|
||||
.modal { width: 100%; height: 100%; border-radius: 0; }
|
||||
#other-controls-container { width: 100vw; }
|
||||
}
|
||||
|
||||
@media screen and (max-height: 600px) {
|
||||
#mission-modal #mission-detail { display: none; }
|
||||
#mission-modal #mission-icon { display: block; max-height: 20%; margin: 10px 0 10px 0; object-fit: contain; }
|
||||
}
|
@ -173,7 +173,7 @@ class commonFunctions {
|
||||
}
|
||||
|
||||
static getPropertiesFromTweenCommand(props, reverseY = true) {
|
||||
var retval = {};
|
||||
let retval = {};
|
||||
let indexX = props.indexOf("x=");
|
||||
if(indexX !== -1) {
|
||||
retval.x = "";
|
||||
|
49
Js/Main.js
49
Js/Main.js
@ -20,6 +20,7 @@ let screenh = Math.max(document.documentElement.clientHeight, window.innerHeight
|
||||
let screenSizeTimeout = undefined;
|
||||
let isMuted = false;
|
||||
let volume = 0.5;
|
||||
let prevMission = '{Select}';
|
||||
|
||||
function onBodyLoaded() {
|
||||
bodyLoaded = true;
|
||||
@ -99,9 +100,9 @@ function buildMissionSelectList() {
|
||||
opt.innerText = 'Select Mission';
|
||||
} else {
|
||||
let m = utage.missionsList[i];
|
||||
//if(m.includes('MA1-') || m.includes('MA2-')|| m.includes('MA3-')) {
|
||||
// continue;
|
||||
//}
|
||||
if(!m.includes('MA3.5-')) {
|
||||
continue;
|
||||
}
|
||||
opt.setAttribute('value', m);
|
||||
opt.innerText = m.replace('|', ' - ');
|
||||
}
|
||||
@ -121,16 +122,52 @@ function buildLanguageList() {
|
||||
selectBox.value = selectedLang;
|
||||
}
|
||||
|
||||
function missionChanged(event) {
|
||||
function missionDropDownChanged(event) {
|
||||
if(!event || !event.currentTarget || !event.currentTarget.value || event.currentTarget.value === '{Select}') { return; }
|
||||
|
||||
let newMission = utage.availableMissions[event.currentTarget.value.split('|')[0]];
|
||||
let cont = document.getElementById("modal-container");
|
||||
let misId = event.currentTarget.value.split('|')[0];
|
||||
let mis = utage.availableMissions[misId];
|
||||
if(!mis) { console.log(`Mission ${misId} not found`); return; }
|
||||
cont.innerHTML = '' +
|
||||
'<div id="mission-modal" class="modal">' +
|
||||
`<span class="mission-title">Name: ${mis.Name || 'none'}</span>` +
|
||||
`<img id="mission-detail" src="${rootUrl}XDUPlayer/XDUData/Asset/Image/Quest/Snap/Detail/${mis.MstId}.png">` +
|
||||
`<img id="mission-icon" src="${rootUrl}XDUPlayer/XDUData/Asset/Image/Quest/Snap/Icon/${mis.MstId}.png">` +
|
||||
`<span>Summary: ${mis.SummaryText || 'none'}</span>` +
|
||||
'<div id="mission-ids">' +
|
||||
`<span>MstId: ${mis.MstId}</span>` +
|
||||
`<span>Id: ${mis.Id}</span>` +
|
||||
'</div>' +
|
||||
'<div id="modal-buttons">' +
|
||||
'<button onclick="closeMissionModal(event, false)">Close</button>' +
|
||||
`<button onclick="missionChanged(${misId})">Play</button>` +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
document.getElementById("click-catcher").style.cssText = 'display: flex;';
|
||||
cont.style.cssText = 'display: flex;';
|
||||
}
|
||||
|
||||
function closeMissionModal(event, wasStarted) {
|
||||
if(!wasStarted) {
|
||||
document.getElementById('select-mission').value = prevMission;
|
||||
} else {
|
||||
prevMission = document.getElementById('select-mission').value;
|
||||
}
|
||||
let cont = document.getElementById("modal-container");
|
||||
document.getElementById("click-catcher").style.cssText = 'display: none;';
|
||||
cont.style.cssText = 'display: none;';
|
||||
cont.innerHTML = '';
|
||||
}
|
||||
|
||||
function missionChanged(value) {
|
||||
let newMission = utage.availableMissions[value];
|
||||
currentMission = newMission;
|
||||
let promises = [
|
||||
utage.parseMissionFile(`${utage.rootDirectory}XDUData/${newMission.Path.replace('Asset/', '').replace('.utage', '').replace('.tsv', '_t.tsv')}`),
|
||||
utage.loadMissionTranslation(`${utage.rootDirectory}XDUData/${newMission.Path.replace('Asset/', '').replace('.utage', '').replace('.tsv', `_translations_${selectedLang}.json`)}`, selectedLang),
|
||||
player.resetAll()
|
||||
];
|
||||
closeMissionModal(undefined, true);
|
||||
|
||||
Promise.all(promises)
|
||||
.then((success) => {
|
||||
|
66
Js/Player.js
66
Js/Player.js
@ -9,14 +9,13 @@ class Player {
|
||||
this.text = text;
|
||||
this.audio = audio;
|
||||
//consts
|
||||
this.resolutionScale = 1;
|
||||
this.resolutionScale = 1; //I created this thinking that I would need to handle changing offset when resolution changes. But lucikly I can just scale the parent container and it works without needing this.
|
||||
this.baseFps = 60; //I am assuming that PIXI is going to stay as keeping 60fps = delta1.
|
||||
this.bgLayerName = "背景";
|
||||
this.defaultCharPattern = 'すまし';
|
||||
this.bgLayerName = "背景"; //The label for the BG layer.
|
||||
this.defaultCharPattern = 'すまし'; //The mission file doesn't always give a pattern for putting a character on the screen.
|
||||
this.backCharTint = 0x808080;
|
||||
this.titleWaitTime = 1;
|
||||
this.titleWaitTime = 5;
|
||||
|
||||
this.blackBackSp = undefined;
|
||||
this.currentCharacters = {};
|
||||
this.lastCharOffLayer = undefined;
|
||||
this.layers = {};
|
||||
@ -49,6 +48,7 @@ class Player {
|
||||
return runningPromise;
|
||||
}
|
||||
|
||||
//Runs through the tsv file and loads any files it will need to play.
|
||||
preCheckFilesToGet() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let toLoadBgm = {};
|
||||
@ -143,7 +143,9 @@ class Player {
|
||||
});
|
||||
}
|
||||
|
||||
//note containers render in the order they are added, eg. the last added is always on top.
|
||||
//Creates all the pixi containers for ther layers defined in layers.tsv
|
||||
//also creates containers for fading
|
||||
//note containers render in the order they are added, eg. the last added is always on top
|
||||
buildLayerContainers() {
|
||||
let layersToAdd = [];
|
||||
for(let l of Object.keys(this.utage.layerInfo)) {
|
||||
@ -180,6 +182,8 @@ class Player {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Laoding progress functions
|
||||
onPixiProgress(loader, resource) {
|
||||
this.assetLoadPercent = loader.progress;
|
||||
this.text.titleText(true, `Loading Assets... ${loader.progress.toFixed(0)}%`);
|
||||
@ -211,9 +215,9 @@ class Player {
|
||||
}
|
||||
}
|
||||
|
||||
//Runs every frame. Delta is a float scaled from 1=60fps.
|
||||
onPixiTick(delta) {
|
||||
try
|
||||
{
|
||||
try {
|
||||
if(!this.runEvent) { return; }
|
||||
let deltaTime = (1000/this.baseFps)*delta;
|
||||
this.secondTicker -= deltaTime;
|
||||
@ -243,6 +247,8 @@ class Player {
|
||||
}
|
||||
}
|
||||
|
||||
//This loop is run every frame and handles all the animation liek tweens in the mission.
|
||||
//interpolation is not just linear even if its called HandleLerps
|
||||
loopHandleLerps(deltaTime) {
|
||||
try {
|
||||
//Loop through the lerp targets, modify the needed objects. If a object is at its 1 time state remove it from the list.
|
||||
@ -310,27 +316,23 @@ class Player {
|
||||
}
|
||||
}
|
||||
|
||||
//Processes a line from the mission tsv
|
||||
processCommand(delta) {
|
||||
try {
|
||||
let cur = this.currentCommand;
|
||||
//if(this.checkIfAllOff()) {
|
||||
// this.text.dialogText(false, "");
|
||||
// this.text.characterName(false, "");
|
||||
//} else {
|
||||
// this.text.dialogText(true, "");
|
||||
// this.text.characterName(true, "");
|
||||
//}
|
||||
switch((cur.Command || "").toLowerCase()) {
|
||||
case "scenetitle01":
|
||||
case "scenetitle01": {
|
||||
this.waitTime = this.titleWaitTime * 1000;
|
||||
var text = cur.English ? (utage.currentTranslation[cur.English] || cur.Text) : cur.Text;
|
||||
let text = cur.English ? (utage.currentTranslation[cur.English] || cur.Text) : cur.Text;
|
||||
this.text.titleText(true, text);
|
||||
break;
|
||||
case "divaeffect":
|
||||
this.waitTime = 1000//Number(cur.Arg5) * 1000;
|
||||
var text = cur.English ? (utage.currentTranslation[cur.English] || cur.Text) : cur.Text;
|
||||
}
|
||||
case "divaeffect": {
|
||||
this.waitTime = Number(cur.Arg5) * 1000;
|
||||
let text = cur.English ? (utage.currentTranslation[cur.English] || cur.Text) : cur.Text;
|
||||
this.text.divaText(true, text);
|
||||
break;
|
||||
}
|
||||
//FadeTo
|
||||
case "fadeout":
|
||||
this.text.dialogText(false, "");
|
||||
@ -457,13 +459,14 @@ class Player {
|
||||
this.processShake(delta, cur);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
this.processCommandOther(delta);
|
||||
break;
|
||||
//custom effects
|
||||
case "henshin01_bgmoff":
|
||||
this.audio.stopSound('bgm');
|
||||
this.checkPutCharacterScreen(cur, true);
|
||||
break;
|
||||
default:
|
||||
this.processCommandOther(delta);
|
||||
break;
|
||||
}
|
||||
} catch(error) {
|
||||
console.log(error);
|
||||
@ -479,6 +482,7 @@ class Player {
|
||||
this.checkPutText(cur);
|
||||
}
|
||||
|
||||
//Checks if the current command is trying to put a new character on the screen or not
|
||||
checkPutCharacterScreen(cur, special = false) {
|
||||
if((!cur.Command || special) && cur.Arg1 && this.utage.characterInfo[cur.Arg1]) {
|
||||
let lay = undefined;
|
||||
@ -534,13 +538,14 @@ class Player {
|
||||
}
|
||||
}
|
||||
|
||||
//Checks if the current command is trying to put text on the screen.
|
||||
checkPutText(cur) {
|
||||
if(this.playingVoice) {
|
||||
this.audio.stopSound(this.playingVoice);
|
||||
}
|
||||
if(!cur.Command && cur.Arg1 && cur.Text) {
|
||||
//If its chracter off screen text
|
||||
var text = cur.English ? (utage.currentTranslation[cur.English] || cur.Text) : cur.Text;
|
||||
let text = cur.English ? (utage.currentTranslation[cur.English] || cur.Text) : cur.Text;
|
||||
text = commonFunctions.convertUtageTextTags(text);
|
||||
if(cur.Arg2 && cur.Arg2.toLowerCase() === "<off>") {
|
||||
this.text.characterName(true, cur.Arg1);
|
||||
@ -571,8 +576,9 @@ class Player {
|
||||
}
|
||||
}
|
||||
this.manualNext = true;
|
||||
//Sometimes they don't give a Arg1 for the text.
|
||||
} else if(!cur.Command && cur.Arg2.toLowerCase() === "<off>" && cur.Text) {
|
||||
var text = cur.English ? (utage.currentTranslation[cur.English] || cur.Text) : cur.Text;
|
||||
let text = cur.English ? (utage.currentTranslation[cur.English] || cur.Text) : cur.Text;
|
||||
this.text.characterName(true, "");
|
||||
this.text.dialogText(true, commonFunctions.convertUtageTextTags(text));
|
||||
this.manualNext = true;
|
||||
@ -583,10 +589,12 @@ class Player {
|
||||
}
|
||||
}
|
||||
|
||||
//Handle a tween command
|
||||
processTween(delta, cur) {
|
||||
this.text.dialogText(false, "");
|
||||
this.text.characterName(false, "");
|
||||
let curChar = undefined;
|
||||
//Find the character for the tween.
|
||||
for(let c of Object.keys(this.currentCharacters)) {
|
||||
if(!this.currentCharacters[c]) { continue; }
|
||||
if(this.currentCharacters[c].charName === cur.Arg1) {
|
||||
@ -716,13 +724,6 @@ class Player {
|
||||
this.currentCommand = undefined;
|
||||
}
|
||||
|
||||
checkIfAllOff() {
|
||||
for(let c of Object.keys(this.currentCharacters)) {
|
||||
if(this.currentCharacters[c]) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
onMainClick(event) {
|
||||
if(!this.runEvent) {
|
||||
return
|
||||
@ -791,7 +792,6 @@ class Player {
|
||||
this.lastCharOffLayer = undefined;
|
||||
this.layers = {};
|
||||
this.sprites = {};
|
||||
this.blackBackSp = undefined;
|
||||
this.currentCommand = undefined;
|
||||
this.runEvent = false;
|
||||
this.secondTicker = 1000;
|
||||
|
@ -123,8 +123,13 @@ class UtageInfo {
|
||||
} else {
|
||||
read.NameText = lastNameText;
|
||||
}
|
||||
if(read.FileName && !read.FileName.startsWith('file://')) {
|
||||
read.FileName = `${this.rootDirectory}XDUData/Character/${read.FileName}`;
|
||||
if(read.FileName) {
|
||||
if(!read.FileName.startsWith('file://')) {
|
||||
read.FileName = `${this.rootDirectory}XDUData/Sample/Texture/Character/${read.FileName}`;
|
||||
} else {
|
||||
read.FileName = read.FileName.replace('file://', '');
|
||||
read.FileName = `${this.rootDirectory}XDUData/${read.FileName}`;
|
||||
}
|
||||
}
|
||||
if(!this.characterInfo[lastCharName]) {
|
||||
this.characterInfo[lastCharName] = {};
|
||||
@ -203,7 +208,7 @@ class UtageInfo {
|
||||
read.FileName = `${read.FileName}.opus`;
|
||||
}
|
||||
switch(read.Type.toLowerCase()) {
|
||||
case 'se':
|
||||
case 'se':
|
||||
if(read.FileName.includes(',')) {
|
||||
let s = read.FileName.split(',');
|
||||
read.FileName = `${s[0].split('_').join('/')}/${s[1]}`;
|
||||
@ -232,7 +237,12 @@ class UtageInfo {
|
||||
} else {
|
||||
let read = commonFunctions.readLine(line, headers);
|
||||
if(read && read.Label) {
|
||||
read.FileName = `${this.rootDirectory}XDUData/BG/${read.FileName}`;
|
||||
if(!read.FileName.startsWith("file://")) {
|
||||
read.FileName = `${this.rootDirectory}XDUData/Sample/Texture/BG/${read.FileName}`;
|
||||
} else {
|
||||
read.FileName = read.FileName.replace("file://", '');
|
||||
read.FileName = `${this.rootDirectory}XDUData/${read.FileName}`;
|
||||
}
|
||||
this.textureInfo[read.Label] = read;
|
||||
}
|
||||
}
|
||||
|
21714
Js/XduMissions.json
21714
Js/XduMissions.json
File diff suppressed because it is too large
Load Diff
2
Js/XduPlayer.min.js
vendored
2
Js/XduPlayer.min.js
vendored
File diff suppressed because one or more lines are too long
10
Player.html
10
Player.html
@ -8,6 +8,12 @@
|
||||
<script src="Js/Pixi.min.js"></script>
|
||||
</head>
|
||||
<body onload="onBodyLoaded()">
|
||||
<!-- <script src="Js/Common.js"></script>
|
||||
<script src="Js/TextFunctions.js"></script>
|
||||
<script src="Js/UtageParse.js"></script>
|
||||
<script src="Js/Audio.js"></script>
|
||||
<script src="Js/Player.js"></script>
|
||||
<script src="Js/Main.js"></script> -->
|
||||
<script src="Js/XduPlayer.min.js"></script>
|
||||
<div id="loading-container" class="centered">
|
||||
<h2 id="loading-utage">Loading Utage Data...</h2>
|
||||
@ -19,7 +25,7 @@
|
||||
<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"/>
|
||||
</div>
|
||||
<select id="select-mission" onchange="missionChanged(event);"></select>
|
||||
<select id="select-mission" onchange="missionDropDownChanged(event);"></select>
|
||||
<select id="select-language" onchange="languageChanged(event);"></select>
|
||||
</div>
|
||||
<!-- Im doing weird shit so that text container is always the base resolution of XDU (1334, 750).
|
||||
@ -61,5 +67,7 @@
|
||||
<span style="font-family: 'SourceCodePro-Regular'">test</span> -->
|
||||
</div>
|
||||
</div>
|
||||
<div id="click-catcher" style="display: none;" onclick="closeMissionModal(event, false)"></div>
|
||||
<div id="modal-container" style="display: none;"></div>
|
||||
</body>
|
||||
</html>
|
21
gulpfile.js
21
gulpfile.js
@ -15,19 +15,19 @@ const jsFiles = [
|
||||
"Js/Main.js"
|
||||
];
|
||||
const jsToCopy = [
|
||||
'Js/XduPlayer.min.js',
|
||||
'Js/Pixi.min.js'
|
||||
"Js/XduPlayer.min.js",
|
||||
"Js/Pixi.min.js"
|
||||
];
|
||||
const cssFiles = [
|
||||
'Css/main.css'
|
||||
"Css/main.css"
|
||||
];
|
||||
const cssToCopy = [
|
||||
'Css/main.min.css',
|
||||
'Css/generic.min.css'
|
||||
"Css/main.min.css",
|
||||
"Css/generic.min.css"
|
||||
];
|
||||
const jsonFiles = [
|
||||
'Js/BgmLoop.json',
|
||||
'Js/XduMissions.json'
|
||||
"Js/BgmLoop.json",
|
||||
"Js/XduMissions.json"
|
||||
];
|
||||
|
||||
const jsDest = "Js";
|
||||
@ -54,6 +54,11 @@ gulp.task('dist', gulp.series(
|
||||
)
|
||||
);
|
||||
|
||||
gulp.task('watch', () => {
|
||||
gulp.watch(cssFiles, {ignoreInitial: false}, gulp.series(buildCss)),
|
||||
gulp.watch(jsFiles, {ignoreInitial: false}, gulp.series(buildJs));
|
||||
});
|
||||
|
||||
function buildJs() {
|
||||
return gulp.src(jsFiles)
|
||||
.pipe(sourcemaps.init())
|
||||
@ -67,7 +72,7 @@ function buildJs() {
|
||||
|
||||
function copyJs() {
|
||||
return gulp.src(jsToCopy)
|
||||
.pipe(gulp.dest('Dist/Js'));;
|
||||
.pipe(gulp.dest('Dist/Js'));
|
||||
}
|
||||
|
||||
function buildCss() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user