From a32a75bd940a8bcd1752da340bc209357720b1ad Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Sun, 9 Apr 2023 21:40:12 -0500 Subject: [PATCH] Various docs improvements --- docs/.vitepress/config.js | 3 +- docs/.vitepress/theme/custom.css | 11 ++- docs/guide/advanced-concepts/nodes.md | 36 +++++++- docs/guide/getting-started/setup.md | 40 ++++----- docs/guide/getting-started/workflow-perms.png | Bin 0 -> 27386 bytes docs/guide/recipes/particles.md | 77 ++++++++++++++++++ 6 files changed, 143 insertions(+), 24 deletions(-) create mode 100644 docs/guide/getting-started/workflow-perms.png create mode 100644 docs/guide/recipes/particles.md diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js index 4a484e33..feadd7f8 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.js @@ -74,7 +74,8 @@ module.exports = { text: "Recipes", collapsed: false, items: [ - { text: "Display Save Progress", link: "/guide/recipes/save-progress" } + { text: "Display Save Progress", link: "/guide/recipes/save-progress" }, + { text: "Display Particle Effect", link: "/guide/recipes/particles" } ] }, { diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css index 4ce8865d..36982a15 100644 --- a/docs/.vitepress/theme/custom.css +++ b/docs/.vitepress/theme/custom.css @@ -13,7 +13,16 @@ body { } .custom-block.warning { - background-color: #EBCB8B; + background-color: #3B4252; + border-color: #EBCB8B; +} + +.custom-block.warning > .custom-block-title { + color: #EBCB8B; +} + +.custom-block.warning > :not(.custom-block-title) { + color: var(--vp-custom-block-info-text); } .vp-doc tr:nth-child(2n), diff --git a/docs/guide/advanced-concepts/nodes.md b/docs/guide/advanced-concepts/nodes.md index 10736fff..44342d42 100644 --- a/docs/guide/advanced-concepts/nodes.md +++ b/docs/guide/advanced-concepts/nodes.md @@ -1,7 +1,37 @@ # Nodes -Every feature that is rendered in the DOM should have a `Node` component within it, which registers itself to the closest `Context` component (typically within the`Layer`'s component) and tracks the bounding rect (both size and position) of the DOM element. You can then search for a feature's unique `id` property within `layer.nodes` to get access to the DOM element for that feature, if it currently exists. +Features rendered in the DOM should include a `Node` component, which registers itself to the nearest `Context` component (usually within the `Layer`'s component) and tracks the bounding rect (both size and position) of the DOM element. Access the DOM element for a feature via its unique `id` property within `layer.nodes`, provided it currently exists. -This can be used for features with more complex displays, such as particle effects positioned relative to another feature, or drawing links between different nodes. +This is useful for features with complex displays, such as particle effects positioned relative to another feature or drawing links between different nodes. To illustrate this, let's look at a complete example of using `layer.nodes` to get a node's bounding rect and then placing a particle effect using it. Here's an example from Kronos: -The bounding rect that will typically be kept up to date and react to things like nodes changing size, or moving because of the window resizing or feature's showing or hiding. However, there are ocassional situations where it may become out of sync, so it's recommended to only use the node system for visual effects, where any glitches will be relatively minor. +```ts +const particlesEmitter = ref(particles.addEmitter(element.particlesConfig)); +const updateParticleEffect = async ([shouldEmit, rect, boundingRect]: [ + boolean, + DOMRect | undefined, + DOMRect | undefined +]) => { + const emitter = await particlesEmitter.value; + emitter.emit = isGaining && rect != undefined && boundingRect != undefined; + if (emitter.emit && !emitter.destroyed) { + emitter.cleanup(); + emitter.updateOwnerPos( + rect.x + rect.width / 2 - boundingRect.x, + rect.y + rect.height / 2 - boundingRect.y + ); + emitter.resetPositionTracking(); + } +}; +watch( + [ + () => Decimal.gt(actualGain.value, 0), + () => layer.nodes.value[name]?.rect, + particles.boundingRect + ], + updateParticleEffect +) +``` + +In this example the particle effects will update whenever the window resizes, the feature's bounding rect changes, or the particle effect is supposed to turn on/off. By watching for other relevant properties you can ensure even more complex situations are accounted for. + +The bounding rect is usually kept up-to-date and responsive to changes such as nodes resizing, moving due to window resizing, or features being shown or hidden. However, occasional situations may cause it to be out of sync. Therefore, it's recommended to use the node system for visual effects only, where any glitches have minimal impact. diff --git a/docs/guide/getting-started/setup.md b/docs/guide/getting-started/setup.md index 99a95c9e..60450348 100644 --- a/docs/guide/getting-started/setup.md +++ b/docs/guide/getting-started/setup.md @@ -1,61 +1,63 @@ # Setting Up -Profectus requires a node development environment in order to work on a project. If you are comfortable with the command line, it is recommended to use a local development environment. +Profectus requires a Node.js development environment for working on a project. If you are comfortable with the command line, a local development environment is recommended. ## Local Development -You will require the following tools for local development: +For local development, you will need the following tools: - [git](https://git-scm.com/downloads) - [node](https://nodejs.org/en/download/) -Create a new project from the [Profectus repository](https://github.com/profectus-engine/Profectus) via the "Use this template" button. You can then copy the link for the repository to clone it locally. +Create a new project from the [Profectus repository](https://github.com/profectus-engine/Profectus) by clicking the "Use this template" button. Then, clone the repository locally using the provided link. ::: info -Since the repository is a template repository, you can easily create multiple projects from one repository. However, it does make updating an existing project to a newer version of Profectus more difficult. Consider [updating Profectus](./updating.md) _before_ you start developing, to avoid the issue with unrelated histories. +The template repository allows easy creation of multiple projects from one repository. However, updating an existing project to a newer version of Profectus can be challenging. Consider [updating Profectus](https://chat.openai.com/updating.md) _before_ starting development to avoid issues with unrelated histories. ::: -It's recommended to create a new git branch for development, so you can push your changes without it affecting the live build. This allows you to continue working with smaller commits, and only release new versions when you're actually ready to. The github workflow will automatically rebuild the page whenever you push to the `main` branch. +It's recommended to create a new Git branch for development, allowing you to push changes without affecting the live build. The GitHub workflow will automatically rebuild the page when you push to the `main` branch. -The next step is to install Profectus' dependencies. This is as simple as running `npm install`. +Next, install Profectus' dependencies by running `npm install`. Run `npm run serve` to start a local server hosting your project. The site will automatically reload as you modify files. -You can now run `npm run serve` to start a local server that will host your project so you can work on it. As you change files the site will automatically reload them. - -Also, you might consider following the steps to [update Profectus](./updating.md) before you start working, as it'll make updating in the future easier without needing to worry about unrelated histories. +Also, follow the steps to [update Profectus](https://chat.openai.com/updating.md) before starting to make future updates easier without worrying about unrelated histories. ### Deploying -If you're using git, deploying is as easy as pushing your changes to the `main` branch. In a couple minutes the site will be updated fully automatically. If you'd like to see progress on it, or look at any errors that happened, you can do so from the actions tab on your repository. +Using Git, the repository's workflow action automates deployment. However, you need to grant write permissions for the action in the repository settings. Go to Actions, General, Workflow permissions, and select "Read and write permissions". + +![workflow permissions](./workflow-perms.png) + +To deploy, push changes to the main branch. The site will be updated automatically in a few minutes. Check progress or errors from the Actions tab on your repository. ![actions button](./actionsbutton.png) -Before github knows to actually host the generated site, you'll have to enable github pages in the repo settings. This just means selecting the branch to use - `gh-pages`. You will only need to perform this step once. This will automatically start another github action to deploy the website. +Enable GitHub Pages in the repo settings to host the generated site. Select the `gh-pages` branch. Perform this step once. This will automatically start another GitHub action to deploy the website. ![github pages](./gh-pages.png) -Once the action completes, your project should be available at `https://.github.io//`. For example, the TMT Demo project hosted at https://github.com/profectus-engine/TMT-Demo is available at https://profectus-engine.github.io/TMT-Demo/. +Upon action completion, your project should be available at `https://.github.io//`. For example, the TMT Demo project hosted at https://github.com/profectus-engine/TMT-Demo is available at https://profectus-engine.github.io/TMT-Demo/. ### Visual Studio Code Setup -If you don't already have a preferred IDE, Profectus is currently developed in [Visual Studio Code](https://code.visualstudio.com) and is known to work well with that IDE in particular. +If you don't have a preferred IDE, Profectus is developed in [Visual Studio Code](https://code.visualstudio.com) and is known to work well with it. Recommendations: - Use [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471) for proper type analysis - Turn off `.value` autocomplete by running the `Preferences: Open Settings` command and setting `volar.autoCompleteRefs` to `false` -- Install the [Vitest VS Code extension](https://marketplace.visualstudio.com/items?itemName=ZixuanChen.vitest-explorer&ssr=false#qna) for running and debugging unit tests (if you plan on working on the engine itself) +- Install the [Vitest VS Code extension](https://marketplace.visualstudio.com/items?itemName=ZixuanChen.vitest-explorer&ssr=false#qna) for running and debugging unit tests (if working on the engine itself) ## Replit -As an alternative to local development, you may use [replit](https://replit.com), which will automatically set up your development environment for you and also host your project itself. +As an alternative to local development, you may use [Replit](https://replit.com). Replit sets up your development and hosts your project. -However, on the free plan you will be limited by the amount of resources you can use, and the program will need to start up occasionally. +On the free plan, you'll face limitations, and the program may need occasional startups. -To create a Profectus project on replit, all you have to do is click this button: +To create a Profectus project on Replit, all you have to do is click this button: [![Run on Repl.it](https://repl.it/badge/github/profectus-engine/Profectus)](https://repl.it/github/profectus-engine/Profectus) -You can then start the developing by clicking the "Run" button at the top of the screen. This will also make the project run publicly, so you could consider it as automatically deployed. This does mean you cannot have a separate development environment from your production environment, however. +Click the "Run" button at the top of the screen to start development. This will also make the project publicly accessible, essentially auto-deploying it. However, this means you cannot separate your development and production environments. ## Glitch -[Glitch](https://glitch.com) is a site similar to replit, with much the same pros and cons. To create a projectus project on glitch, select "New Project", "Import from GitHub", and then type in `profectus-engine/Profectus`. The new project will be created and should be automatically configured and ready to go. +[Glitch](https://glitch.com) is a site similar to Replit, with many of the same pros and cons. To create a Profectus project on Glitch, select "New Project", "Import from GitHub", and enter `profectus-engine/Profectus`. The new project will be automatically configured and ready to go. diff --git a/docs/guide/getting-started/workflow-perms.png b/docs/guide/getting-started/workflow-perms.png new file mode 100644 index 0000000000000000000000000000000000000000..b5295eb7a8d7918eb48b25739a58678617baf06b GIT binary patch literal 27386 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
*hOx$6E z6gcbnWMXQGL;0D_S-qx(@o4Z#|n~J;oy{K7}qw;LNL^m2B2u)XP5lqyZfJCS@#5w0n?q_vQBxPz&D1LXSrRu0; zw=#yrhgIeq{zIN3FN@XH(`I$CeXX1j;m!+p_3}CM#zD7y_ZS~5O-`>?t$ZVf>q!dy zeE)9>l~)apr)dofl~xi<1_oSn3qKa#Y9K>~9xV4N>E_#NnnrI?>>`i0O86@+w;*>; z*Ua@YN{K~#zX-s(^38zZ6R71ti!XAfb>H-xb;G+WyT#6ccur9m_BHOB!err?A{`G< z!a&s*Dm5NO>-Z!mV8uAsVAJ`xRZa77a5_|=w@pa0iOBrbfBw&~0ol94GQ~~f?7|iB zlR$$ykletOLr�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 ({ + fullscreen: false, + zIndex: -1, + boundingRect: ref(null), + onContainerResized(boundingRect) { + this.boundingRect.value = boundingRect; + } +})); +``` + +You'll note this adds a bounding rect and updates it's based on the boundingRect set to non-null. The next step will be creating the emitter. Now we can pull in the Kronos example, which make a particle effect that appears when actualGain > 0. + +```ts +const particlesEmitter = ref(particles.addEmitter(element.particlesConfig)); +const updateParticleEffect = async ([shouldEmit, rect, boundingRect]: [ + boolean, + DOMRect | undefined, + DOMRect | undefined +]) => { + const emitter = await particlesEmitter.value; + emitter.emit = isGaining && rect != undefined && boundingRect != undefined; + if (emitter.emit && !emitter.destroyed) { + emitter.cleanup(); + emitter.updateOwnerPos( + rect.x + rect.width / 2 - boundingRect.x, + rect.y + rect.height / 2 - boundingRect.y + ); + emitter.resetPositionTracking(); + } +}; +watch( + [ + () => Decimal.gt(actualGain.value, 0), + () => layer.nodes.value[name]?.rect, + particles.boundingRect + ], + updateParticleEffect +) +``` + +You'll note this checks regularly whether the boundingRect exists. If you ensure all the references to things are being watched, youy can make complex situations for various emitters. + +If you're hot reloading, it may be required to re-load the particle effect. Here's example code from Kronos. + +```ts +const refreshParticleEffect = () => { + particlesEmitter.value + .then(e => e.destroy()) + .then( + () => + (particlesEmitter.value = particles.addEmitter(element.particlesConfig)) + ) + .then(() => + updateParticleEffect([ + Decimal.gt(actualGain.value, 0), + layer.nodes.value[name]?.rect, + particles.boundingRect.value + ]) + ); +}; +```