Compare commits
71 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7c1ca46076 | ||
![]() |
9c30f7858f | ||
![]() |
6802a12a52 | ||
![]() |
99d6f1f5b5 | ||
![]() |
ece7630624 | ||
![]() |
82746b6171 | ||
![]() |
74d8621f53 | ||
![]() |
0b2fc34de1 | ||
![]() |
25febd82ed | ||
![]() |
d809d4122f | ||
![]() |
2e1c7a6701 | ||
![]() |
4fad67d721 | ||
![]() |
a2c97fcd46 | ||
![]() |
c4ad073d1b | ||
![]() |
0f3879e37c | ||
![]() |
05d9c0fab9 | ||
![]() |
bc43365eff | ||
![]() |
8a96ca894c | ||
![]() |
dde6030533 | ||
![]() |
b8abf698c9 | ||
![]() |
f6eb079d41 | ||
![]() |
adca3cd253 | ||
![]() |
33c3fd5fce | ||
![]() |
f2007326b4 | ||
![]() |
02b7e24812 | ||
![]() |
1a5047550d | ||
![]() |
5e28b35f2b | ||
![]() |
19e77e7866 | ||
![]() |
e1d6dac87a | ||
![]() |
4c022f8d79 | ||
![]() |
bbd106044b | ||
![]() |
359b13bd62 | ||
![]() |
513f55f7d4 | ||
![]() |
bbf8610c57 | ||
![]() |
dc0eed8322 | ||
![]() |
ca150aeda1 | ||
![]() |
4d2c773ee6 | ||
![]() |
0b997e4c17 | ||
![]() |
bfef091ac9 | ||
![]() |
bcd43c7c24 | ||
![]() |
4fae03d105 | ||
![]() |
c0f5a31401 | ||
![]() |
5af252eaf1 | ||
![]() |
61904280a3 | ||
![]() |
51f3d7e438 | ||
![]() |
561b2797e8 | ||
![]() |
5525303946 | ||
![]() |
7f6c774bf5 | ||
![]() |
fd255364b3 | ||
![]() |
478973eb3c | ||
![]() |
8fd572d449 | ||
![]() |
7b82ff68e1 | ||
![]() |
7fc2033c9b | ||
![]() |
ff9a8284b4 | ||
![]() |
c25e4c8973 | ||
![]() |
dce906465d | ||
![]() |
53e5e0eb90 | ||
![]() |
ce656ef7c6 | ||
![]() |
fb2f32eb72 | ||
![]() |
917a7b93ce | ||
![]() |
c838158e04 | ||
![]() |
17f7a7b467 | ||
![]() |
e78edd9b94 | ||
![]() |
d13e29cdaf | ||
![]() |
daee939714 | ||
![]() |
44c152ccd0 | ||
![]() |
dfc218c452 | ||
![]() |
9fc60a0c00 | ||
![]() |
f3e36f593b | ||
![]() |
b62375b554 | ||
![]() |
056d3bfa30 |
34
.travis.yml
34
.travis.yml
|
@ -11,18 +11,6 @@ script:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./.travis/build-debian.sh; fi
|
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./.travis/build-debian.sh; fi
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./.travis/build-macos.sh; fi
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./.travis/build-macos.sh; fi
|
||||||
deploy:
|
deploy:
|
||||||
# Releases to solvespace/solvespace
|
|
||||||
- provider: releases
|
|
||||||
api_key:
|
|
||||||
secure: dDlkIawHcODlW9B/20/cQCtzeoocvs0hKuNngRKXKqzXLWTRq33oq/B7+39tAixWbmv6exTpijiKrRNFiSCW5Z4iwHLwaRD4XJznxw63e/Hus/dxg2Tvqx7XFpkCz8mT1Z+gZQE5YxAngeZPpI/sZbZtF1UO3yH5eLeeokZ15p26ZskQUPoYuzrTgTzYL3XfpG3F+20rNBawH1ycsCTVD/08/n31d2m3CrKAsbW7er92ek6w4fzKr7NW8WeXjrPJETVpw5fQg1Od3pRGW8dPQaJcvKQEogMp8Mm0ETYd0qigg89/giBz7QwOgmAWQ4dH+DfZH4Ojl//127QztBolMvyDMQBykWrtJoGcij05sT6K2IJr2FHeUBO12MAEdjiVvhQj3DtTzjPiZAHHDBSLWxLKWWhlhHE4pq7g1MQhqXkaAHI2BLNzwLmaowbMT0bECf9yfz6xx18h6XPQFX44oOktraobVALFlyHqeKa8zdcUt22LF6uAL1m5dxL0tny3eXCIPE4UH/RZgua/cHV9G3cUvKQa/QnFSLRhvWVSbGB+7YsHouBJcsUOOW1gmd5442XuC7mpppccRldh+GSxUk6TBJRAx7TeQ0ybDUaoco9MUqp2twv3KreR2+8Q12PDaAhfQVNEGdF3wTm1sShImjCN4VN3eSLlBEbve1QRQXM=
|
|
||||||
skip_cleanup: true
|
|
||||||
file_glob: true
|
|
||||||
file:
|
|
||||||
- ../*.deb
|
|
||||||
on:
|
|
||||||
repo: solvespace/solvespace
|
|
||||||
tags: true
|
|
||||||
condition: "$TRAVIS_OS_NAME == linux"
|
|
||||||
- provider: releases
|
- provider: releases
|
||||||
api_key:
|
api_key:
|
||||||
secure: dDlkIawHcODlW9B/20/cQCtzeoocvs0hKuNngRKXKqzXLWTRq33oq/B7+39tAixWbmv6exTpijiKrRNFiSCW5Z4iwHLwaRD4XJznxw63e/Hus/dxg2Tvqx7XFpkCz8mT1Z+gZQE5YxAngeZPpI/sZbZtF1UO3yH5eLeeokZ15p26ZskQUPoYuzrTgTzYL3XfpG3F+20rNBawH1ycsCTVD/08/n31d2m3CrKAsbW7er92ek6w4fzKr7NW8WeXjrPJETVpw5fQg1Od3pRGW8dPQaJcvKQEogMp8Mm0ETYd0qigg89/giBz7QwOgmAWQ4dH+DfZH4Ojl//127QztBolMvyDMQBykWrtJoGcij05sT6K2IJr2FHeUBO12MAEdjiVvhQj3DtTzjPiZAHHDBSLWxLKWWhlhHE4pq7g1MQhqXkaAHI2BLNzwLmaowbMT0bECf9yfz6xx18h6XPQFX44oOktraobVALFlyHqeKa8zdcUt22LF6uAL1m5dxL0tny3eXCIPE4UH/RZgua/cHV9G3cUvKQa/QnFSLRhvWVSbGB+7YsHouBJcsUOOW1gmd5442XuC7mpppccRldh+GSxUk6TBJRAx7TeQ0ybDUaoco9MUqp2twv3KreR2+8Q12PDaAhfQVNEGdF3wTm1sShImjCN4VN3eSLlBEbve1QRQXM=
|
secure: dDlkIawHcODlW9B/20/cQCtzeoocvs0hKuNngRKXKqzXLWTRq33oq/B7+39tAixWbmv6exTpijiKrRNFiSCW5Z4iwHLwaRD4XJznxw63e/Hus/dxg2Tvqx7XFpkCz8mT1Z+gZQE5YxAngeZPpI/sZbZtF1UO3yH5eLeeokZ15p26ZskQUPoYuzrTgTzYL3XfpG3F+20rNBawH1ycsCTVD/08/n31d2m3CrKAsbW7er92ek6w4fzKr7NW8WeXjrPJETVpw5fQg1Od3pRGW8dPQaJcvKQEogMp8Mm0ETYd0qigg89/giBz7QwOgmAWQ4dH+DfZH4Ojl//127QztBolMvyDMQBykWrtJoGcij05sT6K2IJr2FHeUBO12MAEdjiVvhQj3DtTzjPiZAHHDBSLWxLKWWhlhHE4pq7g1MQhqXkaAHI2BLNzwLmaowbMT0bECf9yfz6xx18h6XPQFX44oOktraobVALFlyHqeKa8zdcUt22LF6uAL1m5dxL0tny3eXCIPE4UH/RZgua/cHV9G3cUvKQa/QnFSLRhvWVSbGB+7YsHouBJcsUOOW1gmd5442XuC7mpppccRldh+GSxUk6TBJRAx7TeQ0ybDUaoco9MUqp2twv3KreR2+8Q12PDaAhfQVNEGdF3wTm1sShImjCN4VN3eSLlBEbve1QRQXM=
|
||||||
|
@ -32,25 +20,3 @@ deploy:
|
||||||
repo: solvespace/solvespace
|
repo: solvespace/solvespace
|
||||||
tags: true
|
tags: true
|
||||||
condition: "$TRAVIS_OS_NAME == osx"
|
condition: "$TRAVIS_OS_NAME == osx"
|
||||||
# Releases to whitequark/solvespace (to be removed)
|
|
||||||
- provider: releases
|
|
||||||
api_key:
|
|
||||||
secure: DA3tW0My37vbi2t3dZ061281Xm8KSIkeLdFZsQISrut0g1kkbWuBTPxAfvE3B6OE8p47wAclE/wxA1+obMTVkY0oYpd5u+JelYNHxU/oL8Ww0xdUANwKNJ1JD2EZP8nSz7JSvxuGILC6AFPoTjawsG97SXwiTyp7z0PA6nvzraE=
|
|
||||||
skip_cleanup: true
|
|
||||||
file_glob: true
|
|
||||||
file:
|
|
||||||
- ../*.deb
|
|
||||||
on:
|
|
||||||
repo: whitequark/solvespace
|
|
||||||
tags: true
|
|
||||||
condition: "$TRAVIS_OS_NAME == linux"
|
|
||||||
- provider: releases
|
|
||||||
api_key:
|
|
||||||
secure: DA3tW0My37vbi2t3dZ061281Xm8KSIkeLdFZsQISrut0g1kkbWuBTPxAfvE3B6OE8p47wAclE/wxA1+obMTVkY0oYpd5u+JelYNHxU/oL8Ww0xdUANwKNJ1JD2EZP8nSz7JSvxuGILC6AFPoTjawsG97SXwiTyp7z0PA6nvzraE=
|
|
||||||
skip_cleanup: true
|
|
||||||
file: build/solvespace.dmg
|
|
||||||
on:
|
|
||||||
repo: whitequark/solvespace
|
|
||||||
tags: true
|
|
||||||
condition: "$TRAVIS_OS_NAME == osx"
|
|
||||||
|
|
||||||
|
|
|
@ -2,5 +2,7 @@
|
||||||
|
|
||||||
if echo $TRAVIS_TAG | grep ^v; then BUILD_TYPE=RelWithDebInfo; else BUILD_TYPE=Debug; fi
|
if echo $TRAVIS_TAG | grep ^v; then BUILD_TYPE=RelWithDebInfo; else BUILD_TYPE=Debug; fi
|
||||||
|
|
||||||
export BUILD_TYPE
|
mkdir build
|
||||||
dpkg-buildpackage -b -us -uc
|
cd build
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||||
|
make VERBOSE=1
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#!/bin/sh -xe
|
#!/bin/sh -xe
|
||||||
|
|
||||||
brew update
|
brew update
|
||||||
brew upgrade cmake libpng
|
|
||||||
|
|
127
CHANGELOG.md
Normal file
127
CHANGELOG.md
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
Changelog
|
||||||
|
=========
|
||||||
|
|
||||||
|
2.3
|
||||||
|
---
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
* Do not crash when applying a symmetry constraint to two points.
|
||||||
|
* Fix TTF font metrics again (properly this time).
|
||||||
|
* Fix the "draw back faces in red" option.
|
||||||
|
* Fix export of wireframe as 3D DXF.
|
||||||
|
* Various minor crashes.
|
||||||
|
|
||||||
|
2.2
|
||||||
|
---
|
||||||
|
|
||||||
|
Other new features:
|
||||||
|
* OS X: support 3Dconnexion devices (SpaceMouse, SpaceNavigator, etc).
|
||||||
|
* GTK: files with uppercase extensions can be opened.
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
* Do not remove autosaves after successfully opening a file, preventing
|
||||||
|
data loss in case of two abnormal terminations in a row.
|
||||||
|
* Do not crash when changing autosave interval.
|
||||||
|
* Unbreak the "Show degrees of freedom" command.
|
||||||
|
* Three.js: correctly respond to controls when browser zoom is used.
|
||||||
|
* OS X: do not completely hide main window when defocused.
|
||||||
|
* GTK: unbreak 3Dconnexion support.
|
||||||
|
* When pasting transformed entities, multiply constraint values by scale.
|
||||||
|
* Fix TTF font metrics (restore the behavior from version 2.0).
|
||||||
|
* Forcibly show the current group once we start a drawing operation.
|
||||||
|
* DXF export: always declare layers before using them.
|
||||||
|
* Do not truncate operations on selections to first 32 selected entities.
|
||||||
|
* Translate and rotate groups inherit the "suppress solid model" setting.
|
||||||
|
* DXF: files with paths containing non-ASCII or spaces can be exported
|
||||||
|
or imported.
|
||||||
|
* Significantly improved performance when dragging an entity.
|
||||||
|
* Various crashes and minor glitches.
|
||||||
|
|
||||||
|
2.1
|
||||||
|
---
|
||||||
|
|
||||||
|
New sketch features:
|
||||||
|
* Lathe groups create circle and face entities.
|
||||||
|
* New toolbar button for creating lathe groups.
|
||||||
|
* Chord tolerance is separated into two: display chord tolerance (specified
|
||||||
|
in percents, relative to model bounding box), and export chord tolerance
|
||||||
|
(specified in millimeters as absolute value).
|
||||||
|
* Bezier spline points can be added and removed after the spline is created.
|
||||||
|
* When an unconstrained extrusion is switched between "union" and
|
||||||
|
"difference", its normal is flipped.
|
||||||
|
* Groups can be added in the middle of the stack. Note that this results
|
||||||
|
in files incompatible with version 2.0.
|
||||||
|
* Active group can be removed.
|
||||||
|
* Removing an imported group does not cause all subsequent groups to also
|
||||||
|
be removed.
|
||||||
|
* When a new group with a solid is created, the color is taken from
|
||||||
|
a previous group with a solid, if any.
|
||||||
|
* Entities in a newly active group do not become visible.
|
||||||
|
* When entities are selected, "Zoom to fit" zooms to fit only these
|
||||||
|
entities and not the entire sketch.
|
||||||
|
* Zero-length edges are reported with a "zero-length error", not
|
||||||
|
"points not all coplanar".
|
||||||
|
|
||||||
|
New constraint features:
|
||||||
|
* Height of the font used for drawing constraint labels can be changed.
|
||||||
|
* New constraint, length difference, placed with J.
|
||||||
|
(Patch by Peter Ruevski)
|
||||||
|
* Horizontal/vertical constraints are automatically added if a line segment
|
||||||
|
is close enough to being horizontal/vertical. This can be disabled by
|
||||||
|
holding Ctrl.
|
||||||
|
* Reference dimensions and angles can be placed with Shift+D and Shift+N.
|
||||||
|
* Copying and pasting entities duplicates any constraints that only involve
|
||||||
|
entities in the clipboard, as well as selected comments.
|
||||||
|
* Diameter constraints can be shown as radius.
|
||||||
|
* The "pi" identifier can be used in expressions.
|
||||||
|
* Constraint labels can be snapped to grid.
|
||||||
|
* Integer angles are displayed without trailing zeroes.
|
||||||
|
* Angle constraints have proper reference lines and arrowheads.
|
||||||
|
* Extension lines are drawn for point-line distance constraints.
|
||||||
|
|
||||||
|
New solver features:
|
||||||
|
* Sketches with redundant and unsolvable constraints are distinguished.
|
||||||
|
* New group setting, "allow redundant constraints". Note that it makes
|
||||||
|
the solver less stable.
|
||||||
|
|
||||||
|
New rendering and styling features:
|
||||||
|
* New line style parameter: stippling, based on ISO 128.
|
||||||
|
* Outlines of solids can be drawn in a particular style (by default, thick
|
||||||
|
lines) controlled by the "Show outline of solid model" button.
|
||||||
|
* Occluded edges can be drawn in a particular style (by default, stippled
|
||||||
|
with short dashes) controlled by the "Show hidden lines" button.
|
||||||
|
* Solids can be made transparent.
|
||||||
|
|
||||||
|
New export/import features:
|
||||||
|
* The old "import" command (for .slvs files) is renamed to "link".
|
||||||
|
* If a linked .slvs file is not found, first the relative path recorded
|
||||||
|
in the .slvs file is checked and then the absolute path; this is
|
||||||
|
an inversion of the previously used order. If it is still not found,
|
||||||
|
a dialog appears offering to locate it.
|
||||||
|
* DXF and DWG files can be imported, with point-coincident, horizontal and
|
||||||
|
vertical constraints automatically inferred from geometry, and distance
|
||||||
|
and angle constraints created when a dimension placed against geometry
|
||||||
|
exists.
|
||||||
|
* Triangle mesh can be exported for viewing in the browser through WebGL.
|
||||||
|
* Export dialogs remember the last file format used, and preselect it.
|
||||||
|
* Exported DXF files have exact circles, arcs and splines instead of
|
||||||
|
a piecewise linear approximation (unless hidden line removal was needed).
|
||||||
|
* Exported DXF files preserve color and line thickness.
|
||||||
|
* In exported DXF files, constraints are represented as DXF dimensions,
|
||||||
|
instead of piecewise linear geometry.
|
||||||
|
* When exporting 2d views, overlapping lines are removed.
|
||||||
|
|
||||||
|
Other new features:
|
||||||
|
* Native Linux (GTK 2 and GTK 3) and Mac OS X ports.
|
||||||
|
* Automatically save and then restore sketches if SolveSpace crashes.
|
||||||
|
(Patch by Marc Britten)
|
||||||
|
* Unicode is supported everywhere (filenames, group names, TTF text,
|
||||||
|
comments), although RTL scripts and scripts making heavy use of ligatures
|
||||||
|
are not rendered correctly.
|
||||||
|
* The vector font is grid-fitted when rendered on screen to make it easier
|
||||||
|
to read regardless of its size.
|
||||||
|
|
||||||
|
2.0
|
||||||
|
---
|
||||||
|
|
||||||
|
Initial public release.
|
|
@ -17,11 +17,16 @@ set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX
|
||||||
|
|
||||||
# project
|
# project
|
||||||
|
|
||||||
|
# NOTE TO PACKAGERS: The embedded git commit hash is critical for rapid bug triage when the builds
|
||||||
|
# can come from a variety of sources. If you are mirroring the sources or otherwise build when
|
||||||
|
# the .git directory is not present, please comment the following line:
|
||||||
include(GetGitCommitHash)
|
include(GetGitCommitHash)
|
||||||
|
# and instead uncomment the following, adding the complete git hash of the checkout you are using:
|
||||||
|
# set(GIT_COMMIT_HASH 0000000000000000000000000000000000000000)
|
||||||
|
|
||||||
project(solvespace)
|
project(solvespace)
|
||||||
set(solvespace_VERSION_MAJOR 2)
|
set(solvespace_VERSION_MAJOR 2)
|
||||||
set(solvespace_VERSION_MINOR 1)
|
set(solvespace_VERSION_MINOR 3)
|
||||||
string(SUBSTRING "${GIT_COMMIT_HASH}" 0 8 solvespace_GIT_HASH)
|
string(SUBSTRING "${GIT_COMMIT_HASH}" 0 8 solvespace_GIT_HASH)
|
||||||
|
|
||||||
if(NOT WIN32 AND NOT APPLE)
|
if(NOT WIN32 AND NOT APPLE)
|
||||||
|
@ -154,6 +159,8 @@ if(WIN32)
|
||||||
"${CMAKE_SOURCE_DIR}/extlib/si/siapp.lib")
|
"${CMAKE_SOURCE_DIR}/extlib/si/siapp.lib")
|
||||||
endif()
|
endif()
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
|
set(CMAKE_FIND_FRAMEWORK LAST)
|
||||||
|
|
||||||
find_package(PNG REQUIRED)
|
find_package(PNG REQUIRED)
|
||||||
find_package(Freetype REQUIRED)
|
find_package(Freetype REQUIRED)
|
||||||
find_library(APPKIT_LIBRARY AppKit REQUIRED)
|
find_library(APPKIT_LIBRARY AppKit REQUIRED)
|
||||||
|
|
|
@ -26,12 +26,13 @@ Building on Linux
|
||||||
### Building for Linux
|
### Building for Linux
|
||||||
|
|
||||||
You will need CMake, libpng, zlib, json-c, fontconfig, freetype, gtkmm 2.4,
|
You will need CMake, libpng, zlib, json-c, fontconfig, freetype, gtkmm 2.4,
|
||||||
pangomm 1.4, OpenGL and OpenGL GLU.
|
pangomm 1.4, OpenGL, OpenGL GLU and OpenGL GLEW, and optionally, the Space Navigator
|
||||||
|
client library.
|
||||||
On a Debian derivative (e.g. Ubuntu) these can be installed with:
|
On a Debian derivative (e.g. Ubuntu) these can be installed with:
|
||||||
|
|
||||||
apt-get install libpng12-dev libjson-c-dev libfreetype6-dev \
|
apt-get install libpng12-dev libjson-c-dev libfreetype6-dev \
|
||||||
libfontconfig1-dev libgtkmm-2.4-dev libpangomm-1.4-dev \
|
libfontconfig1-dev libgtkmm-2.4-dev libpangomm-1.4-dev \
|
||||||
libgl-dev libglu-dev libglew-dev cmake
|
libgl-dev libglu-dev libglew-dev libspnav-dev cmake
|
||||||
|
|
||||||
Before building, check out the necessary submodules:
|
Before building, check out the necessary submodules:
|
||||||
|
|
||||||
|
|
11
appveyor.yml
11
appveyor.yml
|
@ -1,4 +1,4 @@
|
||||||
version: 2.1.{build}
|
version: 2.2.{build}
|
||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
before_build:
|
before_build:
|
||||||
- git submodule update --init
|
- git submodule update --init
|
||||||
|
@ -19,7 +19,6 @@ artifacts:
|
||||||
- path: build\src\RelWithDebInfo\solvespace.pdb
|
- path: build\src\RelWithDebInfo\solvespace.pdb
|
||||||
name: solvespace.pdb
|
name: solvespace.pdb
|
||||||
deploy:
|
deploy:
|
||||||
# Releases to solvespace/solvespace
|
|
||||||
- provider: GitHub
|
- provider: GitHub
|
||||||
auth_token:
|
auth_token:
|
||||||
secure: P9/pf2nM+jlWKe7pCjMp41HycBNP/+5AsmE/TETrDUoBOa/9WFHelqdVFrbRn9IC
|
secure: P9/pf2nM+jlWKe7pCjMp41HycBNP/+5AsmE/TETrDUoBOa/9WFHelqdVFrbRn9IC
|
||||||
|
@ -27,11 +26,3 @@ deploy:
|
||||||
artifact: solvespace.exe
|
artifact: solvespace.exe
|
||||||
on:
|
on:
|
||||||
appveyor_repo_tag: true
|
appveyor_repo_tag: true
|
||||||
# Releases to whitequark/solvespace (to be removed)
|
|
||||||
- provider: GitHub
|
|
||||||
auth_token:
|
|
||||||
secure: Flqxu1cz6PyxVT1wzTP4bSrQOY8wFrO7pJxYxvjEkLqIUU4dsDQrs2rac/A9deet
|
|
||||||
description: ""
|
|
||||||
artifact: solvespace.exe
|
|
||||||
on:
|
|
||||||
appveyor_repo_tag: true
|
|
||||||
|
|
5
debian/changelog
vendored
5
debian/changelog
vendored
|
@ -1,5 +0,0 @@
|
||||||
solvespace (2.1) unstable; urgency=low
|
|
||||||
|
|
||||||
* Initial Release.
|
|
||||||
|
|
||||||
-- whitequark <whitequark@whitequark.org> Fri, 20 Mar 2015 12:39:28 +0300
|
|
1
debian/compat
vendored
1
debian/compat
vendored
|
@ -1 +0,0 @@
|
||||||
9
|
|
73
debian/control
vendored
73
debian/control
vendored
|
@ -1,73 +0,0 @@
|
||||||
Source: solvespace
|
|
||||||
Section: graphics
|
|
||||||
Priority: optional
|
|
||||||
Maintainer: whitequark <whitequark@whitequark.org>
|
|
||||||
Build-Depends: debhelper (>= 9), cmake, libpng12-dev, zlib1g-dev, libjson-c-dev,
|
|
||||||
libfontconfig1-dev, libgtkmm-2.4-dev, libpangomm-1.4-dev,
|
|
||||||
libgl-dev, libglu-dev, libglew-dev
|
|
||||||
Standards-Version: 3.9.5
|
|
||||||
Homepage: http://solvespace.com
|
|
||||||
Vcs-Git: git://github.com/whitequark/solvespace
|
|
||||||
Vcs-Browser: https://github.com/whitequark/solvespace
|
|
||||||
|
|
||||||
Package: solvespace
|
|
||||||
Architecture: any
|
|
||||||
Multi-Arch: foreign
|
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
|
||||||
Description: SolveSpace parametric 2d/3d CAD
|
|
||||||
SolveSpace is a parametric 2d/3d CAD program. Applications include:
|
|
||||||
.
|
|
||||||
* modeling 3d parts — draw with extrudes, revolves, and Boolean
|
|
||||||
(union / difference) operations;
|
|
||||||
* modeling 2d parts — draw the part as a single section, and export DXF,
|
|
||||||
PDF, SVG; use 3d assembly to verify fit;
|
|
||||||
* 3d-printed parts — export the STL or other triangle mesh expected by
|
|
||||||
most 3d printers;
|
|
||||||
* preparing CAM data — export 2d vector art for a waterjet machine or
|
|
||||||
laser cutter; or generate STEP or STL, for import into third-party
|
|
||||||
CAM software for machining;
|
|
||||||
* mechanism design — use the constraint solver to simulate planar or
|
|
||||||
spatial linkages, with pin, ball, or slide joints;
|
|
||||||
* plane and solid geometry — replace hand-solved trigonometry and
|
|
||||||
spreadsheets with a live dimensioned drawing.
|
|
||||||
|
|
||||||
Package: solvespace-dbg
|
|
||||||
Architecture: any
|
|
||||||
Section: debug
|
|
||||||
Priority: extra
|
|
||||||
Depends: solvespace (= ${binary:Version}), ${misc:Depends}
|
|
||||||
Description: SolveSpace parametric 2d/3d CAD (debugging files)
|
|
||||||
SolveSpace is a parametric 2d/3d CAD.
|
|
||||||
.
|
|
||||||
This package contains the debugging symbols for solvespace.
|
|
||||||
|
|
||||||
Package: libslvs1
|
|
||||||
Section: libs
|
|
||||||
Architecture: any
|
|
||||||
Multi-Arch: same
|
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
|
||||||
Description: SolveSpace geometric kernel
|
|
||||||
SolveSpace is a parametric 2d/3d CAD. libslvs contains the geometric
|
|
||||||
kernel of SolveSpace, built as a library.
|
|
||||||
|
|
||||||
Package: libslvs1-dev
|
|
||||||
Section: libs
|
|
||||||
Architecture: any
|
|
||||||
Multi-Arch: same
|
|
||||||
Depends: libslvs1, ${misc:Depends}
|
|
||||||
Description: SolveSpace geometric kernel (development files)
|
|
||||||
SolveSpace is a parametric 2d/3d CAD. libslvs contains the geometric
|
|
||||||
kernel of SolveSpace, built as a library.
|
|
||||||
.
|
|
||||||
This package includes development files for libslvs.
|
|
||||||
|
|
||||||
Package: libslvs1-dbg
|
|
||||||
Architecture: any
|
|
||||||
Section: debug
|
|
||||||
Priority: extra
|
|
||||||
Depends: libslvs1 (= ${binary:Version}), ${misc:Depends}
|
|
||||||
Description: SolveSpace geometric kernel (debugging files)
|
|
||||||
SolveSpace is a parametric 2d/3d CAD. libslvs contains the geometric
|
|
||||||
kernel of SolveSpace, built as a library.
|
|
||||||
.
|
|
||||||
This package contains the debugging symbols for libslvs1.
|
|
33
debian/copyright
vendored
33
debian/copyright
vendored
|
@ -1,33 +0,0 @@
|
||||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
|
||||||
Upstream-Name: solvespace
|
|
||||||
Source: https://github.com/whitequark/solvespace
|
|
||||||
|
|
||||||
Files: *
|
|
||||||
Copyright: 2008-2013 Jonathan Westhues.
|
|
||||||
License: GPL-3.0+
|
|
||||||
|
|
||||||
Files: debian/*
|
|
||||||
Copyright: 2015 Peter Zotov <whitequark@whitequark.org>
|
|
||||||
License: GPL-3.0+
|
|
||||||
|
|
||||||
License: GPL-3.0+
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
.
|
|
||||||
This package is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
.
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
.
|
|
||||||
On Debian systems, the complete text of the GNU General
|
|
||||||
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
|
|
||||||
|
|
||||||
# Please also look if there are files or directories which have a
|
|
||||||
# different copyright/license attached and list them here.
|
|
||||||
# Please avoid to pick license terms that are more restrictive than the
|
|
||||||
# packaged work, as it may make Debian's contributions unacceptable upstream.
|
|
2
debian/docs
vendored
2
debian/docs
vendored
|
@ -1,2 +0,0 @@
|
||||||
COPYING.txt
|
|
||||||
README.md
|
|
1
debian/libslvs1-dev.install
vendored
1
debian/libslvs1-dev.install
vendored
|
@ -1 +0,0 @@
|
||||||
usr/include/slvs.h
|
|
1
debian/libslvs1.install
vendored
1
debian/libslvs1.install
vendored
|
@ -1 +0,0 @@
|
||||||
usr/lib/**/libslvs.so*
|
|
7
debian/menu
vendored
7
debian/menu
vendored
|
@ -1,7 +0,0 @@
|
||||||
?package(solvespace):needs="X11" section="Applications/Graphics" \
|
|
||||||
title="SolveSpace" command="/usr/bin/solvespace" \
|
|
||||||
hints="CAD" \
|
|
||||||
icon16x16="/usr/share/pixmaps/solvespace-16x16.xpm" \
|
|
||||||
icon24x24="/usr/share/pixmaps/solvespace-24x24.xpm" \
|
|
||||||
icon32x32="/usr/share/pixmaps/solvespace-32x32.xpm" \
|
|
||||||
icon48x48="/usr/share/pixmaps/solvespace-48x48.xpm"
|
|
24
debian/rules
vendored
24
debian/rules
vendored
|
@ -1,24 +0,0 @@
|
||||||
#!/usr/bin/make -f
|
|
||||||
# See debhelper(7) (uncomment to enable)
|
|
||||||
# output every command that modifies files on the build system.
|
|
||||||
#DH_VERBOSE = 1
|
|
||||||
|
|
||||||
# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*
|
|
||||||
DPKG_EXPORT_BUILDFLAGS = 1
|
|
||||||
include /usr/share/dpkg/default.mk
|
|
||||||
|
|
||||||
# main packaging script based on dh7 syntax
|
|
||||||
%:
|
|
||||||
dh $@
|
|
||||||
|
|
||||||
# debmake generated override targets
|
|
||||||
# This is example for Cmake (See http://bugs.debian.org/641051 )
|
|
||||||
override_dh_auto_configure:
|
|
||||||
dh_auto_configure -- \
|
|
||||||
-DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH) \
|
|
||||||
-DCMAKE_BUILD_TYPE=$(BUILD_TYPE)
|
|
||||||
|
|
||||||
# create a -dbg package
|
|
||||||
override_dh_strip:
|
|
||||||
dh_strip -psolvespace --dbg-package=solvespace-dbg
|
|
||||||
dh_strip -plibslvs1 --dbg-package=libslvs1-dbg
|
|
3
debian/solvespace.install
vendored
3
debian/solvespace.install
vendored
|
@ -1,3 +0,0 @@
|
||||||
usr/bin/solvespace
|
|
||||||
usr/share/icons
|
|
||||||
usr/share/applications
|
|
8
debian/solvespace.sharedmimeinfo
vendored
8
debian/solvespace.sharedmimeinfo
vendored
|
@ -1,8 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
|
|
||||||
<mime-type type="application/x-solvespace">
|
|
||||||
<comment>SolveSpace sketch</comment>
|
|
||||||
<glob pattern="*.slvs"/>
|
|
||||||
<generic-icon name="x-office-document"/>
|
|
||||||
</mime-type>
|
|
||||||
</mime-info>
|
|
1
debian/source/format
vendored
1
debian/source/format
vendored
|
@ -1 +0,0 @@
|
||||||
3.0 (native)
|
|
3
debian/source/options
vendored
3
debian/source/options
vendored
|
@ -1,3 +0,0 @@
|
||||||
tar-ignore = "*.sublime-*"
|
|
||||||
tar-ignore = "build*"
|
|
||||||
tar-ignore = ".git"
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8d24e656fbd293cb953828389d01d362f2a1a8e0
|
Subproject commit 8f958955f54668c142ded760dc951ffd16d9c71b
|
|
@ -342,8 +342,9 @@ if(APPLE)
|
||||||
set(fixups)
|
set(fixups)
|
||||||
foreach(lib ${platform_BUNDLED_LIBS})
|
foreach(lib ${platform_BUNDLED_LIBS})
|
||||||
get_filename_component(name ${lib} NAME)
|
get_filename_component(name ${lib} NAME)
|
||||||
execute_process(COMMAND otool -XD ${lib}
|
execute_process(COMMAND otool -D ${lib}
|
||||||
OUTPUT_VARIABLE canonical_lib OUTPUT_STRIP_TRAILING_WHITESPACE)
|
OUTPUT_VARIABLE canonical_lib OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
string(REGEX REPLACE "^.+:\n" "" canonical_lib ${canonical_lib})
|
||||||
add_custom_command(TARGET solvespace POST_BUILD
|
add_custom_command(TARGET solvespace POST_BUILD
|
||||||
COMMAND install_name_tool -change ${canonical_lib} @executable_path/${name}
|
COMMAND install_name_tool -change ${canonical_lib} @executable_path/${name}
|
||||||
$<TARGET_FILE:solvespace>
|
$<TARGET_FILE:solvespace>
|
||||||
|
@ -380,6 +381,10 @@ foreach(SIZE 16x16 24x24 32x32 48x48)
|
||||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}/mimetypes
|
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}/mimetypes
|
||||||
RENAME application.x-solvespace.png)
|
RENAME application.x-solvespace.png)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
foreach(SIZE 16x16 24x24 32x32 48x48)
|
||||||
|
install(FILES unix/solvespace-${SIZE}.xpm
|
||||||
|
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pixmaps/)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
# valgrind
|
# valgrind
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,15 @@ void GraphicsWindow::CopySelection(void) {
|
||||||
SS.clipboard.r.Add(&cr);
|
SS.clipboard.r.Add(&cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(Selection *s = ls->First(); s; s = ls->NextAfter(s)) {
|
||||||
|
if(!s->constraint.v) continue;
|
||||||
|
|
||||||
|
Constraint *c = SK.GetConstraint(s->constraint);
|
||||||
|
if(c->type == Constraint::COMMENT) {
|
||||||
|
SS.clipboard.c.Add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Constraint *c;
|
Constraint *c;
|
||||||
for(c = SK.constraint.First(); c; c = SK.constraint.NextAfter(c)) {
|
for(c = SK.constraint.First(); c; c = SK.constraint.NextAfter(c)) {
|
||||||
if(!SS.clipboard.ContainsEntity(c->ptA) ||
|
if(!SS.clipboard.ContainsEntity(c->ptA) ||
|
||||||
|
@ -124,7 +133,8 @@ void GraphicsWindow::CopySelection(void) {
|
||||||
!SS.clipboard.ContainsEntity(c->entityA) ||
|
!SS.clipboard.ContainsEntity(c->entityA) ||
|
||||||
!SS.clipboard.ContainsEntity(c->entityB) ||
|
!SS.clipboard.ContainsEntity(c->entityB) ||
|
||||||
!SS.clipboard.ContainsEntity(c->entityC) ||
|
!SS.clipboard.ContainsEntity(c->entityC) ||
|
||||||
!SS.clipboard.ContainsEntity(c->entityD)) {
|
!SS.clipboard.ContainsEntity(c->entityD) ||
|
||||||
|
c->type == Constraint::COMMENT) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SS.clipboard.c.Add(c);
|
SS.clipboard.c.Add(c);
|
||||||
|
@ -201,7 +211,27 @@ void GraphicsWindow::PasteClipboard(Vector trans, double theta, double scale) {
|
||||||
c.other2 = cc->other2;
|
c.other2 = cc->other2;
|
||||||
c.reference = cc->reference;
|
c.reference = cc->reference;
|
||||||
c.disp = cc->disp;
|
c.disp = cc->disp;
|
||||||
Constraint::AddConstraint(&c, /*rememberForUndo=*/false);
|
c.comment = cc->comment;
|
||||||
|
switch(c.type) {
|
||||||
|
case Constraint::COMMENT:
|
||||||
|
c.disp.offset = c.disp.offset.Plus(trans);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Constraint::PT_PT_DISTANCE:
|
||||||
|
case Constraint::PT_LINE_DISTANCE:
|
||||||
|
case Constraint::PROJ_PT_DISTANCE:
|
||||||
|
case Constraint::DIAMETER:
|
||||||
|
c.valA *= fabs(scale);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
hConstraint hc = Constraint::AddConstraint(&c, /*rememberForUndo=*/false);
|
||||||
|
if(c.type == Constraint::COMMENT) {
|
||||||
|
MakeSelected(hc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SS.ScheduleGenerateAll();
|
SS.ScheduleGenerateAll();
|
||||||
|
|
|
@ -221,6 +221,9 @@ CONVERT(Rect)
|
||||||
|
|
||||||
CGContextDrawImage((CGContextRef) [[NSGraphicsContext currentContext] graphicsPort],
|
CGContextDrawImage((CGContextRef) [[NSGraphicsContext currentContext] graphicsPort],
|
||||||
[self bounds], image);
|
[self bounds], image);
|
||||||
|
|
||||||
|
CGImageRelease(image);
|
||||||
|
CGDataProviderRelease(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)drawGL {
|
- (void)drawGL {
|
||||||
|
@ -371,8 +374,6 @@ CONVERT(Rect)
|
||||||
if(NSString *nsChr = [event charactersIgnoringModifiers])
|
if(NSString *nsChr = [event charactersIgnoringModifiers])
|
||||||
chr = [nsChr characterAtIndex:0];
|
chr = [nsChr characterAtIndex:0];
|
||||||
|
|
||||||
if(chr == NSDeleteCharacter) /* map delete back to backspace */
|
|
||||||
chr = '\b';
|
|
||||||
if(chr >= NSF1FunctionKey && chr <= NSF12FunctionKey)
|
if(chr >= NSF1FunctionKey && chr <= NSF12FunctionKey)
|
||||||
chr = SolveSpace::GraphicsWindow::FUNCTION_KEY_BASE + (chr - NSF1FunctionKey);
|
chr = SolveSpace::GraphicsWindow::FUNCTION_KEY_BASE + (chr - NSF1FunctionKey);
|
||||||
|
|
||||||
|
@ -397,7 +398,7 @@ CONVERT(Rect)
|
||||||
.x = xy.x + size.width / 2,
|
.x = xy.x + size.width / 2,
|
||||||
.y = xy.y - size.height / 2
|
.y = xy.y - size.height / 2
|
||||||
};
|
};
|
||||||
[[self window] becomeKeyWindow];
|
[[self window] makeKeyWindow];
|
||||||
[super startEditing:text at:[self convertPointFromBacking:point]
|
[super startEditing:text at:[self convertPointFromBacking:point]
|
||||||
withHeight:fontHeight usingMonospace:FALSE];
|
withHeight:fontHeight usingMonospace:FALSE];
|
||||||
[self prepareEditorWithMinWidthInChars:minWidthChars];
|
[self prepareEditorWithMinWidthInChars:minWidthChars];
|
||||||
|
@ -647,12 +648,15 @@ void InitMainMenu(NSMenu *mainMenu) {
|
||||||
label = [[NSString stringWithUTF8String:entry->label]
|
label = [[NSString stringWithUTF8String:entry->label]
|
||||||
stringByReplacingOccurrencesOfString:@"&" withString:@""];
|
stringByReplacingOccurrencesOfString:@"&" withString:@""];
|
||||||
|
|
||||||
unichar accel_char = entry->accel &
|
unichar accelChar = entry->accel &
|
||||||
~(GraphicsWindow::SHIFT_MASK | GraphicsWindow::CTRL_MASK);
|
~(GraphicsWindow::SHIFT_MASK | GraphicsWindow::CTRL_MASK);
|
||||||
if(accel_char > GraphicsWindow::FUNCTION_KEY_BASE &&
|
if(accelChar > GraphicsWindow::FUNCTION_KEY_BASE &&
|
||||||
accel_char <= GraphicsWindow::FUNCTION_KEY_BASE + 12)
|
accelChar <= GraphicsWindow::FUNCTION_KEY_BASE + 12) {
|
||||||
accel_char = NSF1FunctionKey + (accel_char - GraphicsWindow::FUNCTION_KEY_BASE - 1);
|
accelChar = NSF1FunctionKey + (accelChar - GraphicsWindow::FUNCTION_KEY_BASE - 1);
|
||||||
NSString *accel = [NSString stringWithCharacters:&accel_char length:1];
|
} else if(accelChar == GraphicsWindow::DELETE_KEY) {
|
||||||
|
accelChar = NSBackspaceCharacter;
|
||||||
|
}
|
||||||
|
NSString *accel = [NSString stringWithCharacters:&accelChar length:1];
|
||||||
|
|
||||||
menuItem = [levels[entry->level] addItemWithTitle:label
|
menuItem = [levels[entry->level] addItemWithTitle:label
|
||||||
action:NULL keyEquivalent:[accel lowercaseString]];
|
action:NULL keyEquivalent:[accel lowercaseString]];
|
||||||
|
@ -806,6 +810,9 @@ bool SolveSpace::GetSaveFile(std::string *file, const std::string &defExtension,
|
||||||
if(defExtension != "") {
|
if(defExtension != "") {
|
||||||
extensionIndex = [extensions indexOfObject:
|
extensionIndex = [extensions indexOfObject:
|
||||||
[NSString stringWithUTF8String:defExtension.c_str()]];
|
[NSString stringWithUTF8String:defExtension.c_str()]];
|
||||||
|
if(extensionIndex == -1) {
|
||||||
|
extensionIndex = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[button selectItemAtIndex:extensionIndex];
|
[button selectItemAtIndex:extensionIndex];
|
||||||
|
@ -1021,16 +1028,16 @@ void InitTextWindow() {
|
||||||
NSUtilityWindowMask)];
|
NSUtilityWindowMask)];
|
||||||
[[TW standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
|
[[TW standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
|
||||||
[[TW standardWindowButton:NSWindowZoomButton] setHidden:YES];
|
[[TW standardWindowButton:NSWindowZoomButton] setHidden:YES];
|
||||||
[TW setTitle:@"Browser"];
|
[TW setTitle:@"Property Browser"];
|
||||||
[TW setFrameAutosaveName:@"TextWindow"];
|
[TW setFrameAutosaveName:@"TextWindow"];
|
||||||
[TW setFloatingPanel:YES];
|
[TW setFloatingPanel:YES];
|
||||||
[TW setBecomesKeyOnlyIfNeeded:YES];
|
[TW setBecomesKeyOnlyIfNeeded:YES];
|
||||||
[GW addChildWindow:TW ordered:NSWindowAbove];
|
|
||||||
|
|
||||||
NSScrollView *scrollView = [[NSScrollView alloc] init];
|
NSScrollView *scrollView = [[NSScrollView alloc] init];
|
||||||
[TW setContentView:scrollView];
|
[TW setContentView:scrollView];
|
||||||
[scrollView setBackgroundColor:[NSColor blackColor]];
|
[scrollView setBackgroundColor:[NSColor blackColor]];
|
||||||
[scrollView setHasVerticalScroller:YES];
|
[scrollView setHasVerticalScroller:YES];
|
||||||
|
[scrollView setScrollerKnobStyle:NSScrollerKnobStyleLight];
|
||||||
[[scrollView contentView] setCopiesOnScroll:YES];
|
[[scrollView contentView] setCopiesOnScroll:YES];
|
||||||
|
|
||||||
TWView = [[TextWindowView alloc] init];
|
TWView = [[TextWindowView alloc] init];
|
||||||
|
@ -1089,6 +1096,7 @@ bool TextEditControlIsVisible(void) {
|
||||||
void SolveSpace::DoMessageBox(const char *str, int rows, int cols, bool error) {
|
void SolveSpace::DoMessageBox(const char *str, int rows, int cols, bool error) {
|
||||||
NSAlert *alert = [[NSAlert alloc] init];
|
NSAlert *alert = [[NSAlert alloc] init];
|
||||||
[alert setAlertStyle:(error ? NSWarningAlertStyle : NSInformationalAlertStyle)];
|
[alert setAlertStyle:(error ? NSWarningAlertStyle : NSInformationalAlertStyle)];
|
||||||
|
[alert addButtonWithTitle:@"OK"];
|
||||||
|
|
||||||
/* do some additional formatting of the message these are
|
/* do some additional formatting of the message these are
|
||||||
heuristics, but they are made failsafe and lead to nice results. */
|
heuristics, but they are made failsafe and lead to nice results. */
|
||||||
|
@ -1153,8 +1161,6 @@ std::vector<std::string> SolveSpace::GetFontFiles() {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||||
SolveSpace::SK.Clear();
|
|
||||||
SolveSpace::SS.Clear();
|
|
||||||
SolveSpace::SS.Exit();
|
SolveSpace::SS.Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1172,6 +1178,155 @@ void SolveSpace::ExitNow(void) {
|
||||||
[NSApp stop:nil];
|
[NSApp stop:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normally we would just link to the 3DconnexionClient framework.
|
||||||
|
* We don't want to (are not allowed to) distribute the official
|
||||||
|
* framework, so we're trying to use the one installed on the users
|
||||||
|
* computer. There are some different versions of the framework,
|
||||||
|
* the official one and re-implementations using an open source driver
|
||||||
|
* for older devices (spacenav-plus). So weak-linking isn't an option,
|
||||||
|
* either. The only remaining way is using CFBundle to dynamically
|
||||||
|
* load the library at runtime, and also detect its availability.
|
||||||
|
*
|
||||||
|
* We're also defining everything needed from the 3DconnexionClientAPI,
|
||||||
|
* so we're not depending on the API headers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma pack(push,2)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kConnexionClientModeTakeOver = 1,
|
||||||
|
kConnexionClientModePlugin = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
#define kConnexionMsgDeviceState '3dSR'
|
||||||
|
#define kConnexionMaskButtons 0x00FF
|
||||||
|
#define kConnexionMaskAxis 0x3F00
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t version;
|
||||||
|
uint16_t client;
|
||||||
|
uint16_t command;
|
||||||
|
int16_t param;
|
||||||
|
int32_t value;
|
||||||
|
UInt64 time;
|
||||||
|
uint8_t report[8];
|
||||||
|
uint16_t buttons8;
|
||||||
|
int16_t axis[6];
|
||||||
|
uint16_t address;
|
||||||
|
uint32_t buttons;
|
||||||
|
} ConnexionDeviceState, *ConnexionDeviceStatePtr;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
typedef void (*ConnexionAddedHandlerProc)(io_connect_t);
|
||||||
|
typedef void (*ConnexionRemovedHandlerProc)(io_connect_t);
|
||||||
|
typedef void (*ConnexionMessageHandlerProc)(io_connect_t, natural_t, void *);
|
||||||
|
|
||||||
|
typedef OSErr (*InstallConnexionHandlersProc)(ConnexionMessageHandlerProc, ConnexionAddedHandlerProc, ConnexionRemovedHandlerProc);
|
||||||
|
typedef void (*CleanupConnexionHandlersProc)(void);
|
||||||
|
typedef UInt16 (*RegisterConnexionClientProc)(UInt32, UInt8 *, UInt16, UInt32);
|
||||||
|
typedef void (*UnregisterConnexionClientProc)(UInt16);
|
||||||
|
|
||||||
|
static BOOL connexionShiftIsDown = NO;
|
||||||
|
static UInt16 connexionClient = 0;
|
||||||
|
static UInt32 connexionSignature = 'SoSp';
|
||||||
|
static UInt8 *connexionName = (UInt8 *)"SolveSpace";
|
||||||
|
static CFBundleRef spaceBundle = NULL;
|
||||||
|
static InstallConnexionHandlersProc installConnexionHandlers = NULL;
|
||||||
|
static CleanupConnexionHandlersProc cleanupConnexionHandlers = NULL;
|
||||||
|
static RegisterConnexionClientProc registerConnexionClient = NULL;
|
||||||
|
static UnregisterConnexionClientProc unregisterConnexionClient = NULL;
|
||||||
|
|
||||||
|
static void connexionAdded(io_connect_t con) {}
|
||||||
|
static void connexionRemoved(io_connect_t con) {}
|
||||||
|
static void connexionMessage(io_connect_t con, natural_t type, void *arg) {
|
||||||
|
if (type != kConnexionMsgDeviceState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnexionDeviceState *device = (ConnexionDeviceState *)arg;
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^(void){
|
||||||
|
SolveSpace::SS.GW.SpaceNavigatorMoved(
|
||||||
|
(double)device->axis[0] * -0.25,
|
||||||
|
(double)device->axis[1] * -0.25,
|
||||||
|
(double)device->axis[2] * 0.25,
|
||||||
|
(double)device->axis[3] * -0.0005,
|
||||||
|
(double)device->axis[4] * -0.0005,
|
||||||
|
(double)device->axis[5] * -0.0005,
|
||||||
|
(connexionShiftIsDown == YES) ? 1 : 0
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void connexionInit() {
|
||||||
|
NSString *bundlePath = @"/Library/Frameworks/3DconnexionClient.framework";
|
||||||
|
NSURL *bundleURL = [NSURL fileURLWithPath:bundlePath];
|
||||||
|
spaceBundle = CFBundleCreate(kCFAllocatorDefault, (__bridge CFURLRef)bundleURL);
|
||||||
|
|
||||||
|
// Don't continue if no Spacemouse driver is installed on this machine
|
||||||
|
if (spaceBundle == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
installConnexionHandlers = (InstallConnexionHandlersProc)
|
||||||
|
CFBundleGetFunctionPointerForName(spaceBundle,
|
||||||
|
CFSTR("InstallConnexionHandlers"));
|
||||||
|
|
||||||
|
cleanupConnexionHandlers = (CleanupConnexionHandlersProc)
|
||||||
|
CFBundleGetFunctionPointerForName(spaceBundle,
|
||||||
|
CFSTR("CleanupConnexionHandlers"));
|
||||||
|
|
||||||
|
registerConnexionClient = (RegisterConnexionClientProc)
|
||||||
|
CFBundleGetFunctionPointerForName(spaceBundle,
|
||||||
|
CFSTR("RegisterConnexionClient"));
|
||||||
|
|
||||||
|
unregisterConnexionClient = (UnregisterConnexionClientProc)
|
||||||
|
CFBundleGetFunctionPointerForName(spaceBundle,
|
||||||
|
CFSTR("UnregisterConnexionClient"));
|
||||||
|
|
||||||
|
// Only continue if all required symbols have been loaded
|
||||||
|
if ((installConnexionHandlers == NULL) || (cleanupConnexionHandlers == NULL)
|
||||||
|
|| (registerConnexionClient == NULL) || (unregisterConnexionClient == NULL)) {
|
||||||
|
CFRelease(spaceBundle);
|
||||||
|
spaceBundle = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
installConnexionHandlers(&connexionMessage, &connexionAdded, &connexionRemoved);
|
||||||
|
connexionClient = registerConnexionClient(connexionSignature, connexionName,
|
||||||
|
kConnexionClientModeTakeOver, kConnexionMaskButtons | kConnexionMaskAxis);
|
||||||
|
|
||||||
|
// Monitor modifier flags to detect Shift button state changes
|
||||||
|
[NSEvent addLocalMonitorForEventsMatchingMask:(NSKeyDownMask | NSFlagsChangedMask)
|
||||||
|
handler:^(NSEvent *event) {
|
||||||
|
if (event.modifierFlags & NSShiftKeyMask) {
|
||||||
|
connexionShiftIsDown = YES;
|
||||||
|
}
|
||||||
|
return event;
|
||||||
|
}];
|
||||||
|
|
||||||
|
[NSEvent addLocalMonitorForEventsMatchingMask:(NSKeyUpMask | NSFlagsChangedMask)
|
||||||
|
handler:^(NSEvent *event) {
|
||||||
|
if (!(event.modifierFlags & NSShiftKeyMask)) {
|
||||||
|
connexionShiftIsDown = NO;
|
||||||
|
}
|
||||||
|
return event;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void connexionClose() {
|
||||||
|
if (spaceBundle == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unregisterConnexionClient(connexionClient);
|
||||||
|
cleanupConnexionHandlers();
|
||||||
|
|
||||||
|
CFRelease(spaceBundle);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
int main(int argc, const char *argv[]) {
|
||||||
[NSApplication sharedApplication];
|
[NSApplication sharedApplication];
|
||||||
ApplicationDelegate *delegate = [[ApplicationDelegate alloc] init];
|
ApplicationDelegate *delegate = [[ApplicationDelegate alloc] init];
|
||||||
|
@ -1182,11 +1337,15 @@ int main(int argc, const char *argv[]) {
|
||||||
[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:nil topLevelObjects:nil];
|
[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:nil topLevelObjects:nil];
|
||||||
SolveSpace::InitMainMenu([NSApp mainMenu]);
|
SolveSpace::InitMainMenu([NSApp mainMenu]);
|
||||||
|
|
||||||
|
connexionInit();
|
||||||
SolveSpace::SS.Init();
|
SolveSpace::SS.Init();
|
||||||
|
|
||||||
[GW makeKeyAndOrderFront:nil];
|
[GW makeKeyAndOrderFront:nil];
|
||||||
[NSApp activateIgnoringOtherApps:YES];
|
|
||||||
[NSApp run];
|
[NSApp run];
|
||||||
|
|
||||||
|
connexionClose();
|
||||||
|
SolveSpace::SK.Clear();
|
||||||
|
SolveSpace::SS.Clear();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -453,6 +453,7 @@ bool TextWindow::EditControlDoneForConfiguration(const char *s) {
|
||||||
} else {
|
} else {
|
||||||
Error("Bad format: specify interval in integral minutes");
|
Error("Bad format: specify interval in integral minutes");
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: return false;
|
default: return false;
|
||||||
|
|
|
@ -370,6 +370,7 @@ void Constraint::MenuConstrain(int id) {
|
||||||
((gs.workplanes == 1 && gs.n == 3) ||
|
((gs.workplanes == 1 && gs.n == 3) ||
|
||||||
(gs.n == 2)))
|
(gs.n == 2)))
|
||||||
{
|
{
|
||||||
|
if(gs.entities > 0)
|
||||||
c.entityA = gs.entity[0];
|
c.entityA = gs.entity[0];
|
||||||
c.ptA = gs.point[0];
|
c.ptA = gs.point[0];
|
||||||
c.ptB = gs.point[1];
|
c.ptB = gs.point[1];
|
||||||
|
@ -377,9 +378,13 @@ void Constraint::MenuConstrain(int id) {
|
||||||
((gs.workplanes == 1 && gs.n == 2) ||
|
((gs.workplanes == 1 && gs.n == 2) ||
|
||||||
(gs.n == 1)))
|
(gs.n == 1)))
|
||||||
{
|
{
|
||||||
int i = SK.GetEntity(gs.entity[0])->IsWorkplane() ? 1 : 0;
|
Entity *line;
|
||||||
Entity *line = SK.GetEntity(gs.entity[i]);
|
if(SK.GetEntity(gs.entity[0])->IsWorkplane()) {
|
||||||
c.entityA = gs.entity[1-i];
|
line = SK.GetEntity(gs.entity[1]);
|
||||||
|
c.entityA = gs.entity[0];
|
||||||
|
} else {
|
||||||
|
line = SK.GetEntity(gs.entity[0]);
|
||||||
|
}
|
||||||
c.ptA = line->point[0];
|
c.ptA = line->point[0];
|
||||||
c.ptB = line->point[1];
|
c.ptB = line->point[1];
|
||||||
} else if(SS.GW.LockedInWorkplane()
|
} else if(SS.GW.LockedInWorkplane()
|
||||||
|
|
30
src/draw.cpp
30
src/draw.cpp
|
@ -156,6 +156,13 @@ void GraphicsWindow::MakeSelected(hEntity he) {
|
||||||
stog.entity = he;
|
stog.entity = he;
|
||||||
MakeSelected(&stog);
|
MakeSelected(&stog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphicsWindow::MakeSelected(hConstraint hc) {
|
||||||
|
Selection stog = {};
|
||||||
|
stog.constraint = hc;
|
||||||
|
MakeSelected(&stog);
|
||||||
|
}
|
||||||
|
|
||||||
void GraphicsWindow::MakeSelected(Selection *stog) {
|
void GraphicsWindow::MakeSelected(Selection *stog) {
|
||||||
if(stog->IsEmpty()) return;
|
if(stog->IsEmpty()) return;
|
||||||
if(IsSelected(stog)) return;
|
if(IsSelected(stog)) return;
|
||||||
|
@ -242,7 +249,7 @@ void GraphicsWindow::SelectByMarquee(void) {
|
||||||
void GraphicsWindow::GroupSelection(void) {
|
void GraphicsWindow::GroupSelection(void) {
|
||||||
gs = {};
|
gs = {};
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < selection.n && i < MAX_SELECTED; i++) {
|
for(i = 0; i < selection.n; i++) {
|
||||||
Selection *s = &(selection.elem[i]);
|
Selection *s = &(selection.elem[i]);
|
||||||
if(s->entity.v) {
|
if(s->entity.v) {
|
||||||
(gs.n)++;
|
(gs.n)++;
|
||||||
|
@ -253,27 +260,33 @@ void GraphicsWindow::GroupSelection(void) {
|
||||||
|
|
||||||
// A list of points, and a list of all entities that aren't points.
|
// A list of points, and a list of all entities that aren't points.
|
||||||
if(e->IsPoint()) {
|
if(e->IsPoint()) {
|
||||||
gs.point[(gs.points)++] = s->entity;
|
gs.points++;
|
||||||
|
gs.point.push_back(s->entity);
|
||||||
} else {
|
} else {
|
||||||
gs.entity[(gs.entities)++] = s->entity;
|
gs.entities++;
|
||||||
|
gs.entity.push_back(s->entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// And an auxiliary list of normals, including normals from
|
// And an auxiliary list of normals, including normals from
|
||||||
// workplanes.
|
// workplanes.
|
||||||
if(e->IsNormal()) {
|
if(e->IsNormal()) {
|
||||||
gs.anyNormal[(gs.anyNormals)++] = s->entity;
|
gs.anyNormals++;
|
||||||
|
gs.anyNormal.push_back(s->entity);
|
||||||
} else if(e->IsWorkplane()) {
|
} else if(e->IsWorkplane()) {
|
||||||
gs.anyNormal[(gs.anyNormals)++] = e->Normal()->h;
|
gs.anyNormals++;
|
||||||
|
gs.anyNormal.push_back(e->Normal()->h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// And of vectors (i.e., stuff with a direction to constrain)
|
// And of vectors (i.e., stuff with a direction to constrain)
|
||||||
if(e->HasVector()) {
|
if(e->HasVector()) {
|
||||||
gs.vector[(gs.vectors)++] = s->entity;
|
gs.vectors++;
|
||||||
|
gs.vector.push_back(s->entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Faces (which are special, associated/drawn with triangles)
|
// Faces (which are special, associated/drawn with triangles)
|
||||||
if(e->IsFace()) {
|
if(e->IsFace()) {
|
||||||
gs.face[(gs.faces)++] = s->entity;
|
gs.faces++;
|
||||||
|
gs.face.push_back(s->entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e->HasEndpoints()) {
|
if(e->HasEndpoints()) {
|
||||||
|
@ -296,7 +309,8 @@ void GraphicsWindow::GroupSelection(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(s->constraint.v) {
|
if(s->constraint.v) {
|
||||||
gs.constraint[(gs.constraints)++] = s->constraint;
|
gs.constraints++;
|
||||||
|
gs.constraint.push_back(s->constraint);
|
||||||
Constraint *c = SK.GetConstraint(s->constraint);
|
Constraint *c = SK.GetConstraint(s->constraint);
|
||||||
if(c->IsStylable()) gs.stylables++;
|
if(c->IsStylable()) gs.stylables++;
|
||||||
if(c->HasLabel()) gs.constraintLabels++;
|
if(c->HasLabel()) gs.constraintLabels++;
|
||||||
|
|
|
@ -661,8 +661,8 @@ void Entity::DrawOrGetDistance(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!h.isFromRequest()) {
|
if(!h.isFromRequest()) {
|
||||||
mm = mm.Plus(v.ScaledBy(60/SS.GW.scale));
|
mm = mm.Plus(v.ScaledBy(70/SS.GW.scale));
|
||||||
mm2 = mm2.Plus(u.ScaledBy(60/SS.GW.scale));
|
mm2 = mm2.Plus(u.ScaledBy(70/SS.GW.scale));
|
||||||
LineDrawOrGetDistance(mm2, mm);
|
LineDrawOrGetDistance(mm2, mm);
|
||||||
}
|
}
|
||||||
LineDrawOrGetDistance(pp, pm);
|
LineDrawOrGetDistance(pp, pm);
|
||||||
|
@ -676,7 +676,9 @@ void Entity::DrawOrGetDistance(void) {
|
||||||
std::string str = DescriptionString().substr(5);
|
std::string str = DescriptionString().substr(5);
|
||||||
double th = Style::DefaultTextHeight();
|
double th = Style::DefaultTextHeight();
|
||||||
if(dogd.drawing) {
|
if(dogd.drawing) {
|
||||||
ssglWriteText(str, th, mm2, u, v, NULL, NULL);
|
Vector o = mm2.Plus(u.ScaledBy(3/SS.GW.scale)).Plus(
|
||||||
|
v.ScaledBy(3/SS.GW.scale));
|
||||||
|
ssglWriteText(str, th, o, u, v, NULL, NULL);
|
||||||
} else {
|
} else {
|
||||||
Vector pos = mm2.Plus(u.ScaledBy(ssglStrWidth(str, th)/2)).Plus(
|
Vector pos = mm2.Plus(u.ScaledBy(ssglStrWidth(str, th)/2)).Plus(
|
||||||
v.ScaledBy(ssglStrCapHeight(th)/2));
|
v.ScaledBy(ssglStrCapHeight(th)/2));
|
||||||
|
|
|
@ -859,6 +859,8 @@ void SolveSpaceUI::ExportMeshAsThreeJsTo(FILE *f, const std::string &filename,
|
||||||
<script>
|
<script>
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
|
window.devicePixelRatio = window.devicePixelRatio || 1;
|
||||||
|
|
||||||
SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset) {
|
SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset) {
|
||||||
THREE.Camera.call(this);
|
THREE.Camera.call(this);
|
||||||
|
|
||||||
|
@ -1014,13 +1016,13 @@ SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset)
|
||||||
|
|
||||||
switch (event.button) {
|
switch (event.button) {
|
||||||
case 0:
|
case 0:
|
||||||
_rotateCur.set(event.screenX, event.screenY);
|
_rotateCur.set(event.screenX/window.devicePixelRatio, event.screenY/window.devicePixelRatio);
|
||||||
_rotatePrev.copy(_rotateCur);
|
_rotatePrev.copy(_rotateCur);
|
||||||
document.addEventListener('mousemove', mousemove, false);
|
document.addEventListener('mousemove', mousemove, false);
|
||||||
document.addEventListener('mouseup', mouseup, false);
|
document.addEventListener('mouseup', mouseup, false);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_offsetCur.set(event.screenX, event.screenY);
|
_offsetCur.set(event.screenX/window.devicePixelRatio, event.screenY/window.devicePixelRatio);
|
||||||
_offsetPrev.copy(_offsetCur);
|
_offsetPrev.copy(_offsetCur);
|
||||||
document.addEventListener('mousemove', mousemove, false);
|
document.addEventListener('mousemove', mousemove, false);
|
||||||
document.addEventListener('mouseup', mouseup, false);
|
document.addEventListener('mouseup', mouseup, false);
|
||||||
|
@ -1043,7 +1045,7 @@ SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset)
|
||||||
function mousemove(event) {
|
function mousemove(event) {
|
||||||
switch (event.button) {
|
switch (event.button) {
|
||||||
case 0:
|
case 0:
|
||||||
_rotateCur.set(event.screenX, event.screenY);
|
_rotateCur.set(event.screenX/window.devicePixelRatio, event.screenY/window.devicePixelRatio);
|
||||||
var diff = new THREE.Vector2().subVectors(_rotateCur, _rotatePrev)
|
var diff = new THREE.Vector2().subVectors(_rotateCur, _rotatePrev)
|
||||||
.multiplyScalar(1 / object.zoomScale);
|
.multiplyScalar(1 / object.zoomScale);
|
||||||
object.rotate(-0.3 * Math.PI / 180 * diff.x * object.zoomScale,
|
object.rotate(-0.3 * Math.PI / 180 * diff.x * object.zoomScale,
|
||||||
|
@ -1053,7 +1055,7 @@ SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset)
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_mouseMoved = true;
|
_mouseMoved = true;
|
||||||
_offsetCur.set(event.screenX, event.screenY);
|
_offsetCur.set(event.screenX/window.devicePixelRatio, event.screenY/window.devicePixelRatio);
|
||||||
var diff = new THREE.Vector2().subVectors(_offsetCur, _offsetPrev)
|
var diff = new THREE.Vector2().subVectors(_offsetCur, _offsetPrev)
|
||||||
.multiplyScalar(1 / object.zoomScale);
|
.multiplyScalar(1 / object.zoomScale);
|
||||||
object.offsetProj(diff.x, -diff.y);
|
object.offsetProj(diff.x, -diff.y);
|
||||||
|
@ -1197,6 +1199,9 @@ SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset)
|
||||||
height = params.height;
|
height = params.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
width *= window.devicePixelRatio;
|
||||||
|
height *= window.devicePixelRatio;
|
||||||
|
|
||||||
domElement = init();
|
domElement = init();
|
||||||
render();
|
render();
|
||||||
return domElement;
|
return domElement;
|
||||||
|
@ -1206,8 +1211,8 @@ SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset)
|
||||||
scene = new THREE.Scene();
|
scene = new THREE.Scene();
|
||||||
edgeScene = new THREE.Scene();
|
edgeScene = new THREE.Scene();
|
||||||
|
|
||||||
camera = new SolvespaceCamera(width,
|
camera = new SolvespaceCamera(width/window.devicePixelRatio,
|
||||||
height, 5, new THREE.Vector3(0, 1, 0),
|
height/window.devicePixelRatio, 5, new THREE.Vector3(0, 1, 0),
|
||||||
new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 0, 0));
|
new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 0, 0));
|
||||||
|
|
||||||
mesh = createMesh(obj);
|
mesh = createMesh(obj);
|
||||||
|
@ -1232,6 +1237,7 @@ SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset)
|
||||||
renderer = new THREE.WebGLRenderer({ antialias: true});
|
renderer = new THREE.WebGLRenderer({ antialias: true});
|
||||||
renderer.setSize(width, height);
|
renderer.setSize(width, height);
|
||||||
renderer.autoClear = false;
|
renderer.autoClear = false;
|
||||||
|
renderer.domElement.style = "width:"+width/window.devicePixelRatio+"px;height:"+height/window.devicePixelRatio+"px;";
|
||||||
|
|
||||||
controls = new SolvespaceControls(camera, renderer.domElement);
|
controls = new SolvespaceControls(camera, renderer.domElement);
|
||||||
controls.addEventListener("change", render);
|
controls.addEventListener("change", render);
|
||||||
|
|
|
@ -175,21 +175,16 @@ public:
|
||||||
layer.name = "text";
|
layer.name = "text";
|
||||||
dxf->writeLayer(&layer);
|
dxf->writeLayer(&layer);
|
||||||
|
|
||||||
for(int i = 0; i < SK.style.n; i++) {
|
std::set<uint32_t> usedStyles;
|
||||||
Style *s = &SK.style.elem[i];
|
|
||||||
|
|
||||||
// check for using
|
|
||||||
bool used = false;
|
|
||||||
for(DxfFileWriter::BezierPath &path : writer->paths) {
|
for(DxfFileWriter::BezierPath &path : writer->paths) {
|
||||||
for(SBezier *sb : path.beziers) {
|
for(SBezier *sb : path.beziers) {
|
||||||
if((uint32_t)sb->auxA != s->h.v) continue;
|
usedStyles.insert((uint32_t)sb->auxA);
|
||||||
used = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if(used) break;
|
|
||||||
}
|
}
|
||||||
if(!used) continue;
|
|
||||||
|
|
||||||
|
for(uint32_t v : usedStyles) {
|
||||||
|
Style *s = Style::Get(hStyle{v});
|
||||||
layer.name = s->DescriptionString();
|
layer.name = s->DescriptionString();
|
||||||
dxf->writeLayer(&layer);
|
dxf->writeLayer(&layer);
|
||||||
}
|
}
|
||||||
|
@ -264,14 +259,17 @@ public:
|
||||||
found = true;
|
found = true;
|
||||||
e->tag = 1;
|
e->tag = 1;
|
||||||
|
|
||||||
DRW_LWPolyline polyline;
|
DRW_Polyline polyline;
|
||||||
assignEntityDefaults(&polyline, e->style);
|
assignEntityDefaults(&polyline, e->style);
|
||||||
polyline.vertlist.push_back(new DRW_Vertex2D(start->pos.x, start->pos.y, 0.0));
|
polyline.vertlist.push_back(
|
||||||
polyline.vertlist.push_back(new DRW_Vertex2D(next->pos.x, next->pos.y, 0.0));
|
new DRW_Vertex(start->pos.x, start->pos.y, start->pos.z, 0.0));
|
||||||
|
polyline.vertlist.push_back(
|
||||||
|
new DRW_Vertex(next->pos.x, next->pos.y, next->pos.z, 0.0));
|
||||||
while(next->getNext(e->style, &next)) {
|
while(next->getNext(e->style, &next)) {
|
||||||
polyline.vertlist.push_back(new DRW_Vertex2D(next->pos.x, next->pos.y, 0.0));
|
polyline.vertlist.push_back(
|
||||||
|
new DRW_Vertex(next->pos.x, next->pos.y, next->pos.z, 0.0));
|
||||||
}
|
}
|
||||||
dxf->writeLWPolyline(&polyline);
|
dxf->writePolyline(&polyline);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!found && !loop) {
|
if(!found && !loop) {
|
||||||
|
@ -484,16 +482,14 @@ public:
|
||||||
List<Vector> lv = {};
|
List<Vector> lv = {};
|
||||||
sb->MakePwlInto(&lv, SS.ExportChordTolMm());
|
sb->MakePwlInto(&lv, SS.ExportChordTolMm());
|
||||||
hStyle hs = { (uint32_t)sb->auxA };
|
hStyle hs = { (uint32_t)sb->auxA };
|
||||||
DRW_LWPolyline polyline;
|
DRW_Polyline polyline;
|
||||||
assignEntityDefaults(&polyline, hs);
|
assignEntityDefaults(&polyline, hs);
|
||||||
for(int i = 0; i < lv.n; i++) {
|
for(int i = 0; i < lv.n; i++) {
|
||||||
Vector *v = &lv.elem[i];
|
Vector *v = &lv.elem[i];
|
||||||
DRW_Vertex2D *vertex = new DRW_Vertex2D();
|
DRW_Vertex *vertex = new DRW_Vertex(v->x, v->y, v->z, 0.0);
|
||||||
vertex->x = v->x;
|
|
||||||
vertex->y = v->y;
|
|
||||||
polyline.vertlist.push_back(vertex);
|
polyline.vertlist.push_back(vertex);
|
||||||
}
|
}
|
||||||
dxf->writeLWPolyline(&polyline);
|
dxf->writePolyline(&polyline);
|
||||||
lv.Clear();
|
lv.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,7 +528,8 @@ public:
|
||||||
spline.ncontrol = sb->deg + 1;
|
spline.ncontrol = sb->deg + 1;
|
||||||
makeKnotsFor(&spline);
|
makeKnotsFor(&spline);
|
||||||
for(int i = 0; i <= sb->deg; i++) {
|
for(int i = 0; i <= sb->deg; i++) {
|
||||||
spline.controllist.push_back(new DRW_Coord(sb->ctrl[i].x, sb->ctrl[i].y, 0.0));
|
spline.controllist.push_back(
|
||||||
|
new DRW_Coord(sb->ctrl[i].x, sb->ctrl[i].y, sb->ctrl[i].z));
|
||||||
if(isRational) spline.weightlist.push_back(sb->weight[i]);
|
if(isRational) spline.weightlist.push_back(sb->weight[i]);
|
||||||
}
|
}
|
||||||
dxf->writeSpline(&spline);
|
dxf->writeSpline(&spline);
|
||||||
|
@ -689,12 +686,19 @@ void DxfFileWriter::Bezier(SBezier *sb) {
|
||||||
paths.back().beziers.push_back(sb);
|
paths.back().beziers.push_back(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DxfFileWriter::FinishAndCloseFile(void) {
|
void DxfFileWriter::FinishAndCloseFile() {
|
||||||
dxfRW dxf(filename.c_str());
|
dxfRW dxf;
|
||||||
|
|
||||||
DxfWriteInterface interface(this, &dxf);
|
DxfWriteInterface interface(this, &dxf);
|
||||||
dxf.write(&interface, DRW::AC1021, false);
|
std::stringstream stream;
|
||||||
|
dxf.write(stream, &interface, DRW::AC1021, /*bin=*/false);
|
||||||
paths.clear();
|
paths.clear();
|
||||||
constraint = NULL;
|
constraint = NULL;
|
||||||
|
|
||||||
|
if(!WriteFile(filename, stream.str())) {
|
||||||
|
Error("Couldn't write to '%s'", filename.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DxfFileWriter::NeedToOutput(Constraint *c) {
|
bool DxfFileWriter::NeedToOutput(Constraint *c) {
|
||||||
|
|
|
@ -806,6 +806,8 @@ bool SolveSpaceUI::ReloadAllImported(bool canCancel)
|
||||||
g->linkFile = newPath;
|
g->linkFile = newPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In a newly created group we only have an absolute path.
|
||||||
|
if(!g->linkFileRel.empty()) {
|
||||||
std::string rel = PathSepUNIXToPlatform(g->linkFileRel);
|
std::string rel = PathSepUNIXToPlatform(g->linkFileRel);
|
||||||
std::string fromRel = MakePathAbsolute(SS.saveFile, rel);
|
std::string fromRel = MakePathAbsolute(SS.saveFile, rel);
|
||||||
FILE *test = ssfopen(fromRel, "rb");
|
FILE *test = ssfopen(fromRel, "rb");
|
||||||
|
@ -818,6 +820,7 @@ bool SolveSpaceUI::ReloadAllImported(bool canCancel)
|
||||||
// can use the absolute filename to get us back. The relative path will be
|
// can use the absolute filename to get us back. The relative path will be
|
||||||
// updated below.
|
// updated below.
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try_load_file:
|
try_load_file:
|
||||||
if(LoadEntitiesFromFile(g->linkFile, &(g->impEntity), &(g->impMesh), &(g->impShell)))
|
if(LoadEntitiesFromFile(g->linkFile, &(g->impEntity), &(g->impMesh), &(g->impShell)))
|
||||||
|
|
Binary file not shown.
|
@ -205,7 +205,7 @@ void SolveSpaceUI::GenerateAll(GenerateType type, bool andFindFree, bool genForB
|
||||||
// If we're generating entities for display, first we need to find
|
// If we're generating entities for display, first we need to find
|
||||||
// the bounding box to turn relative chord tolerance to absolute.
|
// the bounding box to turn relative chord tolerance to absolute.
|
||||||
if(!SS.exportMode && !genForBBox) {
|
if(!SS.exportMode && !genForBBox) {
|
||||||
GenerateAll(type, /*andFindFree=*/false, /*genForBBox=*/true);
|
GenerateAll(type, andFindFree, /*genForBBox=*/true);
|
||||||
BBox box = SK.CalculateEntityBBox(/*includeInvisibles=*/true);
|
BBox box = SK.CalculateEntityBBox(/*includeInvisibles=*/true);
|
||||||
Vector size = box.maxp.Minus(box.minp);
|
Vector size = box.maxp.Minus(box.minp);
|
||||||
double maxSize = std::max({ size.x, size.y, size.z });
|
double maxSize = std::max({ size.x, size.y, size.z });
|
||||||
|
@ -293,7 +293,10 @@ void SolveSpaceUI::GenerateAll(GenerateType type, bool andFindFree, bool genForB
|
||||||
if(newp->known) continue;
|
if(newp->known) continue;
|
||||||
|
|
||||||
Param *prevp = prev.FindByIdNoOops(newp->h);
|
Param *prevp = prev.FindByIdNoOops(newp->h);
|
||||||
if(prevp) newp->val = prevp->val;
|
if(prevp) {
|
||||||
|
newp->val = prevp->val;
|
||||||
|
newp->free = prevp->free;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(g->h.v == Group::HGROUP_REFERENCES.v) {
|
if(g->h.v == Group::HGROUP_REFERENCES.v) {
|
||||||
|
@ -305,7 +308,7 @@ void SolveSpaceUI::GenerateAll(GenerateType type, bool andFindFree, bool genForB
|
||||||
// The group falls inside the range, so really solve it,
|
// The group falls inside the range, so really solve it,
|
||||||
// and then regenerate the mesh based on the solved stuff.
|
// and then regenerate the mesh based on the solved stuff.
|
||||||
if(genForBBox) {
|
if(genForBBox) {
|
||||||
SolveGroup(g->h, andFindFree);
|
SolveGroupAndReport(g->h, andFindFree);
|
||||||
} else {
|
} else {
|
||||||
g->GenerateLoops();
|
g->GenerateLoops();
|
||||||
g->GenerateShellAndMesh();
|
g->GenerateShellAndMesh();
|
||||||
|
@ -488,6 +491,23 @@ void SolveSpaceUI::MarkDraggedParams(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SolveSpaceUI::SolveGroupAndReport(hGroup hg, bool andFindFree) {
|
||||||
|
SolveGroup(hg, andFindFree);
|
||||||
|
|
||||||
|
Group *g = SK.GetGroup(hg);
|
||||||
|
if(g->solved.how == System::REDUNDANT_OKAY) {
|
||||||
|
// Solve again, in case we lost a degree of freedom because of a numeric error.
|
||||||
|
SolveGroup(hg, andFindFree);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isOkay = g->solved.how == System::SOLVED_OKAY ||
|
||||||
|
(g->allowRedundant && g->solved.how == System::REDUNDANT_OKAY);
|
||||||
|
|
||||||
|
if(!isOkay || (isOkay && !g->IsSolvedOkay())) {
|
||||||
|
TextWindow::ReportHowGroupSolved(g->h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) {
|
void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) {
|
||||||
int i;
|
int i;
|
||||||
// Clear out the system to be solved.
|
// Clear out the system to be solved.
|
||||||
|
@ -515,12 +535,6 @@ void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) {
|
||||||
g->solved.remove.Clear();
|
g->solved.remove.Clear();
|
||||||
int how = sys.Solve(g, &(g->solved.dof),
|
int how = sys.Solve(g, &(g->solved.dof),
|
||||||
&(g->solved.remove), true, andFindFree);
|
&(g->solved.remove), true, andFindFree);
|
||||||
bool isOkay = how == System::SOLVED_OKAY ||
|
|
||||||
(g->allowRedundant && how == System::REDUNDANT_OKAY);
|
|
||||||
if(!isOkay || (isOkay && !g->IsSolvedOkay()))
|
|
||||||
{
|
|
||||||
TextWindow::ReportHowGroupSolved(g->h);
|
|
||||||
}
|
|
||||||
g->solved.how = how;
|
g->solved.how = how;
|
||||||
FreeAllTemporary();
|
FreeAllTemporary();
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
||||||
{ 1, "Show Menu &Bar", MNU_SHOW_MENU_BAR, C|F(12), TC, mView },
|
{ 1, "Show Menu &Bar", MNU_SHOW_MENU_BAR, C|F(12), TC, mView },
|
||||||
#endif
|
#endif
|
||||||
{ 1, "Show &Toolbar", MNU_SHOW_TOOLBAR, 0, TC, mView },
|
{ 1, "Show &Toolbar", MNU_SHOW_TOOLBAR, 0, TC, mView },
|
||||||
{ 1, "Show Text &Window", MNU_SHOW_TEXT_WND, '\t', TC, mView },
|
{ 1, "Show Property Bro&wser", MNU_SHOW_TEXT_WND, '\t', TC, mView },
|
||||||
{ 1, NULL, 0, 0, TN, NULL },
|
{ 1, NULL, 0, 0, TN, NULL },
|
||||||
{ 1, "Dimensions in &Inches", MNU_UNITS_INCHES, 0, TR, mView },
|
{ 1, "Dimensions in &Inches", MNU_UNITS_INCHES, 0, TR, mView },
|
||||||
{ 1, "Dimensions in &Millimeters", MNU_UNITS_MM, 0, TR, mView },
|
{ 1, "Dimensions in &Millimeters", MNU_UNITS_MM, 0, TR, mView },
|
||||||
|
@ -488,7 +488,6 @@ void GraphicsWindow::MenuView(int id) {
|
||||||
case MNU_ONTO_WORKPLANE:
|
case MNU_ONTO_WORKPLANE:
|
||||||
if(SS.GW.LockedInWorkplane()) {
|
if(SS.GW.LockedInWorkplane()) {
|
||||||
SS.GW.AnimateOntoWorkplane();
|
SS.GW.AnimateOntoWorkplane();
|
||||||
SS.GW.ClearSuper();
|
|
||||||
SS.ScheduleShowTW();
|
SS.ScheduleShowTW();
|
||||||
break;
|
break;
|
||||||
} // if not in 2d mode fall through and use ORTHO logic
|
} // if not in 2d mode fall through and use ORTHO logic
|
||||||
|
@ -911,7 +910,8 @@ void GraphicsWindow::MenuEdit(int id) {
|
||||||
SS.MarkGroupDirty(ep->group);
|
SS.MarkGroupDirty(ep->group);
|
||||||
} else if(s->constraint.v) {
|
} else if(s->constraint.v) {
|
||||||
Constraint *c = SK.GetConstraint(s->constraint);
|
Constraint *c = SK.GetConstraint(s->constraint);
|
||||||
c->disp.offset = SS.GW.SnapToGrid(c->disp.offset);
|
Vector refp = c->GetReferencePos();
|
||||||
|
c->disp.offset = c->disp.offset.Plus(SS.GW.SnapToGrid(refp).Minus(refp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Regenerate, with these points marked as dragged so that they
|
// Regenerate, with these points marked as dragged so that they
|
||||||
|
|
|
@ -203,8 +203,10 @@ void Group::GenerateShellAndMesh(void) {
|
||||||
// not our own previous group.
|
// not our own previous group.
|
||||||
srcg = SK.GetGroup(opA);
|
srcg = SK.GetGroup(opA);
|
||||||
|
|
||||||
|
if(!srcg->suppress) {
|
||||||
GenerateForStepAndRepeat<SShell>(&(srcg->thisShell), &thisShell);
|
GenerateForStepAndRepeat<SShell>(&(srcg->thisShell), &thisShell);
|
||||||
GenerateForStepAndRepeat<SMesh> (&(srcg->thisMesh), &thisMesh);
|
GenerateForStepAndRepeat<SMesh> (&(srcg->thisMesh), &thisMesh);
|
||||||
|
}
|
||||||
} else if(type == EXTRUDE && haveSrc) {
|
} else if(type == EXTRUDE && haveSrc) {
|
||||||
Group *src = SK.GetGroup(opA);
|
Group *src = SK.GetGroup(opA);
|
||||||
Vector translate = Vector::From(h.param(0), h.param(1), h.param(2));
|
Vector translate = Vector::From(h.param(0), h.param(1), h.param(2));
|
||||||
|
|
|
@ -55,10 +55,7 @@
|
||||||
#include "../unix/gloffscreen.h"
|
#include "../unix/gloffscreen.h"
|
||||||
|
|
||||||
#ifdef HAVE_SPACEWARE
|
#ifdef HAVE_SPACEWARE
|
||||||
# include <spnav.h>
|
#include <spnav.h>
|
||||||
# ifndef SI_APP_FIT_BUTTON
|
|
||||||
# define SI_APP_FIT_BUTTON 31
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace SolveSpace {
|
namespace SolveSpace {
|
||||||
|
@ -368,6 +365,8 @@ private:
|
||||||
class EditorOverlay : public Gtk::Fixed {
|
class EditorOverlay : public Gtk::Fixed {
|
||||||
public:
|
public:
|
||||||
EditorOverlay(Gtk::Widget &underlay) : _underlay(underlay) {
|
EditorOverlay(Gtk::Widget &underlay) : _underlay(underlay) {
|
||||||
|
set_size_request(0, 0);
|
||||||
|
|
||||||
add(_underlay);
|
add(_underlay);
|
||||||
|
|
||||||
_entry.set_no_show_all(true);
|
_entry.set_no_show_all(true);
|
||||||
|
@ -513,10 +512,6 @@ public:
|
||||||
set_double_buffered(true);
|
set_double_buffered(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void emulate_key_press(GdkEventKey *event) {
|
|
||||||
on_key_press_event(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool on_configure_event(GdkEventConfigure *event) {
|
virtual bool on_configure_event(GdkEventConfigure *event) {
|
||||||
_w = event->width;
|
_w = event->width;
|
||||||
|
@ -596,45 +591,6 @@ protected:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool on_key_press_event(GdkEventKey *event) {
|
|
||||||
int chr;
|
|
||||||
|
|
||||||
switch(event->keyval) {
|
|
||||||
case GDK_KEY_Escape:
|
|
||||||
chr = GraphicsWindow::ESCAPE_KEY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GDK_KEY_Delete:
|
|
||||||
chr = GraphicsWindow::DELETE_KEY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GDK_KEY_Tab:
|
|
||||||
chr = '\t';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GDK_KEY_BackSpace:
|
|
||||||
case GDK_KEY_Back:
|
|
||||||
chr = '\b';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if(event->keyval >= GDK_KEY_F1 && event->keyval <= GDK_KEY_F12)
|
|
||||||
chr = GraphicsWindow::FUNCTION_KEY_BASE + (event->keyval - GDK_KEY_F1);
|
|
||||||
else
|
|
||||||
chr = gdk_keyval_to_unicode(event->keyval);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(event->state & GDK_SHIFT_MASK)
|
|
||||||
chr |= GraphicsWindow::SHIFT_MASK;
|
|
||||||
if(event->state & GDK_CONTROL_MASK)
|
|
||||||
chr |= GraphicsWindow::CTRL_MASK;
|
|
||||||
|
|
||||||
if(chr && SS.GW.KeyDown(chr))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _w, _h;
|
int _w, _h;
|
||||||
void ij_to_xy(int i, int j, int &x, int &y) {
|
void ij_to_xy(int i, int j, int &x, int &y) {
|
||||||
|
@ -675,6 +631,10 @@ public:
|
||||||
return _is_fullscreen;
|
return _is_fullscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool emulate_key_press(GdkEventKey *event) {
|
||||||
|
return on_key_press_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void on_show() {
|
virtual void on_show() {
|
||||||
Gtk::Window::on_show();
|
Gtk::Window::on_show();
|
||||||
|
@ -689,6 +649,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool on_delete_event(GdkEventAny *) {
|
virtual bool on_delete_event(GdkEventAny *) {
|
||||||
|
if(!SS.OkayToStartNewFile()) return true;
|
||||||
SS.Exit();
|
SS.Exit();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -705,6 +666,55 @@ protected:
|
||||||
return Gtk::Window::on_window_state_event(event);
|
return Gtk::Window::on_window_state_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool on_key_press_event(GdkEventKey *event) {
|
||||||
|
int chr;
|
||||||
|
|
||||||
|
switch(event->keyval) {
|
||||||
|
case GDK_KEY_Escape:
|
||||||
|
chr = GraphicsWindow::ESCAPE_KEY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GDK_KEY_Delete:
|
||||||
|
chr = GraphicsWindow::DELETE_KEY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GDK_KEY_Tab:
|
||||||
|
chr = '\t';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GDK_KEY_BackSpace:
|
||||||
|
case GDK_KEY_Back:
|
||||||
|
chr = '\b';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if(event->keyval >= GDK_KEY_F1 && event->keyval <= GDK_KEY_F12) {
|
||||||
|
chr = GraphicsWindow::FUNCTION_KEY_BASE + (event->keyval - GDK_KEY_F1);
|
||||||
|
} else {
|
||||||
|
chr = gdk_keyval_to_unicode(event->keyval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(event->state & GDK_SHIFT_MASK){
|
||||||
|
chr |= GraphicsWindow::SHIFT_MASK;
|
||||||
|
}
|
||||||
|
if(event->state & GDK_CONTROL_MASK) {
|
||||||
|
chr |= GraphicsWindow::CTRL_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chr && SS.GW.KeyDown(chr)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chr == '\t') {
|
||||||
|
// Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=123994.
|
||||||
|
GraphicsWindow::MenuView(GraphicsWindow::MNU_SHOW_TEXT_WND);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Gtk::Window::on_key_press_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void on_editing_done(Glib::ustring value) {
|
virtual void on_editing_done(Glib::ustring value) {
|
||||||
SS.GW.EditControlDone(value.c_str());
|
SS.GW.EditControlDone(value.c_str());
|
||||||
}
|
}
|
||||||
|
@ -900,6 +910,10 @@ public:
|
||||||
accel_key = GDK_KEY_Escape;
|
accel_key = GDK_KEY_Escape;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '\t':
|
||||||
|
accel_key = GDK_KEY_Tab;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
accel_key = _entry.accel & ~(GraphicsWindow::SHIFT_MASK | GraphicsWindow::CTRL_MASK);
|
accel_key = _entry.accel & ~(GraphicsWindow::SHIFT_MASK | GraphicsWindow::CTRL_MASK);
|
||||||
if(accel_key > GraphicsWindow::FUNCTION_KEY_BASE &&
|
if(accel_key > GraphicsWindow::FUNCTION_KEY_BASE &&
|
||||||
|
@ -1069,6 +1083,7 @@ static std::string ConvertFilters(std::string active, const FileFilter ssFilters
|
||||||
for(const char *const *ssPattern = ssFilter->patterns; *ssPattern; ssPattern++) {
|
for(const char *const *ssPattern = ssFilter->patterns; *ssPattern; ssPattern++) {
|
||||||
std::string pattern = "*." + std::string(*ssPattern);
|
std::string pattern = "*." + std::string(*ssPattern);
|
||||||
filter->add_pattern(pattern);
|
filter->add_pattern(pattern);
|
||||||
|
filter->add_pattern(Glib::ustring(pattern).uppercase());
|
||||||
if(active == "")
|
if(active == "")
|
||||||
active = pattern.substr(2);
|
active = pattern.substr(2);
|
||||||
if("*." + active == pattern)
|
if("*." + active == pattern)
|
||||||
|
@ -1324,7 +1339,7 @@ public:
|
||||||
set_type_hint(Gdk::WINDOW_TYPE_HINT_UTILITY);
|
set_type_hint(Gdk::WINDOW_TYPE_HINT_UTILITY);
|
||||||
set_skip_taskbar_hint(true);
|
set_skip_taskbar_hint(true);
|
||||||
set_skip_pager_hint(true);
|
set_skip_pager_hint(true);
|
||||||
set_title("SolveSpace - Browser");
|
set_title("SolveSpace - Property Browser");
|
||||||
set_default_size(420, 300);
|
set_default_size(420, 300);
|
||||||
|
|
||||||
_box.pack_start(_overlay, true, true);
|
_box.pack_start(_overlay, true, true);
|
||||||
|
@ -1391,6 +1406,14 @@ protected:
|
||||||
return _widget.event((GdkEvent*) event);
|
return _widget.event((GdkEvent*) event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool on_key_press_event(GdkEventKey *event) {
|
||||||
|
if(GW->emulate_key_press(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Gtk::Window::on_key_press_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Gtk::VScrollbar _scrollbar;
|
Gtk::VScrollbar _scrollbar;
|
||||||
TextWidget _widget;
|
TextWidget _widget;
|
||||||
|
@ -1497,7 +1520,7 @@ static GdkFilterReturn GdkSpnavFilter(GdkXEvent *gxevent, GdkEvent *, gpointer)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPNAV_EVENT_BUTTON:
|
case SPNAV_EVENT_BUTTON:
|
||||||
if(!sev.button.press && sev.button.bnum == SI_APP_FIT_BUTTON) {
|
if(!sev.button.press && sev.button.bnum == 0) {
|
||||||
SS.GW.SpaceNavigatorButtonUp();
|
SS.GW.SpaceNavigatorButtonUp();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1553,6 +1576,17 @@ int main(int argc, char** argv) {
|
||||||
TW->show_all();
|
TW->show_all();
|
||||||
GW->show_all();
|
GW->show_all();
|
||||||
|
|
||||||
|
#ifdef HAVE_SPACEWARE
|
||||||
|
#ifdef HAVE_GTK3
|
||||||
|
// We don't care if it can't be opened; just continue without.
|
||||||
|
spnav_x11_open(gdk_x11_get_default_xdisplay(),
|
||||||
|
gdk_x11_window_get_xid(GW->get_window()->gobj()));
|
||||||
|
#else
|
||||||
|
spnav_x11_open(gdk_x11_get_default_xdisplay(),
|
||||||
|
GDK_WINDOW_XWINDOW(GW->get_window()->gobj()));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
SS.Init();
|
SS.Init();
|
||||||
|
|
||||||
if(argc >= 2) {
|
if(argc >= 2) {
|
||||||
|
|
|
@ -902,12 +902,21 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
void ImportDxf(const std::string &filename) {
|
void ImportDxf(const std::string &filename) {
|
||||||
dxfRW dxf(filename.c_str());
|
|
||||||
DxfReadInterface interface;
|
DxfReadInterface interface;
|
||||||
interface.clearBlockTransform();
|
interface.clearBlockTransform();
|
||||||
if(!dxf.read(&interface, false)) {
|
|
||||||
Error("Corrupted DXF file!");
|
std::string data;
|
||||||
|
if(!ReadFile(filename, &data)) {
|
||||||
|
Error("Couldn't read from '%s'", filename.c_str());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SS.UndoRemember();
|
||||||
|
std::stringstream stream(data);
|
||||||
|
if(!dxfRW().read(stream, &interface, /*ext=*/false)) {
|
||||||
|
Error("Corrupted DXF file.");
|
||||||
|
}
|
||||||
|
|
||||||
if(interface.unknownEntities > 0) {
|
if(interface.unknownEntities > 0) {
|
||||||
Message(ssprintf("%u DXF entities of unknown type were ignored.",
|
Message(ssprintf("%u DXF entities of unknown type were ignored.",
|
||||||
interface.unknownEntities).c_str());
|
interface.unknownEntities).c_str());
|
||||||
|
@ -915,12 +924,21 @@ void ImportDxf(const std::string &filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImportDwg(const std::string &filename) {
|
void ImportDwg(const std::string &filename) {
|
||||||
dwgR dwg(filename.c_str());
|
|
||||||
DxfReadInterface interface;
|
DxfReadInterface interface;
|
||||||
interface.clearBlockTransform();
|
interface.clearBlockTransform();
|
||||||
if(!dwg.read(&interface, false)) {
|
|
||||||
Error("Corrupted DWG file!");
|
std::string data;
|
||||||
|
if(!ReadFile(filename, &data)) {
|
||||||
|
Error("Couldn't read from '%s'", filename.c_str());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SS.UndoRemember();
|
||||||
|
std::stringstream stream(data);
|
||||||
|
if(!dwgR().read(stream, &interface, /*ext=*/false)) {
|
||||||
|
Error("Corrupted DWG file.");
|
||||||
|
}
|
||||||
|
|
||||||
if(interface.unknownEntities > 0) {
|
if(interface.unknownEntities > 0) {
|
||||||
Message(ssprintf("%u DWG entities of unknown type were ignored.",
|
Message(ssprintf("%u DWG entities of unknown type were ignored.",
|
||||||
interface.unknownEntities).c_str());
|
interface.unknownEntities).c_str());
|
||||||
|
|
|
@ -34,7 +34,8 @@ void SMesh::AddTriangle(STriMeta meta, Vector a, Vector b, Vector c) {
|
||||||
AddTriangle(&t);
|
AddTriangle(&t);
|
||||||
}
|
}
|
||||||
void SMesh::AddTriangle(STriangle *st) {
|
void SMesh::AddTriangle(STriangle *st) {
|
||||||
if(st->meta.color.alpha != 255) isTransparent = true;
|
RgbaColor color = st->meta.color;
|
||||||
|
if(color.ToARGB32() != 0 && color.alpha != 255) isTransparent = true;
|
||||||
l.Add(st);
|
l.Add(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -463,6 +463,15 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
pending.operation != DRAGGING_MARQUEE)
|
pending.operation != DRAGGING_MARQUEE)
|
||||||
{
|
{
|
||||||
SS.GenerateAll();
|
SS.GenerateAll();
|
||||||
|
|
||||||
|
// Activate degraded mode, and regenerate display items without edges.
|
||||||
|
if(activeGroup.v != 0) {
|
||||||
|
bool showEdges = SS.GW.showEdges;
|
||||||
|
SS.GW.showEdges = false;
|
||||||
|
SK.GetGroup(activeGroup)->GenerateDisplayItems();
|
||||||
|
SS.GW.showEdges = showEdges;
|
||||||
|
isDegraded = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,6 +479,12 @@ void GraphicsWindow::ClearPending(void) {
|
||||||
pending.points.Clear();
|
pending.points.Clear();
|
||||||
pending = {};
|
pending = {};
|
||||||
SS.ScheduleShowTW();
|
SS.ScheduleShowTW();
|
||||||
|
|
||||||
|
// If degraded mode was enabled, we need to regenerate again to get edges back.
|
||||||
|
if(isDegraded) {
|
||||||
|
isDegraded = false;
|
||||||
|
SK.GetGroup(activeGroup)->displayDirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsWindow::MouseMiddleOrRightDown(double x, double y) {
|
void GraphicsWindow::MouseMiddleOrRightDown(double x, double y) {
|
||||||
|
@ -619,7 +634,7 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SS.clipboard.r.n > 0 && LockedInWorkplane()) {
|
if((SS.clipboard.r.n > 0 || SS.clipboard.c.n > 0) && LockedInWorkplane()) {
|
||||||
AddContextMenuItem("Paste", CMNU_PASTE);
|
AddContextMenuItem("Paste", CMNU_PASTE);
|
||||||
AddContextMenuItem("Paste Transformed...", CMNU_PASTE_XFRM);
|
AddContextMenuItem("Paste Transformed...", CMNU_PASTE_XFRM);
|
||||||
}
|
}
|
||||||
|
@ -892,6 +907,9 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
||||||
if(ToolbarMouseDown((int)mx, (int)my)) return;
|
if(ToolbarMouseDown((int)mx, (int)my)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This will be clobbered by MouseMoved below.
|
||||||
|
SuggestedConstraint constraintSuggestion = SS.GW.pending.suggestion;
|
||||||
|
|
||||||
// Make sure the hover is up to date.
|
// Make sure the hover is up to date.
|
||||||
MouseMoved(mx, my, false, false, false, false, false);
|
MouseMoved(mx, my, false, false, false, false, false);
|
||||||
orig.mouse.x = mx;
|
orig.mouse.x = mx;
|
||||||
|
@ -903,7 +921,8 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
||||||
v = v.Plus(projRight.ScaledBy(mx/scale));
|
v = v.Plus(projRight.ScaledBy(mx/scale));
|
||||||
v = v.Plus(projUp.ScaledBy(my/scale));
|
v = v.Plus(projUp.ScaledBy(my/scale));
|
||||||
|
|
||||||
hRequest hr;
|
hRequest hr = {};
|
||||||
|
hConstraint hc = {};
|
||||||
switch(pending.operation) {
|
switch(pending.operation) {
|
||||||
case MNU_DATUM_POINT:
|
case MNU_DATUM_POINT:
|
||||||
hr = AddRequest(Request::DATUM_POINT);
|
hr = AddRequest(Request::DATUM_POINT);
|
||||||
|
@ -958,6 +977,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
||||||
pending.operation = DRAGGING_NEW_POINT;
|
pending.operation = DRAGGING_NEW_POINT;
|
||||||
pending.point = lns[1].entity(2);
|
pending.point = lns[1].entity(2);
|
||||||
pending.description = "click to place other corner of rectangle";
|
pending.description = "click to place other corner of rectangle";
|
||||||
|
hr = lns[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MNU_CIRCLE:
|
case MNU_CIRCLE:
|
||||||
|
@ -1060,7 +1080,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
||||||
c.type = Constraint::COMMENT;
|
c.type = Constraint::COMMENT;
|
||||||
c.disp.offset = v;
|
c.disp.offset = v;
|
||||||
c.comment = "NEW COMMENT -- DOUBLE-CLICK TO EDIT";
|
c.comment = "NEW COMMENT -- DOUBLE-CLICK TO EDIT";
|
||||||
Constraint::AddConstraint(&c);
|
hc = Constraint::AddConstraint(&c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1127,8 +1147,8 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
||||||
|
|
||||||
case DRAGGING_NEW_LINE_POINT: {
|
case DRAGGING_NEW_LINE_POINT: {
|
||||||
// Constrain the line segment horizontal or vertical if close enough
|
// Constrain the line segment horizontal or vertical if close enough
|
||||||
if(SS.GW.pending.suggestion != SUGGESTED_NONE) {
|
if(constraintSuggestion != SUGGESTED_NONE) {
|
||||||
Constraint::Constrain(SS.GW.pending.suggestion,
|
Constraint::Constrain(constraintSuggestion,
|
||||||
Entity::NO_ENTITY, Entity::NO_ENTITY, pending.request.entity(0));
|
Entity::NO_ENTITY, Entity::NO_ENTITY, pending.request.entity(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1185,6 +1205,20 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Activate group with newly created request/constraint
|
||||||
|
Group *g = NULL;
|
||||||
|
if(hr.v != 0) {
|
||||||
|
Request *req = SK.GetRequest(hr);
|
||||||
|
g = SK.GetGroup(req->group);
|
||||||
|
}
|
||||||
|
if(hc.v != 0) {
|
||||||
|
Constraint *c = SK.GetConstraint(hc);
|
||||||
|
g = SK.GetGroup(c->group);
|
||||||
|
}
|
||||||
|
if(g != NULL) {
|
||||||
|
g->visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
SS.ScheduleShowTW();
|
SS.ScheduleShowTW();
|
||||||
InvalidateGraphics();
|
InvalidateGraphics();
|
||||||
}
|
}
|
||||||
|
|
|
@ -827,7 +827,7 @@ public:
|
||||||
|
|
||||||
static void CreateAllDefaultStyles(void);
|
static void CreateAllDefaultStyles(void);
|
||||||
static void CreateDefaultStyle(hStyle h);
|
static void CreateDefaultStyle(hStyle h);
|
||||||
static void FillDefaultStyle(Style *s, const Default *d = NULL);
|
static void FillDefaultStyle(Style *s, const Default *d = NULL, bool factory = false);
|
||||||
static void FreezeDefaultStyles(void);
|
static void FreezeDefaultStyles(void);
|
||||||
static void LoadFactoryDefaults(void);
|
static void LoadFactoryDefaults(void);
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,6 @@ bool SolveSpaceUI::OpenFile(const std::string &filename) {
|
||||||
saveFile = filename;
|
saveFile = filename;
|
||||||
bool success = fileLoaded && ReloadAllImported(/*canCancel=*/true);
|
bool success = fileLoaded && ReloadAllImported(/*canCancel=*/true);
|
||||||
if(success) {
|
if(success) {
|
||||||
RemoveAutosave();
|
|
||||||
AddToRecentList(filename);
|
AddToRecentList(filename);
|
||||||
} else {
|
} else {
|
||||||
saveFile = "";
|
saveFile = "";
|
||||||
|
@ -144,9 +143,6 @@ bool SolveSpaceUI::OpenFile(const std::string &filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SolveSpaceUI::Exit(void) {
|
void SolveSpaceUI::Exit(void) {
|
||||||
if(!OkayToStartNewFile())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Recent files
|
// Recent files
|
||||||
for(int i = 0; i < MAX_RECENT; i++)
|
for(int i = 0; i < MAX_RECENT; i++)
|
||||||
CnfFreezeString(RecentFile[i], "RecentFile_" + std::to_string(i));
|
CnfFreezeString(RecentFile[i], "RecentFile_" + std::to_string(i));
|
||||||
|
@ -221,9 +217,6 @@ void SolveSpaceUI::Exit(void) {
|
||||||
// And the default styles, colors and line widths and such.
|
// And the default styles, colors and line widths and such.
|
||||||
Style::FreezeDefaultStyles();
|
Style::FreezeDefaultStyles();
|
||||||
|
|
||||||
// Exiting cleanly.
|
|
||||||
RemoveAutosave();
|
|
||||||
|
|
||||||
ExitNow();
|
ExitNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,6 +411,7 @@ bool SolveSpaceUI::OkayToStartNewFile(void) {
|
||||||
return GetFilenameAndSave(false);
|
return GetFilenameAndSave(false);
|
||||||
|
|
||||||
case DIALOG_NO:
|
case DIALOG_NO:
|
||||||
|
RemoveAutosave();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case DIALOG_CANCEL:
|
case DIALOG_CANCEL:
|
||||||
|
@ -433,8 +427,11 @@ void SolveSpaceUI::UpdateWindowTitle(void) {
|
||||||
|
|
||||||
static std::string Extension(const std::string &filename) {
|
static std::string Extension(const std::string &filename) {
|
||||||
int dot = filename.rfind('.');
|
int dot = filename.rfind('.');
|
||||||
if(dot >= 0)
|
if(dot >= 0) {
|
||||||
return filename.substr(dot + 1, filename.length());
|
std::string ext = filename.substr(dot + 1, filename.length());
|
||||||
|
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
|
||||||
|
return ext;
|
||||||
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,7 +551,10 @@ void SolveSpaceUI::MenuFile(int id) {
|
||||||
ImportDxf(importFile);
|
ImportDxf(importFile);
|
||||||
} else if(Extension(importFile) == "dwg") {
|
} else if(Extension(importFile) == "dwg") {
|
||||||
ImportDwg(importFile);
|
ImportDwg(importFile);
|
||||||
} else oops();
|
} else {
|
||||||
|
Error("Can't identify file type from file extension of "
|
||||||
|
"filename '%s'; try .dxf or .dwg.", importFile.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
SS.GenerateAll(SolveSpaceUI::GENERATE_UNTIL_ACTIVE);
|
SS.GenerateAll(SolveSpaceUI::GENERATE_UNTIL_ACTIVE);
|
||||||
SS.ScheduleShowTW();
|
SS.ScheduleShowTW();
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <sstream>
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
# include <windows.h> // required by GL headers
|
# include <windows.h> // required by GL headers
|
||||||
#endif
|
#endif
|
||||||
|
@ -135,6 +136,7 @@ class RgbaColor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FILE *ssfopen(const std::string &filename, const char *mode);
|
FILE *ssfopen(const std::string &filename, const char *mode);
|
||||||
|
std::fstream ssfstream(const std::string &filename, std::ios_base::openmode mode);
|
||||||
void ssremove(const std::string &filename);
|
void ssremove(const std::string &filename);
|
||||||
|
|
||||||
#define MAX_RECENT 8
|
#define MAX_RECENT 8
|
||||||
|
@ -374,6 +376,8 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
|
||||||
double a41, double a42, double a43, double a44);
|
double a41, double a42, double a43, double a44);
|
||||||
std::string MakeAcceleratorLabel(int accel);
|
std::string MakeAcceleratorLabel(int accel);
|
||||||
bool FilenameHasExtension(const std::string &str, const char *ext);
|
bool FilenameHasExtension(const std::string &str, const char *ext);
|
||||||
|
bool ReadFile(const std::string &filename, std::string *data);
|
||||||
|
bool WriteFile(const std::string &filename, const std::string &data);
|
||||||
void Message(const char *str, ...);
|
void Message(const char *str, ...);
|
||||||
void Error(const char *str, ...);
|
void Error(const char *str, ...);
|
||||||
void CnfFreezeBool(bool v, const std::string &name);
|
void CnfFreezeBool(bool v, const std::string &name);
|
||||||
|
@ -908,6 +912,7 @@ public:
|
||||||
void GenerateAll(GenerateType type = GENERATE_DIRTY, bool andFindFree = false,
|
void GenerateAll(GenerateType type = GENERATE_DIRTY, bool andFindFree = false,
|
||||||
bool genForBBox = false);
|
bool genForBBox = false);
|
||||||
void SolveGroup(hGroup hg, bool andFindFree);
|
void SolveGroup(hGroup hg, bool andFindFree);
|
||||||
|
void SolveGroupAndReport(hGroup hg, bool andFindFree);
|
||||||
void MarkDraggedParams(void);
|
void MarkDraggedParams(void);
|
||||||
void ForceReferences(void);
|
void ForceReferences(void);
|
||||||
|
|
||||||
|
|
|
@ -426,6 +426,7 @@ void SSurface::TriangulateInto(SShell *shell, SMesh *sm) {
|
||||||
for(i = start; i < sm->l.n; i++) {
|
for(i = start; i < sm->l.n; i++) {
|
||||||
STriangle *st = &(sm->l.elem[i]);
|
STriangle *st = &(sm->l.elem[i]);
|
||||||
st->meta = meta;
|
st->meta = meta;
|
||||||
|
if(st->meta.color.alpha != 255) sm->isTransparent = true;
|
||||||
st->an = NormalAt(st->a.x, st->a.y);
|
st->an = NormalAt(st->a.x, st->a.y);
|
||||||
st->bn = NormalAt(st->b.x, st->b.y);
|
st->bn = NormalAt(st->b.x, st->b.y);
|
||||||
st->cn = NormalAt(st->c.x, st->c.y);
|
st->cn = NormalAt(st->c.x, st->c.y);
|
||||||
|
|
|
@ -83,12 +83,13 @@ void Style::CreateDefaultStyle(hStyle h) {
|
||||||
SK.style.Add(&ns);
|
SK.style.Add(&ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Style::FillDefaultStyle(Style *s, const Default *d) {
|
void Style::FillDefaultStyle(Style *s, const Default *d, bool factory) {
|
||||||
if(d == NULL) d = &Defaults[0];
|
if(d == NULL) d = &Defaults[0];
|
||||||
s->color = CnfThawColor(d->color, CnfColor(d->cnfPrefix));
|
s->color = (factory) ? d->color : CnfThawColor(d->color, CnfColor(d->cnfPrefix));
|
||||||
s->width = CnfThawFloat((float)(d->width), CnfWidth(d->cnfPrefix));
|
s->width = (factory) ? d->width : CnfThawFloat((float)(d->width), CnfWidth(d->cnfPrefix));
|
||||||
s->widthAs = UNITS_AS_PIXELS;
|
s->widthAs = UNITS_AS_PIXELS;
|
||||||
s->textHeight = CnfThawFloat(DEFAULT_TEXT_HEIGHT, CnfTextHeight(d->cnfPrefix));
|
s->textHeight = (factory) ? DEFAULT_TEXT_HEIGHT
|
||||||
|
: CnfThawFloat(DEFAULT_TEXT_HEIGHT, CnfTextHeight(d->cnfPrefix));
|
||||||
s->textHeightAs = UNITS_AS_PIXELS;
|
s->textHeightAs = UNITS_AS_PIXELS;
|
||||||
s->textOrigin = 0;
|
s->textOrigin = 0;
|
||||||
s->textAngle = 0;
|
s->textAngle = 0;
|
||||||
|
@ -106,7 +107,7 @@ void Style::LoadFactoryDefaults(void) {
|
||||||
const Default *d;
|
const Default *d;
|
||||||
for(d = &(Defaults[0]); d->h.v; d++) {
|
for(d = &(Defaults[0]); d->h.v; d++) {
|
||||||
Style *s = Get(d->h);
|
Style *s = Get(d->h);
|
||||||
FillDefaultStyle(s, d);
|
FillDefaultStyle(s, d, /*factory=*/true);
|
||||||
}
|
}
|
||||||
SS.backgroundColor = RGBi(0, 0, 0);
|
SS.backgroundColor = RGBi(0, 0, 0);
|
||||||
if(SS.bgImage.fromFile) MemFree(SS.bgImage.fromFile);
|
if(SS.bgImage.fromFile) MemFree(SS.bgImage.fromFile);
|
||||||
|
|
|
@ -463,10 +463,8 @@ int System::Solve(Group *g, int *dof, List<hConstraint> *bad,
|
||||||
if(!rankOk) {
|
if(!rankOk) {
|
||||||
if(!g->allowRedundant) {
|
if(!g->allowRedundant) {
|
||||||
if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad);
|
if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad);
|
||||||
return System::REDUNDANT_OKAY;
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
|
||||||
// This is not the full Jacobian, but any substitutions or single-eq
|
// This is not the full Jacobian, but any substitutions or single-eq
|
||||||
// solves removed one equation and one unknown, therefore no effect
|
// solves removed one equation and one unknown, therefore no effect
|
||||||
// on the number of DOF.
|
// on the number of DOF.
|
||||||
|
@ -492,7 +490,7 @@ int System::Solve(Group *g, int *dof, List<hConstraint> *bad,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// System solved correctly, so write the new values back in to the
|
// System solved correctly, so write the new values back in to the
|
||||||
// main parameter table.
|
// main parameter table.
|
||||||
for(i = 0; i < param.n; i++) {
|
for(i = 0; i < param.n; i++) {
|
||||||
|
|
|
@ -988,7 +988,7 @@ void TextWindow::MouseEvent(bool leftClick, bool leftDown, double x, double y) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(r >= rows) {
|
if(r < 0 || c < 0 || r >= rows || c >= MAX_COLS) {
|
||||||
SetMousePointerToHand(false);
|
SetMousePointerToHand(false);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
76
src/ttf.cpp
76
src/ttf.cpp
|
@ -88,7 +88,9 @@ void TtfFontList::PlotString(const std::string &font, const std::string &str,
|
||||||
[&](const TtfFont &tf) { return tf.FontFileBaseName() == font; });
|
[&](const TtfFont &tf) { return tf.FontFileBaseName() == font; });
|
||||||
|
|
||||||
if(!str.empty() && tf != &l.elem[l.n]) {
|
if(!str.empty() && tf != &l.elem[l.n]) {
|
||||||
|
if(tf->fontFace == NULL) {
|
||||||
tf->LoadFromFile(fontLibrary, /*nameOnly=*/false);
|
tf->LoadFromFile(fontLibrary, /*nameOnly=*/false);
|
||||||
|
}
|
||||||
tf->PlotString(str, sbl, origin, u, v);
|
tf->PlotString(str, sbl, origin, u, v);
|
||||||
} else {
|
} else {
|
||||||
// No text or no font; so draw a big X for an error marker.
|
// No text or no font; so draw a big X for an error marker.
|
||||||
|
@ -135,6 +137,7 @@ bool TtfFont::LoadFromFile(FT_Library fontLibrary, bool nameOnly) {
|
||||||
dbp("freetype: loading unicode CMap for file '%s' failed: %s",
|
dbp("freetype: loading unicode CMap for file '%s' failed: %s",
|
||||||
fontFile.c_str(), ft_error_string(fterr));
|
fontFile.c_str(), ft_error_string(fterr));
|
||||||
FT_Done_Face(fontFace);
|
FT_Done_Face(fontFace);
|
||||||
|
fontFace = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +147,47 @@ bool TtfFont::LoadFromFile(FT_Library fontLibrary, bool nameOnly) {
|
||||||
if(nameOnly) {
|
if(nameOnly) {
|
||||||
FT_Done_Face(fontFace);
|
FT_Done_Face(fontFace);
|
||||||
fontFace = NULL;
|
fontFace = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We always ask Freetype to give us a unit size character.
|
||||||
|
// It uses fixed point; put the unit size somewhere in the middle of the dynamic
|
||||||
|
// range of its 26.6 fixed point type, and adjust the factors so that the unit
|
||||||
|
// matches cap height.
|
||||||
|
FT_Size_RequestRec sizeRequest;
|
||||||
|
sizeRequest.type = FT_SIZE_REQUEST_TYPE_REAL_DIM;
|
||||||
|
sizeRequest.width = 1 << 16;
|
||||||
|
sizeRequest.height = 1 << 16;
|
||||||
|
sizeRequest.horiResolution = 128;
|
||||||
|
sizeRequest.vertResolution = 128;
|
||||||
|
if(int fterr = FT_Request_Size(fontFace, &sizeRequest)) {
|
||||||
|
dbp("freetype: cannot set character size: %s",
|
||||||
|
ft_error_string(fterr));
|
||||||
|
FT_Done_Face(fontFace);
|
||||||
|
fontFace = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char chr = 'A';
|
||||||
|
uint32_t gid = FT_Get_Char_Index(fontFace, 'A');
|
||||||
|
if (gid == 0) {
|
||||||
|
dbp("freetype: CID-to-GID mapping for CID 0x%04x failed: %s; using CID as GID",
|
||||||
|
chr, ft_error_string(gid));
|
||||||
|
gid = chr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(gid) {
|
||||||
|
if(int fterr = FT_Load_Glyph(fontFace, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING)) {
|
||||||
|
dbp("freetype: cannot load glyph for GID 0x%04x: %s",
|
||||||
|
gid, ft_error_string(fterr));
|
||||||
|
FT_Done_Face(fontFace);
|
||||||
|
fontFace = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_BBox bbox;
|
||||||
|
FT_Outline_Get_CBox(&fontFace->glyph->outline, &bbox);
|
||||||
|
capHeight = (double)bbox.yMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -211,28 +255,26 @@ static int CubicTo(const FT_Vector *c1, const FT_Vector *c2, const FT_Vector *p,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const FT_Outline_Funcs outline_funcs = {
|
|
||||||
MoveTo, LineTo, ConicTo, CubicTo, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
void TtfFont::PlotString(const std::string &str,
|
void TtfFont::PlotString(const std::string &str,
|
||||||
SBezierList *sbl, Vector origin, Vector u, Vector v)
|
SBezierList *sbl, Vector origin, Vector u, Vector v)
|
||||||
{
|
{
|
||||||
if(fontFace == NULL) oops();
|
if(fontFace == NULL) oops();
|
||||||
|
|
||||||
|
FT_Outline_Funcs outlineFuncs;
|
||||||
|
outlineFuncs.move_to = MoveTo;
|
||||||
|
outlineFuncs.line_to = LineTo;
|
||||||
|
outlineFuncs.conic_to = ConicTo;
|
||||||
|
outlineFuncs.cubic_to = CubicTo;
|
||||||
|
outlineFuncs.shift = 0;
|
||||||
|
outlineFuncs.delta = 0;
|
||||||
|
|
||||||
FT_Pos dx = 0;
|
FT_Pos dx = 0;
|
||||||
for(char32_t chr : ReadUTF8(str)) {
|
for(char32_t cid : ReadUTF8(str)) {
|
||||||
uint32_t gid = FT_Get_Char_Index(fontFace, chr);
|
uint32_t gid = FT_Get_Char_Index(fontFace, cid);
|
||||||
if (gid == 0) {
|
if (gid == 0) {
|
||||||
dbp("freetype: CID-to-GID mapping for CID 0x%04x failed: %s; using CID as GID",
|
dbp("freetype: CID-to-GID mapping for CID 0x%04x failed: %s; using CID as GID",
|
||||||
chr, ft_error_string(gid));
|
cid, ft_error_string(gid));
|
||||||
}
|
gid = cid;
|
||||||
|
|
||||||
FT_F26Dot6 scale = fontFace->units_per_EM;
|
|
||||||
if(int fterr = FT_Set_Char_Size(fontFace, scale, scale, 72, 72)) {
|
|
||||||
dbp("freetype: cannot set character size: %s",
|
|
||||||
ft_error_string(fterr));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -244,7 +286,7 @@ void TtfFont::PlotString(const std::string &str,
|
||||||
* ones, antialiasing mitigates this considerably though.
|
* ones, antialiasing mitigates this considerably though.
|
||||||
*/
|
*/
|
||||||
if(int fterr = FT_Load_Glyph(fontFace, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING)) {
|
if(int fterr = FT_Load_Glyph(fontFace, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING)) {
|
||||||
dbp("freetype: cannot load glyph (gid %d): %s",
|
dbp("freetype: cannot load glyph for GID 0x%04x: %s",
|
||||||
gid, ft_error_string(fterr));
|
gid, ft_error_string(fterr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -274,9 +316,9 @@ void TtfFont::PlotString(const std::string &str,
|
||||||
data.u = u;
|
data.u = u;
|
||||||
data.v = v;
|
data.v = v;
|
||||||
data.beziers = sbl;
|
data.beziers = sbl;
|
||||||
data.factor = 1.0f/(float)scale;
|
data.factor = 1.0 / capHeight;
|
||||||
data.bx = bx;
|
data.bx = bx;
|
||||||
if(int fterr = FT_Outline_Decompose(&fontFace->glyph->outline, &outline_funcs, &data)) {
|
if(int fterr = FT_Outline_Decompose(&fontFace->glyph->outline, &outlineFuncs, &data)) {
|
||||||
dbp("freetype: bezier decomposition failed (gid %d): %s",
|
dbp("freetype: bezier decomposition failed (gid %d): %s",
|
||||||
gid, ft_error_string(fterr));
|
gid, ft_error_string(fterr));
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ public:
|
||||||
std::string fontFile;
|
std::string fontFile;
|
||||||
std::string name;
|
std::string name;
|
||||||
FT_FaceRec_ *fontFace;
|
FT_FaceRec_ *fontFace;
|
||||||
|
double capHeight;
|
||||||
|
|
||||||
std::string FontFileBaseName() const;
|
std::string FontFileBaseName() const;
|
||||||
bool LoadFromFile(FT_LibraryRec_ *fontLibrary, bool nameOnly = true);
|
bool LoadFromFile(FT_LibraryRec_ *fontLibrary, bool nameOnly = true);
|
||||||
|
|
17
src/ui.h
17
src/ui.h
|
@ -504,6 +504,9 @@ public:
|
||||||
// allowing a paint in between. The extra solves are wasted if they're
|
// allowing a paint in between. The extra solves are wasted if they're
|
||||||
// not displayed.
|
// not displayed.
|
||||||
bool havePainted;
|
bool havePainted;
|
||||||
|
// Similarly, don't draw edges and outlines, since that's too slow
|
||||||
|
// for real-time dragging.
|
||||||
|
bool isDegraded;
|
||||||
|
|
||||||
// Some state for the context menu.
|
// Some state for the context menu.
|
||||||
struct {
|
struct {
|
||||||
|
@ -629,14 +632,13 @@ public:
|
||||||
void HitTestMakeSelection(Point2d mp);
|
void HitTestMakeSelection(Point2d mp);
|
||||||
void ClearSelection(void);
|
void ClearSelection(void);
|
||||||
void ClearNonexistentSelectionItems(void);
|
void ClearNonexistentSelectionItems(void);
|
||||||
enum { MAX_SELECTED = 32 };
|
|
||||||
struct {
|
struct {
|
||||||
hEntity point[MAX_SELECTED];
|
std::vector<hEntity> point;
|
||||||
hEntity entity[MAX_SELECTED];
|
std::vector<hEntity> entity;
|
||||||
hEntity anyNormal[MAX_SELECTED];
|
std::vector<hEntity> anyNormal;
|
||||||
hEntity vector[MAX_SELECTED];
|
std::vector<hEntity> vector;
|
||||||
hEntity face[MAX_SELECTED];
|
std::vector<hEntity> face;
|
||||||
hConstraint constraint[MAX_SELECTED];
|
std::vector<hConstraint> constraint;
|
||||||
int points;
|
int points;
|
||||||
int entities;
|
int entities;
|
||||||
int workplanes;
|
int workplanes;
|
||||||
|
@ -658,6 +660,7 @@ public:
|
||||||
bool IsSelected(Selection *s);
|
bool IsSelected(Selection *s);
|
||||||
bool IsSelected(hEntity he);
|
bool IsSelected(hEntity he);
|
||||||
void MakeSelected(hEntity he);
|
void MakeSelected(hEntity he);
|
||||||
|
void MakeSelected(hConstraint hc);
|
||||||
void MakeSelected(Selection *s);
|
void MakeSelected(Selection *s);
|
||||||
void MakeUnselected(hEntity he, bool coincidentPointTrick);
|
void MakeUnselected(hEntity he, bool coincidentPointTrick);
|
||||||
void MakeUnselected(Selection *s, bool coincidentPointTrick);
|
void MakeUnselected(Selection *s, bool coincidentPointTrick);
|
||||||
|
|
27
src/unix/solvespace-16x16.xpm
Normal file
27
src/unix/solvespace-16x16.xpm
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/* XPM */
|
||||||
|
static char *solvespace_16x16[] = {
|
||||||
|
/* columns rows colors chars-per-pixel */
|
||||||
|
"16 16 5 1 ",
|
||||||
|
" c black",
|
||||||
|
". c #1ED500",
|
||||||
|
"X c #DE00D6",
|
||||||
|
"o c #CBCBCB",
|
||||||
|
"O c None",
|
||||||
|
/* pixels */
|
||||||
|
"OOO OOOOOOOOOOOO",
|
||||||
|
"OOO OOOOOOOOOOOO",
|
||||||
|
"OOO OOOOOOOOOOOO",
|
||||||
|
"OOO OOOOOXOOOOOO",
|
||||||
|
"OOO OOOOOXoOOOOO",
|
||||||
|
"OOO OOOOOXoOOOOO",
|
||||||
|
"OOO OOOOOXoOOOOO",
|
||||||
|
"OOO OOOOOXoOOOOO",
|
||||||
|
"OOO OOOOOXoOOOOO",
|
||||||
|
"OOO OOXXXXXXXOOO",
|
||||||
|
"OOO OOOoooooooOO",
|
||||||
|
"OO...OOOOOOOOOOO",
|
||||||
|
" ... ",
|
||||||
|
"OO...OOOOOOOOOOO",
|
||||||
|
"OOO OOOOOOOOOOOO",
|
||||||
|
"OOO OOOOOOOOOOOO"
|
||||||
|
};
|
35
src/unix/solvespace-24x24.xpm
Normal file
35
src/unix/solvespace-24x24.xpm
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* XPM */
|
||||||
|
static char *solvespace_24x24[] = {
|
||||||
|
/* columns rows colors chars-per-pixel */
|
||||||
|
"24 24 5 1 ",
|
||||||
|
" c black",
|
||||||
|
". c #1ED500",
|
||||||
|
"X c #DE00D6",
|
||||||
|
"o c #CBCBCB",
|
||||||
|
"O c None",
|
||||||
|
/* pixels */
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOO OOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOO OOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOO OOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOO OOOOOXOOOOOOOOOO",
|
||||||
|
"OOOOOOO OOOOOXoOOOOOOOOO",
|
||||||
|
"OOOOOOO OOOOOXoOOOOOOOOO",
|
||||||
|
"OOOOOOO OOOOOXoOOOOOOOOO",
|
||||||
|
"OOOOOOO OOOOOXoOOOOOOOOO",
|
||||||
|
"OOOOOOO OOOOOXoOOOOOOOOO",
|
||||||
|
"OOOOOOO OOXXXXXXXOOOOOOO",
|
||||||
|
"OOOOOOO OOOoooooooOOOOOO",
|
||||||
|
"OOOOOO...OOOOOOOOOOOOOOO",
|
||||||
|
"OOOO ... OOOO",
|
||||||
|
"OOOOOO...OOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOO OOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOO OOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOO"
|
||||||
|
};
|
43
src/unix/solvespace-32x32.xpm
Normal file
43
src/unix/solvespace-32x32.xpm
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/* XPM */
|
||||||
|
static char *solvespace_32x32[] = {
|
||||||
|
/* columns rows colors chars-per-pixel */
|
||||||
|
"32 32 5 1 ",
|
||||||
|
" c black",
|
||||||
|
". c #1ED500",
|
||||||
|
"X c #DE00D6",
|
||||||
|
"o c #CBCBCB",
|
||||||
|
"O c None",
|
||||||
|
/* pixels */
|
||||||
|
"OOOOOO OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOXXOOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOXXoOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOXXoOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOXXoOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOXXoOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOXXoOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOXXoOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOXXoOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOXXoOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOXXoOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOXXoOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOXXXXXXXXXXXXOOOOOOOO",
|
||||||
|
"OOOOOO OOOOXXXXXXXXXXXXOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOooooooooooooOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOO......OOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOO......OOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
" ...... ",
|
||||||
|
" ...... ",
|
||||||
|
"OOOO......OOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOO......OOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOO OOOOOOOOOOOOOOOOOOOOOOOO"
|
||||||
|
};
|
59
src/unix/solvespace-48x48.xpm
Normal file
59
src/unix/solvespace-48x48.xpm
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/* XPM */
|
||||||
|
static char *solvespace_48x48[] = {
|
||||||
|
/* columns rows colors chars-per-pixel */
|
||||||
|
"48 48 5 1 ",
|
||||||
|
" c black",
|
||||||
|
". c #1ED500",
|
||||||
|
"X c #DE00D6",
|
||||||
|
"o c #CBCBCB",
|
||||||
|
"O c None",
|
||||||
|
/* pixels */
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOXXOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOXXoOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOXXXXXXXXXXXXOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOXXXXXXXXXXXXOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOooooooooooooOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOO......OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOO......OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOO ...... OOOOOOOO",
|
||||||
|
"OOOOOOOO ...... OOOOOOOO",
|
||||||
|
"OOOOOOOOOOOO......OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOO......OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
|
||||||
|
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"
|
||||||
|
};
|
27
src/util.cpp
27
src/util.cpp
|
@ -61,6 +61,33 @@ bool SolveSpace::FilenameHasExtension(const std::string &str, const char *ext)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SolveSpace::ReadFile(const std::string &filename, std::string *data)
|
||||||
|
{
|
||||||
|
FILE *f = ssfopen(filename.c_str(), "rb");
|
||||||
|
if(f == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
data->resize(ftell(f));
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
fread(&(*data)[0], 1, data->size(), f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SolveSpace::WriteFile(const std::string &filename, const std::string &data)
|
||||||
|
{
|
||||||
|
FILE *f = ssfopen(filename.c_str(), "wb");
|
||||||
|
if(f == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fwrite(&data[0], 1, data.size(), f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void SolveSpace::MakeMatrix(double *mat,
|
void SolveSpace::MakeMatrix(double *mat,
|
||||||
double a11, double a12, double a13, double a14,
|
double a11, double a12, double a13, double a14,
|
||||||
double a21, double a22, double a23, double a24,
|
double a21, double a22, double a23, double a24,
|
||||||
|
|
|
@ -56,6 +56,7 @@ SiHdl SpaceNavigator = SI_NO_HANDLE;
|
||||||
|
|
||||||
HWND MessageWnd, OkButton;
|
HWND MessageWnd, OkButton;
|
||||||
bool MessageDone;
|
bool MessageDone;
|
||||||
|
int MessageWidth, MessageHeight;
|
||||||
const char *MessageString;
|
const char *MessageString;
|
||||||
|
|
||||||
static LRESULT CALLBACK MessageProc(HWND hwnd, UINT msg, WPARAM wParam,
|
static LRESULT CALLBACK MessageProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||||
|
@ -76,21 +77,13 @@ static LRESULT CALLBACK MessageProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||||
case WM_PAINT: {
|
case WM_PAINT: {
|
||||||
PAINTSTRUCT ps;
|
PAINTSTRUCT ps;
|
||||||
HDC hdc = BeginPaint(hwnd, &ps);
|
HDC hdc = BeginPaint(hwnd, &ps);
|
||||||
int row = 0, col = 0, i;
|
|
||||||
SelectObject(hdc, FixedFont);
|
SelectObject(hdc, FixedFont);
|
||||||
SetTextColor(hdc, 0x000000);
|
SetTextColor(hdc, 0x000000);
|
||||||
SetBkMode(hdc, TRANSPARENT);
|
SetBkMode(hdc, TRANSPARENT);
|
||||||
for(i = 0; MessageString[i]; i++) {
|
RECT rc;
|
||||||
if(MessageString[i] == '\n') {
|
SetRect(&rc, 10, 10, MessageWidth, MessageHeight);
|
||||||
col = 0;
|
std::wstring text = Widen(MessageString);
|
||||||
row++;
|
DrawText(hdc, text.c_str(), text.length(), &rc, DT_LEFT | DT_WORDBREAK);
|
||||||
} else {
|
|
||||||
TextOutW(hdc, col*SS.TW.CHAR_WIDTH + 10,
|
|
||||||
row*SS.TW.LINE_HEIGHT + 10,
|
|
||||||
Widen(&(MessageString[i])).c_str(), 1);
|
|
||||||
col++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EndPaint(hwnd, &ps);
|
EndPaint(hwnd, &ps);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -147,6 +140,8 @@ void SolveSpace::DoMessageBox(const char *str, int rows, int cols, bool error)
|
||||||
const char *title = error ? "SolveSpace - Error" : "SolveSpace - Message";
|
const char *title = error ? "SolveSpace - Error" : "SolveSpace - Message";
|
||||||
int width = cols*SS.TW.CHAR_WIDTH + 20,
|
int width = cols*SS.TW.CHAR_WIDTH + 20,
|
||||||
height = rows*SS.TW.LINE_HEIGHT + 60;
|
height = rows*SS.TW.LINE_HEIGHT + 60;
|
||||||
|
MessageWidth = width;
|
||||||
|
MessageHeight = height;
|
||||||
MessageWnd = CreateWindowClient(0, L"MessageWnd", Widen(title).c_str(),
|
MessageWnd = CreateWindowClient(0, L"MessageWnd", Widen(title).c_str(),
|
||||||
WS_OVERLAPPED | WS_SYSMENU,
|
WS_OVERLAPPED | WS_SYSMENU,
|
||||||
r.left + 100, r.top + 100, width, height, NULL, NULL, Instance, NULL);
|
r.left + 100, r.top + 100, width, height, NULL, NULL, Instance, NULL);
|
||||||
|
@ -1299,7 +1294,7 @@ static void CreateMainWindows(void)
|
||||||
// We get the desired Alt+Tab behaviour by specifying that the text
|
// We get the desired Alt+Tab behaviour by specifying that the text
|
||||||
// window is a child of the graphics window.
|
// window is a child of the graphics window.
|
||||||
TextWnd = CreateWindowExW(0,
|
TextWnd = CreateWindowExW(0,
|
||||||
L"TextWnd", L"SolveSpace - Browser", WS_THICKFRAME | WS_CLIPCHILDREN,
|
L"TextWnd", L"SolveSpace - Property Browser", WS_THICKFRAME | WS_CLIPCHILDREN,
|
||||||
650, 500, 420, 300, GraphicsWnd, (HMENU)NULL, Instance, NULL);
|
650, 500, 420, 300, GraphicsWnd, (HMENU)NULL, Instance, NULL);
|
||||||
if(!TextWnd) oops();
|
if(!TextWnd) oops();
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ std::wstring Widen(const std::string &in)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *ssfopen(const std::string &filename, const char *mode)
|
static std::string MakeUNCFilename(const std::string &filename)
|
||||||
{
|
{
|
||||||
// Prepend \\?\ UNC prefix unless already an UNC path.
|
// Prepend \\?\ UNC prefix unless already an UNC path.
|
||||||
// We never try to fopen paths that are not absolute or
|
// We never try to fopen paths that are not absolute or
|
||||||
|
@ -76,9 +76,13 @@ FILE *ssfopen(const std::string &filename, const char *mode)
|
||||||
std::string uncFilename = filename;
|
std::string uncFilename = filename;
|
||||||
if(uncFilename.substr(0, 2) != "\\\\")
|
if(uncFilename.substr(0, 2) != "\\\\")
|
||||||
uncFilename = "\\\\?\\" + uncFilename;
|
uncFilename = "\\\\?\\" + uncFilename;
|
||||||
|
return uncFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *ssfopen(const std::string &filename, const char *mode)
|
||||||
|
{
|
||||||
if(filename.length() != strlen(filename.c_str())) oops();
|
if(filename.length() != strlen(filename.c_str())) oops();
|
||||||
return _wfopen(Widen(uncFilename).c_str(), Widen(mode).c_str());
|
return _wfopen(Widen(MakeUNCFilename(filename)).c_str(), Widen(mode).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssremove(const std::string &filename)
|
void ssremove(const std::string &filename)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user