Skip to content

Instantly share code, notes, and snippets.

@mmckegg
Last active November 12, 2015 09:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmckegg/4b45bf8d7b509df3976c to your computer and use it in GitHub Desktop.
Save mmckegg/4b45bf8d7b509df3976c to your computer and use it in GitHub Desktop.
experiment with another form of grid looping
var ArrayGrid = require('array-grid')
var deepEqual = require('deep-equal')
var unwrap = require('./unwrap')
module.exports = createLoop
function createLoop (frames, startTime, loopLength) {
if (frames.length) {
var shape = frames[frames.length - 1].value.shape
var length = shape[0] * shape[1]
var data = Array(length).fill(null)
for (var f = 0; f < frames.length; f++) {
var frame = frames[f]
if (frame.at < startTime) {
data = frame.value.data.slice()
}
if (frame.at >= startTime && frame.at < startTime + loopLength) {
var value = frame.value.data
for (var i = 0; i < length; i++) {
if (notSame(data[i], value[i])) {
var a = slice(unwrap(data[i], startTime, loopLength), startTime, frame.at)
var b = slice(unwrap(value[i], startTime, loopLength), frame.at)
data[i] = wrap(squish(a.concat(b)), loopLength)
}
}
}
}
return ArrayGrid(data, shape)
}
}
function notSame (a, b) {
return a !== b || !deepEqual(a, b)
}
function slice (events, start, end) {
var result = []
var lastValue = null
for (var i = 0; i < events.length; i++) {
var event = events[i]
if (event[0] >= start && (event[0] < end || end == null)) {
if (!result.length && event[0] > start) {
result.push([start, lastValue])
}
result.push(event)
}
lastValue = event[1]
}
if (!result.length && (end > start || end == null)) {
result.push([start, lastValue])
}
return result
}
function squish (items) {
return items.reduce(function (result, item, i) {
var lastItem = result[result.length - 1]
if (!lastItem || lastItem[1] !== item[1]) {
result.push(item)
}
return result
}, [])
}
function wrap (events, loopLength) {
if (events.length === 1) {
return events[0][1]
}
var result = [loopLength]
events.forEach(function (ev) {
result.push([ev[0] % loopLength, ev[1]])
})
result.sort(byTime)
return result
}
function byTime (a, b) {
return a[0] - b[0]
}
var Observ = require('observ')
var ArrayGrid = require('array-grid')
module.exports = GridPlayer
function GridPlayer (currentPosition, frameDuration) {
var obs = Observ()
var set = obs.set
var grid = null
var result = []
obs.set = function (value) {
grid = value
refresh()
}
currentPosition(refresh)
return obs
function refresh () {
var changed = false
if (grid && grid.data) {
grid.data.forEach(function (loop, i) {
var newValue = valueOf(loop, currentPosition() || 0)
if (newValue !== result[i]) {
if (!changed) {
changed = true
result = result.slice()
}
result[i] = newValue
}
})
}
if (changed) {
set(ArrayGrid(result, grid.shape))
}
}
}
function valueOf (loop, currentPosition) {
var result = []
if (Array.isArray(loop) && loop.length > 1) {
var startPosition = 0
var length = loop[0]
var events = loop.slice(1)
var start = currentPosition % length
while (events[startPosition] && events[startPosition][0] <= start) {
startPosition = startPosition + 1
if (startPosition > events.length) {
startPosition = 0
break
}
}
var event = events[mod(startPosition - 1, events.length)]
return event[1]
} else {
var value = Array.isArray(loop) ? null : loop
return value
}
return result
}
function mod (n, m) {
return ((n % m) + m) % m
}
var Observ = require('observ')
module.exports = ObservRecorder
function ObservRecorder (currentTime) {
var obs = Observ([])
var set = obs.set
obs.set = function (value) {
var newValue = obs().concat({
at: currentTime(),
value: value
})
set(newValue)
}
return obs
}
module.exports = unwrap
function unwrap (loop, startTime, targetLength) {
var result = []
if (Array.isArray(loop) && loop.length > 1) {
var startPosition = 0
var length = loop[0]
var events = loop.slice(1)
var start = startTime % length
while (events[startPosition] && events[startPosition][0] < start) {
startPosition = startPosition + 1
if (startPosition > events.length) {
startPosition = 0
break
}
}
for (var i = startPosition; true; i++) {
var event = events[i % events.length]
var offset = Math.floor(i / events.length) * length
var position = event[0] - start + startTime + offset
if (position < startTime + targetLength) {
result.push([position, event[1]])
} else {
break
}
}
} else {
var value = Array.isArray(loop) ? null : loop
result.push([startTime, value])
}
return result
}
//
// console.log(unwrap([4,
// [0, 1], [0.5, 0],
// [1, 2], [1.5, 0],
// [2, 3], [2.5, 0],
// [3, 4], [3.5, 0]
// ], 0.1, 0.1))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment