mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-12-23 10:11:54 +00:00
Update website and add student project info
This commit is contained in:
parent
12e16b9a4e
commit
9edd9233db
13 changed files with 234 additions and 109 deletions
|
|
@ -46,7 +46,8 @@ js = ["image-interaction.js", "video-embed.js"]
|
|||
|
||||
<h1 class="balance-text">Redefining state‑of‑the‑art graphics editing</h1>
|
||||
|
||||
<p class="balance-text"><strong>Graphite</strong> is an in-development raster and vector graphics package that's free and open source. It is powered by a node graph compositing engine that fuses layers with nodes, providing a fully nondestructive editing experience.</p>
|
||||
<p class="balance-text"><strong>Graphite</strong> is an in-development raster and vector graphics package that's free and open source. It is powered by a node graph compositing engine that fuses layers with nodes, bringing a procedural approach to your design workflow.</p>
|
||||
<!-- <p class="balance-text"><strong>Graphite</strong> is an in-development raster and vector graphics package that's free and open source. It is powered by a node graph compositing engine that fuses layers with nodes, providing a fully nondestructive editing experience.</p> -->
|
||||
|
||||
</section>
|
||||
<!-- ▙ TAGLINE ▟ -->
|
||||
|
|
@ -66,18 +67,21 @@ js = ["image-interaction.js", "video-embed.js"]
|
|||
<!-- ▛ SCREENSHOTS ▜ -->
|
||||
<section id="screenshots" class="carousel window-size-1" data-carousel data-carousel-jostle-hint>
|
||||
<div class="carousel-slide">
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-valley-of-spires__4.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #1" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-procedural-string-lights.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #2" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-nodes__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #3" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-viewport__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #4" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-red-dress.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #1" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-valley-of-spires__4.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #2" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-procedural-string-lights.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #3" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-nodes__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #4" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-viewport__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite UI image #5" data-carousel-image />
|
||||
</div>
|
||||
<div class="carousel-slide torn left">
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-red-dress.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-valley-of-spires__4.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-procedural-string-lights.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-nodes__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-viewport__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
</div>
|
||||
<div class="carousel-slide torn right">
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-red-dress.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-valley-of-spires__4.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-demo-procedural-string-lights.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
<img src="https://static.graphite.rs/content/index/gui-mockup-nodes__5.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="" data-carousel-image />
|
||||
|
|
@ -95,6 +99,7 @@ js = ["image-interaction.js", "video-embed.js"]
|
|||
<button class="dot" data-carousel-dot></button>
|
||||
<button class="dot" data-carousel-dot></button>
|
||||
<button class="dot" data-carousel-dot></button>
|
||||
<button class="dot" data-carousel-dot></button>
|
||||
<button class="direction next" data-carousel-next>
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20,0C8.95,0,0,8.95,0,20c0,11.05,8.95,20,20,20c11.05,0,20-8.95,20-20C40,8.95,31.05,0,20,0z M20,38c-9.93,0-18-8.07-18-18S10.07,2,20,2s18,8.07,18,18S29.93,38,20,38z" />
|
||||
|
|
@ -104,10 +109,13 @@ js = ["image-interaction.js", "video-embed.js"]
|
|||
</div>
|
||||
<div class="screenshot-description">
|
||||
<p class="active" data-carousel-description>
|
||||
<em>Valley of Spires</em> — Vector art made with the Pen and Gradient tools. <a href="https://editor.graphite.rs/#demo/valley-of-spires">Open this artwork</a> to explore it yourself.
|
||||
<a href="https://editor.graphite.rs/#demo/red-dress"><em>Red Dress</em></a> — Illustration made with the help of procedurally generating hundreds of circles in the node graph.
|
||||
</p>
|
||||
<p data-carousel-description>
|
||||
<em>Procedural String Lights</em> — Partly made in the node graph (pictured) to auto-place light bulbs along the wire. <a href="https://editor.graphite.rs/#demo/procedural-string-lights">Open this artwork</a> to explore it yourself.
|
||||
<a href="https://editor.graphite.rs/#demo/valley-of-spires"><em>Valley of Spires</em></a> — Vector art made with the Pen and Gradient tools without needing to touch the node graph.
|
||||
</p>
|
||||
<p data-carousel-description>
|
||||
<a href="https://editor.graphite.rs/#demo/procedural-string-lights"><em>Procedural String Lights</em></a> — Drawing of a tree adorned by reusable, auto-placed light bulbs along the wire path made using this node graph.
|
||||
</p>
|
||||
<p data-carousel-description>
|
||||
Design mockup for the work-in-progress raster editing pipeline. Some of these raster-specific nodes are not implemented yet, but will be soon!
|
||||
|
|
@ -161,11 +169,11 @@ Graphite is a lightweight vector graphics editor that runs offline in your brows
|
|||
<div class="informational-group features">
|
||||
<div class="informational">
|
||||
<img class="atlas" style="--atlas-index: 4" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Looks and feels like traditional <span style="text-decoration: underline dotted; text-decoration-color: #16323f77;" title=""what you see is what you get"">WYSIWYG</span> design apps</span>
|
||||
<span>All-in-one creative tools for animation, art, and design</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<img class="atlas" style="--atlas-index: 5" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span>Clean, intuitive interface built by designers, for designers</span>
|
||||
<span>Clean, familiar interface built by designers, for designers</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<img class="atlas" style="--atlas-index: 6" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
|
|
@ -299,19 +307,19 @@ You'll receive your first newsletter email with the next major Graphite news.
|
|||
<!-- ▙ COMMUNITY ▟ -->
|
||||
<!-- -->
|
||||
<!-- ▛ JUMP RIGHT IN ▜ -->
|
||||
<section id="jump-right-in">
|
||||
<div class="section">
|
||||
<!-- <section id="jump-right-in">
|
||||
<div class="section"> -->
|
||||
|
||||
# Jump right in
|
||||
<!-- # Jump right in -->
|
||||
|
||||
**Get started with Graphite by following along to a hands-on quickstart tutorial.**
|
||||
<!-- **Get started with Graphite by following along to a hands-on quickstart tutorial.** -->
|
||||
|
||||
<div class="video-embed aspect-16x9">
|
||||
<!-- <div class="video-embed aspect-16x9">
|
||||
<img data-video-embed="7gjUhl_3X10" src="https://static.graphite.rs/content/index/tutorial-1-youtube.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Graphite Tutorial 1 - Hands-On Quickstart" />
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<!-- </div>
|
||||
</section> -->
|
||||
<!-- ▙ JUMP RIGHT IN ▟ -->
|
||||
<!-- -->
|
||||
<!-- ▛ PROCEDURALISM ▜ -->
|
||||
|
|
@ -358,7 +366,7 @@ Proceduralism lets you create sophisticated design elements that are easy to edi
|
|||
<section id="proceduralism-features">
|
||||
<div class="section">
|
||||
|
||||
Graphite's procedural, data-driven approach to graphic design affords unique capabilities (while in alpha, these remain a work in progress):
|
||||
Graphite's procedural, data-driven approach to graphic design affords unique capabilities *(while in alpha, these remain a work in progress)*:
|
||||
|
||||
<div class="informational-group features four-wide">
|
||||
<div class="informational">
|
||||
|
|
@ -372,7 +380,7 @@ Graphite's procedural, data-driven approach to graphic design affords unique cap
|
|||
<div class="informational">
|
||||
<!-- <img class="atlas" style="--atlas-index: 10" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" /> -->
|
||||
<img class="atlas" style="--atlas-index: 2" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
<span class="balance-text">Integrated generative AI models and graphics algorithms</span>
|
||||
<span class="balance-text">Versatile modularity of node-based generative AI models</span>
|
||||
</div>
|
||||
<div class="informational">
|
||||
<img class="atlas" style="--atlas-index: 11" src="https://static.graphite.rs/icons/icon-atlas-features.png" alt="" />
|
||||
|
|
@ -431,7 +439,7 @@ Graphite is built by a small, dedicated crew of volunteers in need of resources
|
|||
<section id="vector-art">
|
||||
<div class="section">
|
||||
|
||||
# Art takes shape
|
||||
# Taking shape
|
||||
|
||||
**All you've come to expect from a professional vector graphics editor. Now readily accessible in your browser.**
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ css = ["features.css"]
|
|||
|
||||
# Graphite features
|
||||
|
||||
The current alpha version of Graphite is a tool for vector art and graphic design. It also supports a limited, experimental raster editing toolset. All this is built around a central node graph that stores layer data and provides a basic—but continually improving—procedural design and non-destructive editing workflow which is a unique feature among vector editing software.
|
||||
The current alpha version of Graphite is a tool for vector art and graphic design. It also supports a limited, experimental raster editing toolset. All this is built around a central node graph that stores layer data and provides a basic—but continually improving—procedural design and nondestructive editing workflow which is a unique feature among vector editing software.
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -12,64 +12,6 @@ js = ["video-embed.js"]
|
|||
<img data-video-embed="vUzIeg8frh4" src="https://static.graphite.rs/content/volunteer/guide/workshop-intro-to-coding-for-graphite-youtube.avif" onerror="this.onerror = null; this.src = this.src.replace('.avif', '.png')" alt="Workshop: Intro to Coding for Graphite" />
|
||||
</div>
|
||||
|
||||
The Graphite editor is built as a web app powered by Svelte in the frontend and Rust in the backend which is compiled to WebAssembly (wasm) and run in the browser.
|
||||
The Graphite editor is built as a web app powered by Svelte and TypeScript in the frontend and Rust in the backend which is compiled to WebAssembly and run in the browser. The editor makes calls into Graphene, the node graph engine which manages and renders the documents.
|
||||
|
||||
The Editor's frontend web code lives in `/frontend/src` and the backend Rust code lives in `/editor`. The web-based frontend is intended to be semi-temporary and eventually replaceable with a pure-Rust GUI frontend. Therefore, all backend code should be unaware of JavaScript or web concepts and all Editor application logic should be written in Rust not JS.
|
||||
|
||||
## Frontend/backend communication
|
||||
|
||||
Frontend (JS) -> backend (Rust/wasm) communication is achieved through a thin Rust translation layer in `/frontend/wasm/src/editor_api.rs` which wraps the Editor backend's complex Rust data type API and provides the JS with a simpler API of callable functions. These wrapper functions are compiled by wasm-bindgen into autogenerated JS functions that serve as an entry point into the wasm.
|
||||
|
||||
Backend (Rust) -> frontend (JS) communication happens by sending a queue of messages to the frontend message dispatcher. After the JS calls any wrapper API function to get into backend (Rust) code execution, the Editor's business logic runs and queues up `FrontendMessage`s (defined in `/editor/src/messages/frontend/frontend_message.rs`) which get mapped from Rust to JS-friendly data types in `/frontend/src/wasm-communication/messages.ts`. Various JS code subscribes to these messages by calling `subscribeJsMessage(MessageName, (messageData) => { /* callback code */ });`.
|
||||
|
||||
## The Editor backend and Legacy Document modules
|
||||
|
||||
The Graphite editor backend handles all the day-to-day logic and responsibilities of a user-facing interactive application. Some duties include: user input, GUI state management, viewport tool behavior, layer management and selection, and handling of multiple document tabs.
|
||||
|
||||
The actual document (the artwork data and layers included in a saved `.graphite` file) is part of another core module located in `/document-legacy`. The (soon-to-be-replaced) Legacy Document codebase manages a user's document. Once it is replaced, the new Document module (that will be located in `/document`) will store a document's node graph and change history. While it's OK for the Editor to read data from—or make immutable function calls upon—the user's document controlled by the Legacy Document module, it should never be directly mutated. Instead, messages (called Operations) should be sent to the document to request changes occur. The Legacy Document code is designed to be used by the Editor or by third-party Rust or C/C++ code directly so a careful separation of concerns between the Editor and Legacy Document modules should be considered.
|
||||
|
||||
## The message bus
|
||||
|
||||
Every part of the Graphite stack works based on the concept of message passing. Messages are pushed to the front or back of a queue and each one is processed by the module's dispatcher in the order encountered. Only the dispatcher owns a mutable reference to update its module's state.
|
||||
|
||||
### Additional technical details
|
||||
|
||||
A message is an enum variant of a certain message sub-type like `FrontendMessage`, `ToolMessage`, `PortfolioMessage`, or `DocumentMessage`. Two example messages:
|
||||
```rs
|
||||
// Carries no data
|
||||
DocumentMessage::DeleteSelectedLayers
|
||||
|
||||
// Carries a layer path and a string as data
|
||||
DocumentMessage::DeleteLayer {
|
||||
id: NodeId,
|
||||
}
|
||||
```
|
||||
|
||||
Message sub-types hierarchically wrap other message sub-types; for example, `DocumentMessage` is wrapped by `PortfolioMessage` via:
|
||||
```rs
|
||||
// Carries the child message as data
|
||||
PortfolioMessage::Document(DocumentMessage)
|
||||
```
|
||||
and `EllipseMessage` is wrapped by `ToolMessage` via:
|
||||
```rs
|
||||
// Carries the child message as data
|
||||
ToolMessage::Ellipse(EllipseMessage)
|
||||
```
|
||||
Every message sub-type is wrapped by the top-level `Message`, so the previous example is actually:
|
||||
```rs
|
||||
Message::Tool(ToolMessage::Ellipse(EllipseMessage))
|
||||
```
|
||||
|
||||
Because this is cumbersome, we have a proc macro `#[child]` that automatically implements the `From` trait on message sub-types and lets you write:
|
||||
```rs
|
||||
DocumentMessage::DeleteSelectedLayers.into()
|
||||
```
|
||||
instead of:
|
||||
```rs
|
||||
Message(PortfolioMessage::Document(DocumentMessage::DeleteSelectedLayers))
|
||||
```
|
||||
|
||||
And when pushing a message to the queue, we have the `add` and `add_front` functions which call `.into()` for you. Therefore it's as simple as writing:
|
||||
```rs
|
||||
responses.add(DocumentMessage::DeleteSelectedLayers.into());
|
||||
```
|
||||
The Editor's frontend web code lives in `/frontend/src`. The backend Rust code is located in `/editor`. Graphene is found in `/node-graph`.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
+++
|
||||
title = "Code structure"
|
||||
|
||||
[extra]
|
||||
order = 1 # Page number after chapter intro
|
||||
+++
|
||||
|
||||
## Tech stack
|
||||
|
||||
- rustc: Compiler for node graph generics and custom nodes
|
||||
- rust-gpu: Compiler backend to generate compute shaders from Rust source code
|
||||
- wgpu: Portable graphics API for running compute shaders on desktop and web
|
||||
- Tauri: lightweight desktop web UI shell while the backend runs natively (experimental)
|
||||
<!-- - Vello: GPU-accelerated vector graphics renderer -->
|
||||
<!-- - COSMIC Text: Text shaping and typesetting -->
|
||||
<!-- - Wasmer or Wasmtime: Portable, sandboxed runtime for custom nodes -->
|
||||
<!-- - Tokio: parallelized job execution in the node graph pipeline -->
|
||||
<!-- - Xilem: High-performance native UI framework, to replace Tauri when ready -->
|
||||
|
||||
## Frontend/backend communication
|
||||
|
||||
The Graphite editor frontend is the web code which displays the user interface. It passes user interactions to the backend. The Graphite editor backend handles all the day-to-day logic and responsibilities of a user-facing interactive application. Some duties include: user input, GUI state management, viewport tool behavior, layer management and selection, and handling of multiple document tabs.
|
||||
|
||||
Frontend (TS) -> backend (Rust/wasm) communication is achieved through a thin Rust translation layer in `/frontend/wasm/src/editor_api.rs` which wraps the Editor backend's complex Rust data type API and provides the TS with a simpler API of callable functions. These wrapper functions are compiled by wasm-bindgen into autogenerated TS functions that serve as an entry point into the wasm.
|
||||
|
||||
Backend (Rust) -> frontend (TS) communication happens by sending a queue of messages to the frontend message dispatcher. After the TS has called any wrapper API function to get into backend (Rust) code execution, the Editor's business logic runs and queues up `FrontendMessage`s (defined in `/editor/src/messages/frontend/frontend_message.rs`) which get mapped from Rust to TS-friendly data types in `/frontend/src/wasm-communication/messages.ts`. Various TS code subscribes to these messages by calling `subscribeJsMessage(MessageName, (messageData) => { /* callback code */ });`.
|
||||
|
||||
## The message system
|
||||
|
||||
The Graphite editor backend is organized into a hierarchy of systems, called *message handlers*, which talk to one another through message passing. Messages are pushed to the front or back of a queue and each one is processed sequentially by the backend's dispatcher. The dispatcher lives at the root of the application hierarchy and it owns its message handlers. Thus, Rust's restrictions on mutable borrowing are satisfied because only the dispatcher mutably borrows its message handlers, one at a time, while each message is processed.
|
||||
|
||||
### Messages
|
||||
|
||||
Messages are enum variants that are dispatched to perform some intended activity within their respective message handlers. Here are two `DocumentMessage` definitions:
|
||||
```rs
|
||||
pub enum DocumentMessage {
|
||||
...
|
||||
// A message that carries a layer path and a string as data
|
||||
DocumentMessage::DeleteLayer {
|
||||
id: NodeId,
|
||||
}
|
||||
// A message that carries no data
|
||||
DocumentMessage::DeleteSelectedLayers,
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
As shown above, data can be included with each message. But as a special case denoted by the `#[child]` attribute, that data can also be a sub-message, which enables us to nest message handler systems hierarchically. The `DocumentMessage` enum of the previous example is defined as a child of `PortfolioMessage` which wraps it like this:
|
||||
|
||||
```rs
|
||||
pub enum PortfolioMessage {
|
||||
...
|
||||
// A message that carries the `DocumentMessage` child enum as data
|
||||
#[child]
|
||||
PortfolioMessage::Document(DocumentMessage),
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Likewise, the `PortfolioMessage` enum is wrapped by the top-level `Message` enum. The dispatcher operates on the queue of these base-level `Message` types.
|
||||
|
||||
So for example, the `DeleteSelectedLayers` message mentioned previously will look like this as a `Message` data type:
|
||||
|
||||
```rs
|
||||
Message::Portfolio(
|
||||
PortfolioMessage::Document(
|
||||
DocumentMessage::DeleteSelectedLayers
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
Writing out these nested message enum variants would be cumbersome, so that `#[child]` attribute shown earlier invokes a proc macro that automatically implements the `From` trait, letting you write this instead to get a `Message` data type:
|
||||
|
||||
```rs
|
||||
DocumentMessage::DeleteSelectedLayers.into()
|
||||
```
|
||||
|
||||
Most often, this is simplified even further because the `.into()` is called for you when pushing a message to the queue with `.add()` or `.add_front()`. So this becomes as simple as:
|
||||
|
||||
```rs
|
||||
responses.add(DocumentMessage::DeleteSelectedLayers);
|
||||
```
|
||||
|
||||
The `responses` message queue is composed of `Message` data types, and thanks to this system, child messages like `DocumentMessage::DeleteSelectedLayers` are automatically wrapped in their ancestor enum variants to become a `Message`, saving you from writing the verbose nested form.
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
title = "Contributing guidelines"
|
||||
|
||||
[extra]
|
||||
order = 2 # Page number after chapter intro
|
||||
order = 3 # Page number after chapter intro
|
||||
+++
|
||||
|
||||
## Code style
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title = "Debugging"
|
||||
|
||||
[extra]
|
||||
order = 1 # Page number after chapter intro
|
||||
order = 2 # Page number after chapter intro
|
||||
+++
|
||||
|
||||
## Deployed builds
|
||||
|
|
@ -23,7 +23,7 @@ To show `trace!()` logs, activate *Help* > *Debug: Print Trace Logs*.
|
|||
|
||||
## Message system logs
|
||||
|
||||
To also view logs of the messages dispatched by the message bus system, activate *Help* > *Debug: Print Messages* > *Only Names*. Or use *Full Contents* for more verbose insight with the actual data being passed. This is an invaluable window into the activity of the message flow and works well together with `debug!()` printouts for tracking down message-related issues.
|
||||
To also view logs of the messages dispatched by the message system, activate *Help* > *Debug: Print Messages* > *Only Names*. Or use *Full Contents* for more verbose insight with the actual data being passed. This is an invaluable window into the activity of the message flow and works well together with `debug!()` printouts for tracking down message-related issues.
|
||||
|
||||
## Node/layer and document IDs
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
+++
|
||||
title = "Tech stack"
|
||||
|
||||
[extra]
|
||||
order = 3 # Page number after chapter intro
|
||||
+++
|
||||
|
||||
- rustc: Compiler for node graph generics and custom nodes
|
||||
- rust-gpu: Compiler backend to generate compute shaders from Rust source code
|
||||
- wgpu: Portable graphics API for running compute shaders on desktop and web
|
||||
- Tauri: lightweight desktop web UI shell while the backend runs natively (experimental)
|
||||
<!-- - Vello: GPU-accelerated vector graphics renderer -->
|
||||
<!-- - COSMIC Text: Text shaping and typesetting -->
|
||||
<!-- - Wasmer or Wasmtime: Portable, sandboxed runtime for custom nodes -->
|
||||
<!-- - Tokio: parallelized job execution in the node graph pipeline -->
|
||||
<!-- - Xilem: High-performance native UI framework, to replace Tauri when ready -->
|
||||
|
|
@ -50,4 +50,4 @@ cargo install cargo-about
|
|||
npm run build
|
||||
```
|
||||
|
||||
It produces the `/frontend/dist` directory containing the static site files that must be served by your own web server.
|
||||
This produces the `/frontend/dist` directory containing the static site files that must be served by your own web server.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ template = "book.html"
|
|||
page_template = "book.html"
|
||||
|
||||
[extra]
|
||||
order = 3 # Chapter number
|
||||
order = 4 # Chapter number
|
||||
+++
|
||||
|
||||
**NOTE: Developers probably don't need to read this chapter.**
|
||||
|
|
|
|||
30
website/content/volunteer/guide/projects/_index.md
Normal file
30
website/content/volunteer/guide/projects/_index.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
+++
|
||||
title = "Projects"
|
||||
template = "book.html"
|
||||
page_template = "book.html"
|
||||
|
||||
[extra]
|
||||
order = 3 # Chapter number
|
||||
+++
|
||||
|
||||
Graphite is built from a number of separate projects, each with a distinct focus. New developers may choose to specialize in one or more area without having to attain a working knowledge of the entire codebase. This chapter details each project's purpose, what knowledge or background is best suited for getting involved with it, and how to begin making useful contributions. Opportunities also exist for contributing to specific self-contained sub-projects for students interested in completing a Google Summer of Code or other internship program, a university capstone project, or another similar endeavor.
|
||||
|
||||
## Frontend
|
||||
|
||||
The frontend is the interface for Graphite which users see and interact with. It is built using web technologies with TypeScript, Svelte, and SCSS. The frontend's philosophy is to be as lightweight and minimal as possible. It acts as the entry point for user input and quickly hands off its work to the WebAssembly editor backend via its Wasm wrapper API. That API is written in Rust but has TypeScript bindings generated by the wasm-bindgen tooling that is part of the Vite-based build chain. The frontend is built of many components that recursively form the window, panels, and widgets that make up the user interface.
|
||||
|
||||
## Editor
|
||||
|
||||
The editor is the core of the Graphite application, and it's where all the business logic occurs for the tooling and user interaction. It is written in Rust and compiled to WebAssembly, and at its heart is the message system [described here](../codebase-overview/code-structure#the-message-system).
|
||||
|
||||
## Graphene
|
||||
|
||||
Graphene is the node graph engine which manages and renders the documents. It is itself a programming language, where Graphene programs are compiled while being edited live by the user, and where executing the program renders the document.
|
||||
|
||||
## Libraries
|
||||
|
||||
Graphite maintains several Rust libraries that are published to crates.io for use by other developers, in addition to internal use by Graphite itself.
|
||||
|
||||
### Bezier-rs
|
||||
|
||||
Bezier-rs is a computational geometry library. It provides a rich selection of types and functions for working with Bézier segments and paths. There is also an [interactive demo](/libraries/bezier-rs/) gallery. This was initially developed as a successful [student project](./student-projects). Contribution opportunities include optimization, code cleanup and refactoring, and implementing new algorithms.
|
||||
77
website/content/volunteer/guide/projects/student-projects.md
Normal file
77
website/content/volunteer/guide/projects/student-projects.md
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
+++
|
||||
title = "Student projects"
|
||||
|
||||
[extra]
|
||||
order = 1 # Page number after chapter intro
|
||||
+++
|
||||
|
||||
Graphite offers a number of opportunities for students to contribute by building a self-contained project as part of a structured format. These projects are designed to be completed over several months and are ideal for Google Summer of Code or similar internship programs, solo or group university capstone projects, or other arrangements. Each project has a distinct focus and is a great way to make a meaningful contribution to open source over the length of the program while receiving mentorship and guidance from the Graphite team. Student projects require adherence to a set schedule with regular check-ins, milestones, and evaluations.
|
||||
|
||||
The structured setting is designed to provide a supportive environment for students to learn and grow as developers while gaining real-world industry experience from collaborating on a sizable software product and remaining accountable to stakeholders.
|
||||
|
||||
To date, three student project experiences have been completed successfully. [See below](#successful-past-projects) for summaries to get a feel for what has worked before.
|
||||
|
||||
Reach out through [Discord](https://discord.graphite.rs) (preferred) or [by email](/contact) to discuss and propose a project.
|
||||
|
||||
## Google Summer of Code
|
||||
|
||||
GSoC is a program offering students a stipend for successful completion of an internship-style experience with an open source organization. Read about [how it works](https://summerofcode.withgoogle.com/how-it-works/). Graphite intends to participate as a mentoring organization in GSoC 2024, pending acceptance.
|
||||
|
||||
### GSoC Proposals
|
||||
|
||||
Writing a good proposal is an important first step that demonstrates your understanding of the project and your ability to plan and execute it. A well-defined proposal will set you up for success throughout the rest of the program.
|
||||
|
||||
You are encouraged to reference the project idea list below to find several potential projects suited to your experience, interest, and choice of scope. Then, we highly recommend reaching out to a core team member through Discord to discuss your plan in detail before writing a proposal. This will help you understand the project's scope and requirements, and it will help us understand your background and capabilities to offer you feedback and suggestions for the best outcome.
|
||||
|
||||
## Project idea list
|
||||
|
||||
The following will be expanded upon in detail later today, 2024-01-06.
|
||||
|
||||
- Port LibRaw to Rust
|
||||
|
||||
- PDF export
|
||||
|
||||
- ONNX model embedding to run in WebGPU and native (Tauri) and server
|
||||
|
||||
- Node auto layout
|
||||
|
||||
- Select mode
|
||||
|
||||
- GPU-based node graph UI
|
||||
|
||||
- Complex widget layout system
|
||||
|
||||
- Spreadsheet viewer/editor
|
||||
|
||||
- Testing and performance instrumentation infrastructure
|
||||
|
||||
- Animation system
|
||||
|
||||
- Infrastructure for generating subsystem visualizations for docs, debugging, and identifying redundant message traffic
|
||||
|
||||
|
||||
## Successful past projects
|
||||
|
||||
### 2022: Backend layout system
|
||||
|
||||
Institution: California Polytechnic State University, San Luis Obispo, USA
|
||||
|
||||
Duration: 3 months
|
||||
|
||||
Student: Max Fisher
|
||||
|
||||
### 2022: Path boolean operations
|
||||
|
||||
Institution: California Polytechnic State University, San Luis Obispo, USA
|
||||
|
||||
Duration: 3 months
|
||||
|
||||
Student: Caleb Dennis
|
||||
|
||||
### 2023: Bezier-rs library
|
||||
|
||||
Institution: University of Waterloo, Ontario, Canada
|
||||
|
||||
Duration: 9 months
|
||||
|
||||
Students: Hannah Li, Rob Nadal, Thomas Cheng, Linda Zheng, Jackie Chen
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
--font-size-subheading: 24px;
|
||||
--font-size-body: 18px;
|
||||
--font-size-article-h2: 32px;
|
||||
--font-size-article-h3: 24px;
|
||||
--font-size-article-h3: 22px;
|
||||
--font-size-article-h4: 18px;
|
||||
|
||||
--max-width: 1600px;
|
||||
|
|
|
|||
|
|
@ -266,13 +266,13 @@
|
|||
// ▙ COMMUNITY ▟
|
||||
|
||||
// ▛ JUMP RIGHT IN ▜
|
||||
#jump-right-in {
|
||||
max-width: 1000px;
|
||||
// #jump-right-in {
|
||||
// max-width: 1000px;
|
||||
|
||||
.section {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
// .section {
|
||||
// align-items: center;
|
||||
// }
|
||||
// }
|
||||
// ▙ JUMP RIGHT IN ▟
|
||||
|
||||
// ▛ PROCEDURALISM ▜
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue