Skip to content

Commit

Permalink
Merge pull request #7 from IPLSplatoon/break-casters
Browse files Browse the repository at this point in the history
Casters on break screen
  • Loading branch information
inkfarer authored Oct 9, 2024
2 parents 14f1090 + 5040b7c commit f0034d0
Show file tree
Hide file tree
Showing 17 changed files with 319 additions and 38 deletions.
1 change: 0 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
.eslintrc.*.js
webpack.config.ts
dashboard/**/*
extension/**/*
graphics/**/*
node_modules/**/*
schemas/**/*
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
continue-on-error: true
working-directory: ./sac-overlays
run: |
git add -f graphics
git add -f graphics dashboard
git commit -m "Build result from master branch" -a
- name: Push built files to "build" branch
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ bower_components

/graphics
/dashboard
/extension

/.idea

Expand Down
8 changes: 8 additions & 0 deletions extension/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = function (nodecg) {
const breakCastersVisible = nodecg.Replicant('breakCastersVisible', { defaultValue: false });
const activeBreakScene = nodecg.Replicant('activeBreakScene', 'ipl-overlay-controls');

activeBreakScene.on('change', () => {
breakCastersVisible.value = false;
});
}
12 changes: 11 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
],
"scripts": {
"build": "cross-env NODE_ENV=production webpack",
"clean": "trash node_modules/.cache && trash graphics",
"clean": "trash node_modules/.cache && trash graphics && trash dashboard",
"cleanbuild": "npm run clean && npm run build",
"start": "node ../..",
"watch": "webpack -w",
Expand All @@ -43,6 +43,16 @@
"width": 1920,
"height": 1080
}
],
"dashboardPanels": [
{
"name": "sac-dash",
"title": "SAC Options",
"width": 2,
"file": "sac-dash.html",
"workspace": "ipl",
"headerColor": "#F0094C"
}
]
},
"license": "SEE LICENSE IN LICENSE",
Expand Down
3 changes: 3 additions & 0 deletions src/dashboard/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.browser.json"
}
10 changes: 10 additions & 0 deletions src/dashboard/sac-dash/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const breakCastersCheckbox = document.getElementById('break-casters-checkbox') as HTMLInputElement;
const breakCastersVisible = nodecg.Replicant<boolean>('breakCastersVisible', { defaultValue: false });

breakCastersCheckbox.addEventListener('change', event => {
breakCastersVisible.value = (event.target as HTMLInputElement).checked;
});

breakCastersVisible.on('change', newValue => {
breakCastersCheckbox.checked = newValue;
});
13 changes: 13 additions & 0 deletions src/dashboard/sac-dash/sac-dash.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>sac-dash@sac-overlays</title>
</head>
<body>
<label>
<input type="checkbox" id="break-casters-checkbox">
Show casters on break
</label>
</body>
</html>
3 changes: 3 additions & 0 deletions src/dashboard/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../../tsconfig-browser.json"
}
5 changes: 5 additions & 0 deletions src/graphics/break/break.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@
<div class="content-wrapper stages-wrapper layout horiz c-vert c-horiz">
<div class="stages-layout" id="stages-layout">

</div>
</div>
<div class="content-wrapper casters-wrapper layout horiz c-vert c-horiz">
<div class="casters-layout" id="casters-layout">

</div>
</div>
</div>
Expand Down
91 changes: 90 additions & 1 deletion src/graphics/break/scripts/casters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import { casters } from '../../helpers/replicants';
import { elementById } from '../../helpers/elem';
import gsap from 'gsap';
import { getPrevious } from '../../helpers/object';
import { isBlank } from '../../helpers/string';
import { Caster } from 'schemas';

const castersWrapper = elementById('info-bar-casters');
const twittersWrapper = elementById('info-bar-twitters');
const castersLayout = elementById('casters-layout');

