diff --git a/src/mami.js/audio/context.js b/src/mami.js/audio/context.js
index 2c88fdf..41a1fd7 100644
--- a/src/mami.js/audio/context.js
+++ b/src/mami.js/audio/context.js
@@ -66,10 +66,27 @@ const MamiAudioContext = function() {
return await ctx.decodeAudioData(result.body());
},
- createSource: buffer => {
+ createSource: (buffer, reverse) => {
if(ctx === undefined || buffer === undefined)
return new MamiAudioSourceDummy;
+ if(reverse) {
+ const reverse = new AudioBuffer({
+ length: buffer.length,
+ numberOfChannels: buffer.numberOfChannels,
+ sampleRate: buffer.sampleRate,
+ });
+
+ const data = new Float32Array(buffer.length);
+ for(let i = 0; i < reverse.numberOfChannels; ++i) {
+ buffer.copyFromChannel(data, i, 0);
+ data.reverse();
+ reverse.copyToChannel(data, i, 0);
+ }
+
+ buffer = reverse;
+ }
+
const gain = ctx.createGain();
gain.connect(mainGain);
diff --git a/src/mami.js/ui/baka.jsx b/src/mami.js/ui/baka.jsx
index f11429e..5d65a04 100644
--- a/src/mami.js/ui/baka.jsx
+++ b/src/mami.js/ui/baka.jsx
@@ -27,16 +27,16 @@ const MamiForceDisconnectNotice = function(banInfo) {
marqueeElem.append(
{marqueeString}
);
const rng = new MamiRNG;
- let sfxBuf, sfxSrc, bgmSrc;
+ const rotate = rng.next(-20, 20);
+ let sfxBuf, bgmSrc;
const pub = {
getElement: () => html,
onViewPush: async () => {
try {
sfxBuf = await mami.sound.library.loadBuffer('touhou:pichuun');
- sfxSrc = mami.sound.audio.createSource(sfxBuf);
} catch(ex) {
- sfxBuf = sfxSrc = undefined;
+ sfxBuf = undefined;
}
try {
@@ -48,16 +48,16 @@ const MamiForceDisconnectNotice = function(banInfo) {
},
onViewPop: async () => {
bgmSrc?.stop();
- bgmSrc = sfxBuf = sfxSrc = undefined;
+ bgmSrc = sfxBuf = undefined;
},
pushOn: async views => {
- const rotate = rng.next(-20, 20);
-
await views.push(pub, ctx => MamiAnimate({
async: true,
duration: (sfxBuf?.duration ?? 1.4) * 1000,
start: () => {
- sfxSrc?.play();
+ if(sfxBuf !== undefined)
+ mami.sound.audio.createSource(sfxBuf).play();
+
ctx.toElem.style.top = '-100%';
},
update: t => {
@@ -76,6 +76,33 @@ const MamiForceDisconnectNotice = function(banInfo) {
},
}));
},
+ popOff: async views => {
+ await views.pop(ctx => MamiAnimate({
+ async: true,
+ duration: (sfxBuf?.duration ?? 1.4) * 1000,
+ start: () => {
+ bgmSrc?.stop();
+ if(sfxBuf !== undefined)
+ mami.sound.audio.createSource(sfxBuf, true).play();
+
+ ctx.toElem.style.transform = `scale(1) rotate(${rotate}deg)`;
+ ctx.toElem.style.filter = 'grayscale(100%)';
+ },
+ update: t => {
+ const tOutBounce = MamiEasings.inBounce(t);
+ ctx.fromElem.style.top = `${tOutBounce * -100}%`;
+
+ const tOutExpo = MamiEasings.inExpo(t);
+ ctx.toElem.style.transform = `scale(${1 * tOutExpo}) rotate(${rotate - (rotate * tOutExpo)}deg)`;
+ ctx.toElem.style.filter = `grayscale(${100 - (tOutExpo * 100)}%)`;
+ },
+ end: () => {
+ ctx.fromElem.style.top = null;
+ ctx.toElem.style.transform = null;
+ ctx.toElem.style.filter = null;
+ },
+ }));
+ },
};
return pub;
diff --git a/src/mami.js/ui/settings.jsx b/src/mami.js/ui/settings.jsx
index f32cf0d..a66f245 100644
--- a/src/mami.js/ui/settings.jsx
+++ b/src/mami.js/ui/settings.jsx
@@ -391,12 +391,10 @@ Umi.UI.Settings = (function() {
type: 'button',
invoke: async button => {
button.disabled = true;
- await (new MamiForceDisconnectNotice({
- perma: true,
- type: 'ban',
- })).pushOn(mami.views);
+ const notice = new MamiForceDisconnectNotice({ perma: true, type: 'ban' });
+ await notice.pushOn(mami.views);
await MamiSleep(5000);
- await mami.views.pop();
+ await notice.popOff(mami.views);
button.disabled = false;
},
},