diff --git a/src/mami.css/sound/sndtest.css b/src/mami.css/sound/sndtest.css index 0cbf7fb..1875775 100644 --- a/src/mami.css/sound/sndtest.css +++ b/src/mami.css/sound/sndtest.css @@ -19,11 +19,11 @@ .sndtest-view button { flex-grow: 1; flex-shrink: 1; - background: #f99; + background: #f55; color: #fff; border: 0; border-radius: 0; - border-bottom: #f33; + border-bottom: #f00; padding: 10px; } @@ -31,6 +31,7 @@ display: flex; gap: 10px; margin: 10px; + overflow: auto; } .sndtest-library { diff --git a/src/mami.js/controls/views.js b/src/mami.js/controls/views.js index 58a7e7b..cf11a1c 100644 --- a/src/mami.js/controls/views.js +++ b/src/mami.js/controls/views.js @@ -27,16 +27,6 @@ const MamiViewsControl = function(options) { return element; }; - const doTransition = async (transition, ctx) => { - if(transition === undefined) - return; - - if(typeof transition !== 'function') - return; - - await transition(ctx); - }; - const updateZIncides = () => { let index = 0; for(const view of views) @@ -73,12 +63,18 @@ const MamiViewsControl = function(options) { if(typeof prevElemInfo.onViewBackground === 'function') await prevElemInfo.onViewBackground(); - await doTransition(transition, { - toInfo: elementInfo, - toElem: element, - fromInfo: prevElemInfo, - fromElem: prevElem, - }); + if(transition !== false) { + if(typeof transition !== 'function' && typeof elementInfo.getViewTransition === 'function') + transition = elementInfo.getViewTransition('push'); + + if(typeof transition === 'function') + await transition({ + toInfo: elementInfo, + toElem: element, + fromInfo: prevElemInfo, + fromElem: prevElem, + }); + } } }; @@ -100,12 +96,18 @@ const MamiViewsControl = function(options) { if(typeof nextElemInfo.onViewForeground === 'function') await nextElemInfo.onViewForeground(); - await doTransition(transition, { - toInfo: nextElemInfo, - toElem: nextElem, - fromInfo: elementInfo, - fromElem: element, - }); + if(transition !== false) { + if(typeof transition !== 'function' && typeof elementInfo.getViewTransition === 'function') + transition = elementInfo.getViewTransition('pop'); + + if(typeof transition === 'function') + await transition({ + toInfo: nextElemInfo, + toElem: nextElem, + fromInfo: elementInfo, + fromElem: element, + }); + } } if(typeof elementInfo.onViewBackground === 'function') diff --git a/src/mami.js/sockchat/handlers.js b/src/mami.js/sockchat/handlers.js index 9f5cdae..b1708c1 100644 --- a/src/mami.js/sockchat/handlers.js +++ b/src/mami.js/sockchat/handlers.js @@ -121,7 +121,7 @@ const MamiSockChatHandlers = function(ctx, client, setLoadingOverlay, sockChatRe if(dumpEvents) console.log('session:fail', ev.detail); if(ev.detail.baka !== undefined) { - new MamiForceDisconnectNotice(ev.detail.baka).pushOn(ctx.views); + ctx.views.push(new MamiForceDisconnectNotice(ev.detail.baka)); return; } @@ -135,7 +135,7 @@ const MamiSockChatHandlers = function(ctx, client, setLoadingOverlay, sockChatRe handlers['session:term'] = ev => { if(dumpEvents) console.log('session:term', ev.detail); - new MamiForceDisconnectNotice(ev.detail.baka).pushOn(ctx.views); + ctx.views.push(new MamiForceDisconnectNotice(ev.detail.baka)); }; diff --git a/src/mami.js/sound/sndtest.jsx b/src/mami.js/sound/sndtest.jsx index 361152d..3e08d94 100644 --- a/src/mami.js/sound/sndtest.jsx +++ b/src/mami.js/sound/sndtest.jsx @@ -1,6 +1,6 @@ #include awaitable.js -const MamiSoundTest = function(settings, audio, manager, library) { +const MamiSoundTest = function(settings, audio, manager, library, clickPos) { if(!settings.defined('soundRate')) settings.define('soundRate').default(1.0).min(0.001).max(2.0).virtual().create(); if(!settings.defined('soundDetune')) @@ -12,6 +12,7 @@ const MamiSoundTest = function(settings, audio, manager, library) { if(!settings.defined('soundReverse')) settings.define('soundReverse').default(false).virtual().create(); + const hasClickPos = Array.isArray(clickPos) && clickPos.length > 1; const volumeSetting = settings.info('soundVolume'); const rateSetting = settings.info('soundRate'); const detuneSetting = settings.info('soundDetune'); @@ -153,5 +154,41 @@ const MamiSoundTest = function(settings, audio, manager, library) { for(const source of sources) source.stop(); }, + getViewTransition: mode => { + if(!hasClickPos) + return; + + if(mode === 'push') + return ctx => MamiAnimate({ + async: true, + duration: 1500, + easing: 'inQuad', + start: () => { + library.play('mario:keyhole'); + ctx.toElem.style.transform = 'scale(0) translate(25%, 25%)'; + ctx.toElem.style.transformOrigin = `${clickPos[0]}px ${clickPos[1]}px`; + }, + update: (t, rt) => ctx.toElem.style.transform = `scale(${t}) translate(${25 * (1 - rt)}%, ${25 * (1 - rt)}%)`, + end: () => { + ctx.toElem.style.transform = null; + ctx.toElem.style.transformOrigin = null; + }, + }); + + if(mode === 'pop') + return ctx => MamiAnimate({ + async: true, + duration: 1000, + easing: 'outQuad', + start: () => { + ctx.fromElem.style.transformOrigin = `${clickPos[0]}px ${clickPos[1]}px`; + }, + update: (t, rt) => ctx.fromElem.style.transform = `scale(${1 - t}) rotate(${-1080 * t}deg) translate(${50 * rt}%, ${50 * rt}%)`, + end: () => { + ctx.fromElem.style.transform = null; + ctx.fromElem.style.transformOrigin = null; + }, + }); + }, }; }; diff --git a/src/mami.js/ui/baka.jsx b/src/mami.js/ui/baka.jsx index 5d65a04..a183424 100644 --- a/src/mami.js/ui/baka.jsx +++ b/src/mami.js/ui/baka.jsx @@ -47,61 +47,64 @@ const MamiForceDisconnectNotice = function(banInfo) { } }, onViewPop: async () => { - bgmSrc?.stop(); + try { + bgmSrc?.stop(); + } catch(ex) {} bgmSrc = sfxBuf = undefined; }, - pushOn: async views => { - await views.push(pub, ctx => MamiAnimate({ - async: true, - duration: (sfxBuf?.duration ?? 1.4) * 1000, - start: () => { - if(sfxBuf !== undefined) - mami.sound.audio.createSource(sfxBuf).play(); + getViewTransition: mode => { + if(mode === 'push') + return ctx => MamiAnimate({ + async: true, + duration: (sfxBuf?.duration ?? 1.4) * 1000, + start: () => { + if(sfxBuf !== undefined) + mami.sound.audio.createSource(sfxBuf).play(); - ctx.toElem.style.top = '-100%'; - }, - update: t => { - const tOutBounce = MamiEasings.outBounce(t); - ctx.toElem.style.top = `${-100 + (tOutBounce * 100)}%`; + ctx.toElem.style.top = '-100%'; + }, + update: t => { + const tOutBounce = MamiEasings.outBounce(t); + ctx.toElem.style.top = `${-100 + (tOutBounce * 100)}%`; - const tOutExpo = MamiEasings.outExpo(t); - ctx.fromElem.style.transform = `scale(${1 - (1 * tOutExpo)}) rotate(${rotate * tOutExpo}deg)`; - ctx.fromElem.style.filter = `grayscale(${tOutExpo * 100}%)`; - }, - end: () => { - bgmSrc?.play(); - ctx.toElem.style.top = null; - ctx.fromElem.style.transform = null; - ctx.fromElem.style.filter = null; - }, - })); - }, - 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(); + const tOutExpo = MamiEasings.outExpo(t); + ctx.fromElem.style.transform = `scale(${1 - (1 * tOutExpo)}) rotate(${rotate * tOutExpo}deg)`; + ctx.fromElem.style.filter = `grayscale(${tOutExpo * 100}%)`; + }, + end: () => { + bgmSrc?.play(); + ctx.toElem.style.top = null; + ctx.fromElem.style.transform = null; + ctx.fromElem.style.filter = null; + }, + }); - 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}%`; + if(mode === 'pop') + return ctx => MamiAnimate({ + async: true, + duration: (sfxBuf?.duration ?? 1.4) * 1000, + start: () => { + bgmSrc?.stop(); + if(sfxBuf !== undefined) + mami.sound.audio.createSource(sfxBuf, true).play(); - 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; - }, - })); + 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; + }, + }); }, }; diff --git a/src/mami.js/ui/settings.jsx b/src/mami.js/ui/settings.jsx index c5b9670..0402291 100644 --- a/src/mami.js/ui/settings.jsx +++ b/src/mami.js/ui/settings.jsx @@ -438,10 +438,9 @@ Umi.UI.Settings = (function() { type: 'button', invoke: async button => { button.disabled = true; - const notice = new MamiForceDisconnectNotice({ perma: true, type: 'ban' }); - await notice.pushOn(mami.views); + await mami.views.push(new MamiForceDisconnectNotice({ perma: true, type: 'ban' })); await MamiSleep(5000); - await notice.popOff(mami.views); + await mami.views.pop(); button.disabled = false; }, }, @@ -450,20 +449,21 @@ Umi.UI.Settings = (function() { type: 'button', invoke: async button => { button.disabled = true; - await (new MamiYouAreAnIdiot()).pushOn(mami.views); + await mami.views.push(new MamiYouAreAnIdiot(mami.sound.library, mami.views)); button.disabled = false; }, }, { title: 'Sound Test', type: 'button', - invoke: async button => { + invoke: async (button, ev) => { button.disabled = true; - mami.views.push(new MamiSoundTest( + await mami.views.push(new MamiSoundTest( mami.settings, mami.sound.audio, mami.sound.manager, mami.sound.library, + [ev.clientX, ev.clientY], )); button.disabled = false; }, @@ -471,7 +471,7 @@ Umi.UI.Settings = (function() { { title: 'Reset audio context', type: 'button', - invoke: async () => { + invoke: () => { mami.sound.reset(); }, }, @@ -512,15 +512,15 @@ Umi.UI.Settings = (function() { updateSelectOptions(); } else if(display.type === 'button') { input.value = display.title; - input.addEventListener('click', () => { + input.addEventListener('click', ev => { if(display.confirm !== undefined) mami.msgbox.show({ body: display.confirm, yes: { primary: false }, no: { primary: true }, - }).then(() => { display.invoke(input); }).catch(() => {}); + }).then(() => { display.invoke(input, ev); }).catch(() => {}); else - display.invoke(input); + display.invoke(input, ev); }); } diff --git a/src/mami.js/ui/youare.jsx b/src/mami.js/ui/youare.jsx index da3c8eb..12a8ec1 100644 --- a/src/mami.js/ui/youare.jsx +++ b/src/mami.js/ui/youare.jsx @@ -1,13 +1,13 @@ #include animate.js -const MamiYouAreAnIdiot = function() { +const MamiYouAreAnIdiot = function(sndLibrary, views) { const html =
-
+
you are an idiot
!
-
+
@@ -15,13 +15,16 @@ const MamiYouAreAnIdiot = function() {
; + if(views !== undefined) + html.addEventListener('dblclick', () => { views.pop(); }); + let soundSrc; const pub = { getElement: () => html, onViewPush: async () => { try { - soundSrc = await mami.sound.library.loadSource('misc:youare'); + soundSrc = await sndLibrary.loadSource('misc:youare'); soundSrc.setMuted(true); soundSrc.setLoop(true, 0.21, 5); soundSrc.play(); @@ -42,14 +45,17 @@ const MamiYouAreAnIdiot = function() { soundSrc.stop(); soundSrc = undefined; }, - pushOn: async views => views.push(pub, ctx => MamiAnimate({ - async: true, - duration: 1500, - easing: 'outBounce', - start: () => ctx.toElem.style.top = '-100%', - update: t => ctx.toElem.style.top = `${-100 + (t * 100)}%`, - end: () => ctx.toElem.style.top = null, - })), + getViewTransition: mode => { + if(mode === 'push') + return ctx => MamiAnimate({ + async: true, + duration: 1500, + easing: 'outBounce', + start: () => ctx.toElem.style.top = '-100%', + update: t => ctx.toElem.style.top = `${-100 + (t * 100)}%`, + end: () => ctx.toElem.style.top = null, + }); + }, }; return pub;