Skip to content
This repository has been archived by the owner on Jun 12, 2019. It is now read-only.

Commit

Permalink
Playing with lifecycles?
Browse files Browse the repository at this point in the history
  • Loading branch information
c-dante committed Feb 22, 2017
1 parent 0138e19 commit 6d313fc
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 43 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"lodash": "^4.17.4",
"object-path-immutable": "^0.5.1",
"redux-logger": "^2.8.1",
"redux-thunk": "^2.2.0",
"reselect": "^2.5.4",
"three": "^0.84.0"
},
Expand Down
50 changes: 40 additions & 10 deletions src/examples/boxes.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { Mesh } from 'three';
import fp from 'lodash/fp';

import * as $ from '../util';
import * as G from '../geom';
import * as S from '../scene';
import * as X from '../selectors';

// SHIT IS BONKERS
export const {
SHOW, HIDE, actions,
} = $.showHideExt('BoxesExample');

// init
const defaultBoxesState = (state) => {
const boxes = new Array(1000).fill(0).map(() => {
const mesh = new Mesh(G.newBox(), G.Debug.normals);
Expand All @@ -15,24 +23,46 @@ const defaultBoxesState = (state) => {
return mesh;
});

S.addActors(boxes, state.engine.scene);

Object.assign(state.actors, { boxes });

return {
boxes,
shown: false,
};
};

export const boxesReducer = (state, action, global) => {
if (!state) {
return defaultBoxesState(global, action);
}
export const reducer = (slice, action, global) => {
const state = !slice ? defaultBoxesState(global, action) : slice;

switch (action.type) {
case SHOW: {
if (!state.shown) {
const scene = X.activeScene(global);
S.addActors(state.boxes, scene);
}
return {
...state,
shown: true,
};
}

case HIDE: {
if (state.shown) {
const scene = X.activeScene(global);
S.removeActors(state.boxes, scene);
}
return {
...state,
shown: false,
};
}

for (let i = 0; i < state.boxes.length; i++) {
state.boxes[i].rotation.x += (i % 3) * 0.01;
state.boxes[i].rotation.y += (i % 4) * 0.01;
default:
for (let i = 0; i < state.boxes.length; i++) {
state.boxes[i].rotation.x += (i % 3) * 0.01;
state.boxes[i].rotation.y += (i % 4) * 0.01;
}
return state;
}

return state;
};
70 changes: 59 additions & 11 deletions src/examples/index.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,87 @@
import immutable from 'object-path-immutable';
import * as $ from '../util';
import { wiggleReducer } from './wiggle';
import { boxesReducer } from './boxes';
import * as wiggle from './wiggle';
import * as boxes from './boxes';
import * as vox from './vox';
import * as X from '../selectors';

// @todo: clean up for full example stack
const children = { boxes, vox };

export const SET_EXAMPLE = 'Examples:SET_EXAMPLE';
export const actions = {
setExample: d => (dispatch, getState) => {
const local = X.example(getState()) || {};

const old = children[local.selected];
if (old && old.actions && old.actions.hide) {
dispatch(old.actions.hide());
}

const res = dispatch($.act(SET_EXAMPLE, d));

const updated = X.example(getState()) || {};
const current = children[updated.selected];
if (current && current.actions && current.actions.show) {
return dispatch(current.actions.show());
}

return res;
},
};


// @todo: weird pattern: fucking poltergeist
// @todo @todo -- classes of reducers.... hmmmmm....
const bluh = $.keyedReducer({
a: wiggleReducer,
b: boxesReducer,
a: wiggle.reducer,
b: boxes.reducer,
});
// @todo: weird pattern: fucking poltergeist -- composition?! WHAT.


// @todo: this is a nice template reducer -- basics of "slice" reducer?
// examples as discrete slices
export const registry = {
boxes: (slice, action, global) => bluh(global, action),
vox: vox.reducer,
};

export const registryKeys = Object.keys(registry);

// Discrete examples
const defaultState = {
selected: registryKeys[0],
selected: undefined,
slice: {},
};

const sliceReducer = $.keyedReducer(registry);
export const reducer = (state = defaultState, action, global) => {
const sliceReducer = registry[state.selected];
const sliceState = state.slice[state.selected];

switch (action.type) {
case SET_EXAMPLE:
case SET_EXAMPLE: {
if (!registry[action.payload]) {
throw new Error('Unknown slice selected.');
}

return {
...state,
example: action.payload,
selected: action.payload,
};
}

// Run the current slice
default:
if (!sliceReducer) {
return state;
}

return {
...state,
slice: sliceReducer(global, action),
slice: immutable.set(
state.slice,
state.selected,
sliceReducer(sliceState, action, global)
),
};
}
};
38 changes: 38 additions & 0 deletions src/examples/vox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Mesh } from 'three';
import fp from 'lodash/fp';

import * as G from '../geom';
import * as S from '../scene';

const initVoxState = (state) => {
const boxes = new Array(1000).fill(0).map(() => {
const mesh = new Mesh(G.newBox(), G.Debug.normals);

mesh.position.x = fp.random(-10000, 10000);
mesh.position.y = fp.random(-10000, 10000);
mesh.position.z = fp.random(-10000, 10000);

return mesh;
});

S.addActors(boxes, state.engine.scene);

Object.assign(state.actors, { boxes });

return {
boxes,
};
};

export const reducer = (state, action, global) => {
if (!state) {
return initVoxState(global, action);
}

for (let i = 0; i < state.boxes.length; i++) {
state.boxes[i].rotation.x += (i % 3) * 0.01;
state.boxes[i].rotation.y += (i % 4) * 0.01;
}

return state;
};
18 changes: 15 additions & 3 deletions src/examples/wiggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,40 @@ const defaultWiggleState = (state) => {
floor.rotation.x = Math.PI / 2;
floor.position.y = -1000;

const ceiling = new Mesh(G.newPlane(20000, 20000, 200, 200), G.Debug.normals);
ceiling.rotation.x = -Math.PI / 2;
ceiling.position.y = 1000;

S.addActors({ floor }, state.engine.scene);

Object.assign(state.actors, { floor });
S.addActors({ floor, ceiling }, state.engine.scene);

Object.assign(state.actors, { floor, ceiling });

return {
floor,
ceiling,
};
};

export const wiggleReducer = (state, action, global) => {
export const reducer = (state, action, global) => {
if (!state) {
return defaultWiggleState(global, action);
}

// @todo: move into example once I convert to naff
const td = (X.tickSelector(global) / 100000000) * Math.PI;

// Double apply
state.ceiling.geometry.vertices.forEach((vert, i) => {
const a = Math.cos(td / i + vert.x) * Math.sin(td * i) * 100;
vert.z = a;
});
state.floor.geometry.vertices.forEach((vert, i) => {
const a = Math.cos(td / i + vert.x) * Math.sin(td * i) * 100;
vert.z = a;
});
state.floor.geometry.verticesNeedUpdate = true;
state.ceiling.geometry.verticesNeedUpdate = true;

return state;
};
8 changes: 7 additions & 1 deletion src/main.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fp from 'lodash/fp';
import flyd from 'flyd';
import immutable from 'object-path-immutable';
import ReduxThunk from 'redux-thunk';
import createLogger from 'redux-logger';
import { Quaternion } from 'three';
import * as $ from './util';
Expand Down Expand Up @@ -109,6 +110,7 @@ const store = createStore(
reducer,
defaultState,
applyMiddleware(
ReduxThunk,
createLogger({
collapsed: true,
predicate: (getState, action) => !fp.isNumber(action),
Expand Down Expand Up @@ -139,7 +141,7 @@ store.subscribe(() => {

// Hook into event delegation @todo: hmmmmm
dom.examples.addEventListener('input', (evt) => {
store.dispatch($.act('SET_EXAMPLE', evt.target.value));
store.dispatch(EX.actions.setExample(evt.target.value));
});
dom.debug.addEventListener('click', (evt) => {
switch (evt.target.getAttribute('data-action')) {
Expand All @@ -152,5 +154,9 @@ dom.debug.addEventListener('click', (evt) => {
}
});

// @todo: fire off default example
store.dispatch(EX.actions.setExample(EX.registryKeys[0]));

// Render/Update pipeline @todo: woof
flyd.on(time => store.dispatch(time), $.tick);

22 changes: 13 additions & 9 deletions src/scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,24 @@ export const createBasicScene = () => {
};
};

/**
* Add a bunch of actors to a scene.
* @param {Array<Actor>|Object.<Key, Actor|Array<Actor>>} actors
* @param {THREE.Scene} scene
* @returns actors
*/
export const addActors = (actors, scene) => {

const apActors = fn => (actors, scene) => {
fp.forEach((actor) => {
if (fp.isArray(actor)) {
actor.forEach(a => scene.add(a), actor);
actor.forEach(a => scene[fn](a), actor);
} else {
scene.add(actor);
scene[fn](actor);
}
return actor;
}, actors);
return actors;
};

/**
* Add a bunch of actors to a scene.
* @param {Array<Actor>|Object.<Key, Actor|Array<Actor>>} actors
* @param {THREE.Scene} scene
* @returns actors
*/
export const addActors = apActors('add');
export const removeActors = apActors('remove');
9 changes: 9 additions & 0 deletions src/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,12 @@ export const debugStateSelector = createSelector(
[() => I.keys.activeCtrl(), () => I.Controls],
(activeMap, controls) => ({ activeMap, controls })
);

export const app = fp.get('app');
export const example = createSelector([app], fp.get('examples'));
// export const exampleSelected = createSelector([example], fp.get('selected'));
// export const exampleSlices = createSelector([example], fp.get('slice'));
// export const currentExampleSlice = createSelector(
// [exampleSelected, exampleSlices],
// (selected, slices) => slices[selected]
// );
25 changes: 16 additions & 9 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,21 @@ export const keyedReducer = (obj) => {
};
};


/**
* Switch reducer to a slice. Passthrough.
* Basics for a show/hide reducer
*/
// export const passReducer = (obj, path) => {
// const state = fp.fromPairs(Object.keys(obj).map(
// key => [key, undefined]
// ));

// return (global, action, ...rest) => mapValues(
// );
// };
export const showHideExt = (namespace) => {
const SHOW = `${namespace}:SHOW`;
const HIDE = `${namespace}:HIDE`;

// Easier to destructure
return {
SHOW,
HIDE,
actions: {
show: () => act(SHOW),
hide: () => act(HIDE),
},
};
};

0 comments on commit 6d313fc

Please sign in to comment.