Skip to content
Open
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
6 changes: 6 additions & 0 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ jobs:
with:
fetch-depth: 0 # Fetch all history for versioning

- name: Checkout raygeo source
uses: actions/checkout@v6
with:
repository: barebaric/raygeo
path: external/raygeo

- name: Set up Pixi
uses: prefix-dev/setup-pixi@v0.9.4
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ debian/.debhelper
website/node_modules/
website/.docusaurus/
website/build/
website/docs/developer/raygeo-api/

.mac_env
rayforge/private_addons
Expand Down
9 changes: 9 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
o `pixi run test`: Run backend tests
o `pixi run uitest`: Run UI tests
o `pixi run lint`. Performs linting and static code analysis
o `pixi run raygeo-check`: Check Raygeo changes before compilation
o `pixi run raygeo-build`: Build and install the raygeo Rust extension
o `pixi run raygeo-test`: Run raygeo tests
o `pixi run print-untranslated list`: List languages with untranslated strings
o `pixi run print-untranslated <lang>`: Print untranslated strings from po file

Expand All @@ -18,6 +21,12 @@
- Never mark your changes with inline comments. Code is for clean, final implementation only
- Retain exiting formatting, docstrings, and comments

## Raygeo (Rust/PyO3 geometry library)

- Location: a separate repository in `external/raygeo/` that you may also edit
- All commands must be run via pixi from the workspace root
- The pixi environment includes `maturin`, `cargo`, and `rustc` — never install these separately

## Other rules

- Do not run the full test suite prematurely. Fix all linter errors first. Run targeted tests.
Expand Down
62 changes: 38 additions & 24 deletions pixi.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 27 additions & 3 deletions pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ PyOpenGL-accelerate = "==3.1.10"
PyGObject = "==3.50.0"
pkg-config = "*"
rust = "*"
patchelf = "*"

[feature.app.pypi-dependencies]
raygeo = "==0.2.0"
raygeo = ">=0.2.0"
rayforge = { editable = true, path = "." }
aiohttp = "==3.13.5"
asyncudp = "==0.11.0"
Expand Down Expand Up @@ -144,6 +145,22 @@ cmd = "scripts/with_gdk.sh scripts/screenshot/cli.py"
cmd = "python3 -m build"
depends-on = ["compile-translations"]

[tasks.raygeo-build]
cmd = "bash scripts/build-raygeo.sh"

[tasks.raygeo-check]
cmd = "cargo check --manifest-path external/raygeo/Cargo.toml"

[tasks.raygeo-test]
cmd = "cargo test --manifest-path external/raygeo/crates/raygeo/Cargo.toml && pytest -v external/raygeo/tests/"

[tasks.raygeo-clean-stubs]
cmd = "rm -rf external/raygeo/raygeo-stubs website/docs/developer/raygeo-api/*.md"

[tasks.raygeo-gen-stubs]
cmd = "mkdir -p external/raygeo/raygeo-stubs && python3 -c 'import raygeo; raygeo.generate_stubs(\"external/raygeo/raygeo-stubs\")'"
depends-on = ["raygeo-clean-stubs", "raygeo-build"]

[tasks.build-deb]
# Builds a binary .deb package for local installation and testing.
cmd = "bash scripts/build-deb.sh"
Expand All @@ -161,11 +178,18 @@ pyright = ">=1.1.409,<2"

# Tasks for developing and generating the website
[feature.website.tasks]
site-gen-api = "python3 scripts/update_api_docs.py"
site-install = { cmd = "npm install", cwd = "website" }
site-serve = { cmd = "npm start", cwd = "website" }
site-build = { cmd = "npm run build", cwd = "website" }
site-serve = { cmd = "npm start", cwd = "website", depends-on = ["update-api-docs"] }
site-build = { cmd = "npm run build", cwd = "website", depends-on = ["site-gen-api"] }
site-deploy = "bash scripts/deploy_website.sh"

[tasks.update-stubs]
cmd = "python3 scripts/update_stubs.py"

[tasks.update-api-docs]
cmd = "python3 scripts/update_api_docs.py"