casters.on('change', newValue => {
casters.on('change', (newValue, oldValue) => {
const values = Object.values(newValue);

castersWrapper.innerHTML = values.reduce((existing, elem) => {
Expand All @@ -21,6 +24,51 @@ casters.on('change', newValue => {
}, '');

gsap.set([ castersWrapper, twittersWrapper ], { scale: values.length > 2 ? 0.7 : 1 });

const newCasterIds = Object.keys(newValue);
const oldCasterIds = oldValue == null ? null : Object.keys(oldValue);
const shouldRecreateCasterElements
= oldCasterIds == null
|| newCasterIds.length !== oldCasterIds.length
|| newCasterIds.some((elem, i) => oldCasterIds[i] !== elem);

if (shouldRecreateCasterElements) {
const casterWidth = getCasterWidth(values.length);
castersLayout.innerHTML = values.reduce((result, elem, i) => {
result += `
<div
class="caster-wrapper"
style="--caster-width: ${casterWidth}px"
data-caster-id="${newCasterIds[i]}"
>
<div class="caster-visual-wrapper">
${getCasterVisual(elem)}
</div>
<div class="caster-nametag">
<fitted-text max-width="${casterWidth - 50}" text="${elem.name}" class="caster-name" align="right"></fitted-text>
<fitted-text max-width="${casterWidth - 50}" text="${elem.twitter}" class="caster-twitter" align="right"></fitted-text>
</div>
</div>
`;

return result;
}, '');
} else {
newCasterIds.forEach((casterId) => {
const casterElem = document.querySelector(`[data-caster-id="${casterId}"]`);
const caster = newValue[casterId];
const oldCaster = oldValue[casterId];
(casterElem.querySelector('.caster-name') as FittedText).text = caster.name;
(casterElem.querySelector('.caster-twitter') as FittedText).text = caster.twitter;

if (
caster.videoUrl !== oldCaster.videoUrl
|| (isBlank(caster.videoUrl) && caster.imageUrl !== oldCaster.imageUrl)
) {
casterElem.querySelector('.caster-visual-wrapper').innerHTML = getCasterVisual(caster);
}
});
}
});

const casterInfoLoopTl = gsap.timeline({ repeat: -1 });
Expand All @@ -34,3 +82,44 @@ for (let i = 0; i < casterInfoElems.length; i++) {
.to(`#${previousElem}`, { duration: 0.35, opacity: 1 })
.to({}, { duration: 30 });
}

function getCasterWidth(casterCount: number): number {
switch (casterCount) {
case 1:
return 1200;
case 2:
return 750;
default:
return 625;
}
}

function getCasterVisual(caster: Caster): string {
if (!isBlank(caster.videoUrl)) {
return `
<div class="video-loader-wrapper">
<iframe
allow="autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;midi;geolocation;"
src="${caster.videoUrl}"
width="1280"
height="720"
></iframe>
</div>
`;
} else if (!isBlank(caster.imageUrl)) {
return `
<img
class="caster-image"
src="${caster.imageUrl}"
>
`;
} else {
return `
<img
class="caster-image-placeholder"
src="assets/sac-logo-white.png"
>
`;
}

}
95 changes: 73 additions & 22 deletions src/graphics/break/scripts/sceneSwitcher.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { activeBreakScene } from '../../helpers/replicants';
import { ActiveBreakScene } from 'schemas';
import { activeBreakScene, breakCastersVisible } from '../../helpers/replicants';
import gsap from 'gsap';

export const sceneSwitchTl = gsap.timeline({
Expand All @@ -8,39 +9,64 @@ export const sceneSwitchTl = gsap.timeline({
}
});

activeBreakScene.on('change', (newValue, oldValue) => {
NodeCG.waitForReplicants(breakCastersVisible, activeBreakScene).then(() => {
breakCastersVisible.on('change', (newValue, oldValue) => {
if (oldValue == null && !newValue) return;
onSceneSwitch(activeBreakScene.value, activeBreakScene.value, newValue);
});

activeBreakScene.on('change', (newValue, oldValue) => {
if (breakCastersVisible.value) return;
onSceneSwitch(newValue, oldValue, null);
});
});

function onSceneSwitch(
newActiveBreakScene: ActiveBreakScene,
oldActiveBreakScene: ActiveBreakScene,
breakCastersVisible: boolean | null
) {
sceneSwitchTl.addLabel('sceneHide');

switch (oldValue) {
case 'main':
sceneSwitchTl.add(hideMainScene(), 'sceneHide');
break;
case 'teams':
sceneSwitchTl.add(hideTeams(), 'sceneHide');
break;
case 'stages':
sceneSwitchTl.add(hideStages(), 'sceneHide');
if (breakCastersVisible === false) {
sceneSwitchTl.add(hideCasters(), 'sceneHide');
} else {
switch (oldActiveBreakScene) {
case 'main':
sceneSwitchTl.add(hideMainScene(), 'sceneHide');
break;
case 'teams':
sceneSwitchTl.add(hideTeams(), 'sceneHide');
break;
case 'stages':
sceneSwitchTl.add(hideStages(), 'sceneHide');
}

}

if (newValue === 'main') {
if (newActiveBreakScene === 'main' && breakCastersVisible !== true) {
sceneSwitchTl.add(hideInfoBar(), 'sceneHide');
sceneSwitchTl.addLabel('sceneShow');
} else {
sceneSwitchTl.addLabel('sceneShow');
sceneSwitchTl.add(showInfoBar(), 'sceneShow');
}

switch (newValue) {
case 'main':
sceneSwitchTl.add(showMainScene(), 'sceneShow');
break;
case 'teams':
sceneSwitchTl.add(showTeams(), 'sceneShow');
break;
case 'stages':
sceneSwitchTl.add(showStages(), 'sceneShow');
if (breakCastersVisible) {
sceneSwitchTl.add(showCasters(), 'sceneShow');
} else {
switch (newActiveBreakScene) {
case 'main':
sceneSwitchTl.add(showMainScene(), 'sceneShow');
break;
case 'teams':
sceneSwitchTl.add(showTeams(), 'sceneShow');
break;
case 'stages':
sceneSwitchTl.add(showStages(), 'sceneShow');
}
}
});
}

function hideMainScene(): gsap.core.Timeline {
const tl = gsap.timeline({
Expand Down Expand Up @@ -226,3 +252,28 @@ function hideStages(): gsap.core.Timeline {

return tl;
}

function showCasters(): gsap.core.Timeline {
const tl = gsap.timeline({
onStart: () => {
gsap.set('.caster-wrapper', { opacity: 0 });
gsap.set('.casters-wrapper', { display: 'flex' });
}
});

tl.to('.caster-wrapper', { opacity: 1, duration: 0.5, stagger: 0.1 });

return tl;
}

function hideCasters(): gsap.core.Timeline {
const tl = gsap.timeline({
onComplete: () => {
gsap.set('.casters-wrapper', { display: 'none' });
}
});

tl.to('.caster-wrapper', { opacity: 0, duration: 0.5, stagger: 0.1 });

return tl;
}
1 change: 1 addition & 0 deletions src/graphics/break/styles/break.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@import './infoBar.scss';
@import './teams.scss';
@import './stages.scss';
@import './casters.scss';

body {
margin: 0;
Expand Down
Loading

0 comments on commit f0034d0

Please sign in to comment.