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" == "osx" ]]; then ./.travis/build-macos.sh; fi
|
||||
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
|
||||
api_key:
|
||||
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
|
||||
tags: true
|
||||
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
|
||||
|
||||
export BUILD_TYPE
|
||||
dpkg-buildpackage -b -us -uc
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||
make VERBOSE=1
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/bin/sh -xe
|
||||
|
||||
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
|
||||
|
||||
# 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)
|
||||
# and instead uncomment the following, adding the complete git hash of the checkout you are using:
|
||||
# set(GIT_COMMIT_HASH 0000000000000000000000000000000000000000)
|
||||
|
||||
project(solvespace)
|
||||
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)
|
||||
|
||||
if(NOT WIN32 AND NOT APPLE)
|
||||
|
@ -154,6 +159,8 @@ if(WIN32)
|
|||
"${CMAKE_SOURCE_DIR}/extlib/si/siapp.lib")
|
||||
endif()
|
||||
elseif(APPLE)
|
||||
set(CMAKE_FIND_FRAMEWORK LAST)
|
||||
|
||||
find_package(PNG REQUIRED)
|
||||
find_package(Freetype REQUIRED)
|
||||
find_library(APPKIT_LIBRARY AppKit REQUIRED)
|
||||
|
|
|
@ -26,12 +26,13 @@ Building on Linux
|
|||
### Building for Linux
|
||||
|
||||
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:
|
||||
|
||||
apt-get install libpng12-dev libjson-c-dev libfreetype6-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:
|
||||
|
||||
|
|
11
appveyor.yml
11
appveyor.yml
|
@ -1,4 +1,4 @@
|
|||
version: 2.1.{build}
|
||||
version: 2.2.{build}
|
||||
clone_depth: 1
|
||||
before_build:
|
||||
- git submodule update --init
|
||||
|
@ -19,7 +19,6 @@ artifacts:
|
|||
- path: build\src\RelWithDebInfo\solvespace.pdb
|
||||
name: solvespace.pdb
|
||||
deploy:
|
||||
# Releases to solvespace/solvespace
|
||||
- provider: GitHub
|
||||
auth_token:
|
||||
secure: P9/pf2nM+jlWKe7pCjMp41HycBNP/+5AsmE/TETrDUoBOa/9WFHelqdVFrbRn9IC
|
||||
|
@ -27,11 +26,3 @@ deploy:
|
|||
artifact: solvespace.exe
|
||||
on:
|
||||
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)
|
||||
foreach(lib ${platform_BUNDLED_LIBS})
|
||||
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)
|
||||
string(REGEX REPLACE "^.+:\n" "" canonical_lib ${canonical_lib})
|
||||
add_custom_command(TARGET solvespace POST_BUILD
|
||||
COMMAND install_name_tool -change ${canonical_lib} @executable_path/${name}
|
||||
$<TARGET_FILE:solvespace>
|
||||
|
@ -380,6 +381,10 @@ foreach(SIZE 16x16 24x24 32x32 48x48)
|
|||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}/mimetypes
|
||||
RENAME application.x-solvespace.png)
|
||||
endforeach()
|
||||
foreach(SIZE 16x16 24x24 32x32 48x48)
|
||||
install(FILES unix/solvespace-${SIZE}.xpm
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pixmaps/)
|
||||
endforeach()
|
||||
|
||||
# valgrind
|
||||
|
||||
|
|
|
@ -117,6 +117,15 @@ void GraphicsWindow::CopySelection(void) {
|
|||
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;
|
||||
for(c = SK.constraint.First(); c; c = SK.constraint.NextAfter(c)) {
|
||||
if(!SS.clipboard.ContainsEntity(c->ptA) ||
|
||||
|
@ -124,7 +133,8 @@ void GraphicsWindow::CopySelection(void) {
|
|||
!SS.clipboard.ContainsEntity(c->entityA) ||
|
||||
!SS.clipboard.ContainsEntity(c->entityB) ||
|
||||
!SS.clipboard.ContainsEntity(c->entityC) ||
|
||||
!SS.clipboard.ContainsEntity(c->entityD)) {
|
||||
!SS.clipboard.ContainsEntity(c->entityD) ||
|
||||
c->type == Constraint::COMMENT) {
|
||||
continue;
|
||||
}
|
||||
SS.clipboard.c.Add(c);
|
||||
|
@ -201,7 +211,27 @@ void GraphicsWindow::PasteClipboard(Vector trans, double theta, double scale) {
|
|||
c.other2 = cc->other2;
|
||||
c.reference = cc->reference;
|
||||
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();
|
||||
|
|
|
@ -221,6 +221,9 @@ CONVERT(Rect)
|
|||
|
||||
CGContextDrawImage((CGContextRef) [[NSGraphicsContext currentContext] graphicsPort],
|
||||
[self bounds], image);
|
||||
|
||||
CGImageRelease(image);
|
||||
CGDataProviderRelease(provider);
|
||||
}
|
||||
|
||||
- (void)drawGL {
|
||||
|
@ -371,8 +374,6 @@ CONVERT(Rect)
|
|||
if(NSString *nsChr = [event charactersIgnoringModifiers])
|
||||
chr = [nsChr characterAtIndex:0];
|
||||
|
||||
if(chr == NSDeleteCharacter) /* map delete back to backspace */
|
||||
chr = '\b';
|
||||
if(chr >= NSF1FunctionKey && chr <= NSF12FunctionKey)
|
||||
chr = SolveSpace::GraphicsWindow::FUNCTION_KEY_BASE + (chr - NSF1FunctionKey);
|
||||
|
||||
|
@ -397,7 +398,7 @@ CONVERT(Rect)
|
|||
.x = xy.x + size.width / 2,
|
||||
.y = xy.y - size.height / 2
|
||||
};
|
||||
[[self window] becomeKeyWindow];
|
||||
[[self window] makeKeyWindow];
|
||||
[super startEditing:text at:[self convertPointFromBacking:point]
|
||||
withHeight:fontHeight usingMonospace:FALSE];
|
||||
[self prepareEditorWithMinWidthInChars:minWidthChars];
|
||||
|
@ -647,12 +648,15 @@ void InitMainMenu(NSMenu *mainMenu) {
|
|||
label = [[NSString stringWithUTF8String:entry->label]
|
||||
stringByReplacingOccurrencesOfString:@"&" withString:@""];
|
||||
|
||||
unichar accel_char = entry->accel &
|
||||
unichar accelChar = entry->accel &
|
||||
~(GraphicsWindow::SHIFT_MASK | GraphicsWindow::CTRL_MASK);
|
||||
if(accel_char > GraphicsWindow::FUNCTION_KEY_BASE &&
|
||||
accel_char <= GraphicsWindow::FUNCTION_KEY_BASE + 12)
|
||||
accel_char = NSF1FunctionKey + (accel_char - GraphicsWindow::FUNCTION_KEY_BASE - 1);
|
||||
NSString *accel = [NSString stringWithCharacters:&accel_char length:1];
|
||||
if(accelChar > GraphicsWindow::FUNCTION_KEY_BASE &&
|
||||
accelChar <= GraphicsWindow::FUNCTION_KEY_BASE + 12) {
|
||||
accelChar = NSF1FunctionKey + (accelChar - GraphicsWindow::FUNCTION_KEY_BASE - 1);
|
||||
} else if(accelChar == GraphicsWindow::DELETE_KEY) {
|
||||
accelChar = NSBackspaceCharacter;
|
||||
}
|
||||
NSString *accel = [NSString stringWithCharacters:&accelChar length:1];
|
||||
|
||||
menuItem = [levels[entry->level] addItemWithTitle:label
|
||||
action:NULL keyEquivalent:[accel lowercaseString]];
|
||||
|
@ -806,6 +810,9 @@ bool SolveSpace::GetSaveFile(std::string *file, const std::string &defExtension,
|
|||
if(defExtension != "") {
|
||||
extensionIndex = [extensions indexOfObject:
|
||||
[NSString stringWithUTF8String:defExtension.c_str()]];
|
||||
if(extensionIndex == -1) {
|
||||
extensionIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
[button selectItemAtIndex:extensionIndex];
|
||||
|
@ -1021,16 +1028,16 @@ void InitTextWindow() {
|
|||
NSUtilityWindowMask)];
|
||||
[[TW standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
|
||||
[[TW standardWindowButton:NSWindowZoomButton] setHidden:YES];
|
||||
[TW setTitle:@"Browser"];
|
||||
[TW setTitle:@"Property Browser"];
|
||||
[TW setFrameAutosaveName:@"TextWindow"];
|
||||
[TW setFloatingPanel:YES];
|
||||
[TW setBecomesKeyOnlyIfNeeded:YES];
|
||||
[GW addChildWindow:TW ordered:NSWindowAbove];
|
||||
|
||||
NSScrollView *scrollView = [[NSScrollView alloc] init];
|
||||
[TW setContentView:scrollView];
|
||||
[scrollView setBackgroundColor:[NSColor blackColor]];
|
||||
[scrollView setHasVerticalScroller:YES];
|
||||
[scrollView setScrollerKnobStyle:NSScrollerKnobStyleLight];
|
||||
[[scrollView contentView] setCopiesOnScroll:YES];
|
||||
|
||||
TWView = [[TextWindowView alloc] init];
|
||||
|
@ -1089,6 +1096,7 @@ bool TextEditControlIsVisible(void) {
|
|||
void SolveSpace::DoMessageBox(const char *str, int rows, int cols, bool error) {
|
||||
NSAlert *alert = [[NSAlert alloc] init];
|
||||
[alert setAlertStyle:(error ? NSWarningAlertStyle : NSInformationalAlertStyle)];
|
||||
[alert addButtonWithTitle:@"OK"];
|
||||
|
||||
/* do some additional formatting of the message these are
|
||||
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 {
|
||||
SolveSpace::SK.Clear();
|
||||
SolveSpace::SS.Clear();
|
||||
SolveSpace::SS.Exit();
|
||||
}
|
||||
|
||||
|
@ -1172,6 +1178,155 @@ void SolveSpace::ExitNow(void) {
|
|||
[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[]) {
|
||||
[NSApplication sharedApplication];
|
||||
ApplicationDelegate *delegate = [[ApplicationDelegate alloc] init];
|
||||
|
@ -1182,11 +1337,15 @@ int main(int argc, const char *argv[]) {
|
|||
[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:nil topLevelObjects:nil];
|
||||
SolveSpace::InitMainMenu([NSApp mainMenu]);
|
||||
|
||||
connexionInit();
|
||||
SolveSpace::SS.Init();
|
||||
|
||||
[GW makeKeyAndOrderFront:nil];
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
[NSApp run];
|
||||
|
||||
connexionClose();
|
||||
SolveSpace::SK.Clear();
|
||||
SolveSpace::SS.Clear();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -453,6 +453,7 @@ bool TextWindow::EditControlDoneForConfiguration(const char *s) {
|
|||
} else {
|
||||
Error("Bad format: specify interval in integral minutes");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: return false;
|
||||
|
|
|
@ -370,6 +370,7 @@ void Constraint::MenuConstrain(int id) {
|
|||
((gs.workplanes == 1 && gs.n == 3) ||
|
||||
(gs.n == 2)))
|
||||
{
|
||||
if(gs.entities > 0)
|
||||
c.entityA = gs.entity[0];
|
||||
c.ptA = gs.point[0];
|
||||
c.ptB = gs.point[1];
|
||||
|
@ -377,9 +378,13 @@ void Constraint::MenuConstrain(int id) {
|
|||
((gs.workplanes == 1 && gs.n == 2) ||
|
||||
(gs.n == 1)))
|
||||
{
|
||||
int i = SK.GetEntity(gs.entity[0])->IsWorkplane() ? 1 : 0;
|
||||
Entity *line = SK.GetEntity(gs.entity[i]);
|
||||
c.entityA = gs.entity[1-i];
|
||||
Entity *line;
|
||||
if(SK.GetEntity(gs.entity[0])->IsWorkplane()) {
|
||||
line = SK.GetEntity(gs.entity[1]);
|
||||
c.entityA = gs.entity[0];
|
||||
} else {
|
||||
line = SK.GetEntity(gs.entity[0]);
|
||||
}
|
||||
c.ptA = line->point[0];
|
||||
c.ptB = line->point[1];
|
||||
} 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;
|
||||
MakeSelected(&stog);
|
||||
}
|
||||
|
||||
void GraphicsWindow::MakeSelected(hConstraint hc) {
|
||||
Selection stog = {};
|
||||
stog.constraint = hc;
|
||||
MakeSelected(&stog);
|
||||
}
|
||||
|
||||
void GraphicsWindow::MakeSelected(Selection *stog) {
|
||||
if(stog->IsEmpty()) return;
|
||||
if(IsSelected(stog)) return;
|
||||
|
@ -242,7 +249,7 @@ void GraphicsWindow::SelectByMarquee(void) {
|
|||
void GraphicsWindow::GroupSelection(void) {
|
||||
gs = {};
|
||||
int i;
|
||||
for(i = 0; i < selection.n && i < MAX_SELECTED; i++) {
|
||||
for(i = 0; i < selection.n; i++) {
|
||||
Selection *s = &(selection.elem[i]);
|
||||
if(s->entity.v) {
|
||||
(gs.n)++;
|
||||
|
@ -253,27 +260,33 @@ void GraphicsWindow::GroupSelection(void) {
|
|||
|
||||
// A list of points, and a list of all entities that aren't points.
|
||||
if(e->IsPoint()) {
|
||||
gs.point[(gs.points)++] = s->entity;
|
||||
gs.points++;
|
||||
gs.point.push_back(s->entity);
|
||||
} else {
|
||||
gs.entity[(gs.entities)++] = s->entity;
|
||||
gs.entities++;
|
||||
gs.entity.push_back(s->entity);
|
||||
}
|
||||
|
||||
// And an auxiliary list of normals, including normals from
|
||||
// workplanes.
|
||||
if(e->IsNormal()) {
|
||||
gs.anyNormal[(gs.anyNormals)++] = s->entity;
|
||||
gs.anyNormals++;
|
||||
gs.anyNormal.push_back(s->entity);
|
||||
} 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)
|
||||
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)
|
||||
if(e->IsFace()) {
|
||||
gs.face[(gs.faces)++] = s->entity;
|
||||
gs.faces++;
|
||||
gs.face.push_back(s->entity);
|
||||
}
|
||||
|
||||
if(e->HasEndpoints()) {
|
||||
|
@ -296,7 +309,8 @@ void GraphicsWindow::GroupSelection(void) {
|
|||
}
|
||||
}
|
||||
if(s->constraint.v) {
|
||||
gs.constraint[(gs.constraints)++] = s->constraint;
|
||||
gs.constraints++;
|
||||
gs.constraint.push_back(s->constraint);
|
||||
Constraint *c = SK.GetConstraint(s->constraint);
|
||||
if(c->IsStylable()) gs.stylables++;
|
||||
if(c->HasLabel()) gs.constraintLabels++;
|
||||
|
|
|
@ -661,8 +661,8 @@ void Entity::DrawOrGetDistance(void) {
|
|||
}
|
||||
|
||||
if(!h.isFromRequest()) {
|
||||
mm = mm.Plus(v.ScaledBy(60/SS.GW.scale));
|
||||
mm2 = mm2.Plus(u.ScaledBy(60/SS.GW.scale));
|
||||
mm = mm.Plus(v.ScaledBy(70/SS.GW.scale));
|
||||
mm2 = mm2.Plus(u.ScaledBy(70/SS.GW.scale));
|
||||
LineDrawOrGetDistance(mm2, mm);
|
||||
}
|
||||
LineDrawOrGetDistance(pp, pm);
|
||||
|
@ -676,7 +676,9 @@ void Entity::DrawOrGetDistance(void) {
|
|||
std::string str = DescriptionString().substr(5);
|
||||
double th = Style::DefaultTextHeight();
|
||||
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 {
|
||||
Vector pos = mm2.Plus(u.ScaledBy(ssglStrWidth(str, th)/2)).Plus(
|
||||
v.ScaledBy(ssglStrCapHeight(th)/2));
|
||||
|
|
|
@ -859,6 +859,8 @@ void SolveSpaceUI::ExportMeshAsThreeJsTo(FILE *f, const std::string &filename,
|
|||
<script>
|
||||
</script>
|
||||
<script>
|
||||
window.devicePixelRatio = window.devicePixelRatio || 1;
|
||||
|
||||
SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset) {
|
||||
THREE.Camera.call(this);
|
||||
|
||||
|
@ -1014,13 +1016,13 @@ SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset)
|
|||
|
||||
switch (event.button) {
|
||||
case 0:
|
||||
_rotateCur.set(event.screenX, event.screenY);
|
||||
_rotateCur.set(event.screenX/window.devicePixelRatio, event.screenY/window.devicePixelRatio);
|
||||
_rotatePrev.copy(_rotateCur);
|
||||
document.addEventListener('mousemove', mousemove, false);
|
||||
document.addEventListener('mouseup', mouseup, false);
|
||||
break;
|
||||
case 2:
|
||||
_offsetCur.set(event.screenX, event.screenY);
|
||||
_offsetCur.set(event.screenX/window.devicePixelRatio, event.screenY/window.devicePixelRatio);
|
||||
_offsetPrev.copy(_offsetCur);
|
||||
document.addEventListener('mousemove', mousemove, false);
|
||||
document.addEventListener('mouseup', mouseup, false);
|
||||
|
@ -1043,7 +1045,7 @@ SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset)
|
|||
function mousemove(event) {
|
||||
switch (event.button) {
|
||||
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)
|
||||
.multiplyScalar(1 / 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;
|
||||
case 2:
|
||||
_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)
|
||||
.multiplyScalar(1 / object.zoomScale);
|
||||
object.offsetProj(diff.x, -diff.y);
|
||||
|
@ -1197,6 +1199,9 @@ SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset)
|
|||
height = params.height;
|
||||
}
|
||||
|
||||
width *= window.devicePixelRatio;
|
||||
height *= window.devicePixelRatio;
|
||||
|
||||
domElement = init();
|
||||
render();
|
||||
return domElement;
|
||||
|
@ -1206,8 +1211,8 @@ SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset)
|
|||
scene = new THREE.Scene();
|
||||
edgeScene = new THREE.Scene();
|
||||
|
||||
camera = new SolvespaceCamera(width,
|
||||
height, 5, new THREE.Vector3(0, 1, 0),
|
||||
camera = new SolvespaceCamera(width/window.devicePixelRatio,
|
||||
height/window.devicePixelRatio, 5, new THREE.Vector3(0, 1, 0),
|
||||
new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 0, 0));
|
||||
|
||||
mesh = createMesh(obj);
|
||||
|
@ -1232,6 +1237,7 @@ SolvespaceCamera = function(renderWidth, renderHeight, scale, up, right, offset)
|
|||
renderer = new THREE.WebGLRenderer({ antialias: true});
|
||||
renderer.setSize(width, height);
|
||||
renderer.autoClear = false;
|
||||
renderer.domElement.style = "width:"+width/window.devicePixelRatio+"px;height:"+height/window.devicePixelRatio+"px;";
|
||||
|
||||
controls = new SolvespaceControls(camera, renderer.domElement);
|
||||
controls.addEventListener("change", render);
|
||||
|
|
|
@ -175,21 +175,16 @@ public:
|
|||
layer.name = "text";
|
||||
dxf->writeLayer(&layer);
|
||||
|
||||
for(int i = 0; i < SK.style.n; i++) {
|
||||
Style *s = &SK.style.elem[i];
|
||||
std::set<uint32_t> usedStyles;
|
||||
|
||||
// check for using
|
||||
bool used = false;
|
||||
for(DxfFileWriter::BezierPath &path : writer->paths) {
|
||||
for(SBezier *sb : path.beziers) {
|
||||
if((uint32_t)sb->auxA != s->h.v) continue;
|
||||
used = true;
|
||||
break;
|
||||
usedStyles.insert((uint32_t)sb->auxA);
|
||||
}
|
||||
if(used) break;
|
||||
}
|
||||
if(!used) continue;
|
||||
|
||||
for(uint32_t v : usedStyles) {
|
||||
Style *s = Style::Get(hStyle{v});
|
||||
layer.name = s->DescriptionString();
|
||||
dxf->writeLayer(&layer);
|
||||
}
|
||||
|
@ -264,14 +259,17 @@ public:
|
|||
found = true;
|
||||
e->tag = 1;
|
||||
|
||||
DRW_LWPolyline polyline;
|
||||
DRW_Polyline polyline;
|
||||
assignEntityDefaults(&polyline, e->style);
|
||||
polyline.vertlist.push_back(new DRW_Vertex2D(start->pos.x, start->pos.y, 0.0));
|
||||
polyline.vertlist.push_back(new DRW_Vertex2D(next->pos.x, next->pos.y, 0.0));
|
||||
polyline.vertlist.push_back(
|
||||
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)) {
|
||||
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) {
|
||||
|
@ -484,16 +482,14 @@ public:
|
|||
List<Vector> lv = {};
|
||||
sb->MakePwlInto(&lv, SS.ExportChordTolMm());
|
||||
hStyle hs = { (uint32_t)sb->auxA };
|
||||
DRW_LWPolyline polyline;
|
||||
DRW_Polyline polyline;
|
||||
assignEntityDefaults(&polyline, hs);
|
||||
for(int i = 0; i < lv.n; i++) {
|
||||
Vector *v = &lv.elem[i];
|
||||
DRW_Vertex2D *vertex = new DRW_Vertex2D();
|
||||
vertex->x = v->x;
|
||||
vertex->y = v->y;
|
||||
DRW_Vertex *vertex = new DRW_Vertex(v->x, v->y, v->z, 0.0);
|
||||
polyline.vertlist.push_back(vertex);
|
||||
}
|
||||
dxf->writeLWPolyline(&polyline);
|
||||
dxf->writePolyline(&polyline);
|
||||
lv.Clear();
|
||||
}
|
||||
|
||||
|
@ -532,7 +528,8 @@ public:
|
|||
spline.ncontrol = sb->deg + 1;
|
||||
makeKnotsFor(&spline);
|
||||
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]);
|
||||
}
|
||||
dxf->writeSpline(&spline);
|
||||
|
@ -689,12 +686,19 @@ void DxfFileWriter::Bezier(SBezier *sb) {
|
|||
paths.back().beziers.push_back(sb);
|
||||
}
|
||||
|
||||
void DxfFileWriter::FinishAndCloseFile(void) {
|
||||
dxfRW dxf(filename.c_str());
|
||||
void DxfFileWriter::FinishAndCloseFile() {
|
||||
dxfRW dxf;
|
||||
|
||||
DxfWriteInterface interface(this, &dxf);
|
||||
dxf.write(&interface, DRW::AC1021, false);
|
||||
std::stringstream stream;
|
||||
dxf.write(stream, &interface, DRW::AC1021, /*bin=*/false);
|
||||
paths.clear();
|
||||
constraint = NULL;
|
||||
|
||||
if(!WriteFile(filename, stream.str())) {
|
||||
Error("Couldn't write to '%s'", filename.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool DxfFileWriter::NeedToOutput(Constraint *c) {
|
||||
|
|
|
@ -806,6 +806,8 @@ bool SolveSpaceUI::ReloadAllImported(bool canCancel)
|
|||
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 fromRel = MakePathAbsolute(SS.saveFile, rel);
|
||||
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
|
||||
// updated below.
|
||||
}
|
||||
}
|
||||
|
||||
try_load_file:
|
||||
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
|
||||
// the bounding box to turn relative chord tolerance to absolute.
|
||||
if(!SS.exportMode && !genForBBox) {
|
||||
GenerateAll(type, /*andFindFree=*/false, /*genForBBox=*/true);
|
||||
GenerateAll(type, andFindFree, /*genForBBox=*/true);
|
||||
BBox box = SK.CalculateEntityBBox(/*includeInvisibles=*/true);
|
||||
Vector size = box.maxp.Minus(box.minp);
|
||||
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;
|
||||
|
||||
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) {
|
||||
|
@ -305,7 +308,7 @@ void SolveSpaceUI::GenerateAll(GenerateType type, bool andFindFree, bool genForB
|
|||
// The group falls inside the range, so really solve it,
|
||||
// and then regenerate the mesh based on the solved stuff.
|
||||
if(genForBBox) {
|
||||
SolveGroup(g->h, andFindFree);
|
||||
SolveGroupAndReport(g->h, andFindFree);
|
||||
} else {
|
||||
g->GenerateLoops();
|
||||
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) {
|
||||
int i;
|
||||
// Clear out the system to be solved.
|
||||
|
@ -515,12 +535,6 @@ void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) {
|
|||
g->solved.remove.Clear();
|
||||
int how = sys.Solve(g, &(g->solved.dof),
|
||||
&(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;
|
||||
FreeAllTemporary();
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
{ 1, "Show Menu &Bar", MNU_SHOW_MENU_BAR, C|F(12), TC, mView },
|
||||
#endif
|
||||
{ 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, "Dimensions in &Inches", MNU_UNITS_INCHES, 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:
|
||||
if(SS.GW.LockedInWorkplane()) {
|
||||
SS.GW.AnimateOntoWorkplane();
|
||||
SS.GW.ClearSuper();
|
||||
SS.ScheduleShowTW();
|
||||
break;
|
||||
} // if not in 2d mode fall through and use ORTHO logic
|
||||
|
@ -911,7 +910,8 @@ void GraphicsWindow::MenuEdit(int id) {
|
|||
SS.MarkGroupDirty(ep->group);
|
||||
} else if(s->constraint.v) {
|
||||
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
|
||||
|
|
|
@ -203,8 +203,10 @@ void Group::GenerateShellAndMesh(void) {
|
|||
// not our own previous group.
|
||||
srcg = SK.GetGroup(opA);
|
||||
|
||||
if(!srcg->suppress) {
|
||||
GenerateForStepAndRepeat<SShell>(&(srcg->thisShell), &thisShell);
|
||||
GenerateForStepAndRepeat<SMesh> (&(srcg->thisMesh), &thisMesh);
|
||||
}
|
||||
} else if(type == EXTRUDE && haveSrc) {
|
||||
Group *src = SK.GetGroup(opA);
|
||||
Vector translate = Vector::From(h.param(0), h.param(1), h.param(2));
|
||||
|
|
|
@ -56,9 +56,6 @@
|
|||
|
||||
#ifdef HAVE_SPACEWARE
|
||||
#include <spnav.h>
|
||||
# ifndef SI_APP_FIT_BUTTON
|
||||
# define SI_APP_FIT_BUTTON 31
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace SolveSpace {
|
||||
|
@ -368,6 +365,8 @@ private:
|
|||
class EditorOverlay : public Gtk::Fixed {
|
||||
public:
|
||||
EditorOverlay(Gtk::Widget &underlay) : _underlay(underlay) {
|
||||
set_size_request(0, 0);
|
||||
|
||||
add(_underlay);
|
||||
|
||||
_entry.set_no_show_all(true);
|
||||
|
@ -513,10 +512,6 @@ public:
|
|||
set_double_buffered(true);
|
||||
}
|
||||
|
||||
void emulate_key_press(GdkEventKey *event) {
|
||||
on_key_press_event(event);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool on_configure_event(GdkEventConfigure *event) {
|
||||
_w = event->width;
|
||||
|
@ -596,45 +591,6 @@ protected:
|
|||
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:
|
||||
int _w, _h;
|
||||
void ij_to_xy(int i, int j, int &x, int &y) {
|
||||
|
@ -675,6 +631,10 @@ public:
|
|||
return _is_fullscreen;
|
||||
}
|
||||
|
||||
bool emulate_key_press(GdkEventKey *event) {
|
||||
return on_key_press_event(event);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void on_show() {
|
||||
Gtk::Window::on_show();
|
||||
|
@ -689,6 +649,7 @@ protected:
|
|||
}
|
||||
|
||||
virtual bool on_delete_event(GdkEventAny *) {
|
||||
if(!SS.OkayToStartNewFile()) return true;
|
||||
SS.Exit();
|
||||
|
||||
return true;
|
||||
|
@ -705,6 +666,55 @@ protected:
|
|||
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) {
|
||||
SS.GW.EditControlDone(value.c_str());
|
||||
}
|
||||
|
@ -900,6 +910,10 @@ public:
|
|||
accel_key = GDK_KEY_Escape;
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
accel_key = GDK_KEY_Tab;
|
||||
break;
|
||||
|
||||
default:
|
||||
accel_key = _entry.accel & ~(GraphicsWindow::SHIFT_MASK | GraphicsWindow::CTRL_MASK);
|
||||
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++) {
|
||||
std::string pattern = "*." + std::string(*ssPattern);
|
||||
filter->add_pattern(pattern);
|
||||
filter->add_pattern(Glib::ustring(pattern).uppercase());
|
||||
if(active == "")
|
||||
active = pattern.substr(2);
|
||||
if("*." + active == pattern)
|
||||
|
@ -1324,7 +1339,7 @@ public:
|
|||
set_type_hint(Gdk::WINDOW_TYPE_HINT_UTILITY);
|
||||
set_skip_taskbar_hint(true);
|
||||
set_skip_pager_hint(true);
|
||||
set_title("SolveSpace - Browser");
|
||||
set_title("SolveSpace - Property Browser");
|
||||
set_default_size(420, 300);
|
||||
|
||||
_box.pack_start(_overlay, true, true);
|
||||
|
@ -1391,6 +1406,14 @@ protected:
|
|||
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:
|
||||
Gtk::VScrollbar _scrollbar;
|
||||
TextWidget _widget;
|
||||
|
@ -1497,7 +1520,7 @@ static GdkFilterReturn GdkSpnavFilter(GdkXEvent *gxevent, GdkEvent *, gpointer)
|
|||
break;
|
||||
|
||||
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();
|
||||
}
|
||||
break;
|
||||
|
@ -1553,6 +1576,17 @@ int main(int argc, char** argv) {
|
|||
TW->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();
|
||||
|
||||
if(argc >= 2) {
|
||||
|
|
|
@ -902,12 +902,21 @@ public:
|
|||
};
|
||||
|
||||
void ImportDxf(const std::string &filename) {
|
||||
dxfRW dxf(filename.c_str());
|
||||
DxfReadInterface interface;
|
||||
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) {
|
||||
Message(ssprintf("%u DXF entities of unknown type were ignored.",
|
||||
interface.unknownEntities).c_str());
|
||||
|
@ -915,12 +924,21 @@ void ImportDxf(const std::string &filename) {
|
|||
}
|
||||
|
||||
void ImportDwg(const std::string &filename) {
|
||||
dwgR dwg(filename.c_str());
|
||||
DxfReadInterface interface;
|
||||
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) {
|
||||
Message(ssprintf("%u DWG entities of unknown type were ignored.",
|
||||
interface.unknownEntities).c_str());
|
||||
|
|
|
@ -34,7 +34,8 @@ void SMesh::AddTriangle(STriMeta meta, Vector a, Vector b, Vector c) {
|
|||
AddTriangle(&t);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -463,6 +463,15 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
|||
pending.operation != DRAGGING_MARQUEE)
|
||||
{
|
||||
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 = {};
|
||||
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) {
|
||||
|
@ -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 Transformed...", CMNU_PASTE_XFRM);
|
||||
}
|
||||
|
@ -892,6 +907,9 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
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.
|
||||
MouseMoved(mx, my, false, false, false, false, false);
|
||||
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(projUp.ScaledBy(my/scale));
|
||||
|
||||
hRequest hr;
|
||||
hRequest hr = {};
|
||||
hConstraint hc = {};
|
||||
switch(pending.operation) {
|
||||
case MNU_DATUM_POINT:
|
||||
hr = AddRequest(Request::DATUM_POINT);
|
||||
|
@ -958,6 +977,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
pending.operation = DRAGGING_NEW_POINT;
|
||||
pending.point = lns[1].entity(2);
|
||||
pending.description = "click to place other corner of rectangle";
|
||||
hr = lns[0];
|
||||
break;
|
||||
}
|
||||
case MNU_CIRCLE:
|
||||
|
@ -1060,7 +1080,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
c.type = Constraint::COMMENT;
|
||||
c.disp.offset = v;
|
||||
c.comment = "NEW COMMENT -- DOUBLE-CLICK TO EDIT";
|
||||
Constraint::AddConstraint(&c);
|
||||
hc = Constraint::AddConstraint(&c);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1127,8 +1147,8 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
|
||||
case DRAGGING_NEW_LINE_POINT: {
|
||||
// Constrain the line segment horizontal or vertical if close enough
|
||||
if(SS.GW.pending.suggestion != SUGGESTED_NONE) {
|
||||
Constraint::Constrain(SS.GW.pending.suggestion,
|
||||
if(constraintSuggestion != SUGGESTED_NONE) {
|
||||
Constraint::Constrain(constraintSuggestion,
|
||||
Entity::NO_ENTITY, Entity::NO_ENTITY, pending.request.entity(0));
|
||||
}
|
||||
|
||||
|
@ -1185,6 +1205,20 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
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();
|
||||
InvalidateGraphics();
|
||||
}
|
||||
|
|
|
@ -827,7 +827,7 @@ public:
|
|||
|
||||
static void CreateAllDefaultStyles(void);
|
||||
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 LoadFactoryDefaults(void);
|
||||
|
||||
|
|
|
@ -132,7 +132,6 @@ bool SolveSpaceUI::OpenFile(const std::string &filename) {
|
|||
saveFile = filename;
|
||||
bool success = fileLoaded && ReloadAllImported(/*canCancel=*/true);
|
||||
if(success) {
|
||||
RemoveAutosave();
|
||||
AddToRecentList(filename);
|
||||
} else {
|
||||
saveFile = "";
|
||||
|
@ -144,9 +143,6 @@ bool SolveSpaceUI::OpenFile(const std::string &filename) {
|
|||
}
|
||||
|
||||
void SolveSpaceUI::Exit(void) {
|
||||
if(!OkayToStartNewFile())
|
||||
return;
|
||||
|
||||
// Recent files
|
||||
for(int i = 0; i < MAX_RECENT; 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.
|
||||
Style::FreezeDefaultStyles();
|
||||
|
||||
// Exiting cleanly.
|
||||
RemoveAutosave();
|
||||
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
|
@ -418,6 +411,7 @@ bool SolveSpaceUI::OkayToStartNewFile(void) {
|
|||
return GetFilenameAndSave(false);
|
||||
|
||||
case DIALOG_NO:
|
||||
RemoveAutosave();
|
||||
return true;
|
||||
|
||||
case DIALOG_CANCEL:
|
||||
|
@ -433,8 +427,11 @@ void SolveSpaceUI::UpdateWindowTitle(void) {
|
|||
|
||||
static std::string Extension(const std::string &filename) {
|
||||
int dot = filename.rfind('.');
|
||||
if(dot >= 0)
|
||||
return filename.substr(dot + 1, filename.length());
|
||||
if(dot >= 0) {
|
||||
std::string ext = filename.substr(dot + 1, filename.length());
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
|
||||
return ext;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@ -554,7 +551,10 @@ void SolveSpaceUI::MenuFile(int id) {
|
|||
ImportDxf(importFile);
|
||||
} else if(Extension(importFile) == "dwg") {
|
||||
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.ScheduleShowTW();
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#ifdef WIN32
|
||||
# include <windows.h> // required by GL headers
|
||||
#endif
|
||||
|
@ -135,6 +136,7 @@ class RgbaColor;
|
|||
#endif
|
||||
|
||||
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);
|
||||
|
||||
#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);
|
||||
std::string MakeAcceleratorLabel(int accel);
|
||||
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 Error(const char *str, ...);
|
||||
void CnfFreezeBool(bool v, const std::string &name);
|
||||
|
@ -908,6 +912,7 @@ public:
|
|||
void GenerateAll(GenerateType type = GENERATE_DIRTY, bool andFindFree = false,
|
||||
bool genForBBox = false);
|
||||
void SolveGroup(hGroup hg, bool andFindFree);
|
||||
void SolveGroupAndReport(hGroup hg, bool andFindFree);
|
||||
void MarkDraggedParams(void);
|
||||
void ForceReferences(void);
|
||||
|
||||
|
|
|
@ -426,6 +426,7 @@ void SSurface::TriangulateInto(SShell *shell, SMesh *sm) {
|
|||
for(i = start; i < sm->l.n; i++) {
|
||||
STriangle *st = &(sm->l.elem[i]);
|
||||
st->meta = meta;
|
||||
if(st->meta.color.alpha != 255) sm->isTransparent = true;
|
||||
st->an = NormalAt(st->a.x, st->a.y);
|
||||
st->bn = NormalAt(st->b.x, st->b.y);
|
||||
st->cn = NormalAt(st->c.x, st->c.y);
|
||||
|
|
|
@ -83,12 +83,13 @@ void Style::CreateDefaultStyle(hStyle h) {
|
|||
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];
|
||||
s->color = CnfThawColor(d->color, CnfColor(d->cnfPrefix));
|
||||
s->width = CnfThawFloat((float)(d->width), CnfWidth(d->cnfPrefix));
|
||||
s->color = (factory) ? d->color : CnfThawColor(d->color, CnfColor(d->cnfPrefix));
|
||||
s->width = (factory) ? d->width : CnfThawFloat((float)(d->width), CnfWidth(d->cnfPrefix));
|
||||
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->textOrigin = 0;
|
||||
s->textAngle = 0;
|
||||
|
@ -106,7 +107,7 @@ void Style::LoadFactoryDefaults(void) {
|
|||
const Default *d;
|
||||
for(d = &(Defaults[0]); d->h.v; d++) {
|
||||
Style *s = Get(d->h);
|
||||
FillDefaultStyle(s, d);
|
||||
FillDefaultStyle(s, d, /*factory=*/true);
|
||||
}
|
||||
SS.backgroundColor = RGBi(0, 0, 0);
|
||||
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(!g->allowRedundant) {
|
||||
if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad);
|
||||
return System::REDUNDANT_OKAY;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// This is not the full Jacobian, but any substitutions or single-eq
|
||||
// solves removed one equation and one unknown, therefore no effect
|
||||
// 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
|
||||
// main parameter table.
|
||||
for(i = 0; i < param.n; i++) {
|
||||
|
|
|
@ -988,7 +988,7 @@ void TextWindow::MouseEvent(bool leftClick, bool leftDown, double x, double y) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if(r >= rows) {
|
||||
if(r < 0 || c < 0 || r >= rows || c >= MAX_COLS) {
|
||||
SetMousePointerToHand(false);
|
||||
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; });
|
||||
|
||||
if(!str.empty() && tf != &l.elem[l.n]) {
|
||||
if(tf->fontFace == NULL) {
|
||||
tf->LoadFromFile(fontLibrary, /*nameOnly=*/false);
|
||||
}
|
||||
tf->PlotString(str, sbl, origin, u, v);
|
||||
} else {
|
||||
// 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",
|
||||
fontFile.c_str(), ft_error_string(fterr));
|
||||
FT_Done_Face(fontFace);
|
||||
fontFace = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -144,6 +147,47 @@ bool TtfFont::LoadFromFile(FT_Library fontLibrary, bool nameOnly) {
|
|||
if(nameOnly) {
|
||||
FT_Done_Face(fontFace);
|
||||
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;
|
||||
|
@ -211,28 +255,26 @@ static int CubicTo(const FT_Vector *c1, const FT_Vector *c2, const FT_Vector *p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const FT_Outline_Funcs outline_funcs = {
|
||||
MoveTo, LineTo, ConicTo, CubicTo, 0, 0
|
||||
};
|
||||
|
||||
void TtfFont::PlotString(const std::string &str,
|
||||
SBezierList *sbl, Vector origin, Vector u, Vector v)
|
||||
{
|
||||
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;
|
||||
for(char32_t chr : ReadUTF8(str)) {
|
||||
uint32_t gid = FT_Get_Char_Index(fontFace, chr);
|
||||
for(char32_t cid : ReadUTF8(str)) {
|
||||
uint32_t gid = FT_Get_Char_Index(fontFace, cid);
|
||||
if (gid == 0) {
|
||||
dbp("freetype: CID-to-GID mapping for CID 0x%04x failed: %s; using CID as GID",
|
||||
chr, ft_error_string(gid));
|
||||
}
|
||||
|
||||
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;
|
||||
cid, ft_error_string(gid));
|
||||
gid = cid;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -244,7 +286,7 @@ void TtfFont::PlotString(const std::string &str,
|
|||
* ones, antialiasing mitigates this considerably though.
|
||||
*/
|
||||
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));
|
||||
return;
|
||||
}
|
||||
|
@ -274,9 +316,9 @@ void TtfFont::PlotString(const std::string &str,
|
|||
data.u = u;
|
||||
data.v = v;
|
||||
data.beziers = sbl;
|
||||
data.factor = 1.0f/(float)scale;
|
||||
data.factor = 1.0 / capHeight;
|
||||
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",
|
||||
gid, ft_error_string(fterr));
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ public:
|
|||
std::string fontFile;
|
||||
std::string name;
|
||||
FT_FaceRec_ *fontFace;
|
||||
double capHeight;
|
||||
|
||||
std::string FontFileBaseName() const;
|
||||
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
|
||||
// not displayed.
|
||||
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.
|
||||
struct {
|
||||
|
@ -629,14 +632,13 @@ public:
|
|||
void HitTestMakeSelection(Point2d mp);
|
||||
void ClearSelection(void);
|
||||
void ClearNonexistentSelectionItems(void);
|
||||
enum { MAX_SELECTED = 32 };
|
||||
struct {
|
||||
hEntity point[MAX_SELECTED];
|
||||
hEntity entity[MAX_SELECTED];
|
||||
hEntity anyNormal[MAX_SELECTED];
|
||||
hEntity vector[MAX_SELECTED];
|
||||
hEntity face[MAX_SELECTED];
|
||||
hConstraint constraint[MAX_SELECTED];
|
||||
std::vector<hEntity> point;
|
||||
std::vector<hEntity> entity;
|
||||
std::vector<hEntity> anyNormal;
|
||||
std::vector<hEntity> vector;
|
||||
std::vector<hEntity> face;
|
||||
std::vector<hConstraint> constraint;
|
||||
int points;
|
||||
int entities;
|
||||
int workplanes;
|
||||
|
@ -658,6 +660,7 @@ public:
|
|||
bool IsSelected(Selection *s);
|
||||
bool IsSelected(hEntity he);
|
||||
void MakeSelected(hEntity he);
|
||||
void MakeSelected(hConstraint hc);
|
||||
void MakeSelected(Selection *s);
|
||||
void MakeUnselected(hEntity he, 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;
|
||||
}
|
||||
|
||||
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,
|
||||
double a11, double a12, double a13, double a14,
|
||||
double a21, double a22, double a23, double a24,
|
||||
|
|
|
@ -56,6 +56,7 @@ SiHdl SpaceNavigator = SI_NO_HANDLE;
|
|||
|
||||
HWND MessageWnd, OkButton;
|
||||
bool MessageDone;
|
||||
int MessageWidth, MessageHeight;
|
||||
const char *MessageString;
|
||||
|
||||
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: {
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(hwnd, &ps);
|
||||
int row = 0, col = 0, i;
|
||||
SelectObject(hdc, FixedFont);
|
||||
SetTextColor(hdc, 0x000000);
|
||||
SetBkMode(hdc, TRANSPARENT);
|
||||
for(i = 0; MessageString[i]; i++) {
|
||||
if(MessageString[i] == '\n') {
|
||||
col = 0;
|
||||
row++;
|
||||
} else {
|
||||
TextOutW(hdc, col*SS.TW.CHAR_WIDTH + 10,
|
||||
row*SS.TW.LINE_HEIGHT + 10,
|
||||
Widen(&(MessageString[i])).c_str(), 1);
|
||||
col++;
|
||||
}
|
||||
}
|
||||
RECT rc;
|
||||
SetRect(&rc, 10, 10, MessageWidth, MessageHeight);
|
||||
std::wstring text = Widen(MessageString);
|
||||
DrawText(hdc, text.c_str(), text.length(), &rc, DT_LEFT | DT_WORDBREAK);
|
||||
EndPaint(hwnd, &ps);
|
||||
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";
|
||||
int width = cols*SS.TW.CHAR_WIDTH + 20,
|
||||
height = rows*SS.TW.LINE_HEIGHT + 60;
|
||||
MessageWidth = width;
|
||||
MessageHeight = height;
|
||||
MessageWnd = CreateWindowClient(0, L"MessageWnd", Widen(title).c_str(),
|
||||
WS_OVERLAPPED | WS_SYSMENU,
|
||||
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
|
||||
// window is a child of the graphics window.
|
||||
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);
|
||||
if(!TextWnd) oops();
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ std::wstring Widen(const std::string &in)
|
|||
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.
|
||||
// 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;
|
||||
if(uncFilename.substr(0, 2) != "\\\\")
|
||||
uncFilename = "\\\\?\\" + uncFilename;
|
||||
return uncFilename;
|
||||
}
|
||||
|
||||
FILE *ssfopen(const std::string &filename, const char *mode)
|
||||
{
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue
Block a user