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
151 changes: 0 additions & 151 deletions .github/workflows/cmake-single-platform.yml
Original file line number Diff line number Diff line change
@@ -1,152 +1 @@
# This starter workflow is for a CMake project running on a single platform. There is a different starter workflow if you need cross-platform coverage.
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml
name: CMake on a single platform

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release

jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
# You can convert this to a matrix build if you need cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: windows-latest

steps:
- uses: actions/checkout@v4

- name: Install NuGet
uses: nuget/setup-nuget@v1
with:
nuget-version: 'latest'

- name: Setup vcpkg
uses: friendlyanon/setup-vcpkg@v1

- name: Try to download pre-built OpenCASCADE
id: download_occt
shell: pwsh
continue-on-error: true
run: |
$OCCT_VERSION = "7.9.1"
$OCCT_EXTRACT_DIR = "$env:RUNNER_TEMP\occt"
$OCCT_ZIP = "$env:RUNNER_TEMP\occt.zip"

# Try multiple possible download URLs
$urls = @(
"https://github.com/Open-Cascade-SAS/OCCT/releases/download/V7_9_1/opencascade-$OCCT_VERSION-vc14-64.zip",
"https://github.com/Open-Cascade-SAS/OCCT/releases/download/V7_9_1/OCC-$OCCT_VERSION-VC14-64.zip",
"https://dev.opencascade.org/system/files/occt/opencascade-$OCCT_VERSION-vc14-64.zip",
"https://dev.opencascade.org/system/files/occt/OCC-$OCCT_VERSION-VC14-64.zip"
)

$downloaded = $false
foreach ($url in $urls) {
try {
Write-Host "Trying to download from: $url"
Invoke-WebRequest -Uri $url -OutFile $OCCT_ZIP -UseBasicParsing -TimeoutSec 30
Write-Host "Successfully downloaded from: $url"
$downloaded = $true
break
} catch {
Write-Host "Failed to download from $url : $_"
continue
}
}

if ($downloaded) {
Write-Host "Extracting OpenCASCADE..."
if (Test-Path $OCCT_EXTRACT_DIR) {
Remove-Item -Path $OCCT_EXTRACT_DIR -Recurse -Force
}
Expand-Archive -Path $OCCT_ZIP -DestinationPath $OCCT_EXTRACT_DIR -Force

# Find OpenCASCADEConfig.cmake
$OCCT_CONFIG = Get-ChildItem -Path $OCCT_EXTRACT_DIR -Recurse -Filter "OpenCASCADEConfig.cmake" -ErrorAction SilentlyContinue | Select-Object -First 1
if ($OCCT_CONFIG) {
$OCCT_CMAKE_DIR = $OCCT_CONFIG.DirectoryName
Write-Host "Found OpenCASCADE CMake config at: $OCCT_CMAKE_DIR"
echo "OpenCASCADE_DIR=$OCCT_CMAKE_DIR" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "USE_VCPKG=false" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "Pre-built binaries found" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
} else {
Write-Host "Warning: Downloaded but could not find OpenCASCADEConfig.cmake"
echo "USE_VCPKG=true" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
}
} else {
Write-Host "Could not download pre-built binaries, will use vcpkg"
echo "USE_VCPKG=true" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
}

- name: Install OpenCASCADE via vcpkg (if needed)
if: env.USE_VCPKG == 'true'
shell: pwsh
run: |
Write-Host "Installing OpenCASCADE via vcpkg (this may take several minutes)..."
vcpkg install opencascade:x64-windows --triplet x64-windows

- name: Find OpenCASCADE CMake config (vcpkg)
if: env.USE_VCPKG == 'true'
shell: pwsh
run: |
$VCPKG_INSTALLED = "$env:VCPKG_ROOT\installed\x64-windows"

# Find OpenCASCADEConfig.cmake
$OCCT_CONFIG = Get-ChildItem -Path $VCPKG_INSTALLED -Recurse -Filter "OpenCASCADEConfig.cmake" -ErrorAction SilentlyContinue | Select-Object -First 1
if ($OCCT_CONFIG) {
$OCCT_CMAKE_DIR = $OCCT_CONFIG.DirectoryName
Write-Host "Found OpenCASCADE CMake config at: $OCCT_CMAKE_DIR"
echo "OpenCASCADE_DIR=$OCCT_CMAKE_DIR" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
} else {
# Try common vcpkg locations
$possiblePaths = @(
"$VCPKG_INSTALLED\share\opencascade",
"$VCPKG_INSTALLED\share\occt"
)
foreach ($path in $possiblePaths) {
if (Test-Path $path) {
Write-Host "Using OpenCASCADE path: $path"
echo "OpenCASCADE_DIR=$path" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
break
}
}
}

Write-Host "OpenCASCADE_DIR is set to: $env:OpenCASCADE_DIR"

