Commit graph

2,440 commits

Author SHA1 Message Date
Hakan Seven
617d7ba56a Feat: Phase 2 — expanded PageSetup panel and PlotSettings integration
PageSetup panel:
- Paper size presets (A4/A3/A2/A1/A0 portrait+landscape, Letter)
- Plot area selector: Layout vs Extents
- Center-on-page toggle
- Plot offset X/Y fields
- Rotation picker: 0° / 90° / 180° / 270°

PlotSettings (acadrust object):
- PageSetupCommit finds or creates a PlotSettings object in the document
- Writes paper size, plot type, centering, offset, rotation to it
- DXF round-trip: PlotSettings persisted to file

PDF export:
- Reads PlotSettings for the active layout
- Applies centering (auto-computes offset from wire extents)
- Applies offset X/Y from PlotSettings
- Applies rotation via PDF CTM transformation matrix
- Swaps paper dimensions for 90°/270° rotation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 00:12:07 +03:00
Hakan Seven
73b224c191 Feat: viewport display lock, extended properties, VPLAYER and VPORTS commands
- Enforce status.locked in pan_active_viewport and zoom_active_viewport:
  locked viewports now reject pan/zoom inputs entirely
- Add perspective, render_mode, shade_plot_mode, hide_plot, ucs_icon_visible
  fields to the viewport property panel with appropriate pickers/toggles
- Add VPORTS command: lists all user viewports in the current layout
  (id, size, position, scale, on/locked state) in the command line
- Add VPLAYER command: per-viewport layer freeze/thaw from the command line
  (F <layer> to freeze, T <layer> to thaw, Enter to exit)
- Add CmdResult::VpLayerUpdate variant and its handler in apply_cmd_result

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 23:52:18 +03:00
Hakan Seven
b013619c25 Chore: ignore ROADMAP.md from version control
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 23:43:51 +03:00
Hakan Seven
748d90af7e Fix: disable snap during entity-pick and selection-gathering modes
Snap is now suppressed (both cursor indicator and coordinate snapping)
when a command is in entity-pick mode (needs_entity_pick) or
selection-gathering mode (is_selection_gathering), and restored
automatically when the mode ends.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 23:05:24 +03:00
Hakan Seven
f01e4f69be Fix: viewport line weights no longer scale with viewport zoom
line_weight_px was multiplied by the viewport scale factor, making lines
near-invisible at small scales (e.g. 1:100) and overly thick at large
scales (e.g. 5:1). Line weights represent physical pen widths on the
plotted sheet and must be constant regardless of viewport scale.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 13:17:42 +03:00
Hakan Seven
a0596a14ff Fix: MVIEW preview rectangle drawn in XZ plane instead of XY
The preview rectangle used c1.y (constant) for all four corners and
pt.z for Z instead of c1.z. Corners 3 and 4 now correctly use pt.y
(varying Y) and the constant c1.z, producing a proper XY-plane rectangle.
Fixed in both layout/mview.rs and manage/mview.rs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 13:15:06 +03:00
Hakan Seven
9cee12d1c7 Feat: PSPACE/MSPACE interaction isolation + paper-space drawing
Selection, snapping and editing are now mode-aware:

PSPACE (paper layout, no active viewport)
- Only paper-space entities (viewport borders, title blocks, etc.) are
  hit-testable and selectable. Viewport content wires are invisible to
  the interaction layer.
- Drawing commands add entities to the paper-space layout block so
  annotations/title blocks land on the sheet, not in model space.

MSPACE (active viewport entered)
- Only model-space entities visible through the active viewport are
  hit-testable. Other viewports' content and paper entities are ignored.
- Drawing commands add entities to model space (correct DXF block).
- Snap results from projected viewport-content wires are converted from
  paper-space back to model-space via paper_to_model so that placed
  coordinates and command previews are consistent.

Entering/exiting MSPACE clears the current selection so no stale
cross-space selection is carried over.

Implementation:
- Scene::hit_test_wires() returns mode-filtered wires for all
  hit-tests, snaps, and selections (entity_wires() still returns
  everything for rendering and PDF export).
- viewport_content_wires() gains an Option<Handle> filter to render
  only the active viewport's content for MSPACE hit-testing.
- Scene::add_entity() routes to the paper-layout block or model-space
  block depending on current_layout / active_viewport.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 13:07:25 +03:00
Hakan Seven
0beb589f2c Fix: viewport MSPACE activation and navigation
Four bugs prevented viewports from working like AutoCAD model-space windows:

1. Dead-code double-click block: `!is_down2` was always false because
   `is_down2 = sel.left_down` is captured while the button is still held
   (before the selection block clears it). Changed to `is_down` so the
   double-click handler actually fires.

2. Inverted pan direction: pan_active_viewport used `-=` on the delta
   returned by screen_delta_to_world, which is the same delta that cam.pan
   *adds* to its target — causing reversed drag. Changed to `+=`.

3. Zoom not cursor-centered: zoom_active_viewport now accepts an optional
   paper-space cursor position and adjusts view_target so the model point
   under the cursor stays fixed (same as cam.zoom_about_point).

4. ESC did not exit MSPACE: CommandEscape now calls ExitViewport when
   active_viewport is set and no command is running.

Also added MS/MSPACE and PSPACE command aliases, and MspaceCommand /
PspaceCommand messages so MS auto-enters the first viewport.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:52:07 +03:00
Hakan Seven
0b8f9bfa5b Fix: deduplicate layout tabs when opening DXF/DWG files
CadDocument::new() inserts default Layout1; DXF/DWG readers then add
the file's own Layout1 on top, producing duplicate tabs with the same
name but different handles. layout_names() now deduplicates by name,
preferring the entry with a non-null block_record (the real layout from
the file).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:24:49 +03:00
Hakan Seven
a65a09c59e Fix: layout block-record resolution for DXF files
Root cause: the DXF reader never reads group code 340 (block_record
handle) inside LAYOUT objects, so layout.block_record stays Handle::NULL
after opening any DXF file.  This caused current_layout_block_handle()
to return NULL, which made belongs_to_visible_block() return true for
every entity — all entities appeared in all layouts simultaneously.

Fix in current_layout_block_handle() — three-tier lookup:
  1. Layout.block_record (non-null) — works for DWG files.
  2. Conventional DXF name ("*Model_Space", "*Paper_Space", …) derived
     from the layout's tab_order — works for standard DXF exporters.
  3. Position-based fallback: sort paper-space block records and paper
     layouts independently, then match by index — handles exporters that
     set tab_order = 0 for all layouts.

Apply the same two-tier lookup to model_space_block_handle().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:08:27 +03:00
Hakan Seven
845770938c Fix: paper limits, Cohen-Sutherland clipping, frozen layers UI, PDF improvements
Paper limits:
- Change A4 fallback from 12×9 to 297×210 mm in paper_limits()

Context menu:
- Translate layout context menu labels to English (Rename / Delete)

Viewport clipping:
- Replace AABB-only culling with proper Cohen-Sutherland line clipping
  in viewport_content_wires(); each projected segment is now clipped at
  the exact viewport boundary instead of being included or discarded whole
- Add cs_clip() and clip_polyline_to_rect() free functions in scene/mod.rs

Frozen layers per-viewport UI:
- Inject a "Frozen Layers" EditText property in the Properties panel for
  viewport entities (layer names resolved from handles at display time)
- Handle "frozen_layers" in PropGeomCommit: parse comma-separated names,
  resolve to layer handles, update vp.frozen_layers in-place

PDF export improvements:
- Add offset_x/offset_y params to export_pdf() for model-space normalization:
  coordinates are shifted so the drawing origin maps to the page origin
- Model space export computes extents via model_space_extents() (now public)
  and adds a 5 % margin; falls back to A4 landscape for empty drawings
- Skip __paper_boundary__ wire in PDF (white background covers it)
- Map yellow (active viewport border) → black and cyan (vp border) → dark
  blue for print-friendly output

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 08:18:29 +03:00
Hakan Seven
e1d296da10 Phase 7: Plot settings and PDF export
- Add printpdf 0.9.1 dependency for native PDF generation.
- New src/io/pdf_export.rs: converts paper-space WireModels to a PDF
  page (per-wire stroke color, line weight in Pt, NaN-split segments).
  White/near-white colors are inverted to black for print output.
- Add PlotExport / PlotExportPath messages: opens a save-file dialog
  and writes a .pdf next to the drawing file.
- Add PageSetupOpen/Close/WidthEdit/HeightEdit/Commit messages: a
  centered modal panel lets the user enter paper width and height (mm);
  on commit the Layout object's min/max_limits are updated in-place.
- Register PRINT / PLOT / EXPORT and PAGESETUP (PS) commands in
  dispatch_command; fix MVIEW error message to English.