# Tasks for video processing
[feature.video-tools.tasks]
process-audio = "python3 scripts/media/process_audio.py"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@
from typing import Optional, TYPE_CHECKING, Dict, Any

from raygeo import Geometry
from rayforge.core.ops import (
Ops,
OpsSectionStartCommand,
OpsSectionEndCommand,
SectionType,
)
from rayforge.core.ops import Ops, SectionType
from rayforge.shared.tasker.progress import ProgressContext
from rayforge.pipeline.artifact import WorkPieceArtifact
from rayforge.pipeline.coord import CoordinateSystem
Expand Down Expand Up @@ -103,14 +98,12 @@ def run(
)
# Build the final Ops object
final_ops.set_laser(laser.uid)
final_ops.add(
OpsSectionStartCommand(
SectionType.VECTOR_OUTLINE, workpiece.uid
)
final_ops.ops_section_start(
SectionType.VECTOR_OUTLINE, workpiece.uid
)
final_ops.set_power((settings or {}).get("power", 0))
final_ops.extend(frame_ops)
final_ops.add(OpsSectionEndCommand(SectionType.VECTOR_OUTLINE))
final_ops.ops_section_end(SectionType.VECTOR_OUTLINE)

# 5. Return a NON-SCALABLE artifact. The ops are already at the correct
# final size, ready for positioning.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@

from raygeo.path import normalize_winding_orders
from rayforge.core.matrix import Matrix
from rayforge.core.ops import (
Ops,
OpsSectionStartCommand,
OpsSectionEndCommand,
SectionType,
)
from rayforge.core.ops import Ops, SectionType
from rayforge.image.hull import get_concave_hull
from rayforge.image.tracing import prepare_surface
from rayforge.shared.tasker.progress import ProgressContext
Expand Down Expand Up @@ -146,14 +141,12 @@ def run(

# 7. Convert to Ops
final_ops.set_laser(laser.uid)
final_ops.add(
OpsSectionStartCommand(
SectionType.VECTOR_OUTLINE, workpiece.uid
)
final_ops.ops_section_start(
SectionType.VECTOR_OUTLINE, workpiece.uid
)
final_ops.set_power(settings.get("power", 0))
final_ops.extend(Ops.from_geometry(hull_geometry))
final_ops.add(OpsSectionEndCommand(SectionType.VECTOR_OUTLINE))
final_ops.ops_section_end(SectionType.VECTOR_OUTLINE)

# 8. Create the artifact. The ops are pre-scaled, so they are not
# scalable in the pipeline cache sense.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def get_geo_from_artifact(artifact: WorkPieceArtifact) -> List[Geometry]:
Ops are flattened, so we reconstruct geometries based on MoveTo commands.
"""
# Create a single geometry from all ops
full_geo = Geometry.from_dict(artifact.ops.to_dict())
full_geo = artifact.ops.to_geometry()
# Split into individual closed loops (contours)
return full_geo.split_into_contours()

Expand Down Expand Up @@ -290,7 +290,7 @@ def test_cut_order_inside_outside(laser, dummy_surface, vector_workpiece):
# The artifact.ops object contains sections. We need to convert to
# geometries sequentially.

full_geo = Geometry.from_dict(artifact.ops.to_dict())
full_geo = artifact.ops.to_geometry()
# split_into_contours preserves order of occurrence in command list
contours = full_geo.split_into_contours()

Expand Down Expand Up @@ -319,7 +319,7 @@ def test_cut_order_outside_inside(laser, dummy_surface, vector_workpiece):
generation_id=1,
)

full_geo = Geometry.from_dict(artifact.ops.to_dict())
full_geo = artifact.ops.to_geometry()
contours = full_geo.split_into_contours()

assert len(contours) == 2
Expand Down Expand Up @@ -441,8 +441,8 @@ def test_overcut_zero_is_noop(laser, dummy_surface, vector_workpiece):
generation_id=1,
)

geo_a = Geometry.from_dict(artifact_a.ops.to_dict())
geo_b = Geometry.from_dict(artifact_b.ops.to_dict())
geo_a = artifact_a.ops.to_geometry()
geo_b = artifact_b.ops.to_geometry()
assert geo_a == geo_b


Expand Down
Loading
Loading