- name: Configure CMake
shell: pwsh
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: |
$cmakeArgs = @(
"-B", "${{github.workspace}}\build",
"-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}",
"-DOpenCASCADE_DIR=`"${{env.OpenCASCADE_DIR}}`""
)

if ("${{env.USE_VCPKG}}" -eq "true") {
$cmakeArgs += "-DCMAKE_TOOLCHAIN_FILE=`"$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake`""
$cmakeArgs += "-DVCPKG_TARGET_TRIPLET=x64-windows"
}

cmake @cmakeArgs

- name: Build
shell: pwsh
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}\build --config ${{env.BUILD_TYPE}}

- name: Test
working-directory: ${{github.workspace}}\build
shell: pwsh
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}} --output-on-failure
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
/build2/.vs
/build2
/.vs
/.vscode/settings.json
2 changes: 1 addition & 1 deletion src/modes.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ enum class Mode
Move,
Scale,
Rotate,
Sketch_inspection_mode, // For inspecting sketch elements
Sketch_inspection_mode, // For inspecting sketch elements
Sketch_from_face, // For creating a sketch from a face
Sketch_face_extrude, // For extruding a sketch face
Shape_chamfer, // For chamfering a shape
Expand Down
86 changes: 85 additions & 1 deletion src/occt_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "sketch.h"
#include "sketch_json.h"
#include "utl.h"
#include "utl_json.h"

#ifdef __EMSCRIPTEN__
#include <Wasm_Window.hxx>
Expand Down Expand Up @@ -1036,7 +1037,15 @@ std::string Occt_view::to_json() const
using namespace nlohmann;
json j;
json& sketches = j["sketches"] = json::array();
json& shps = j["shapes"] = json::array();
json& shps = j["shapes"] = json::array();

const auto pnt_to_json = [](Standard_Real x, Standard_Real y, Standard_Real z)
{
return ::to_json(gp_Pnt(x, y, z));
};

// ---------------------------------------------------------------------------
// Sketches / shapes
for (const Sketch_ptr& s : m_sketches)
sketches.push_back(Sketch_json::to_json(*s));

Expand All @@ -1053,6 +1062,34 @@ std::string Occt_view::to_json() const
shps.push_back(shp_json);
}

// ---------------------------------------------------------------------------
// View / camera state
if (!m_view.IsNull())
{
json& view_json = j["view"];

// Eye and target (At) positions
Standard_Real eye_x, eye_y, eye_z;
Standard_Real at_x, at_y, at_z;
m_view->Eye(eye_x, eye_y, eye_z);
m_view->At(at_x, at_y, at_z);

view_json["eye"] = pnt_to_json(eye_x, eye_y, eye_z);
view_json["at"] = pnt_to_json(at_x, at_y, at_z);

// Up and projection directions
Standard_Real up_x, up_y, up_z;
Standard_Real proj_x, proj_y, proj_z;
m_view->Up(up_x, up_y, up_z);
m_view->Proj(proj_x, proj_y, proj_z);

view_json["up"] = ::to_json(gp_Dir(up_x, up_y, up_z));
view_json["proj"] = ::to_json(gp_Dir(proj_x, proj_y, proj_z));

// View scale (zoom level)
view_json["scale"] = m_view->Scale();
}

return j.dump(2);
}

Expand Down Expand Up @@ -1106,6 +1143,53 @@ void Occt_view::load(const std::string& json_str)
m_ctx->Display(shp, AIS_Shaded, 0, true);
}

// ---------------------------------------------------------------------------
// Restore view / camera state if present
if (!m_view.IsNull() && j.contains("view") && j["view"].is_object())
{
const json& view_json = j["view"];
try
{
if (view_json.contains("eye") && view_json["eye"].is_object())
{
gp_Pnt eye = from_json_pnt(view_json["eye"]);
m_view->SetEye(eye.X(), eye.Y(), eye.Z());
}

if (view_json.contains("at") && view_json["at"].is_object())
{
gp_Pnt at = from_json_pnt(view_json["at"]);
m_view->SetAt(at.X(), at.Y(), at.Z());
}

if (view_json.contains("up") && view_json["up"].is_object())
{
gp_Dir up = from_json_dir(view_json["up"]);
m_view->SetUp(up.X(), up.Y(), up.Z());
}

if (view_json.contains("proj") && view_json["proj"].is_object())
{
gp_Dir dir = from_json_dir(view_json["proj"]);
m_view->SetProj(dir.X(), dir.Y(), dir.Z());
}

if (view_json.contains("scale") && view_json["scale"].is_number())
{
const Standard_Real scale = view_json["scale"].get<Standard_Real>();
if (scale > Precision::Confusion())
m_view->SetScale(scale);
}

m_view->Redraw();
m_ctx->UpdateCurrentViewer();
}
catch (const std::exception&)
{
// Ignore view restoration errors; project geometry has already loaded.
}
}

// Ensure correct state
gui().set_mode(Mode::Normal);
}
Expand Down
Loading