Skip to content

Commit

Permalink
feat: smoothly change colours (#43)
Browse files Browse the repository at this point in the history
* feat: improve null context errors handling
  • Loading branch information
ReidyT authored Oct 30, 2024
1 parent b6d9af7 commit 8550e7e
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 34 deletions.
29 changes: 10 additions & 19 deletions src/context/SimulationContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ import {
initSlidingWindow,
} from '../models/TemperatureIterator';

const SIMULATION_ERROR_CONTEXT = undefinedContextErrorFactory('Simulation');

type SimulationContextType = {
status: SimulationStatus;
heatLoss: FormattedHeatLoss;
Expand All @@ -49,21 +47,7 @@ type SimulationContextType = {
startSimulation: () => void;
};

const SimulationContext = createContext<SimulationContextType>({
status: SimulationStatus.IDLE,
heatLoss: { value: 0, unit: 'W' },
totalHeatLoss: { value: 0, unit: 'W' },
electricityCost: 0,
indoorTemperature: 0,
outdoorTemperature: 0,
progression: { progress: 0, timeLeft: 0 },
period: { from: new Date(), to: new Date(), durationInHours: 0 },
duration: { value: 0, unit: TimeUnit.Hours },
material: { price: 0, thermalConductivity: 0, thickness: 0 },
startSimulation: () => {
throw SIMULATION_ERROR_CONTEXT;
},
});
const SimulationContext = createContext<SimulationContextType | null>(null);

type Props = {
children: ReactNode;
Expand Down Expand Up @@ -194,5 +178,12 @@ export const SimulationProvider = ({
);
};

export const useSimulation = (): SimulationContextType =>
useContext<SimulationContextType>(SimulationContext);
export const useSimulation = (): SimulationContextType => {
const context = useContext(SimulationContext);

if (!context) {
throw undefinedContextErrorFactory('Simulation');
}

return context;
};
25 changes: 25 additions & 0 deletions src/hooks/useSmoothTransitionColor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useRef } from 'react';

import { useFrame } from '@react-three/fiber';
import { Color, MeshStandardMaterial } from 'three';

const TRANSITION_SPEED = 5;

export const useSmoothTransitionColor = ({
color,
initialMaterial = new MeshStandardMaterial(),
}: {
color: string | Color;
initialMaterial?: MeshStandardMaterial;
}): MeshStandardMaterial => {
const materialRef = useRef<MeshStandardMaterial>(initialMaterial);

useFrame((_, delta) => {
if (materialRef.current) {
const targetColor = new Color(color);
materialRef.current.color.lerp(targetColor, delta * TRANSITION_SPEED); // Smooth transition
}
});

return materialRef.current ?? initialMaterial;
};
7 changes: 5 additions & 2 deletions src/modules/models/FirTree/useFirTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { GLTF } from 'three-stdlib';

import { MODELS_3D_ROOT_PATH } from '@/config/models';
import { useSeason } from '@/context/SeasonContext';
import { useSmoothTransitionColor } from '@/hooks/useSmoothTransitionColor';
import { Seasons } from '@/types/seasons';
import { fromRGB } from '@/utils/colors';

Expand Down Expand Up @@ -39,8 +40,10 @@ type UseFirTree = {
export const useFirTree = (): UseFirTree => {
const { season } = useSeason();
const { nodes, materials } = useGLTF(GLB_FILE_PATH) as GLTFResult;
const spineMaterial = new MeshStandardMaterial().copy(materials.Spine);
spineMaterial.color = COLORS_BY_SEASON[season];
const spineMaterial = useSmoothTransitionColor({
color: COLORS_BY_SEASON[season],
initialMaterial: materials.Spine,
});

return {
nodes,
Expand Down
9 changes: 6 additions & 3 deletions src/modules/models/Garden.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { RoundedBox } from '@react-three/drei';
import { Vector3 } from '@react-three/fiber';

import { useSeason } from '@/context/SeasonContext';
import { useSmoothTransitionColor } from '@/hooks/useSmoothTransitionColor';
import { Seasons } from '@/types/seasons';

const COLORS_BY_SEASON = {
Expand All @@ -20,13 +21,15 @@ type Props = {

export const Garden = ({ position }: Props): JSX.Element => {
const { season } = useSeason();
const material = useSmoothTransitionColor({
color: COLORS_BY_SEASON[season],
});

return (
<RoundedBox
scale={[SIZE_IN_METERS, HEIGHT_IN_METERS, SIZE_IN_METERS]}
position={position}
>
<meshStandardMaterial color={COLORS_BY_SEASON[season]} />
</RoundedBox>
material={material}
/>
);
};
5 changes: 1 addition & 4 deletions src/modules/models/Tree/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ Model: "Trees" from: https://www.sloyd.ai/
*/
import { GroupProps } from '@react-three/fiber';

import { Seasons } from '@/types/seasons';

import { useTree } from './useTree';

type Props = GroupProps;

export const Tree = (props: Props): JSX.Element => {
const { nodes, materials, season } = useTree();
const { nodes, materials } = useTree();

/**
* This code has been generated with the command `npx gltfjsx`.
Expand All @@ -24,7 +22,6 @@ export const Tree = (props: Props): JSX.Element => {
<mesh
geometry={nodes.Lofted_Patch.geometry}
material={materials.Leaf}
visible={season !== Seasons.Winter}
position={[0, 1.227, 0]}
/>
<mesh
Expand Down
7 changes: 5 additions & 2 deletions src/modules/models/Tree/useTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { GLTF } from 'three-stdlib';

import { MODELS_3D_ROOT_PATH } from '@/config/models';
import { useSeason } from '@/context/SeasonContext';
import { useSmoothTransitionColor } from '@/hooks/useSmoothTransitionColor';
import { Season, Seasons } from '@/types/seasons';
import { fromRGB } from '@/utils/colors';

Expand Down Expand Up @@ -40,8 +41,10 @@ type UseTree = {
export const useTree = (): UseTree => {
const { season } = useSeason();
const { nodes, materials } = useGLTF(GLB_FILE_PATH) as GLTFResult;
const leafMaterial = new MeshStandardMaterial().copy(materials.Leaf);
leafMaterial.color = COLORS_BY_SEASON[season];
const leafMaterial = useSmoothTransitionColor({
color: COLORS_BY_SEASON[season],
initialMaterial: materials.Leaf,
});

return {
season,
Expand Down
7 changes: 3 additions & 4 deletions src/modules/scenes/FirstScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,14 @@ const FirstSceneComponent = (): JSX.Element => {
</Stack>
<Canvas
style={{ height: '100vh', width: '100vw' }}
camera={{ position: [10, 1, -15], fov: 75 }}
camera={{ position: [10, 1, -20], fov: 75 }}
>
<color attach="background" args={[0x87ceeb]} />
{/* Ambient Light for overall illumination */}
<ambientLight intensity={1.2} />
<ambientLight intensity={1.5} />
{/* Main Sunlight Simulation */}
<directionalLight
position={[6, 30, -10]}
intensity={2}
intensity={2.5}
color={0xffffff}
/>
<OrbitControls
Expand Down

0 comments on commit 8550e7e

Please sign in to comment.