Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 26b79dc929 | |||
| 5569ce264a | |||
| efe325f178 |
@@ -0,0 +1,23 @@
|
||||
# Strip upstream (ArtCraft / Discord) branding. Run: ~/.agents/skills/debrand/debrand.pl (--check in CI)
|
||||
delete docs/brand
|
||||
# MIT/Apache texts stay verbatim. The copyright holder line stays everywhere (legal requirement).
|
||||
keep ^(LICENSE-(MIT|APACHE)|\.debrand)$
|
||||
dropline ^crates/ui-egui/src/i18n/.*\.tsv$ :: \t.*(?:ArtCraft|Discord)
|
||||
dropline ^ATTRIBUTION\.md$ :: \|\s*`docs/brand/
|
||||
sub (?s)\nThe ArtCraft name, wordmark and logos in docs/brand/.*?LICENSE-brand\.txt\.\n =>
|
||||
sub (?s)\s*The ArtCraft name, wordmark, and logos in `docs/brand/`.*?source-code license\. =>
|
||||
sub \s*The ArtCraft logos in `docs/brand/` are not open source \(`docs/brand/LICENSE-brand\.txt`\)\. =>
|
||||
sub drawn in ArtCraft, vectorised => drawn by hand, vectorised
|
||||
sub created\s+in ArtCraft, then => created by hand, then
|
||||
sub made in ArtCraft \( => drawn by hand (
|
||||
sub the owner's ArtCraft drawing => the owner's drawing
|
||||
sub the ArtCraft team and CADCraft contributors => the CADCraft contributors
|
||||
sub ArtCraft, ArtCraftX,\s =>
|
||||
sub \bArtCraft, =>
|
||||
sub https://getartcraft\.com/apps/cadcraft => https://github.com/storytold/cadcraft
|
||||
sub https://discord\.gg/artcraft => https://github.com/storytold/cadcraft/issues
|
||||
sub \s*The only exception is the ArtCraft brand in `docs/brand/` \(trademarks, `docs/brand/LICENSE-brand\.txt`\)\. =>
|
||||
sub (?s)\s*The one\nexception is the ArtCraft brand in `docs/brand/`: ArtCraft trademarks, not open source, used under\n`docs/brand/LICENSE-brand\.txt`\. =>
|
||||
forbid (?i)artcraft(?! Team and the CADCraft contributors)
|
||||
forbid (?i)discord
|
||||
sub Discord \(Help › Discord\), then the theme toggle => the theme toggle
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "tools/craft-skills"]
|
||||
path = tools/craft-skills
|
||||
url = https://git.marcospaulo.dev.br/storytold/craft-skills.git
|
||||
@@ -23,7 +23,7 @@ People trust CADCraft with their drawings; a crash loses their work. **This outr
|
||||
|
||||
## Non-negotiables
|
||||
- **Clean-room.** AutoCAD is installed on the dev machine and may be *observed* black-box: run it, use its UI with synthetic drawings, take screenshots (by window id) stored only under `plan/autocad/screenshots/` (never committed). **Never** read, disassemble or copy anything inside the AutoCAD bundle (names/listings only); never copy Autodesk fonts (SHX), hatch patterns (`.pat`), linetypes (`.lin`), templates, CUI/PGP files, icons, artwork or help text; never commit files produced by AutoCAD. File formats come from public specifications (Autodesk's published DXF Reference, the Open Design Alliance's public DWG specification) and our own synthetic tests. Never copy or link GPL/LGPL/AGPL code (LibreDWG, LibreCAD, QCAD, FreeCAD's planegcs, SolveSpace, OpenCASCADE) — don't even read their sources.
|
||||
- **Assets — absolutely essential.** CADCraft contains **no Autodesk, Adobe or Avid iconography, images, fonts, patterns or artwork — ever.** Every icon is drawn in code (`crates/ui-egui/src/icons.rs`), every hatch pattern and linetype is our own definition (`crates/doc/src/library.rs`), the drafting font is our own (`crates/fonts/src/stroke.rs`). Any file asset must be original, public domain/CC0, OSI-licensed, or redistributable Creative Commons (or licensed open source by a contributor who made it), and **must have a row in `ATTRIBUTION.md`** with author, source and licence (`cargo xtask assets` enforces it). The only exception is the ArtCraft brand in `docs/brand/` (trademarks, `docs/brand/LICENSE-brand.txt`). Screenshots of Autodesk software are never committed. Breaking this rule is the most serious mistake you can make in this repo.
|
||||
- **Assets — absolutely essential.** CADCraft contains **no Autodesk, Adobe or Avid iconography, images, fonts, patterns or artwork — ever.** Every icon is drawn in code (`crates/ui-egui/src/icons.rs`), every hatch pattern and linetype is our own definition (`crates/doc/src/library.rs`), the drafting font is our own (`crates/fonts/src/stroke.rs`). Any file asset must be original, public domain/CC0, OSI-licensed, or redistributable Creative Commons (or licensed open source by a contributor who made it), and **must have a row in `ATTRIBUTION.md`** with author, source and licence (`cargo xtask assets` enforces it). Screenshots of Autodesk software are never committed. Breaking this rule is the most serious mistake you can make in this repo.
|
||||
- **Fonts live in [`storytold/craft-fonts`](https://github.com/storytold/craft-fonts)**, never in this repo. It is an optional build input (`CRAFT_FONTS_DIR`, embedded by `crates/fonts/build.rs`), never a `Cargo.toml` dependency. Code and tests must work without it.
|
||||
- **Shared test corpora** live in separate repos (`storytold/<app>-corpus`); never commit large binary fixtures here.
|
||||
- **Everything is a command.** User-visible behaviour = a command in `crates/engine/src/cmd/*` (`CommandSpec`: id = AutoCAD's command name in lower case, label, menu path, shortcut, aliases, params doc, `enabled`, JSON `run`, optional `interactive` prompt machine) + tests. UI-only commands live in `crates/ui-egui/src/menus.rs` (`UI_COMMANDS`). The command line, menus, toolbar, Tool Sets, scripts, CLI, control channel and MCP all reach the same commands.
|
||||
|
||||
@@ -9,9 +9,7 @@ artwork, fonts, hatch patterns, linetypes, templates or presets.** Every asset i
|
||||
CADCraft contributors or third-party material under an open licence (OSI open source, public domain
|
||||
/ CC0, or Creative Commons that allows redistribution). Screenshots of Autodesk software are never
|
||||
committed. Font files are not added here: shared fonts live in
|
||||
[storytold/craft-fonts](https://github.com/storytold/craft-fonts), an optional build input. The one
|
||||
exception is the ArtCraft brand in `docs/brand/`: ArtCraft trademarks, not open source, used under
|
||||
`docs/brand/LICENSE-brand.txt`.
|
||||
[storytold/craft-fonts](https://github.com/storytold/craft-fonts), an optional build input.
|
||||
|
||||
Generated-in-code assets are original and have no file to list:
|
||||
- the UI icon set (`crates/ui-egui/src/icons.rs`);
|
||||
@@ -43,14 +41,6 @@ Generated-in-code assets are original and have no file to list:
|
||||
| `docs/images/ui-apartment.png` | CADCraft contributors | screenshot of CADCraft itself (examples/apartment.dxf) | MIT OR Apache-2.0 | Original; no Autodesk UI |
|
||||
| `docs/images/ui-layout.png` | CADCraft contributors | screenshot of CADCraft itself (a layout of examples/apartment.dxf) | MIT OR Apache-2.0 | Original; no Autodesk UI |
|
||||
| `docs/images/ui-bracket.png` | CADCraft contributors | screenshot of CADCraft itself (sample drawing generated in code) | MIT OR Apache-2.0 | Original; no Autodesk UI |
|
||||
| `docs/brand/artcraft-logo-white.png` | ArtCraft Team | storytold/craftrules `assets/brand/` | ArtCraft brand terms (`docs/brand/LICENSE-brand.txt`) | Trademark, not open source |
|
||||
| `docs/brand/artcraft-logo-white.svg` | ArtCraft Team | storytold/craftrules `assets/brand/` | ArtCraft brand terms (`docs/brand/LICENSE-brand.txt`) | Trademark, not open source |
|
||||
| `docs/brand/artcraft-logo.png` | ArtCraft Team | storytold/craftrules `assets/brand/` | ArtCraft brand terms (`docs/brand/LICENSE-brand.txt`) | Trademark, not open source |
|
||||
| `docs/brand/artcraft-logo.svg` | ArtCraft Team | storytold/craftrules `assets/brand/` | ArtCraft brand terms (`docs/brand/LICENSE-brand.txt`) | Trademark, not open source |
|
||||
| `docs/brand/artcraft-mark-black.png` | ArtCraft Team | storytold/craftrules `assets/brand/` | ArtCraft brand terms (`docs/brand/LICENSE-brand.txt`) | Trademark, not open source |
|
||||
| `docs/brand/artcraft-mark-black.svg` | ArtCraft Team | storytold/craftrules `assets/brand/` | ArtCraft brand terms (`docs/brand/LICENSE-brand.txt`) | Trademark, not open source |
|
||||
| `docs/brand/artcraft-mark.png` | ArtCraft Team | storytold/craftrules `assets/brand/` | ArtCraft brand terms (`docs/brand/LICENSE-brand.txt`) | Trademark, not open source |
|
||||
| `docs/brand/artcraft-mark.svg` | ArtCraft Team | storytold/craftrules `assets/brand/` | ArtCraft brand terms (`docs/brand/LICENSE-brand.txt`) | Trademark, not open source |
|
||||
|
||||
## Interface translations
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ People trust CADCraft with their drawings; a crash loses their work. **This outr
|
||||
|
||||
## Non-negotiables
|
||||
- **Clean-room.** AutoCAD is installed on the dev machine and may be *observed* black-box: run it, use its UI with synthetic drawings, take screenshots (by window id) stored only under `plan/autocad/screenshots/` (never committed). **Never** read, disassemble or copy anything inside the AutoCAD bundle (names/listings only); never copy Autodesk fonts (SHX), hatch patterns (`.pat`), linetypes (`.lin`), templates, CUI/PGP files, icons, artwork or help text; never commit files produced by AutoCAD. File formats come from public specifications (Autodesk's published DXF Reference, the Open Design Alliance's public DWG specification) and our own synthetic tests. Never copy or link GPL/LGPL/AGPL code (LibreDWG, LibreCAD, QCAD, FreeCAD's planegcs, SolveSpace, OpenCASCADE) — don't even read their sources.
|
||||
- **Assets — absolutely essential.** CADCraft contains **no Autodesk, Adobe or Avid iconography, images, fonts, patterns or artwork — ever.** Every icon is drawn in code (`crates/ui-egui/src/icons.rs`), every hatch pattern and linetype is our own definition (`crates/doc/src/library.rs`), the drafting font is our own (`crates/fonts/src/stroke.rs`). Any file asset must be original, public domain/CC0, OSI-licensed, or redistributable Creative Commons (or licensed open source by a contributor who made it), and **must have a row in `ATTRIBUTION.md`** with author, source and licence (`cargo xtask assets` enforces it). The only exception is the ArtCraft brand in `docs/brand/` (trademarks, `docs/brand/LICENSE-brand.txt`). Screenshots of Autodesk software are never committed. Breaking this rule is the most serious mistake you can make in this repo.
|
||||
- **Assets — absolutely essential.** CADCraft contains **no Autodesk, Adobe or Avid iconography, images, fonts, patterns or artwork — ever.** Every icon is drawn in code (`crates/ui-egui/src/icons.rs`), every hatch pattern and linetype is our own definition (`crates/doc/src/library.rs`), the drafting font is our own (`crates/fonts/src/stroke.rs`). Any file asset must be original, public domain/CC0, OSI-licensed, or redistributable Creative Commons (or licensed open source by a contributor who made it), and **must have a row in `ATTRIBUTION.md`** with author, source and licence (`cargo xtask assets` enforces it). Screenshots of Autodesk software are never committed. Breaking this rule is the most serious mistake you can make in this repo.
|
||||
- **Fonts live in [`storytold/craft-fonts`](https://github.com/storytold/craft-fonts)**, never in this repo. It is an optional build input (`CRAFT_FONTS_DIR`, embedded by `crates/fonts/build.rs`), never a `Cargo.toml` dependency. Code and tests must work without it.
|
||||
- **Shared test corpora** live in separate repos (`storytold/<app>-corpus`); never commit large binary fixtures here.
|
||||
- **Everything is a command.** User-visible behaviour = a command in `crates/engine/src/cmd/*` (`CommandSpec`: id = AutoCAD's command name in lower case, label, menu path, shortcut, aliases, params doc, `enabled`, JSON `run`, optional `interactive` prompt machine) + tests. UI-only commands live in `crates/ui-egui/src/menus.rs` (`UI_COMMANDS`). The command line, menus, toolbar, Tool Sets, scripts, CLI, control channel and MCP all reach the same commands.
|
||||
|
||||
@@ -546,7 +546,7 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"cadcraft-engine",
|
||||
"cadcraft-io",
|
||||
@@ -566,7 +566,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-cli"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"cadcraft-engine",
|
||||
"cadcraft-io",
|
||||
@@ -577,14 +577,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-color"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-constraints"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"cadcraft-doc",
|
||||
"cadcraft-geom",
|
||||
@@ -594,7 +594,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-doc"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"cadcraft-color",
|
||||
"cadcraft-geom",
|
||||
@@ -605,14 +605,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-dwg"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"acadrust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-dxf"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"log",
|
||||
@@ -621,7 +621,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-engine"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"cadcraft-color",
|
||||
"cadcraft-constraints",
|
||||
@@ -640,7 +640,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-fonts"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"cadcraft-geom",
|
||||
"harfrust",
|
||||
@@ -650,14 +650,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-geom"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-io"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"cadcraft-color",
|
||||
"cadcraft-doc",
|
||||
@@ -675,7 +675,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-mcp"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"cadcraft-engine",
|
||||
"cadcraft-io",
|
||||
@@ -686,7 +686,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-render"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"cadcraft-color",
|
||||
"cadcraft-doc",
|
||||
@@ -700,7 +700,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-ui-egui"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"cadcraft-color",
|
||||
"cadcraft-doc",
|
||||
@@ -721,7 +721,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cadcraft-web"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"cadcraft-engine",
|
||||
"cadcraft-io",
|
||||
@@ -925,7 +925,7 @@ checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48"
|
||||
[[package]]
|
||||
name = "craft-ui"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=5c874d51eeb3de70e735c8ce87a59a7dedd47675#5c874d51eeb3de70e735c8ce87a59a7dedd47675"
|
||||
source = "git+https://git.marcospaulo.dev.br/masi/craft-libs?rev=22544b6d619d4f16779b8bdfa3f0b642a86fc065#22544b6d619d4f16779b8bdfa3f0b642a86fc065"
|
||||
dependencies = [
|
||||
"egui",
|
||||
"serde",
|
||||
@@ -4772,7 +4772,7 @@ checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7"
|
||||
|
||||
[[package]]
|
||||
name = "xtask"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
@@ -4,7 +4,7 @@ members = ["crates/*", "apps/*", "xtask"]
|
||||
# default-members
|
||||
|
||||
[workspace.package]
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
edition = "2024"
|
||||
license = "MIT OR Apache-2.0"
|
||||
rust-version = "1.90"
|
||||
@@ -46,7 +46,7 @@ encoding_rs = "0.8.35"
|
||||
quick-xml = "0.41"
|
||||
|
||||
# ui
|
||||
craft-ui = { version = "0.1.0", git = "https://github.com/storytold/craft-libs", rev = "5c874d51eeb3de70e735c8ce87a59a7dedd47675", features = ["serde"] }
|
||||
craft-ui = { version = "0.1.0", git = "https://git.marcospaulo.dev.br/masi/craft-libs", rev = "22544b6d619d4f16779b8bdfa3f0b642a86fc065", features = ["serde"] }
|
||||
egui = "0.36"
|
||||
egui_kittest = "0.36"
|
||||
eframe = { version = "0.36", default-features = false }
|
||||
|
||||
@@ -3,10 +3,6 @@ Copyright (c) 2026 ArtCraft Team and the CADCraft contributors.
|
||||
Licensed under the MIT License or the Apache License, Version 2.0, at your option
|
||||
(LICENSE-MIT, LICENSE-APACHE).
|
||||
|
||||
The ArtCraft name, wordmark and logos in docs/brand/ are trademarks of the ArtCraft Team. They are
|
||||
not open source and are not covered by the license above; their terms are in
|
||||
docs/brand/LICENSE-brand.txt.
|
||||
|
||||
Third-party material
|
||||
|
||||
Software dependencies are listed in Cargo.lock. One is under a weak-copyleft licence: the acadrust
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
<p align="center">
|
||||
<a href="https://getartcraft.com/">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="docs/brand/artcraft-logo-white.svg">
|
||||
<img alt="ArtCraft" src="docs/brand/artcraft-logo.svg" width="200">
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h1 align="center">CADCraft</h1>
|
||||
|
||||
<p align="center">
|
||||
@@ -16,8 +7,7 @@
|
||||
<p align="center">
|
||||
A fast, open-source take on the AutoCAD workflow: the command line, object snaps, layers,
|
||||
dimensions, hatches, blocks and DXF drawings you already know. It runs natively on macOS,
|
||||
Windows, Linux and FreeBSD, and in the browser via WebAssembly.<br>
|
||||
<i>By the ArtCraft team.</i>
|
||||
Windows, Linux and FreeBSD, and in the browser via WebAssembly.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
@@ -28,16 +18,6 @@
|
||||
<img alt="Status: early development" src="https://img.shields.io/badge/status-early%20development-f07a3a?style=flat-square">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/artcraft"><img alt="Join the ArtCraft community on Discord" src="https://img.shields.io/badge/Join%20us%20on%20Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" height="40"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://getartcraft.com/apps/cadcraft"><b>CADCraft on getartcraft.com</b></a> ·
|
||||
<a href="https://getartcraft.com/">ArtCraft</a> ·
|
||||
<a href="https://getartcraft.com/apps">All Crafting Apps</a>
|
||||
</p>
|
||||
|
||||
<br>
|
||||
|
||||
<p align="center">
|
||||
@@ -45,11 +25,6 @@
|
||||
<br><sub><b>Apartment plan</b> (<a href="examples/apartment.dxf">examples/apartment.dxf</a>): walls with pick-point hatching, TrueType MTEXT room labels, a TABLE, a multileader and architectural dimensions — built entirely from CADCraft commands.</sub>
|
||||
</p>
|
||||
|
||||
> [!NOTE]
|
||||
> **ArtCraft is a community of artists from all walks of life.** Painters, photographers,
|
||||
> filmmakers, illustrators, designers, animators, hobbyists, and people who picked up a pencil
|
||||
> last week. If you make things, you're one of us. **[Come say hi on Discord](https://discord.gg/artcraft).**
|
||||
|
||||
<p align="center">
|
||||
<a href="#screenshots">Screenshots</a> ·
|
||||
<a href="#why-cadcraft">Why CADCraft</a> ·
|
||||
@@ -322,44 +297,20 @@ RISC-V (riscv64): `cadcraft-<ver>-linux-riscv64.tar.gz`, cross-compiled; needs g
|
||||
|
||||
## The Crafting Apps
|
||||
|
||||
CADCraft is one of the **Crafting Apps**: free, open-source creative tools from the
|
||||
[ArtCraft](https://getartcraft.com/) team, each written from scratch in Rust and each able to
|
||||
CADCraft is one of the **Crafting Apps**: free, open-source creative tools, each written from scratch in Rust and each able to
|
||||
stand on its own.
|
||||
|
||||
| | App | What it's for | Code | Learn more |
|
||||
|:-:|---|---|---|---|
|
||||
| <img src="https://raw.githubusercontent.com/storytold/photocraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.photocraft.png" alt="" width="32" height="32"> | **PhotoCraft** | Image editing: layers, masks, type and real PSD files | [GitHub](https://github.com/storytold/photocraft) | [Website](https://getartcraft.com/apps/photocraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/vectorcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.vectorcraft.png" alt="" width="32" height="32"> | **VectorCraft** | Vector illustration | [GitHub](https://github.com/storytold/vectorcraft) | [Website](https://getartcraft.com/apps/vectorcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/filmcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.filmcraft.png" alt="" width="32" height="32"> | **FilmCraft** | Video editing, color and sound | [GitHub](https://github.com/storytold/filmcraft) | [Website](https://getartcraft.com/apps/filmcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/lightcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.lightcraft.png" alt="" width="32" height="32"> | **LightCraft** | Photo library and raw development | [GitHub](https://github.com/storytold/lightcraft) | [Website](https://getartcraft.com/apps/lightcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/pdfcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.pdfcraft.png" alt="" width="32" height="32"> | **PdfCraft** | Reading, organizing and protecting PDFs | [GitHub](https://github.com/storytold/pdfcraft) | [Website](https://getartcraft.com/apps/pdfcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/effectcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.effectcraft.png" alt="" width="32" height="32"> | **EffectCraft** | Motion graphics and visual effects | [GitHub](https://github.com/storytold/effectcraft) | [Website](https://getartcraft.com/apps/effectcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/designcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.designcraft.png" alt="" width="32" height="32"> | **DesignCraft** | Page layout and publishing | [GitHub](https://github.com/storytold/designcraft) | [Website](https://getartcraft.com/apps/designcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/cadcraft/main/assets/app-icon/cadcraft-64.png" alt="" width="32" height="32"> | **CADCraft** | **Computer-aided design and drafting · you are here** | [GitHub](https://github.com/storytold/cadcraft) | [Website](https://getartcraft.com/apps/cadcraft) |
|
||||
| | App | What it's for | Code |
|
||||
|:-:|---|---|---|
|
||||
| <img src="https://raw.githubusercontent.com/storytold/photocraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.photocraft.png" alt="" width="32" height="32"> | **PhotoCraft** | Image editing: layers, masks, type and real PSD files | [GitHub](https://github.com/storytold/photocraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/vectorcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.vectorcraft.png" alt="" width="32" height="32"> | **VectorCraft** | Vector illustration | [GitHub](https://github.com/storytold/vectorcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/filmcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.filmcraft.png" alt="" width="32" height="32"> | **FilmCraft** | Video editing, color and sound | [GitHub](https://github.com/storytold/filmcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/lightcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.lightcraft.png" alt="" width="32" height="32"> | **LightCraft** | Photo library and raw development | [GitHub](https://github.com/storytold/lightcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/pdfcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.pdfcraft.png" alt="" width="32" height="32"> | **PdfCraft** | Reading, organizing and protecting PDFs | [GitHub](https://github.com/storytold/pdfcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/effectcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.effectcraft.png" alt="" width="32" height="32"> | **EffectCraft** | Motion graphics and visual effects | [GitHub](https://github.com/storytold/effectcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/designcraft/main/assets/app-icon/hicolor/64x64/apps/ai.storyteller.designcraft.png" alt="" width="32" height="32"> | **DesignCraft** | Page layout and publishing | [GitHub](https://github.com/storytold/designcraft) |
|
||||
| <img src="https://raw.githubusercontent.com/storytold/cadcraft/main/assets/app-icon/cadcraft-64.png" alt="" width="32" height="32"> | **CADCraft** | **Computer-aided design and drafting · you are here** | [GitHub](https://github.com/storytold/cadcraft) |
|
||||
|
||||
And [**ArtCraft**](https://getartcraft.com/) itself, our AI image and video studio for artists who want real control.
|
||||
|
||||
<br>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/artcraft"><img alt="Join the ArtCraft community on Discord" src="https://img.shields.io/badge/Join%20us%20on%20Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" height="40"></a>
|
||||
</p>
|
||||
|
||||
<h3 align="center">Come make things with us</h3>
|
||||
|
||||
<p align="center">
|
||||
Our Discord is where artists of every kind hang out: people who paint, shoot, draw, cut film,
|
||||
set type, and people still figuring out what they like to make. Share what you're working on,
|
||||
ask for help, tell us what's broken, or tell us what you wish these tools could do.
|
||||
Whatever your medium and however long you've been at it, you're welcome here.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/artcraft"><b>discord.gg/artcraft</b></a> ·
|
||||
<a href="https://getartcraft.com/">getartcraft.com</a> ·
|
||||
<a href="https://getartcraft.com/apps">The Crafting Apps</a> ·
|
||||
<a href="https://getartcraft.com/apps/cadcraft">CADCraft</a>
|
||||
</p>
|
||||
|
||||
## License and credits
|
||||
|
||||
@@ -372,16 +323,6 @@ with its author, source and license in [ATTRIBUTION.md](ATTRIBUTION.md).
|
||||
CADCraft's icons, its single-stroke drafting font, its hatch patterns and its linetypes are all
|
||||
original work, drawn or defined in code. The sample drawings are generated in code too.
|
||||
|
||||
The ArtCraft name, wordmark and logos in [`docs/brand/`](docs/brand/) are trademarks of the
|
||||
ArtCraft Team and are not covered by this license. They may be used only unmodified, and only as
|
||||
part of this repository and CADCraft, under [`docs/brand/LICENSE-brand.txt`](docs/brand/LICENSE-brand.txt).
|
||||
Forks and modified versions must remove them.
|
||||
|
||||
<sub>Autodesk, AutoCAD and DWG are trademarks or registered trademarks of Autodesk, Inc. in the United States and/or other countries. CADCraft is an independent, open-source project and is not affiliated with, sponsored by or endorsed by Autodesk, Inc.; these names are used only to describe the workflows and file formats it is compatible with.</sub>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://getartcraft.com/"><img alt="ArtCraft" src="docs/brand/artcraft-mark.svg" width="28"></a><br>
|
||||
<sub>Made by the <a href="https://getartcraft.com/">ArtCraft</a> team and community.</sub>
|
||||
</p>
|
||||
|
||||
Tool Sets, Layers, and Properties can be regrouped, split, floated within the app window, closed, and reopened. The drawing canvas stays visible and cannot be closed or turned into a tab. Drag a panel header to a target edge or another header. Its context menu offers Float panel, Move to group, and Close panel. Existing panel toggles reopen panels at their saved location; Reset Panel Layout restores the app layout. Floating panels remain inside the current app window.
|
||||
|
||||
@@ -35,7 +35,6 @@ impl NativeMenu {
|
||||
let mut counter = 0usize;
|
||||
let app_menu = Submenu::new("CADCraft", true);
|
||||
let about = MenuItem::with_id("cc-about", i18n::tr(language, "About CADCraft"), true, None);
|
||||
let discord = MenuItem::with_id("cc-discord", i18n::tr(language, "Join the ArtCraft Discord…"), true, None);
|
||||
let predefined = vec![
|
||||
("Services", PredefinedMenuItem::services(Some(i18n::tr(language, "Services")))),
|
||||
("Hide CADCraft", PredefinedMenuItem::hide(Some(i18n::tr(language, "Hide CADCraft")))),
|
||||
@@ -45,7 +44,7 @@ impl NativeMenu {
|
||||
];
|
||||
// The Mac place for preferences: CADCraft ▸ Settings… (⌘,) opens the Options dialog.
|
||||
let settings = MenuItem::with_id("cc-settings", i18n::tr(language, "Settings..."), true, accel("Cmd+Comma"));
|
||||
let _ = app_menu.append_items(&[&about, &discord, &PredefinedMenuItem::separator(), &settings, &PredefinedMenuItem::separator()]);
|
||||
let _ = app_menu.append_items(&[&about, &PredefinedMenuItem::separator(), &settings, &PredefinedMenuItem::separator()]);
|
||||
for (label, item) in &predefined {
|
||||
let _ = app_menu.append(item);
|
||||
if ["Services", "Show All"].contains(label) {
|
||||
@@ -53,7 +52,6 @@ impl NativeMenu {
|
||||
}
|
||||
}
|
||||
items.insert("cc-about".into(), ("ui.dialog.about".into(), "About CADCraft".into(), about));
|
||||
items.insert("cc-discord".into(), ("ui.discord".into(), "Join the ArtCraft Discord…".into(), discord));
|
||||
items.insert("cc-settings".into(), ("options".into(), "Settings...".into(), settings));
|
||||
let _ = menu.append(&app_menu);
|
||||
for (title, entries) in menus::tree(app) {
|
||||
@@ -69,11 +67,7 @@ impl NativeMenu {
|
||||
pub fn poll(&mut self, app: &mut CadApp, ctx: &egui::Context) {
|
||||
while let Ok(ev) = MenuEvent::receiver().try_recv() {
|
||||
if let Some((cmd, _, _)) = self.items.get(ev.id.as_ref()) {
|
||||
if cmd == "ui.discord" {
|
||||
ctx.open_url(egui::OpenUrl::new_tab("https://discord.gg/artcraft"));
|
||||
} else {
|
||||
menus::activate(app, &cmd.clone());
|
||||
}
|
||||
menus::activate(app, &cmd.clone());
|
||||
ctx.request_repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,10 +321,6 @@ fn about(ctx: &egui::Context, open: &mut bool) {
|
||||
ui.label(crate::tf!("Version {version}", version = env!("CARGO_PKG_VERSION")));
|
||||
ui.label(crate::tl!("Computer-aided design and drafting: an open-source, clean-room CAD application written in pure Rust."));
|
||||
ui.add_space(6.0);
|
||||
ui.label(RichText::new(crate::tl!("One of the Crafting Apps by the ArtCraft team and community.")).color(t.text_dim));
|
||||
ui.hyperlink_to("getartcraft.com/apps/cadcraft", "https://getartcraft.com/apps/cadcraft");
|
||||
ui.hyperlink_to(crate::tl!("Join us on Discord"), "https://discord.gg/artcraft");
|
||||
ui.add_space(6.0);
|
||||
ui.label(RichText::new(crate::tl!("MIT OR Apache-2.0. Not affiliated with Autodesk, Inc.")).small().color(t.text_faint));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,8 +434,6 @@
|
||||
Jogged Zalomená
|
||||
Jogged Linear Zalomená lineární
|
||||
Join Spojit
|
||||
Join the ArtCraft Discord… Připojit se na Discord ArtCraft…
|
||||
Join us on Discord Připojte se k nám na Discordu
|
||||
Isometric Plane Izometrická rovina
|
||||
Isometric snap Izometrické uchopení
|
||||
Language Jazyk
|
||||
@@ -575,7 +573,6 @@
|
||||
Offset Ekvidistanta
|
||||
On Zapnuto
|
||||
On/Off Zapnout/Vypnout
|
||||
One of the Crafting Apps by the ArtCraft team and community. Jedna z aplikací Crafting Apps od týmu ArtCraft a komunity.
|
||||
Only in this drawing: {n} Pouze v tomto výkresu: {n}
|
||||
Only in {name}: {n} Pouze v {name}: {n}
|
||||
Open (⌘O) Otevřít (⌘O)
|
||||
|
||||
|
@@ -86,6 +86,10 @@
|
||||
CADCraft Help CADCraft-Hilfe
|
||||
Cancel Abbrechen
|
||||
Cartesian (x, y) Kartesisch (x, y)
|
||||
Catppuccin Latte Catppuccin Latte
|
||||
Catppuccin Frappé Catppuccin Frappé
|
||||
Catppuccin Macchiato Catppuccin Macchiato
|
||||
Catppuccin Mocha Catppuccin Mocha
|
||||
Center Zentrum
|
||||
Center Line Mittellinie
|
||||
Center Mark Zentrumsmarke
|
||||
@@ -357,8 +361,6 @@
|
||||
Isolate Layer Layer isolieren
|
||||
Isometric Drafting Isometrisches Zeichnen
|
||||
Join Verbinden
|
||||
Join the ArtCraft Discord… Dem ArtCraft-Discord beitreten…
|
||||
Join us on Discord Treten Sie uns auf Discord bei
|
||||
Language Sprache
|
||||
Last Letzter
|
||||
Last commit Letzter Commit
|
||||
@@ -486,7 +488,6 @@
|
||||
Offset Versatz
|
||||
On Ein
|
||||
On/Off Ein/Aus
|
||||
One of the Crafting Apps by the ArtCraft team and community. Eine der Crafting Apps vom ArtCraft-Team und seiner Community.
|
||||
Open (⌘O) Öffnen (⌘O)
|
||||
Open Sample Drawing Beispielzeichnung öffnen
|
||||
Open sample drawing Beispielzeichnung öffnen
|
||||
|
||||
|
@@ -110,6 +110,10 @@
|
||||
CADCraft keeps these preferences, object snap modes and drafting toggles for your user account and restores them when it starts. CADCraft guarda estas preferencias, los modos de referencia a objetos y los ajustes de dibujo para tu cuenta de usuario y los restaura al iniciarse.
|
||||
Cancel Cancelar
|
||||
Cartesian (x, y) Cartesianas (x, y)
|
||||
Catppuccin Latte Catppuccin Latte
|
||||
Catppuccin Frappé Catppuccin Frappé
|
||||
Catppuccin Macchiato Catppuccin Macchiato
|
||||
Catppuccin Mocha Catppuccin Mocha
|
||||
Center Centro
|
||||
Center Line Línea de centro
|
||||
Center Mark Marca de centro
|
||||
@@ -455,8 +459,6 @@
|
||||
Jogged Con recodo
|
||||
Jogged Linear Lineal con recodo
|
||||
Join Unir
|
||||
Join the ArtCraft Discord… Únete al Discord de ArtCraft…
|
||||
Join us on Discord Únete a nosotros en Discord
|
||||
Keep the system cursor visible over the drawing area Mantener visible el cursor del sistema sobre el área de dibujo
|
||||
Language Idioma
|
||||
Largest array Matriz más grande
|
||||
@@ -608,7 +610,6 @@
|
||||
Offset Desfase
|
||||
On Activado
|
||||
On/Off Activar/desactivar
|
||||
One of the Crafting Apps by the ArtCraft team and community. Una de las Crafting Apps del equipo y la comunidad de ArtCraft.
|
||||
Only in this drawing: {n} Solo en este dibujo: {n}
|
||||
Only in {name}: {n} Solo en {name}: {n}
|
||||
Open Abrir
|
||||
|
||||
|
@@ -356,8 +356,6 @@
|
||||
Isolate Layer Isoler le calque
|
||||
Isometric Drafting Dessin isométrique
|
||||
Join Rejoindre
|
||||
Join the ArtCraft Discord… Rejoindre le Discord d'ArtCraft…
|
||||
Join us on Discord Rejoignez-nous sur Discord
|
||||
Language Langue
|
||||
Last Dernier
|
||||
Last commit Dernière révision
|
||||
@@ -485,7 +483,6 @@
|
||||
Offset Décalage
|
||||
On Activé
|
||||
On/Off Activer/Désactiver
|
||||
One of the Crafting Apps by the ArtCraft team and community. L'une des applications Crafting Apps de l'équipe et de la communauté ArtCraft.
|
||||
Open (⌘O) Ouvrir (⌘O)
|
||||
Open Sample Drawing Ouvrir un dessin d'exemple
|
||||
Open sample drawing Ouvrir un dessin d'exemple
|
||||
|
||||
|
@@ -86,6 +86,10 @@
|
||||
CADCraft Help Ajuda do CADCraft
|
||||
Cancel Cancelar
|
||||
Cartesian (x, y) Cartesiano (x, y)
|
||||
Catppuccin Latte Catppuccin Latte
|
||||
Catppuccin Frappé Catppuccin Frappé
|
||||
Catppuccin Macchiato Catppuccin Macchiato
|
||||
Catppuccin Mocha Catppuccin Mocha
|
||||
Center Centro
|
||||
Center Line Linha de centro
|
||||
Center Mark Marca de centro
|
||||
@@ -357,8 +361,6 @@
|
||||
Isolate Layer Isolar camada
|
||||
Isometric Drafting Desenho isométrico
|
||||
Join Unir
|
||||
Join the ArtCraft Discord… Entrar no Discord do ArtCraft…
|
||||
Join us on Discord Junte-se a nós no Discord
|
||||
Language Idioma
|
||||
Last Último
|
||||
Last commit Último commit
|
||||
@@ -486,7 +488,6 @@
|
||||
Offset Deslocar
|
||||
On Ativado
|
||||
On/Off Ativar/desativar
|
||||
One of the Crafting Apps by the ArtCraft team and community. Um dos Crafting Apps da equipe e da comunidade ArtCraft.
|
||||
Open (⌘O) Abrir (⌘O)
|
||||
Open Sample Drawing Abrir desenho de exemplo
|
||||
Open sample drawing Abrir desenho de exemplo
|
||||
|
||||
|
@@ -356,8 +356,6 @@
|
||||
Isolate Layer Изолировать слой
|
||||
Isometric Drafting Изометрическое черчение
|
||||
Join Объединить
|
||||
Join the ArtCraft Discord… Присоединяйтесь к Discord ArtCraft…
|
||||
Join us on Discord Присоединяйтесь к нам в Discord
|
||||
Language Язык
|
||||
Last Последний
|
||||
Last commit Последний коммит
|
||||
@@ -485,7 +483,6 @@
|
||||
Offset Смещение
|
||||
On Включено
|
||||
On/Off Включить/выключить
|
||||
One of the Crafting Apps by the ArtCraft team and community. Одна из программ Crafting Apps от команды и сообщества ArtCraft.
|
||||
Open (⌘O) Открыть (⌘O)
|
||||
Open Sample Drawing Открыть образец чертежа
|
||||
Open sample drawing Открыть образец чертежа
|
||||
|
||||
|
@@ -8,6 +8,10 @@
|
||||
Apply Застосувати
|
||||
Attach DWG... Приєднати DWG...
|
||||
Bind Вбудувати
|
||||
Catppuccin Latte Catppuccin Латте
|
||||
Catppuccin Frappé Catppuccin Фраппе
|
||||
Catppuccin Macchiato Catppuccin Макіато
|
||||
Catppuccin Mocha Catppuccin Мока
|
||||
Detach Від'єднати
|
||||
Loaded Завантажено
|
||||
Make it a block of this drawing, keeping its layer names Зробити блоком цього креслення зі збереженням назв шарів
|
||||
@@ -438,8 +442,6 @@
|
||||
Jogged Зі зламом
|
||||
Jogged Linear Лінійний зі зламом
|
||||
Join Об'єднати
|
||||
Join the ArtCraft Discord… Приєднатися до Discord ArtCraft…
|
||||
Join us on Discord Приєднуйтеся до нас у Discord
|
||||
Isometric Plane Ізометрична площина
|
||||
Isometric snap Ізометрична крокова прив'язка
|
||||
Language Мова
|
||||
@@ -579,7 +581,6 @@
|
||||
Offset Зміщення
|
||||
On Увімкнено
|
||||
On/Off Увімкнути/вимкнути
|
||||
One of the Crafting Apps by the ArtCraft team and community. Одна з програм Crafting Apps від команди та спільноти ArtCraft.
|
||||
Only in this drawing: {n} Лише в цьому кресленні: {n}
|
||||
Only in {name}: {n} Лише в {name}: {n}
|
||||
Open (⌘O) Відкрити (⌘O)
|
||||
|
||||
|
@@ -357,8 +357,6 @@
|
||||
Isolate Layer 隔离图层
|
||||
Isometric Drafting 等轴测制图
|
||||
Join 合并
|
||||
Join the ArtCraft Discord… 加入 ArtCraft Discord…
|
||||
Join us on Discord 在 Discord 上加入我们
|
||||
Language 语言
|
||||
Last 最后
|
||||
Last commit 最后提交
|
||||
@@ -486,7 +484,6 @@
|
||||
Offset 偏移
|
||||
On 开启
|
||||
On/Off 开/关
|
||||
One of the Crafting Apps by the ArtCraft team and community. 由 ArtCraft 团队和社区打造的 Crafting 系列应用之一。
|
||||
Open (⌘O) 打开 (⌘O)
|
||||
Open Sample Drawing 打开示例图形
|
||||
Open sample drawing 打开示例图形
|
||||
|
||||
|
@@ -201,6 +201,7 @@ pub struct CadApp {
|
||||
shown_theme: Option<egui::Theme>,
|
||||
/// Whether the last applied theme was handed to egui as the System preference.
|
||||
shown_follows_system: bool,
|
||||
shown_flavor: Option<craft_ui::theme::catppuccin::Flavor>,
|
||||
pub frame_ms: f64,
|
||||
pub quit_requested: bool,
|
||||
/// The app may close although drawings have unsaved changes (they were dealt with, or the
|
||||
@@ -241,6 +242,7 @@ impl CadApp {
|
||||
fonts_cjk: None,
|
||||
shown_theme: None,
|
||||
shown_follows_system: false,
|
||||
shown_flavor: None,
|
||||
frame_ms: 0.0,
|
||||
quit_requested: false,
|
||||
quit_confirmed: false,
|
||||
@@ -423,12 +425,15 @@ impl CadApp {
|
||||
// browser report changes as input); the saved choice itself never changes here.
|
||||
let shown = self.ui.theme.resolve(ctx.system_theme());
|
||||
theme::set_active(shown);
|
||||
let flavor = self.ui.theme.flavor();
|
||||
theme::set_flavor(flavor);
|
||||
theme::set_canvas(self.options.canvas());
|
||||
let follows_system = self.ui.theme == theme::ThemePref::System;
|
||||
if self.shown_theme != Some(shown) || self.shown_follows_system != follows_system {
|
||||
if self.shown_theme != Some(shown) || self.shown_follows_system != follows_system || self.shown_flavor != flavor {
|
||||
theme::apply(ctx, shown, follows_system);
|
||||
self.shown_theme = Some(shown);
|
||||
self.shown_follows_system = follows_system;
|
||||
self.shown_flavor = flavor;
|
||||
}
|
||||
self.drain_control(ctx);
|
||||
if !self.synthetic.is_empty() {
|
||||
|
||||
@@ -33,6 +33,10 @@ pub const UI_COMMANDS: &[(&str, &str, &[&str], Option<&str>)] = &[
|
||||
("ui.theme.system", "Use System Setting", &["View", "Interface Theme", "Use System Setting"], None),
|
||||
("ui.theme.light", "Light", &["View", "Interface Theme", "Light"], None),
|
||||
("ui.theme.dark", "Dark", &["View", "Interface Theme", "Dark"], None),
|
||||
("ui.theme.catppuccinLatte", "Catppuccin Latte", &["View", "Interface Theme", "Catppuccin Latte"], None),
|
||||
("ui.theme.catppuccinFrappe", "Catppuccin Frappé", &["View", "Interface Theme", "Catppuccin Frappé"], None),
|
||||
("ui.theme.catppuccinMacchiato", "Catppuccin Macchiato", &["View", "Interface Theme", "Catppuccin Macchiato"], None),
|
||||
("ui.theme.catppuccinMocha", "Catppuccin Mocha", &["View", "Interface Theme", "Catppuccin Mocha"], None),
|
||||
("ui.theme", "Interface Theme", &[], None),
|
||||
("ui.saveformat.dxf", "DXF", &["File", "Default Save Format", "DXF"], None),
|
||||
("ui.saveformat.dwg", "DWG", &["File", "Default Save Format", "DWG"], None),
|
||||
@@ -223,15 +227,21 @@ fn run_ui_command_inner(app: &mut CadApp, id: &str, params: &Value) -> Option<Re
|
||||
toggle(&mut app.ui.in_window_menu, params);
|
||||
Ok(Value::Null)
|
||||
}
|
||||
"ui.theme.system" | "ui.theme.light" | "ui.theme.dark" => {
|
||||
"ui.theme.system"
|
||||
| "ui.theme.light"
|
||||
| "ui.theme.dark"
|
||||
| "ui.theme.catppuccinLatte"
|
||||
| "ui.theme.catppuccinFrappe"
|
||||
| "ui.theme.catppuccinMacchiato"
|
||||
| "ui.theme.catppuccinMocha" => {
|
||||
let pref = crate::theme::ThemePref::parse(id.trim_start_matches("ui.theme.")).unwrap_or_default();
|
||||
set_theme(app, pref)
|
||||
}
|
||||
// `{"theme": "system"|"light"|"dark"}` sets the choice; without it, reports it.
|
||||
// `{"theme": "system"|"light"|"dark"|"catppuccinLatte"|…}` (see `ThemePref::id_list`) sets the choice; without it, reports it.
|
||||
"ui.theme" => match params.get("theme").and_then(Value::as_str) {
|
||||
Some(name) => match crate::theme::ThemePref::parse(name) {
|
||||
Some(pref) => set_theme(app, pref),
|
||||
None => Err(format!("unknown theme \"{name}\" (system, light or dark)")),
|
||||
None => Err(format!("unknown theme \"{name}\" ({})", crate::theme::ThemePref::id_list())),
|
||||
},
|
||||
None => Ok(theme_json(app)),
|
||||
},
|
||||
|
||||
@@ -97,6 +97,10 @@ fn theme_label(t: ThemePref) -> &'static str {
|
||||
ThemePref::System => crate::tl!("Use System Setting"),
|
||||
ThemePref::Light => crate::tl!("Light"),
|
||||
ThemePref::Dark => crate::tl!("Dark"),
|
||||
ThemePref::CatppuccinLatte => crate::tl!("Catppuccin Latte"),
|
||||
ThemePref::CatppuccinFrappe => crate::tl!("Catppuccin Frappé"),
|
||||
ThemePref::CatppuccinMacchiato => crate::tl!("Catppuccin Macchiato"),
|
||||
ThemePref::CatppuccinMocha => crate::tl!("Catppuccin Mocha"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ fn color_param(key: &str, v: &Value) -> Result<Option<Color32>, String> {
|
||||
fn parse_ui(key: &str, v: &Value, c: &mut UiChanges) -> Result<bool, String> {
|
||||
let text = || v.as_str().ok_or_else(|| format!("{key} must be text"));
|
||||
match key {
|
||||
"theme" => c.theme = Some(ThemePref::parse(text()?).ok_or("theme must be system, light or dark")?),
|
||||
"theme" => c.theme = Some(ThemePref::parse(text()?).ok_or_else(|| format!("theme must be {}", ThemePref::id_list()))?),
|
||||
"interfaceLanguage" => {
|
||||
c.language = Some(
|
||||
crate::i18n::Preference::parse(text()?).ok_or_else(|| format!("interfaceLanguage must be {}", crate::i18n::Preference::codes()))?,
|
||||
|
||||
@@ -6,35 +6,59 @@
|
||||
//! dialogs); the drawing area keeps its model-space colours in both, as drawing colours are not
|
||||
//! part of the interface theme. [`Tokens::get`] returns the palette of the theme in use, which
|
||||
//! [`CadApp::logic`](crate::CadApp::logic) resolves once per frame from the user's [`ThemePref`].
|
||||
//! The four Catppuccin flavours ([`Tokens::catppuccin`]) re-colour the same chrome.
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
use craft_ui::theme::catppuccin::Flavor;
|
||||
use egui::{Color32, FontFamily, FontId, Theme, Visuals};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The interface theme the user chose.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ThemePref {
|
||||
/// Follow the operating system's light/dark appearance, live.
|
||||
#[serde(rename = "system")]
|
||||
System,
|
||||
#[serde(rename = "light")]
|
||||
Light,
|
||||
/// The default: CADCraft's original look.
|
||||
#[default]
|
||||
#[serde(rename = "dark")]
|
||||
Dark,
|
||||
#[serde(rename = "catppuccinLatte")]
|
||||
CatppuccinLatte,
|
||||
#[serde(rename = "catppuccinFrappe")]
|
||||
CatppuccinFrappe,
|
||||
#[serde(rename = "catppuccinMacchiato")]
|
||||
CatppuccinMacchiato,
|
||||
#[serde(rename = "catppuccinMocha")]
|
||||
CatppuccinMocha,
|
||||
}
|
||||
|
||||
/// The theme `System` uses when the OS (or browser) reports no appearance.
|
||||
pub const SYSTEM_FALLBACK: Theme = Theme::Dark;
|
||||
|
||||
impl ThemePref {
|
||||
pub const ALL: [ThemePref; 3] = [ThemePref::System, ThemePref::Light, ThemePref::Dark];
|
||||
pub const ALL: [ThemePref; 7] = [
|
||||
ThemePref::System,
|
||||
ThemePref::Light,
|
||||
ThemePref::Dark,
|
||||
ThemePref::CatppuccinLatte,
|
||||
ThemePref::CatppuccinFrappe,
|
||||
ThemePref::CatppuccinMacchiato,
|
||||
ThemePref::CatppuccinMocha,
|
||||
];
|
||||
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
ThemePref::System => "system",
|
||||
ThemePref::Light => "light",
|
||||
ThemePref::Dark => "dark",
|
||||
ThemePref::CatppuccinLatte => "catppuccinLatte",
|
||||
ThemePref::CatppuccinFrappe => "catppuccinFrappe",
|
||||
ThemePref::CatppuccinMacchiato => "catppuccinMacchiato",
|
||||
ThemePref::CatppuccinMocha => "catppuccinMocha",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,12 +66,29 @@ impl ThemePref {
|
||||
ThemePref::ALL.into_iter().find(|t| t.as_str().eq_ignore_ascii_case(s.trim()))
|
||||
}
|
||||
|
||||
/// Every id, `|`-separated: for error messages and command docs.
|
||||
pub fn id_list() -> String {
|
||||
Self::ALL.map(ThemePref::as_str).join("|")
|
||||
}
|
||||
|
||||
/// The Catppuccin flavour this choice shows, if it is one.
|
||||
pub fn flavor(self) -> Option<Flavor> {
|
||||
match self {
|
||||
ThemePref::CatppuccinLatte => Some(Flavor::Latte),
|
||||
ThemePref::CatppuccinFrappe => Some(Flavor::Frappe),
|
||||
ThemePref::CatppuccinMacchiato => Some(Flavor::Macchiato),
|
||||
ThemePref::CatppuccinMocha => Some(Flavor::Mocha),
|
||||
ThemePref::System | ThemePref::Light | ThemePref::Dark => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// The theme to show, given what the OS reports (`ctx.system_theme()`).
|
||||
pub fn resolve(self, system: Option<Theme>) -> Theme {
|
||||
match self {
|
||||
ThemePref::System => system.unwrap_or(SYSTEM_FALLBACK),
|
||||
ThemePref::Light => Theme::Light,
|
||||
ThemePref::Dark => Theme::Dark,
|
||||
p => p.flavor().map_or(SYSTEM_FALLBACK, |f| if f.is_dark() { Theme::Dark } else { Theme::Light }),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,6 +96,8 @@ impl ThemePref {
|
||||
thread_local! {
|
||||
/// The theme in use on the UI thread (set by [`set_active`] each frame).
|
||||
static ACTIVE: Cell<Theme> = const { Cell::new(Theme::Dark) };
|
||||
/// The Catppuccin flavour in use, if any (set by [`set_flavor`] each frame).
|
||||
static FLAVOR: Cell<Option<Flavor>> = const { Cell::new(None) };
|
||||
}
|
||||
|
||||
/// The theme [`Tokens::get`] returns colours for.
|
||||
@@ -66,6 +109,14 @@ pub fn set_active(theme: Theme) {
|
||||
ACTIVE.with(|a| a.set(theme));
|
||||
}
|
||||
|
||||
pub fn flavor() -> Option<Flavor> {
|
||||
FLAVOR.with(Cell::get)
|
||||
}
|
||||
|
||||
pub fn set_flavor(f: Option<Flavor>) {
|
||||
FLAVOR.with(|c| c.set(f));
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Tokens {
|
||||
pub chrome: Color32,
|
||||
@@ -216,7 +267,42 @@ impl Tokens {
|
||||
|
||||
/// The palette of the theme in use, with the user's drawing-area colours ([`set_canvas`]).
|
||||
pub fn get() -> Tokens {
|
||||
CANVAS.with(Cell::get).over(Tokens::of(active()))
|
||||
CANVAS.with(Cell::get).over(flavor().map_or_else(|| Tokens::of(active()), Tokens::catppuccin))
|
||||
}
|
||||
|
||||
/// A Catppuccin flavour on CADCraft's chrome (mauve accent, blue selection). The drawing-area
|
||||
/// colours stay [`Tokens::DARK`]'s, as in every interface theme.
|
||||
pub fn catppuccin(f: Flavor) -> Tokens {
|
||||
let p = f.palette();
|
||||
let alpha = |c: Color32, a: u8| Color32::from_rgba_unmultiplied(c.r(), c.g(), c.b(), a);
|
||||
Tokens {
|
||||
chrome: p.mantle,
|
||||
chrome_dark: p.crust,
|
||||
panel: p.base,
|
||||
tab_active: p.surface1,
|
||||
control: p.surface0,
|
||||
control_hover: p.surface1,
|
||||
border: p.surface1,
|
||||
text: p.text,
|
||||
text_dim: p.subtext0,
|
||||
text_faint: p.overlay1,
|
||||
icon: p.subtext1,
|
||||
icon_accent: p.blue,
|
||||
icon_point: p.peach,
|
||||
accent: p.mauve,
|
||||
cmd_bg: alpha(p.base, 0xf0),
|
||||
toggle_on: p.mauve,
|
||||
field: if f.is_dark() { p.crust } else { p.base },
|
||||
select_bg: mix(p.base, p.blue, 0.4),
|
||||
cmd_history: alpha(p.mantle, 0xdc),
|
||||
cmd_border: p.surface2,
|
||||
cmd_keyword: p.blue,
|
||||
cmd_keyword_hover: p.surface1,
|
||||
list_bg: p.mantle,
|
||||
list_row: p.surface0,
|
||||
warn: if f.is_dark() { p.yellow } else { p.peach },
|
||||
..Tokens::DARK
|
||||
}
|
||||
}
|
||||
|
||||
/// These tokens with `bg` as the model-space background: the grid, axes, crosshair and the
|
||||
@@ -393,9 +479,9 @@ pub fn can_show(language: &str) -> bool {
|
||||
!language.starts_with("zh") || cjk_font().is_some()
|
||||
}
|
||||
|
||||
/// egui's visuals for `theme`, from its tokens.
|
||||
fn visuals(theme: Theme) -> Visuals {
|
||||
let t = Tokens::of(theme);
|
||||
/// egui's visuals for `theme` (or the Catppuccin flavour `f` of it), from its tokens.
|
||||
fn visuals(theme: Theme, f: Option<Flavor>) -> Visuals {
|
||||
let t = f.map_or_else(|| Tokens::of(theme), Tokens::catppuccin);
|
||||
let mut v = match theme {
|
||||
Theme::Dark => Visuals::dark(),
|
||||
Theme::Light => Visuals::light(),
|
||||
@@ -424,13 +510,14 @@ fn visuals(theme: Theme) -> Visuals {
|
||||
v
|
||||
}
|
||||
|
||||
/// Install the styles of both themes and show `theme` (egui's own widgets, popups and menus
|
||||
/// Install the styles of both themes (the active [`flavor`] colours its side) and show `theme` (egui's own widgets, popups and menus
|
||||
/// follow it; our own painting follows [`Tokens::get`]). `follow_system` is true for the
|
||||
/// [`ThemePref::System`] choice, whose `theme` was resolved from the OS report.
|
||||
pub fn apply(ctx: &egui::Context, theme: Theme, follow_system: bool) {
|
||||
set_active(theme);
|
||||
ctx.set_visuals_of(Theme::Dark, visuals(Theme::Dark));
|
||||
ctx.set_visuals_of(Theme::Light, visuals(Theme::Light));
|
||||
for th in [Theme::Dark, Theme::Light] {
|
||||
ctx.set_visuals_of(th, visuals(th, flavor().filter(|f| f.is_dark() == (th == Theme::Dark))));
|
||||
}
|
||||
// A System choice keeps egui's own System preference: a concrete Light/Dark would pin the native
|
||||
// window appearance (winit then stops reporting OS changes) and the app would never follow again.
|
||||
ctx.set_theme(if follow_system { egui::ThemePreference::System } else { egui::ThemePreference::from(theme) });
|
||||
@@ -444,3 +531,22 @@ pub fn apply(ctx: &egui::Context, theme: Theme, follow_system: bool) {
|
||||
s.text_styles.insert(egui::TextStyle::Monospace, mono());
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn catppuccin_themes_use_the_flavour_palette() {
|
||||
let flavors: Vec<_> = ThemePref::ALL.iter().filter_map(|t| t.flavor()).collect();
|
||||
assert_eq!(flavors, Flavor::ALL);
|
||||
for t in ThemePref::ALL.into_iter().filter(|t| t.flavor().is_some()) {
|
||||
let f = t.flavor().unwrap();
|
||||
let tokens = Tokens::catppuccin(f);
|
||||
assert_eq!((tokens.panel, tokens.text, tokens.accent), (f.palette().base, f.palette().text, f.palette().mauve), "{}", t.as_str());
|
||||
assert_eq!(t.resolve(None) == Theme::Dark, f.is_dark());
|
||||
assert_eq!(ThemePref::parse(t.as_str()), Some(t));
|
||||
}
|
||||
assert_eq!(ThemePref::id_list().split('|').count(), ThemePref::ALL.len());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
ArtCraft brand assets: license
|
||||
|
||||
The ArtCraft name, wordmark and mark (the "ArtCraft Marks"), including every file in this
|
||||
directory in every color, size and format, are owned by the ArtCraft Team. They are trademarks
|
||||
and are NOT open source. They are not covered by CADCraft's MIT OR Apache-2.0 license, and nothing in
|
||||
that license, in NOTICE or in any other file of this repository grants any right to them.
|
||||
|
||||
Permission
|
||||
|
||||
The ArtCraft Team grants a limited, non-exclusive, non-transferable, revocable, royalty-free
|
||||
permission to use the ArtCraft Marks only:
|
||||
|
||||
1. as part of copies of this repository; and
|
||||
2. within CADCraft itself, its documentation and its official builds, to identify CADCraft as made
|
||||
by the ArtCraft team and community and to link to getartcraft.com and its community.
|
||||
|
||||
Conditions
|
||||
|
||||
The permission holds only while every one of these is true:
|
||||
|
||||
- The marks are used exactly as supplied in this directory. Do not redraw, recolor, crop,
|
||||
stretch, rotate, animate, outline or add effects to them, extract parts of them, or combine
|
||||
them with any other name, mark or artwork.
|
||||
- They are used only in the context of CADCraft, and only to say that the ArtCraft team makes it.
|
||||
They must never suggest that the ArtCraft Team made, sponsors, endorses, certifies or supports
|
||||
any other product, service, fork, modified version, plug-in, organization or person.
|
||||
- Neither the marks nor the ArtCraft name appear in the name, logo, icon, domain, social media
|
||||
handle, app-store listing, advertising or marketing of anything other than CADCraft.
|
||||
|
||||
Forks and modified versions
|
||||
|
||||
If you distribute or publish a modified version of CADCraft, or any work derived from it, you must
|
||||
remove the ArtCraft Marks from it (or replace them with your own) and must not call it ArtCraft or
|
||||
present it as an ArtCraft product. You may say, in plain text, that your work is based on CADCraft by
|
||||
the ArtCraft team. A fork kept only to propose changes back to this repository may keep the marks
|
||||
unchanged.
|
||||
|
||||
Everything else
|
||||
|
||||
Any use not expressly permitted here needs prior written permission from the ArtCraft Team
|
||||
(https://getartcraft.com/). The permission ends automatically for anyone who breaks these terms.
|
||||
All other rights are reserved.
|
||||
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 26 KiB |
@@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -19.42 136.34 136.34" role="img" aria-label="ArtCraft">
|
||||
<title>ArtCraft</title>
|
||||
<path fill="#0b0b0c" d="M104.28,49.49L81.55,0h-31.23l-3.17,4.76L14.75,53.63,0,75.85l21.55,21.55,63.79-36.94,16.99,37.04,14.01-21.74-12.06-26.27ZM32.89,65.66l32.42-48.87,10.91,23.77-43.32,25.09Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 341 B |
|
Before Width: | Height: | Size: 24 KiB |
@@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -19.42 136.34 136.34" role="img" aria-label="ArtCraft">
|
||||
<title>ArtCraft</title>
|
||||
<path fill="#4e7bfb" d="M104.28,49.49L81.55,0h-31.23l-3.17,4.76L14.75,53.63,0,75.85l21.55,21.55,63.79-36.94,16.99,37.04,14.01-21.74-12.06-26.27ZM32.89,65.66l32.42-48.87,10.91,23.77-43.32,25.09Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 341 B |
@@ -20,10 +20,10 @@
|
||||
<launchable type="desktop-id">ai.storyteller.cadcraft.desktop</launchable>
|
||||
<icon type="stock">ai.storyteller.cadcraft</icon>
|
||||
<!-- Only url types known to appstream 0.15 (Ubuntu 22.04, where CI validates): no vcs-browser. -->
|
||||
<url type="homepage">https://getartcraft.com/apps/cadcraft</url>
|
||||
<url type="homepage">https://github.com/storytold/cadcraft</url>
|
||||
<url type="bugtracker">https://github.com/storytold/cadcraft/issues</url>
|
||||
<url type="help">https://github.com/storytold/cadcraft</url>
|
||||
<url type="contact">https://discord.gg/artcraft</url>
|
||||
<url type="contact">https://github.com/storytold/cadcraft/issues</url>
|
||||
<categories>
|
||||
<category>Graphics</category>
|
||||
<category>Engineering</category>
|
||||
|
||||
@@ -14,7 +14,7 @@ section: graphics
|
||||
priority: optional
|
||||
maintainer: ${CADCRAFT_MAINTAINER}
|
||||
vendor: Learning Machines LLC
|
||||
homepage: https://getartcraft.com/apps/cadcraft
|
||||
homepage: https://github.com/storytold/cadcraft
|
||||
license: MIT OR Apache-2.0
|
||||
description: |-
|
||||
Open-source computer-aided design and drafting: draft, dimension and plot 2D
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
|
||||
<Icon Id="CadcraftIcon.ico" SourceFile="$(var.IconPath)" />
|
||||
<Property Id="ARPPRODUCTICON" Value="CadcraftIcon.ico" />
|
||||
<Property Id="ARPURLINFOABOUT" Value="https://getartcraft.com/apps/cadcraft" />
|
||||
<Property Id="ARPURLUPDATEINFO" Value="https://getartcraft.com/apps/cadcraft" />
|
||||
<Property Id="ARPHELPLINK" Value="https://discord.gg/artcraft" />
|
||||
<Property Id="ARPURLINFOABOUT" Value="https://github.com/storytold/cadcraft" />
|
||||
<Property Id="ARPURLUPDATEINFO" Value="https://github.com/storytold/cadcraft" />
|
||||
<Property Id="ARPHELPLINK" Value="https://github.com/storytold/cadcraft/issues" />
|
||||
|
||||
<StandardDirectory Id="ProgramFiles6432Folder">
|
||||
<Directory Id="INSTALLFOLDER" Name="CADCraft" />
|
||||
|
||||