This commit removes a large amount of code partially duplicated
between the text and the graphics windows, and opens the path to
having more than one model window on screen at any given time,
as well as simplifies platform work.
This commit also adds complete support for High-DPI device pixel
ratio. It adds support for font scale factor (a fractional factor
on top of integral device pixel ratio) on the platform side, but not
on the application side.
This commit also adds error checking to all Windows API calls
(within the abstracted code) and fixes a significant number of
misuses and non-future-proof uses of Windows API.
This commit also makes uses of Windows API idiomatic, e.g. using
the built-in vertical scroll bar, native tooltips, control
subclassing instead of hooks in the global dispatch loop, and so on.
It reinstates tooltip support and removes menu-related hacks.
We should make good use of in-place member initialization. Many
new classes have constructors that effectively do nothing but
default-initialize POD members, and when adding new members,
it is very easy to miss initializing them. With in-place
initialization, the code is more compact, the diffs are nicer,
and it's harder to miss them.
This commit only converts render/ and platform/ to use in-place
member initialization, since there was a bug in CairoRenderer,
but we should convert the entire codebase.
This commit updates a *lot* of rather questionable path handling
logic to be robust. Specifically:
* All path operations go through Platform::Path.
* All ad-hoc path handling functions are removed, together with
PATH_SEP. This removes code that was in platform-independent
parts, but had platform-dependent behavior.
* Group::linkFileRel is removed; only an absolute path is stored
in Group::linkFile. However, only Group::linkFileRel is saved,
with the relative path calculated on the fly, from the filename
passed into SaveToFile. This eliminates dependence on global
state, and makes it unnecessary to have separare code paths
for saved and not yet saved files.
* In a departure from previous practice, functions with
platform-independent code but platform-dependent behavior
are all grouped under platform/. This makes it easy to grep
for functions with platform-dependent behavior.
* Similarly, new (GUI-independent) code for all platforms is added
in the same platform.cpp file, guarded with #ifs. It turns out
that implementations for different platforms had a lot of shared
code that tended to go out of sync.
Before this commit, the first time NewFrame() is called,
the background color would not be filled, leading to interference
with whatever the GUI toolkit decided to put there.
Before this commit, updates to the bitmap font in the graphics window
cause missing characters in the text window and vice versa. This is
because BitmapFont contains a texture that's mutated, and sharing it
would also require sharing display lists between GL contexts, which
is not done (and overly complicated for this case anyway).
Before this commit, when an entity is clicked at or dragged, and it
shares a place with other entities, which of them is selected is
decided more or less at random. This is particularly annoying when
dragging.
After this commit, when clicking, an entity from the current group
is given preference, and when dragging, an entity from a request
is given preference. This allows e.g. dragging points of a sketch
even when an extrusion of that sketch is active.
The only thing we need it anymore is the package version and platform
configuration, so only include it for that. As a result, less files
are rebuilt when the git commit changes and config.h is regenerated.
The configuration option "draw back faces in red" aids debugging,
in that it allows to visually identify a non-watertight mesh.
When it is disabled, or when the mesh is transparent, we used to not
draw them at all before this commit; after, they are drawn just like
the front faces.
This has two consequences:
1. Inner surfaces of non-watertight meshes are not see-through
anymore. That used to be the behavior in version 2.0, and it
was accidentally broken in 2.1.
2. Transparent meshes look *much* better.
3. Solids made from a union of a non-transparent and a transparent
one look sensibly at all.
This commit also updates the OpenGL 1 renderer to let it render
such meshes correctly.
This commit performs two main changes:
* Alters the shaders to use only strictly conformant GLSL 2.0.
* Alters the Windows UI to use ANGLE via GL ES 2.0 and EGL 1.4.
This commit also drops official support for Windows XP, since ANGLE
requires a non-XP toolset to build. It is still possible to build
SolveSpace for Windows XP using:
cmake -T v120_xp -DOPENGL=1
This commit does three things:
* Recognizes that BeginFrame()/EndFrame() are badly named, since
BeginFrame() sets up framebuffer, and EndFrame() flushes a frame,
and they do not have to be called in pairs; and so renames them
to NewFrame()/FlushFrame().
* Reduces the amount of frame flushes in GraphicsWindow::Paint()
to two, which is the minimum since we use two different cameras
for geometry and UI;
* Changes the FPS measurement code to only take into account
the time spent rendering our main geometry, and not the UI
rendering or window system interaction time.
Before this commit, tooltips in the text window are drawn under
the red "X" indicating a disabled button. After this commit, they
are moved on top of that.
This commit also alters the OpenGL renderers' SetCamera() method
to clear the depth buffer, as that would interfere with drawing
the UI; the toolbar would get occluded by geometry.
To actually achieve improved performance with the OpenGL 2 renderer,
we have to cache geometry that doesn't change when the viewport does
(note that the rendered pixels can change quite dramatically because
we can reconfigure shaders; e.g. stippling can be drawn in screen
coordinates).
This commit adds a BatchCanvas interface that can be implemented
by renderers, and uses it for drawing entities such as lines and
points.
There are two main reasons to desire an OpenGL 2 renderer:
1. Compatibility. The compatibility profile, ironically, does not
offer a lot of compatibility, and our OpenGL 1 renderer will not
run on Android, iOS, or WebGL.
2. Performance. The immediate mode does not scale, and in fact
becomes very slow with only a moderate amount of lines on screen,
and only a somewhat large amount of triangles.
This commit implements a basic OpenGL 2 renderer that uses only
features from the (OpenGL 3.2) core profile. It is not yet faster
than the OpenGL 1 renderer, primarily because it uses a lot of small
draw calls.
This commit uses OpenGL 2 on Linux and Mac OS X directly (i.e. links
to the GL symbols from version 2+); on Windows this is impossible
with the default drivers, so for now OpenGL 1 is still used there.
OpenGL 2 and newer do not have the glPolygonMode(..., GL_LINES) API,
so produce the wireframe on our side. It's somewhat slow, and draws
every line three times, but it is cached when the OpenGL 2 renderer
is used, and this should do for a debugging feature.
gcc 6 displays these when compiling in release mode; all of these
warnings except the rankOk one were benign because there would have
been an error about the incomplete switch statement.
The rankOk warning highlighted a real problem: bailing early to
didnt_converge would have branched on an uninitialized variable.
Abstract the exact details of the OpenGL renderer in the render.h
header; this allows us to use GL-specific types in the renderer
class and functions without including OpenGL (and Windows, where
applicable) headers in every source file.
OpenGL 1.1 permits implementations to reject non-power-of-2 sized
textures. In practice this only affects the default Windows OpenGL
implementation, i.e. with no vendor drivers installed. This is still
important in case the application runs in a VM.
This fixes a strange problem where GTK 2 (but not GTK 3) with NVidia
drivers would not have a depth buffer, but only during exporting
PNGs, despite the fact that normal rendering path and PNG rendering
path come through the same offscreen rendering code.
This commit alters the build system substantially; it adds another
platform, `headless`, that provides stubs in place of all GUI
functions, and provides a library `solvespace_headless` alongside
the main executable. To cut down build times, only the few files
that have #if defined(HEADLESS) are built twice for the executable
and the library; the rest is grouped into a new `solvespace_cad`
library. It is not usable on its own and just serves for grouping.
This commit also gates the tests behind a -DENABLE_TESTS=ON CMake
option, ON by default (but suggested as OFF in the README so that
people don't ever have to install cairo to build the executable.)
The tests introduced in this commit are (so far) rudimentary,
although functional, and they serve as a stepping point towards
introducing coverage analysis.
SurfaceRenderer is a new renderer implementing the Canvas interface
running entirely on the CPU; it projects strokes and triangles
in the exact same way as OpenGL would, and it can be used for
rendering into raster or vector 2d surfaces.