prendy
Version:
Make games with prerendered backdrops using babylonjs and repond
116 lines (96 loc) • 4.46 kB
text/typescript
import delay from "delay";
import { getRefs, getState, makeEffects } from "repond";
import { addMoverEffects } from "repond-movers";
import { getEngine } from "../../helpers/babylonjs/getSceneOrEngineUtils";
import {
focusSlateOnFocusedDoll,
getShaderTransformStuff,
getSlatePositionNotOverEdges,
slateSize,
} from "../../helpers/babylonjs/slate";
import { setGlobalState } from "../../helpers/prendyUtils/global";
import { meta } from "../../meta";
export const globalSlateEffects = makeEffects(({ itemEffect, effect }) => ({
whenSlatePositionChanges: effect({
run(diffInfo) {
const positionChanged = diffInfo.propsChangedBool.global.main.slatePos;
const zoomChanged = diffInfo.propsChangedBool.global.main.slateZoom;
if (positionChanged || zoomChanged) getShaderTransformStuff();
},
check: { prop: ["slatePos", "slateZoom"], type: "global" },
atStepEnd: true,
step: "slatePosition",
}),
whenShouldFocusOnDoll: itemEffect({
run: () => focusSlateOnFocusedDoll(),
check: {
prop: [
"focusedDoll",
"slateZoomGoal",
// recalculating position when slateZoom changes is what allows it to stick to corners when zooming
// it also requires focusSlateOnFocusedDoll to run in the next tick
"slateZoom",
],
type: "global",
},
atStepEnd: true,
step: "slatePosition",
}),
whenSlateZoomChangesToSlatePanOverEdges: itemEffect({
run: () => {
const slatePos = getState().global.main.slatePos;
const newSlatePos = getSlatePositionNotOverEdges(slatePos);
setGlobalState({ slatePos: newSlatePos });
},
check: { prop: ["slateZoom"], type: "global" },
atStepEnd: true,
step: "slatePositionDontGoOverEdges",
}),
// whenNowCamChanges: itemEffect({
// run: () => focusSlateOnFocusedDoll("instant"),
// check: { prop: "nowCamName", type: "global" },
// // atStepEnd: true, // if it runs at step end, then the speech bubble changes position one frame after the camera changes
// step: "slatePosition",
// }),
whenScreenResizes: itemEffect({
run: async () => {
const { prendyOptions } = meta.assets!;
const globalRefs = getRefs().global.main;
await delay(10); // this helps it work on ipad
const engine = getEngine();
if (!engine) return;
const { editedHardwareScaling, editedSlateSceneZoom } = getShaderTransformStuff();
const screenHeight = window.innerHeight;
const screenWidth = window.innerWidth;
// get the slate size here for the ratio instead of 16:9
const slateRatio = slateSize.x / slateSize.y; // originally 16/9
// TODO redo this to try and get the render resolution to matfch the backdrops, including the zoom
const QUALITY = 2; // 1 is normal browser pixel ratio, 2 is retina, 3 is super retina
const newRenderWidth = screenHeight * slateRatio * (1 / (editedHardwareScaling / QUALITY));
const newRenderHeight = screenHeight * (1 / (editedHardwareScaling / QUALITY));
engine.setSize(newRenderWidth, newRenderHeight);
globalRefs.depthRenderTarget?.resize({ width: newRenderWidth, height: newRenderHeight });
// if the new screen ratio is equal to or thinner than a vertical 16:9, then set isOnVerticalPhone to true
const isOnVerticalScreen = screenHeight / screenWidth >= 1;
// check if the screen is super wide (for landscape phones)
const isOnSuperWideScreen = screenWidth / screenHeight >= 16 / 7;
let newZoomMultiplier = 1;
if (isOnVerticalScreen) {
// ifon a vertical screen, get a multiplier to make the zoom levels smaller
// it should be so that (newZoomMultiplier * prendyOptions.zoomLevels.default) is 1
// newZoomMultiplier = 1 / prendyOptions.zoomLevels.default;
// NOTE turned this off, now that there's square videos
} else if (isOnSuperWideScreen) {
// it should be so that (newZoomMultiplier * prendyOptions.zoomLevels.default) is 1.025
newZoomMultiplier = 1.025 / prendyOptions.zoomLevels.default;
}
setGlobalState({ isOnVerticalScreen: true, zoomMultiplier: newZoomMultiplier });
focusSlateOnFocusedDoll("instant");
},
check: { prop: "timeScreenResized", type: "global" },
atStepEnd: true,
step: "slatePosition",
}),
...addMoverEffects("global", "slatePos", "2d"),
...addMoverEffects("global", "slateZoom"),
}));