generated from graasp/graasp-app-starter-ts-vite
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add three.js and the first 3D scene (#6)
* feat: add a scene with an house, some trees and a garden * fix(cypress): remove MirageJS to work with Cypress
- Loading branch information
Showing
32 changed files
with
1,227 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,9 @@ | |
<img style="text-align: center" src="https://graasp.org/favicon.svg" width=100 > | ||
</div> | ||
|
||
# Graasp App Template | ||
# Graasp App Insulation Simulator | ||
|
||
This repository hosts the template code for a **Graasp App** written with [Typescript](https://www.typescriptlang.org/) and [React](https://react.dev/). The bundler used is [Vite](https://vitejs.dev). | ||
This repository hosts the code for the **Graasp App Insulation Simulator** written with [Typescript](https://www.typescriptlang.org/) and [React](https://react.dev/). The bundler used is [Vite](https://vitejs.dev). | ||
|
||
<div style="gap:10px; display:flex; justify-content: center; align-items: center;"> | ||
<img src="https://upload.wikimedia.org/wikipedia/commons/4/4c/Typescript_logo_2020.svg" width=50 > | ||
|
@@ -16,74 +16,18 @@ This repository hosts the template code for a **Graasp App** written with [Types | |
<span>❤️</span> | ||
</div> | ||
|
||
## Using this template | ||
## Purpose | ||
|
||
The recommended way to use this template is with the [Graasp CLI](https://github.com/graasp/graasp-cli) which provides a setup wizard and some convenience tools when creating your project. | ||
The app's purpose is to help users understand and reduce heat loss through conduction in a house by testing various insulation materials, including advanced options like aerogel. Users can customize energy costs and the duration of the simulation (e.g., 1 year or 25 years) to see how these factors affect heat retention and energy efficiency over time. The app simulates heat loss scenarios based on user inputs, comparing them against a baseline to calculate energy savings and cost benefits. This allows users to visualize and quantify the impact of improved insulation on reducing heat loss by conduction. | ||
|
||
Alternatively it is possible to create a new Github repo from this project using the Github Template function. In this case the local setup is left as an exercice to the reader. | ||
|
||
### With the Graasp CLI | ||
|
||
This template can be used with the [graasp CLI](https://www.npmjs.com/package/@graasp/cli?activeTab=readme) to setup your project in a single line: | ||
|
||
```bash | ||
npx @graasp/cli@latest new -s graasp/graasp-app-starter-ts-vite | ||
``` | ||
|
||
The CLI will ask you a few questions to help you setup your project. It suggests sane defaults: | ||
|
||
- Deploying using GitHubActions (recommended) | ||
- Provide an appId | ||
- Auto-install project dependencies | ||
- Initialize a local git repository | ||
|
||
<details > | ||
<summary><h3>Directly from GitHub</h3></summary> | ||
|
||
Should you choose to bootstrap your graasp app manually, you will need to execute the following steps. | ||
|
||
#### Cloning the template | ||
|
||
Get a copy of this repo. | ||
|
||
##### Using the Template button | ||
|
||
Click on the `Use this template` button. For more instructions head over to the [GitHub Docs on Using a template](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template) | ||
|
||
##### Clone from the command line | ||
|
||
With `git`: | ||
|
||
```sh | ||
git clone | ||
``` | ||
|
||
With the [GitHub CLI](https://cli.github.com/): | ||
|
||
```bash | ||
gh repo clone graasp/graasp-app-starter-ts-vite | ||
``` | ||
|
||
#### Adding Workflows | ||
|
||
To deploy your app using github actions. | ||
|
||
#### Renaming | ||
|
||
You will have to look for the `Graasp App Template` string in yours project files and rename it to your project name | ||
|
||
</details> | ||
|
||
### GitHub Repo setup | ||
## GitHub Repo setup | ||
|
||
If you choose to deploy your app with the provided GitHubActions workflows you will need to create the following secrets: | ||
|
||
- `APP_ID`: a UUID v4 that identifies your app for deployment | ||
- `APP_KEY`: a UUID v4 that authorizes your app with the Graasp API | ||
- `SENTRY_DSN`: your Sentry url to report issues and send telemetry | ||
|
||
## Installation | ||
|
||
## Running the app | ||
|
||
Create a `.env.development` file with the following content: | ||
|
@@ -110,3 +54,44 @@ VITE_VERSION=latest | |
# dont open browser | ||
BROWSER=none | ||
``` | ||
|
||
## Working with 3D Models | ||
|
||
This project utilizes **Three.js** and **React-Three-Fiber** to streamline the loading and management of 3D models within a React environment. Additionally, the `gltfjsx` package is employed to optimize and compress GLB models, as well as to automatically generate the corresponding React components for easy integration and rendering of these models. | ||
|
||
To enhance clarity for developers and maintainers, all files generated by the `gltfjsx` package include a standardized header, as shown below: | ||
|
||
```js | ||
/* | ||
Auto-generated by: https://github.com/pmndrs/gltfjsx | ||
Command: npx [email protected] OriginalHouse.glb --transform --types | ||
Files: OriginalHouse.glb [250.7KB] > House.glb [16.05KB] (94%) | ||
Model: "Residential Houses" from: https://www.sloyd.ai/ | ||
*/ | ||
``` | ||
|
||
In this example, we compressed the GLB file using the `--transform` flag, which optimizes the model for better performance, and generated a React component with the full command. The `--types` flag was used to generate TypeScript types for enhanced type safety. By using a compressed version of the GLB file, we consolidate the object's components into organized groups, making the React component easier to understand and improving browser rendering efficiency. | ||
|
||
Indeed, the compressed component for the fir tree will consist of two meshes: one for the spines and one for the trunk. In contrast, the original component would have contained seven meshes for the spines and one for the trunk. This compression significantly reduces the number of meshes, which, in turn, minimizes the lines of code in our component, making it more efficient and easier to manage. The drawback of this compression is that we have less control over the different parts of the object. If this is what we want, we should avoid using the `--transform` flag. | ||
|
||
Additionally, I used Blender to rename the object’s materials for clarity, such as changing `Material-001.002` to more descriptive names like `Wall`. | ||
|
||
Lastly, each header contains the URL of the original model if it wasn't created in-house, providing proper attribution and reference for future modifications. | ||
|
||
This approach simplifies the process of updating or adding a 3D model. To do so, simply place the model in the `public/models` folder and run the `npx gltfjsx` command. Afterward, move the original model into the `/models` folder (if we want to conserve the original) and store the generated code in the `src/modules/models` directory. It is also recommended to extract the logic from this component into a custom hook, making it modular and reusable while keeping the component clean and focused on rendering. | ||
|
||
If an existing model is updated, we should replace the type and the React component group while leaving the logic hooks untouched. This approach ensures that the code remains valid and functional, as the underlying logic and behavior are preserved, reducing the risk of introducing errors. | ||
|
||
The positions of the meshes within the group are auto-generated, and they should never be manually modified. If an object needs to be repositioned, adjust its `position` prop applied directly to the group instead. This maintains consistency and ensures the auto-generated structure remains intact while allowing for flexible positioning. | ||
|
||
### Credits | ||
|
||
The house and tree models are created by [Sloyd.ai](https://www.sloyd.ai). All rights reserved by Sloyd for these models. | ||
|
||
## Known issues | ||
|
||
Three.js and MUI can encounter conflicts when using the `Box` component from MUI. To resolve this issue, you can consider the following options: | ||
|
||
- **Upgrade to MUI 6**: This may resolve the conflict, so it's worth testing. | ||
- **Use the `Box` component with a `div`**: Replace Box with `<Box component="div">...</Box>` to mitigate the issue. | ||
- **Avoid using `Box` altogether**: Instead, opt for the `Stack` component, which may provide a suitable alternative without conflicts. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const MODELS_3D_ROOT_PATH = 'public/models'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { | ||
ReactNode, | ||
createContext, | ||
useCallback, | ||
useContext, | ||
useMemo, | ||
useState, | ||
} from 'react'; | ||
|
||
import { AllSeasons, Season, Seasons } from '@/types/seasons'; | ||
|
||
type SeasonContextType = { | ||
season: Season; | ||
nextSeason: () => void; | ||
}; | ||
|
||
const SeasonContext = createContext<SeasonContextType>({ | ||
season: Seasons.Spring, | ||
nextSeason: () => { | ||
throw new Error( | ||
'The SeasonContext has been used before its initialization', | ||
); | ||
}, | ||
}); | ||
|
||
type Props = { | ||
children: ReactNode; | ||
}; | ||
|
||
export const SeasonProvider = ({ children }: Props): ReactNode => { | ||
const [season, setSeason] = useState<Season>(Seasons.Spring); | ||
|
||
const nextSeason = useCallback((): void => { | ||
setSeason((prev) => { | ||
const prevIdx = AllSeasons.findIndex((s) => s === prev); | ||
const newIdx = (prevIdx + 1) % AllSeasons.length; | ||
|
||
return Seasons[AllSeasons[newIdx]]; | ||
}); | ||
}, []); | ||
|
||
const contextValue = useMemo( | ||
() => ({ | ||
season, | ||
nextSeason, | ||
}), | ||
[season, nextSeason], | ||
); | ||
|
||
return ( | ||
<SeasonContext.Provider value={contextValue}> | ||
{children} | ||
</SeasonContext.Provider> | ||
); | ||
}; | ||
|
||
export const useSeason = (): SeasonContextType => | ||
useContext<SeasonContextType>(SeasonContext); |
4 changes: 2 additions & 2 deletions
4
src/modules/context/SettingsContext.tsx → src/context/SettingsContext.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
import React, { FC } from 'react'; | ||
import { FC } from 'react'; | ||
|
||
import { Box } from '@mui/material'; | ||
import { Stack } from '@mui/material'; | ||
import CircularProgress from '@mui/material/CircularProgress'; | ||
|
||
const Loader: FC = () => ( | ||
<Box sx={{ display: 'flex', justifyContent: 'center' }}> | ||
<Stack justifyContent="center"> | ||
<CircularProgress /> | ||
</Box> | ||
</Stack> | ||
); | ||
|
||
export default Loader; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.