Skip to content

Commit

Permalink
feat(fps): adds configurable frame rate (#543)
Browse files Browse the repository at this point in the history
* feat(fps): adds infrastucture for configuring the target framerate

This allows configuration of the target framerate, UI to follow

re #404

* feat(dialog): adds Dialog component and UI state with FPS Dialog

Creates a reusable Dialog component and adds the FPS dialog

fixes #404
  • Loading branch information
2xAA authored Feb 16, 2021
1 parent 97c7bcf commit fb35520
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 5 deletions.
6 changes: 5 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@

<StatusBar />
<Search />

<FrameRateDialog />
</main>
</template>

Expand All @@ -95,6 +97,7 @@ import StatusBar from "@/components/StatusBar";
import ModuleInspector from "@/components/ModuleInspector";
import InfoView from "@/components/InfoView";
import Search from "@/components/Search";
import FrameRateDialog from "@/components/dialogs/FrameRateDialog";
import getNextName from "@/application/utils/get-next-name";
import constants from "@/application/constants";
Expand All @@ -117,7 +120,8 @@ export default {
StatusBar,
InfoView,
ModuleInspector,
Search
Search,
FrameRateDialog
},
data() {
Expand Down
40 changes: 38 additions & 2 deletions src/application/worker/index.worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ async function start() {
const { getFeatures, setFeatures } = require("./audio-features");
// const featureAssignmentPlugin = require("../plugins/feature-assignment");

let interval = store.getters["fps/interval"];

store.subscribe(mutation => {
const { type, payload } = mutation;

if (type === "beats/SET_BPM") {
if (type === "beats/SET_BPM" || type === "fps/SET_FPS") {
store.dispatch("tweens/updateBpm", { bpm: payload.bpm });
}

Expand All @@ -24,6 +26,10 @@ async function start() {
lastKick = payload.kick;
}

if (type === "fps/SET_FPS") {
interval = store.getters["fps/interval"];
}

if (
type === "modules/UPDATE_ACTIVE_MODULE" &&
(payload.key !== "props" || payload.key !== "meta")
Expand Down Expand Up @@ -125,8 +131,38 @@ async function start() {
let frames = 0;
let prevTime = 0;

function looper(delta) {
let now;
let then = Date.now();
let delta;

function looper(rafDelta) {
raf = requestAnimationFrame(looper);

now = Date.now();
delta = now - then;

if (delta > interval) {
// update time stuffs

// Just `then = now` is not enough.
// Lets say we set fps at 10 which means
// each frame must take 100ms
// Now frame executes in 16ms (60fps) so
// the loop iterates 7 times (16*7 = 112ms) until
// delta > interval === true
// Eventually this lowers down the FPS as
// 112*10 = 1120ms (NOT 1000ms).
// So we have to get rid of that extra 12ms
// by subtracting delta (112) % interval (100).
// Hope that makes sense.

then = now - (delta % interval);

frameActions(rafDelta);
}
}

function frameActions(delta) {
self.postMessage({
type: "tick",
payload: delta
Expand Down
31 changes: 31 additions & 0 deletions src/application/worker/store/modules/fps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const state = {
fps: 60
};

const getters = {
interval: state => 1000 / state.fps
};

const actions = {
setFPS({ commit }, { fps }) {
if (!fps) {
throw new Error("No FPS given");
}

commit("SET_FPS", { fps });
}
};

const mutations = {
SET_FPS(state, { fps }) {
state.fps = fps;
}
};

export default {
namespaced: true,
state,
getters,
mutations,
actions
};
3 changes: 2 additions & 1 deletion src/application/worker/store/modules/tweens.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ async function buildFrames({

const animationCache = [];
let frame = 0;
const framesRequired = Math.round(newDuration / 60) || 1;
const framesRequired =
Math.round(newDuration / (1000 / store.state.fps.fps)) || 1;

let frameRecordingCompleted = false;
let frameRecordingDirection = 1;
Expand Down
75 changes: 75 additions & 0 deletions src/components/Dialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<template>
<dialog ref="dialog">
<header>
<button @click="close" class="close">Close</button>
<span>{{ title }}</span>
</header>

<div class="body">
<slot></slot>
</div>
</dialog>
</template>

<script>
export default {
props: {
title: {
type: String,
default: "modV"
}
},
mounted() {
this.$refs.dialog.showModal();
},
methods: {
close() {
this.$emit("close");
this.$refs.dialog.close();
}
}
};
</script>

<style scoped>
dialog {
/* Dialog Box */
border: 1px solid #c4c4c4;
background-color: #151515;
color: #ffffff;
padding: 0;
min-width: 310px;
}
header {
font-size: 14px;
line-height: 17px;
background-color: #363636;
text-align: center;
padding: 6px 8px;
}
button.close {
/* Close Button */
position: absolute;
width: 12px;
height: 12px;
left: 8px;
top: 8px;
background-color: #bc1010;
border: none;
border-radius: 50%;
font-size: 0;
}
div.body {
min-height: 72px;
padding: 8px;
}
</style>
14 changes: 13 additions & 1 deletion src/components/StatusBar/FPSDisplay.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
<template>
<div>{{ Math.round($modV.store.state.metrics.fps) }} FPS</div>
<div @dblclick="openFrameRateDialog">
{{ Math.round($modV.store.state.metrics.fps) }} FPS
</div>
</template>

<script>
export default {
methods: {
openFrameRateDialog() {
this.$store.commit("dialogs/ADD_OPEN", "frameRate");
}
}
};
</script>
46 changes: 46 additions & 0 deletions src/components/dialogs/FrameRateDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<template>
<Dialog
v-if="$store.state.dialogs.open.includes('frameRate')"
@close="dialogClosed"
title="Framerate Options"
>
<grid columns="4">
<c span="1">
<label>Target FPS</label>
</c>
<c span="3">
<Number v-model.number="fps" />
</c>
</grid>
</Dialog>
</template>

<script>
import Dialog from "../Dialog";
import Number from "../inputs/Number";
export default {
components: {
Dialog,
Number
},
computed: {
fps: {
get() {
return this.$modV.store.state.fps.fps;
},
set(fps) {
this.$modV.store.commit("fps/SET_FPS", { fps });
}
}
},
methods: {
dialogClosed() {
this.$store.commit("dialogs/REMOVE_OPEN", "frameRate");
}
}
};
</script>
27 changes: 27 additions & 0 deletions src/ui-store/modules/dialogs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const state = {
open: []
};

const mutations = {
ADD_OPEN(state, id) {
if (Array.isArray(id)) {
state.open = state.open.concat(id);
} else {
state.open.push(id);
}
},

REMOVE_OPEN(state, id) {
const index = state.open.indexOf(id);

if (index > -1) {
state.open.splice(index, 1);
}
}
};

export default {
namespaced: true,
state,
mutations
};

0 comments on commit fb35520

Please sign in to comment.