- Layout ribbon gains a "Plot" group with Page Setup and Export PDF
  ribbon buttons.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 08:05:17 +03:00
Hakan Seven
ace83a0953 Phase 6: Auto-fit viewport and annotation scale hints
- Add model_space_extents() to Scene: collects key_vertices from all
  model-space entities to compute an AABB.
- Add auto_fit_viewport() to Scene: sets view_target to model centroid
  and derives custom_scale / view_height so the content fits the new
  viewport with a 10% margin.
- Call auto_fit_viewport() in commit_entity() after a viewport is added
  to a paper-space layout, so newly placed viewports immediately show
  model-space content at a sensible scale.
- Scale line_weight_px by the viewport scale factor when projecting
  model-space wires into paper space, so dimension arrows and annotation
  lines appear at the correct visual thickness.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 07:33:11 +03:00
Hakan Seven
403264d3ab Phase 5: Viewport render improvements
- 3D view direction support: model geometry projected using view_right/
  view_up vectors derived from Viewport.view_direction — enables Front,
  Side, Isometric views inside paper-space viewports
- Proper AABB clipping: replaces centroid heuristic with bounding-box
  intersection test against the exact viewport rectangle
- Per-viewport frozen layers: Viewport.frozen_layers Vec<Handle> is
  resolved to layer handles and used to skip frozen entities
- view_target used consistently as the model-space pan origin
- Model wires collected per-viewport (inside the loop) so each viewport
  can apply its own layer-freeze set

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 07:28:42 +03:00
Hakan Seven
031d2311ed Phase 4: Viewport control and properties
- Viewport ID uniqueness: commit_entity assigns max_existing_id+1
  instead of always using id=2
- Lock/On boolean toggles in Properties panel (vp_locked, vp_on)
  backed by status.locked / status.is_on fields
- Standard scale Choice picker: 1:500 to 10:1 (also syncs view_height)
- Numeric scale edit now syncs view_height when changed
- Standard view Choice picker: Top/Bottom/Front/Back/Left/Right/4×Iso
  updates view_direction vector via apply_geom_prop
- Viewport content not rendered when status.is_on is false
- current_layout_block_handle_pub() added for external access

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 07:27:03 +03:00
Hakan Seven
523ba74c10 Phase 3: Active viewport MSPACE/PSPACE workflow
- Add active_viewport: Option<Handle> field to Scene
- Add EnterViewport(Handle) and ExitViewport messages
- Double-click on a user viewport (id > 1) enters MSPACE;
  double-click on empty area while in MSPACE exits to PSPACE
- MSPACE middle-drag pans the viewport's model-space view (view_target)
- MSPACE scroll zooms the viewport's view_height / custom_scale
- Drawing commands inside MSPACE receive model-space coordinates
  via paper_to_model() coordinate transform
- Active viewport rendered with yellow dashed border (vs. cyan solid)
- Camera screen_delta_to_world helper for MSPACE pan conversion
- LayoutSwitch clears active_viewport

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 07:24:16 +03:00
Hakan Seven
474b38f4fb Aşama 2: Paper space görsel düzenleme
- Kağıt sınırı dikdörtgeni: paper layout'ta Layout.min/max_limits'ten
  beyaz çerçeve wire'ı oluşturulur, entity_wires()'a eklenir
- first_viewport_scale(): paper layout'taki ilk kullanıcı viewport'un ölçeğini döner
- paper_limits(): mevcut layout'un kağıt sınırlarını döner, sıfır boyutlu
  layout için varsayılan 12×9 kullanılır
- Status bar scale göstergesi: hardcoded "1:1" yerine aktif viewport ölçeği
  dinamik olarak "1:50", "2:1" vb. formatında gösterilir
