Skip to content

Commit

Permalink
chore - replace constext with zustand
Browse files Browse the repository at this point in the history
  • Loading branch information
sdubourg committed Jul 25, 2023
1 parent 117119b commit 43f3886
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 95 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"react-spring": "^9.7.2",
"three": "0.149.0",
"three-stdlib": "^2.23.13",
"xstate": "^4.38.1"
"xstate": "^4.38.1",
"zustand": "^4.3.9"
},
"devDependencies": {
"@types/react": "^18.2.15",
Expand Down
19 changes: 19 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions src/components/gl/Environment/HotSpot/Bar.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { useInterpret, useSelector } from '@xstate/react';
import { useContext } from 'react';
import { barMachine } from '../../../../machines/bar.machine';
import { DraggingContext } from '../../World/World';
import { useStoreDragging } from '../../../../stores/storeDragging';
import { Hotspot } from './Hotspot';

export const Bar = () => {
const service = useInterpret(barMachine);
const maxPersons = useSelector(service, (s) => s.context.maxPersons);
const { draggingActorRef } = useContext(DraggingContext); //TODO: degager ce contexte de mort XD
const draggingActorRef = useStoreDragging((state) => state.draggingActorRef);

return (
<Hotspot
Expand Down
23 changes: 11 additions & 12 deletions src/components/gl/Environment/HotSpot/Hotspot.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
import type { MeshProps } from '@react-three/fiber';
import {
useContext,
useEffect,
useId,
useMemo,
useReducer,
useRef,
useState,
} from 'react';
import { useEffect, useId, useMemo, useReducer, useRef, useState } from 'react';
import type { CircleGeometry, Mesh } from 'three';
import { shallow } from 'zustand/shallow';
import { getPositionsOnCircle } from '../../../../helpers/getPositionOnCircle';
import { useStoreDragging } from '../../../../stores/storeDragging';
import { DropSpots } from '../DropSpots/DropSpots';
import { DROPSPOT_SIZE, RING_SIZE } from '../DropSpots/dropSpots.constants';
import {
hopSpotReducer,
type ReducerActionHotSpot,
type ReducerStateHotSpot,
hopSpotReducer,
} from './hotSpot.reducer';
import { DraggingContext } from '../../World/World';

type HotSpotProps = {
slotsAmount: number;
Expand All @@ -33,7 +26,13 @@ export const Hotspot = ({
const refHotSpot = useRef<Mesh>(null);
const [isHovered, setIsHovered] = useState(false);

const { isDragging, draggingRef } = useContext(DraggingContext);
const { draggingRef, isDragging } = useStoreDragging(
(state) => ({
isDragging: state.isDragging,
draggingRef: state.draggingRef,
}),
shallow,
);
const uuid = useId();
const isExists = useRef(false);

Expand Down
6 changes: 2 additions & 4 deletions src/components/gl/Environment/HotSpot/Toilet.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { useInterpret, useSelector } from '@xstate/react';
import { useContext } from 'react';
import { toiletMachine } from '../../../../machines/toilet.machine';
import { DraggingContext } from '../../World/World';
import { useStoreDragging } from '../../../../stores/storeDragging';
import { Hotspot } from './Hotspot';

export const Toilet = () => {
const service = useInterpret(toiletMachine);
const maxPersons = useSelector(service, (s) => s.context.maxPersons);
const { draggingActorRef } = useContext(DraggingContext);
const draggingActorRef = useStoreDragging((state) => state.draggingActorRef);

console.log(draggingActorRef?.id);
return (
<Hotspot
slotsAmount={maxPersons}
Expand Down
32 changes: 27 additions & 5 deletions src/components/gl/House/HouseModel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ Files: HOUSE_LOW_POLY_WIP.gltf [797.6KB] > HOUSE_LOW_POLY_WIP-transformed.glb [9
import { useGLTF } from '@react-three/drei';
import { forwardRef } from 'react';
import * as THREE from 'three';
import { type GLTF } from 'three-stdlib';
import { Mesh } from 'three';
import { type GLTF } from 'three-stdlib';
import { shallow } from 'zustand/shallow';
import { useStoreDragging } from '../../../stores/storeDragging';

type GLTFResult = GLTF & {
nodes: {
Expand All @@ -21,14 +23,34 @@ type GLTFResult = GLTF & {
};
};

type HouseModel = {
onClick: () => void;
} & JSX.IntrinsicElements['group'];
type HouseModel = JSX.IntrinsicElements['group'];

export const HouseModel = forwardRef<Mesh, HouseModel>((props, ref) => {
const { setIsDragging, isDragging, setDraggingId } = useStoreDragging(
(state) => ({
isDragging: state.isDragging,
setDraggingId: state.setDraggingId,
setIsDragging: state.setIsDragging,
}),
shallow,
);

const handleOnClick = () => {
if (isDragging) {
setIsDragging(false);
setDraggingId(null);
}
};

const { nodes, materials } = useGLTF('assets/house_low.glb') as GLTFResult;
return (
<group {...props} dispose={null} scale={2} position-y={-6}>
<group
{...props}
dispose={null}
scale={2}
position-y={-6}
onClick={handleOnClick}
>
<group>
<mesh
ref={ref}
Expand Down
22 changes: 17 additions & 5 deletions src/components/gl/Person/Person.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Html, useTexture } from '@react-three/drei';
import { useFrame } from '@react-three/fiber';
import { useSelector } from '@xstate/react';
import { useControls } from 'leva';
import { useContext, useEffect, useRef } from 'react';
import { useEffect, useRef } from 'react';
import {
BufferGeometry,
Group,
Expand All @@ -13,8 +13,9 @@ import {
Vector3,
} from 'three';
import type { ActorRefFrom } from 'xstate';
import { shallow } from 'zustand/shallow';
import type { personMachine } from '../../../machines/person.machine';
import { DraggingContext } from '../World/World';
import { useStoreDragging } from '../../../stores/storeDragging';
import { PersonShadowRecall } from './PersonShadowRecall';
import { Statbar } from './Statbar';
import { PERSON_HEIGHT } from './person.constants';
Expand All @@ -31,14 +32,25 @@ export const Person = ({
const { showActionButtons } = useControls({ showActionButtons: false });

const isExists = useRef(false);

const {
isDragging,
setIsDragging,
setDraggingActorRef,
draggingId,
setDraggingActorRef,
setDraggingId,
setDraggingRef,
} = useContext(DraggingContext);
setIsDragging,
} = useStoreDragging(
(state) => ({
isDragging: state.isDragging,
setIsDragging: state.setIsDragging,
setDraggingActorRef: state.setDraggingActorRef,
draggingId: state.draggingId,
setDraggingId: state.setDraggingId,
setDraggingRef: state.setDraggingRef,
}),
shallow,
);

const ref = useRef<Mesh>(null);
const beforeDragPosition = useRef<Vector3>(new Vector3(0, 0, 0));
Expand Down
4 changes: 3 additions & 1 deletion src/components/gl/World/Cam.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { CameraControls } from '@react-three/drei';
import { useRef } from 'react';
import { DEG2RAD } from 'three/src/math/MathUtils';
import { useStoreDragging } from '../../../stores/storeDragging';

export const Cam = ({ isDragging }: { isDragging: boolean }) => {
export const Cam = () => {
const isDragging = useStoreDragging((state) => state.isDragging);
const cameraControlsRef = useRef<CameraControls>(null);

return (
Expand Down
71 changes: 8 additions & 63 deletions src/components/gl/World/World.tsx
Original file line number Diff line number Diff line change
@@ -1,78 +1,23 @@
import { useSelector } from '@xstate/react';
import { Suspense, createContext, useRef, useState } from 'react';
import type { Group, Mesh } from 'three';
import type { ActorRefFrom } from 'xstate';
import type { personMachine } from '../../../machines/person.machine';
import { Suspense, useRef } from 'react';
import type { Mesh } from 'three';
import { useGameMachineProvider } from '../../../hooks/use';
import { Bar } from '../Environment/HotSpot/Bar';
import { Toilet } from '../Environment/HotSpot/Toilet';
import { HouseModel } from '../House/HouseModel';
import { Person } from '../Person/Person';
import { Cam } from './Cam';
import { Bar } from '../Environment/HotSpot/Bar';
import { Toilet } from '../Environment/HotSpot/Toilet';

// initialize a react context with two values : isDragging and setIsDragging
// all state currently used to safe either ref of threejs object of actor ref
// nit : make a state machine for dragging
export const DraggingContext = createContext<{
isDragging: boolean;
draggingId: string | null;
draggingActorRef: ActorRefFrom<typeof personMachine> | null;
setIsDragging: (isDragging: boolean) => void;
setDraggingId: (draggingId: string | null) => void;
draggingRef: Group | null;
setDraggingRef: (draggingRef: Group | null) => void;
setDraggingActorRef: (
draggingActorRef: ActorRefFrom<typeof personMachine> | null,
) => void;
}>({
isDragging: false,
setDraggingActorRef: () => {},
setIsDragging: () => {},
setDraggingId: () => {},
draggingId: null,
draggingRef: null,
draggingActorRef: null,
setDraggingRef: () => {},
});

DraggingContext.displayName = 'DraggingContext';

export const World = () => {
const refFloor = useRef<Mesh>(null);
const [isDragging, setIsDragging] = useState(false);
const [draggingId, setDraggingId] = useState<null | string>(null);
const [draggingActorRef, setDraggingActorRef] = useState<null | ActorRefFrom<
typeof personMachine
>>(null);
const [draggingRef, setDraggingRef] = useState<Group | null>(null);

const gameService = useGameMachineProvider();
const persons = useSelector(gameService, (state) => state.context.persons);

return (
<DraggingContext.Provider
value={{
isDragging,
setIsDragging,
setDraggingId,
setDraggingActorRef,
draggingId,
draggingActorRef,
draggingRef,
setDraggingRef,
}}
>
<Cam isDragging={isDragging} />
<>
<Cam />

<HouseModel
ref={refFloor}
onClick={() => {
if (isDragging) {
setIsDragging(false);
setDraggingId(null);
}
}}
/>
<HouseModel ref={refFloor} />

<Suspense fallback={null}>
{persons.map((actor) => (
Expand All @@ -82,6 +27,6 @@ export const World = () => {

<Bar />
<Toilet />
</DraggingContext.Provider>
</>
);
};
1 change: 0 additions & 1 deletion src/machines/bar.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export const barMachine = hotspotMachine
.withConfig({
actions: {
updatePersons: (context) => {
console.log(context.persons);
context.persons.forEach((p) => p.send('triggerDrink'));

Check failure on line 11 in src/machines/bar.machine.ts

View workflow job for this annotation

GitHub Actions / main - Build and deploy

'p' is possibly 'null'.
return context;
},
Expand Down
39 changes: 39 additions & 0 deletions src/stores/storeDragging.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { Group } from 'three';
import type { ActorRefFrom } from 'xstate';
import { create } from 'zustand';
import type { personMachine } from '../machines/person.machine';

type InitialState = {
isDragging: boolean;
draggingId: string | null;
draggingActorRef: ActorRefFrom<typeof personMachine> | null;
draggingRef: Group | null;
};

type Actions = {
setIsDragging: (isDragging: boolean) => void;
setDraggingId: (draggingId: string | null) => void;
setDraggingRef: (draggingRef: Group | null) => void;
setDraggingActorRef: (
draggingActorRef: ActorRefFrom<typeof personMachine> | null,
) => void;
};

const InitialState = {
isDragging: false,
draggingId: null,
draggingRef: null,
draggingActorRef: null,
};

export const useStoreDragging = create<InitialState & Actions>((set) => ({
...InitialState,

setIsDragging: (isDragging) => set({ isDragging }),

setDraggingId: (draggingId) => set({ draggingId }),

setDraggingRef: (draggingRef) => set({ draggingRef }),

setDraggingActorRef: (draggingActorRef) => set({ draggingActorRef }),
}));

0 comments on commit 43f3886

Please sign in to comment.