Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
paths:
- ".github/workflows/docs.yml"
- ".readthedocs.yaml"
- "docs/**"
- "doc/**"
- "usage.md"
- "usage-*.md"
- "scripting.md"
Expand All @@ -18,7 +18,7 @@ on:
paths:
- ".github/workflows/docs.yml"
- ".readthedocs.yaml"
- "docs/**"
- "doc/**"
- "usage.md"
- "usage-*.md"
- "scripting.md"
Expand All @@ -36,7 +36,7 @@ jobs:
python-version: "3.13"

- name: Install doc dependencies
run: pip install -r docs/requirements.txt
run: pip install -r doc/requirements.txt

- name: Build HTML (warnings are errors; matches Read the Docs)
run: sphinx-build -b html -W --keep-going docs docs/_build
run: sphinx-build -b html -W --keep-going doc doc/_build
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/build*
/docs/_build
/doc/_build
/.vscode/settings.json
# Legacy name; some toolchains write here. Primary vendored deps live in third_party/.
/thirdParty
Expand Down
4 changes: 2 additions & 2 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ build:
python: "3.13"

sphinx:
configuration: docs/conf.py
configuration: doc/conf.py
fail_on_warning: true

python:
install:
- requirements: docs/requirements.txt
- requirements: doc/requirements.txt
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@ if(MSVC)
set(DOC_FILES
${CMAKE_CURRENT_SOURCE_DIR}/README.md
${CMAKE_CURRENT_SOURCE_DIR}/ezycad_code_style.md
${CMAKE_CURRENT_SOURCE_DIR}/ezycad_doc_style.md
${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG.md
${CMAKE_CURRENT_SOURCE_DIR}/usage.md
${CMAKE_CURRENT_SOURCE_DIR}/usage-settings.md
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# EzyCad

![EzyCad splash screen](res/AI-gen-splashscreen_05_01_2026_512.png)

EzyCad (Easy CAD) is a CAD application for hobbyist machinists to design and edit 2D and 3D models for machining projects. It supports creating precise parts with tools for sketching, extruding, and applying geometric operations, using OpenGL, ImGui, and Open CASCADE Technology (OCCT). Export models to formats like STEP or STL for CNC machines or 3D printers, or [run EzyCad in your browser (WebAssembly)](https://trailcode.github.io/EzyCad/EzyCad.html).

## Features
Expand Down Expand Up @@ -88,7 +90,7 @@ Ensure the following dependencies are installed:
### We need development help
EzyCad is maintained by a small team and we would love more contributors. If you can help with features, bug fixes, documentation, or testing - please jump in. Every contribution helps move the project forward.

**Code style:** When contributing, please follow the project's style guide: [ezycad_code_style.md](ezycad_code_style.md). Both human developers and AI coding agents (e.g. Cursor, GitHub Copilot, ChatGPT) should adhere to it so that patches stay consistent and reviewable. Optional assistant-oriented snippets live under [agents/](agents/) (the repo does not commit `.cursor/`).
**Style guides:** [ezycad_code_style.md](ezycad_code_style.md) for C++ in `src/`; [ezycad_doc_style.md](ezycad_doc_style.md) for user guides and [Read the Docs](https://ezycad.readthedocs.io/). Both human developers and AI coding agents should follow the relevant guide. Optional assistant-oriented snippets live under [agents/](agents/) (the repo does not commit `.cursor/`).

## In-tree third-party libraries

Expand Down
1 change: 1 addition & 0 deletions agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ To use a note in **Cursor**, copy or symlink the relevant file into your user or
| File | Intent |
| --- | --- |
| [ezycad-ascii-source.md](ezycad-ascii-source.md) | ASCII-only comments and strings in `src/`; points at `ezycad_code_style.md` and `scripts/check-nonascii-src.ps1`. |
| *(repo root)* [ezycad_doc_style.md](../ezycad_doc_style.md) | User guides, Read the Docs, images, in-app doc URLs. |
File renamed without changes.
File renamed without changes.
11 changes: 9 additions & 2 deletions docs/conf.py → doc/conf.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Sphinx configuration for EzyCad user documentation (Read the Docs).
# User guides live at the repository root; they are synced into docs/ at build time
# User guides live at the repository root; they are synced into doc/ at build time
# so cross-links (usage.md, usage-sketch.md, ...) and res/icons/ paths keep working.

from __future__ import annotations
Expand All @@ -26,8 +26,15 @@ def _sync_user_docs() -> None:
if src.is_file():
shutil.copy2(src, DOCS_DIR / name)

res_dst = DOCS_DIR / "res"
res_dst.mkdir(exist_ok=True)

splash_src = PROJECT_ROOT / "res" / "AI-gen-splashscreen_05_01_2026_512.png"
if splash_src.is_file():
shutil.copy2(splash_src, res_dst / splash_src.name)

icons_src = PROJECT_ROOT / "res" / "icons"
icons_dst = DOCS_DIR / "res" / "icons"
icons_dst = res_dst / "icons"
if icons_src.is_dir():
shutil.copytree(icons_src, icons_dst, dirs_exist_ok=True)

Expand Down
File renamed without changes.
10 changes: 6 additions & 4 deletions docs/readthedocs.md → doc/readthedocs.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Read the Docs maintenance

Author conventions (Markdown, images, links): **[ezycad_doc_style.md](../ezycad_doc_style.md)**.

Published site: **https://ezycad.readthedocs.io/**

## Repository automation
Expand All @@ -9,7 +11,7 @@ Published site: **https://ezycad.readthedocs.io/**
| [`.readthedocs.yaml`](../.readthedocs.yaml) | RTD build config (Sphinx, Python 3.13). |
| [`.github/workflows/docs.yml`](../.github/workflows/docs.yml) | GitHub Actions: builds docs on push/PR when guides change. |

User guides stay at the **repository root** (`usage.md`, etc.). `docs/conf.py` copies them plus `res/icons/` and `doc/gen/` into `docs/` at build time.
User guides stay at the **repository root** (`usage.md`, etc.). `doc/conf.py` copies them plus `res/icons/` into `doc/` at build time. Screenshots in guides use paths under `doc/gen/` (committed in this folder).

Use Markdown image syntax `![alt](path)` for icons and screenshots. Raw HTML `<img src="...">` is not rewritten by Sphinx and will break on Read the Docs.

Expand All @@ -24,8 +26,8 @@ Configure at [EzyCad admin](https://app.readthedocs.org/dashboard/ezycad/):
## Local build

```bash
pip install -r docs/requirements.txt
sphinx-build -b html docs docs/_build
pip install -r doc/requirements.txt
sphinx-build -b html -W doc doc/_build
```

Open `docs/_build/index.html`.
Open `doc/_build/index.html`.
File renamed without changes.
4 changes: 4 additions & 0 deletions ezycad_code_style.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ Use this style when editing or adding C/C++ code in the EzyCad project (files un
- **Short control flow**: When the body is a single statement you may omit braces; **`AllowShortIfStatementsOnASingleLine: false`** means clang-format will not merge an `if` into one physical line (typically the condition on one line and the statement on the next). Use braces for multi-line or nested bodies. **`for`/`while`** (and other constructs not listed above) follow **`BasedOnStyle: LLVM`** unless overridden in `.clang-format`.
- Use **`// clang-format off`** / **`// clang-format on`** only where layout must be preserved (e.g. macro-like blocks, tables). Prefer running clang-format; it is the source of truth for formatting.

## Documentation

User-facing Markdown (`usage.md`, `usage-*.md`, `scripting.md`, Read the Docs, images, in-app help URLs) is covered in **[ezycad_doc_style.md](ezycad_doc_style.md)**. This file is for **`src/` C++ only**.

## Versioning and releases

- **Product version** lives in **`src/version.h`**: `EZYCAD_VERSION_MAJOR`, `EZYCAD_VERSION_MINOR`, `EZYCAD_VERSION_PATCH`, and `EZYCAD_VERSION_STRING`. Follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html) (MAJOR.MINOR.PATCH). The header is hand-maintained so it stays valid regardless of build system (CMake or otherwise).
Expand Down
66 changes: 66 additions & 0 deletions ezycad_doc_style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# EzyCad documentation style

Use this guide when editing **user-facing Markdown** at the repository root (`usage.md`, `usage-*.md`, `scripting.md`, `README.md`, `CHANGELOG.md`). For C++ in `src/`, see **[ezycad_code_style.md](ezycad_code_style.md)**.

Published HTML: **[https://ezycad.readthedocs.io/](https://ezycad.readthedocs.io/)** (`/en/latest/` tracks `main`). Build plumbing is described in **[doc/readthedocs.md](doc/readthedocs.md)** (Read the Docs dashboard, local `sphinx-build`).

## Canonical files (edit these)

| File | Purpose |
|------|---------|
| `usage.md` | Main usage guide |
| `usage-sketch.md` | 2D sketching |
| `usage-settings.md` | Settings pane and JSON |
| `usage-occt-view.md` | 3D viewer (OCCT) |
| `scripting.md` | Lua / Python consoles |
| `README.md` | Project overview |
| `CHANGELOG.md` | Release notes ([Keep a Changelog](https://keepachangelog.com/)) |

Do **not** edit generated copies under `doc/` for content. At build time, `doc/conf.py` syncs root guides plus `res/icons/` into `doc/` (see `doc/.gitignore`). Screenshots stay in `doc/gen/`.

## Writing conventions

- **Audience**: Machinists and hobby CAD users; prefer plain language and short steps.
- **Headings**: Use `##` / `###` for sections Sphinx/MyST can index; keep a stable **Table of Contents** in `usage.md` when adding major sections.
- **Keyboard shortcuts**: Use `<kbd>Tab</kbd>`, `<kbd>Ctrl</kbd>+<kbd>Z</kbd>`, etc. They render on Read the Docs via MyST.
- **Tables**: GFM pipe tables are fine on Read the Docs.
- **Cross-links**: Link other guides as `usage-sketch.md`, `usage-settings.md#view-menu`, or `#anchor` within the same file. Prefer anchors that match heading text (MyST slugifies headings for URLs).
- **Encoding**: The **ASCII-only** rule in `ezycad_code_style.md` applies to `src/`, not to these guides; Unicode in user docs is acceptable when it helps clarity.

## Images

| Kind | Path | Syntax |
|------|------|--------|
| Toolbar icons | `res/icons/Name.png` | `![alt](res/icons/Name.png)` |
| Screenshots | `doc/gen/name.png` | `![alt](doc/gen/name.png)` |

Rules:

- Use **Markdown image syntax only**. Do **not** use raw HTML `<img src="...">` — Sphinx leaves those paths unchanged and icons **break** on Read the Docs.
- Commit new PNGs under `res/icons/` or `doc/gen/` with the guide change.
- After image or guide edits, run `sphinx-build -b html -W doc doc/_build` locally, or confirm the Read the Docs build is green (`fail_on_warning: true` in [`.readthedocs.yaml`](.readthedocs.yaml)).

## Links from the application

- **Help → Usage Guide** should open Read the Docs, e.g. `https://ezycad.readthedocs.io/en/latest/usage.html`, not a GitHub blob URL.
- In-app help tooltips (Settings **?** buttons, etc.) should use the same base URL and heading anchors (e.g. `#view-roll`).
- When you rename a heading, check for broken anchors in `src/` (grep for `readthedocs.io` and old `#fragments`).

## Build and CI (reference)

| Item | Location |
|------|----------|
| Read the Docs config | [`.readthedocs.yaml`](.readthedocs.yaml) |
| Sphinx | [`doc/conf.py`](doc/conf.py), [`doc/index.rst`](doc/index.rst) |
| Python deps | [`doc/requirements.txt`](doc/requirements.txt) |
| GitHub Actions | [`.github/workflows/docs.yml`](.github/workflows/docs.yml) |

```bash
pip install -r doc/requirements.txt
sphinx-build -b html -W doc doc/_build
```

## Related docs

- **[ezycad_code_style.md](ezycad_code_style.md)** — C++ style, versioning (`version.h`, `CHANGELOG.md`).
- **[doc/readthedocs.md](doc/readthedocs.md)** — RTD integrations, webhooks, PR previews.
2 changes: 1 addition & 1 deletion usage-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Open **View -> Settings**. The window title is **Settings**.

Between those, the pane has **six** collapsible sections. Expand a section to see its controls; when collapsed, only the section title bar is visible.

1. **3D view navigation** — **View rotation step** (degrees per key press for **NumPad 8**/**2**/**4**/**6** orbit and **Shift+NumPad 4**/**6** roll; default **45**). **Zoom scroll scale** (multiplier for wheel and **+**/**-** zoom; default **4**). Hold **Shift** while zooming for a Blender-style finer step (multiply by **0.1**). Numpad shortcuts are documented with **Num Lock off**; with **Num Lock on**, use main-row alternatives in [usage.md -> View navigation](usage.md#view-navigation). Stored as **`gui.view_roll_step_deg`** and **`gui.view_zoom_scroll_scale`**. See **[usage-occt-view.md](usage-occt-view.md)**.
1. **3D view navigation** — **View rotation step** (degrees per key press for **NumPad 8**/**2**/**4**/**6** orbit and **Shift+NumPad 4**/**6** roll; default **45**; **`?`** opens [view roll](https://ezycad.readthedocs.io/en/latest/usage.html#view-roll) on Read the Docs). **Zoom scroll scale** (multiplier for wheel and **+**/**-** zoom; default **4**). Hold **Shift** while zooming for a Blender-style finer step (multiply by **0.1**). Numpad shortcuts are documented with **Num Lock off**; with **Num Lock on**, use main-row alternatives in [usage.md -> View navigation](usage.md#view-navigation). Stored as **`gui.view_roll_step_deg`** and **`gui.view_zoom_scroll_scale`**. See **[usage-occt-view.md](usage-occt-view.md)**.

2. **UI corner rounding** — Sliders **0** to **16** for **Windows, frames, popups**; **Scrollbars and sliders** (has `(?)`); **Tabs**.

Expand Down
38 changes: 37 additions & 1 deletion usage-sketch.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This guide covers all 2D sketching tools and operations in EzyCad. For the main
10. [Dimension Tool](#dimension-tool)
11. [Add Node Tool](#add-node-tool)
12. [Create Sketch from Planar Face Tool](#create-sketch-from-planar-face-tool)
13. [Image underlay](#image-underlay)

---

Expand Down Expand Up @@ -706,4 +707,39 @@ The create sketch from planar face tool allows you to extract the boundary of a
| **Boundary extraction** | Uses `BRepTools::OuterWire()` on the selected face |
| **Sketch plane** | Determined from the face's underlying surface geometry |
| **Supported faces** | Only `Geom_Plane` surfaces - other surface types are rejected |
| **Sketch list** | Created sketch is added and can be managed like any other sketch |
| **Sketch list** | Created sketch is added and can be managed like any other sketch |

### Image underlay

Import a reference image (PNG, JPEG, or BMP) behind a sketch for tracing or alignment. Open **Sketch properties** from the [Sketch List](usage.md#sketch-list) (**`[P]`** on the sketch row) or use the underlay controls there after import.

**Sketch List shortcuts**

| Control | Action |
| --- | --- |
| Underlay checkbox | Show or hide the underlay for that sketch (only when an image is loaded) |
| **`[P]`** | Open **Sketch properties** for import, calibration, and transform |

**Sketch properties — Image underlay**

| Control | Action |
| --- | --- |
| **Import image...** | Load PNG/JPEG/BMP into the current sketch |
| **Remove underlay** | Clear the image from the sketch |
| **White paper -> transparent** | Treat bright pixels as clear (typical for scanned line drawings; turn off for photos) |
| **Tint visible lines** / **Line color** | Recolor non-transparent pixels after the white key (default yellow works on dark backgrounds) |
| **Opacity** | Overall underlay transparency (**0**–**1**) |

**Calibrate from sketch edges** (sketch must be **current** in the Sketch List):

| Button | Action |
| --- | --- |
| **Set X from edge...** | Two clicks along bitmap width (+U), then enter the real drawing distance (same units as sketch dimensions) |
| **Set Y from edge...** | Two clicks along bitmap height (+V), then enter the drawing distance for Y |
| **Define underlay datum...** | Two picks on the sketch plane: corner **(0,0)**, then direction along +U (keeps current half width and height) |

After edge calibration, bitmap axes may be non-orthogonal (shear). The **Transform** sliders (**Center X/Y**, **Half width/height**, **Rotation**) then stay disabled so they do not overwrite that affine fit; use calibration picks or adjust before shear is introduced.

**Transform** (orthogonal underlay only): sliders and **Rotation value** adjust center, half extents, and rotation on the sketch plane; changes apply in real time and support undo.

Default underlay highlight tint for new imports: **Settings -> Sketch -> Underlay highlight color** (see [usage-settings.md](usage-settings.md#settings-pane)).
30 changes: 21 additions & 9 deletions usage.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# EzyCad Usage Guide

![EzyCad splash screen](res/AI-gen-splashscreen_05_01_2026_512.png)

## Table of Contents
1. [Introduction](#introduction)
2. [Getting Started](#getting-started)
Expand Down Expand Up @@ -78,12 +80,20 @@ For **View** (Settings, pane toggles, consoles), saving preferences, and the **S

The **Sketch List** pane lists all 2D sketches in the current document. Open it from **View -> Sketch List**.

For each sketch you can:
Each row is laid out left to right:

- **Expand** - Click **`>`** / **`v`** to show or hide details for that sketch (tooltip *Expand details* / *Collapse details*).
- **Set current** - Radio button (circle). The current sketch is used for editing and for operations such as [extrude](#extrude-sketch-face-tool-e).
- **Rename** - Click the name field and type a new name.
- **Visibility** - Checkbox to show or hide the sketch in the 3D view.
- **Underlay** - Checkbox to show or hide an [image underlay](usage-sketch.md#image-underlay) when one is imported (disabled until an underlay exists; tooltip *Display underlay*).
- **Sketch properties** - **`[P]`** opens the **Sketch properties** window (import/remove underlay, calibration, transform). See [Image underlay](usage-sketch.md#image-underlay).
- **Delete** - Right-click the name and choose **Delete**.

- **Set current** - Use the radio button (circle) to make this sketch the current one. The current sketch is used for editing and for operations such as [extrude](#extrude-sketch-face-tool-e).
- **Rename** - Click the name field and type to change the sketch's name.
- **Visibility** - Use the checkbox to show or hide the sketch in the 3D view.
- **Delete** - Right-click the sketch name and choose **Delete** to remove the sketch from the document.
When expanded, the row shows:

- **Dimensions** - Table of length dimensions: visibility, editable name, and **offset** (label distance from the edge; **0** = automatic).
- **Nodes**, **Edges**, **Faces** - Collapsible lists of element labels for inspection (read-only names).

The window can be closed with its close button; use **View -> Sketch List** again to show it.

Expand Down Expand Up @@ -621,16 +631,18 @@ More context on the 3D viewer stack: **[3D viewer (Open CASCADE)](usage-occt-vie
## Support

### Documentation
- [This usage guide](#ezycad-usage-guide)
- **Online** - [ezycad.readthedocs.io](https://ezycad.readthedocs.io/en/latest/usage.html) (built from this repository; same content as the guides below). Open from **Help -> Usage Guide**.
- [This usage guide](#ezycad-usage-guide) (source: [usage.md](usage.md))
- [Settings](usage-settings.md) (Settings pane, View menu, JSON settings file, startup project)
- [3D viewer (Open CASCADE)](usage-occt-view.md)
- [2D Sketching](usage-sketch.md) (including [add node](usage-sketch.md#add-node-tool))
- [2D Sketching](usage-sketch.md) (including [add node](usage-sketch.md#add-node-tool) and [image underlay](usage-sketch.md#image-underlay))
- [Scripting (Lua / Python)](scripting.md)
- Hosted docs and video tutorials are not published yet; this repository's markdown guides are the reference for now.

The markdown files in the repository remain the canonical source; Read the Docs publishes them on each update. Video tutorials are not published yet.

### Code quality and ongoing work

Contributors should follow **[ezycad_code_style.md](ezycad_code_style.md)** for C++ in `src/`. Sketching, UI, and build paths are still being refined; prefer small, focused changes and match existing patterns in the files you touch.
Contributors should follow **[ezycad_code_style.md](ezycad_code_style.md)** for C++ in `src/` and **[ezycad_doc_style.md](ezycad_doc_style.md)** when editing these guides. Sketching, UI, and build paths are still being refined; prefer small, focused changes and match existing patterns in the files you touch.

### Community
- [User forums](https://github.com/trailcode/EzyCad/discussions)
Expand Down
Loading