- Overall viewport (ID=1) zaten gri renkte render ediliyor (tessellate_one)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 07:17:45 +03:00
Hakan Seven
9b14719ec5 Aşama 1: Layout yönetim UI — yeniden adlandırma, silme, context menüsü
- Layout sekme sağ-tıklamasında context menüsü (Yeniden Adlandır / Sil)
- Inline rename: sekme metin-giriş alanına dönüşür, Enter ile commit, ✕ ile iptal
- LayoutDelete: layout ve sahip olduğu tüm entity'leri kaldırır
- LayoutRename: Layout nesnesinin adını yerinde günceller
- LayoutCreate çakışma koruması: mevcut isimler arasında benzersiz ad bulur
- Escape tuşu açık rename/context menüsünü kapatır

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 07:13:36 +03:00
Hakan Seven
527cce8ff0 Rename workflow and job identifiers for clarity
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 01:18:29 +03:00
Hakan Seven
ab2e7b508d version update 2026-03-31 00:39:03 +03:00
Hakan Seven
a88542a69a Fix ribbon active state, polar snap, FILLET pick mode, and arc preview plane
- Deactivate ribbon tool highlight when command ends (issue #1)
- Reset last_point on new command dispatch to fix polar snap offset (issue #2)
- FILLET/CHAMFER: disable text input during entity pick so clicks reach viewport (issue #3)
- Dropdown icon buttons now use RibbonToolClick so they highlight blue when active
- FILLET/CHAMFER: AutoCAD-style sub-step UX — typing R/D + Enter prompts for value
- Fix FILLET arc preview plane: arc was rendering in XZ instead of XY
- Bump version to 0.1.1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 00:31:28 +03:00
Hakan Seven
468633c1fe Co-locate CadCommand impls with their ribbon toolbar modules
Each command implementation is now in the same file as its ribbon
tool definition. Groups moved to a dedicated groups/ toolbar folder.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 23:21:29 +03:00
Hakan Seven
bdde862597 Split large files: ribbon widgets and scene render/selection
- ribbon.rs → ribbon/mod.rs + ribbon/widgets.rs
  Extracted all rendering helpers, button styles, colour constants,
  layout constants and dropdown position calculators into widgets.rs.

- scene/mod.rs → scene/mod.rs + scene/selection.rs + scene/render.rs
  Moved SelectionState into selection.rs; moved CameraState, Primitive,
  shader::Program/Primitive impls, render_style and resolve_pattern
  into render.rs, reducing mod.rs from 1323 to ~1030 lines.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 23:07:43 +03:00
Hakan Seven
ed9cbc2092 Refactor src/main.rs into modular src/app/ structure
Split the 4500-line main.rs into focused submodules under src/app/:
- mod.rs: H7CAD struct, Message enum, boot/new/run
- document.rs: DocumentTab, HistorySnapshot, HistoryState
- helpers.rs: pure helper functions
- history.rs: undo/redo logic
- properties.rs: properties panel logic
- layers.rs: layer sync
- commands.rs: dispatch_command
- cmd_result.rs: apply_cmd_result
- view.rs: view, subscription, tab bar
- update.rs: update message handler

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 22:44:32 +03:00
Hakan Seven
854f07517e Remove redundant Flatpak README 2026-03-22 20:27:23 +03:00
Hakan Seven
a8089f7c74 Rename flatpak-release.yml to release.yml 2026-03-22 18:36:48 +03:00
Hakan Seven
803f5a005c Add Windows build job to release workflow 2026-03-22 18:35:45 +03:00
Hakan Seven
55bac2a1cb Add README with installation and build instructions 2026-03-22 18:31:46 +03:00
Hakan Seven
ba587e99ec Use gh release upload instead of action for flatpak bundle 2026-03-22 18:16:11 +03:00
Hakan Seven
5a3b92831f Add contents:write permission to Flatpak release workflow 2026-03-22 17:54:38 +03:00
Hakan Seven
536ae5394c Add workflow_dispatch trigger to Flatpak release workflow 2026-03-22 17:38:24 +03:00
Hakan Seven
2b769c3055 Fix CI manifest source paths 2026-03-22 17:35:22 +03:00
Hakan Seven
95d4a2d7c3 Add Flatpak release workflow and CI manifest 2026-03-22 17:31:06 +03:00
Hakan Seven
f52b4661d6 Fix Flathub lint errors in manifest and metainfo 2026-03-22 16:49:56 +03:00
Hakan Seven
c11b28956a fp commit 2026-03-22 15:58:13 +03:00
Hakan Seven
ff84a5e197 flatpak 2026-03-22 15:48:10 +03:00
Hakan Seven
10c40f7ca0
Add Patreon username to FUNDING.yml
Added Patreon username for funding support.
2026-03-22 15:10:36 +03:00
Hakan Seven
4e0b2087b0
Update README with project image
Add an image to the README file.
2026-03-22 14:59:08 +03:00
Hakan Seven
d2fdac7f1e first commit 2026-03-22 14:56:27 +03:00
Hakan Seven
d52c6440ff
Initial commit 2026-03-22 14:53:51 +03:00