Letting the constant resolver throw exceptions prevented us from doing
checking on later initializers anyway, so instead we'll send them to the
error handler. As a special bonus this makes it so we don't crash when
a global variable initializer has errors. Fixes#1850, #1855.
The material map is 1D texture that contains information about every
material-texture combination. There is no point in linear filtering,
i.e. trying to interpolate between two materials such as gold and granite
or whichever two materials happen to be adjacent in the material map texture.
This might or might not be relevant to #1841, but should be more correct
behavior in any case.
I don't know why the viewports are deleted with deleteLater(), but it leads
to an OpenGL context getting deselected behind our back, and so we don't know
when is a good time to re-select it. This leads to termination of the engine
when selecting File->Close (Ctrl+W) in the editor, because the graphics
re-initialization fails with no GL context active.
Instead, just delete the viewport widget immediately, which works fine at
least on Linux. This is also recommended by the Qt documentation at
http://doc.qt.io/qt-5/qopenglwidget.html.
When removing a viewport, then also remove it from the internal list of
viewports. Otherwise, we might attempt to delete it again later. Fixes
crash on editor shutdown on Linux.
This fixes a crash on Linux when exiting the editor. It was caused by
C4Console::~C4Console being called by the C++ runtime after after main()
returned. The C4Console destructor then goes and deletes all the Qt
resources (QApplication and friends), and that caused a segfault, maybe
because some of the static Qt structures have already been deallocated.
Fix this by making the destruction of the Qt components deterministic. Add
a function "DeleteConsoleWindow" which deletes all the Qt components, and
call this function in C4Console::Clear.
By continuing to generate bytecode even after an error is found, we're
able to find more syntax errors and will also be able to keep the value
stack at the expected height.
When an error occurred during codegen of a function, the current
function pointer would not be reset to 0, leading to spurious warnings
about redeclaration of functions.
Uniform variables are read from the "Uniforms" proplist set on Scenario
or on individual objects. Proplist keys are uniform names. Values can
either be an int or an array of one to four ints in C4Script. In GLSL,
the uniforms then need a matching type (int/ivec2/ivec3/ivec4). There is
no error reporting; uniforms are only set if both name and type match.
The implementation walks the "Uniforms" proplists on each Draw call. We
may need to cache the uniform maps if this turns out to be too slow.
The TightGridLayout fills spaces more aggressively. This is slower but makes for a tighter layout. Finding the best layout is NP-complete. This here is just O(N^2) or so.
If a parse error occurs inside a declaration, the codegen should just go
on and deal with the next declaration instead of completely giving up on
the entire script.
9caaf1e introduced an external error handler for easier testing of
error conditions. The default error handler needs to count errors and
warnings if we want to display them, but didn't.
36/1000 is always 0 and doesn't make a lot of sense anyway. Use 1000/36
(aka 1000ms/36fps) instead so the UI thread has some time to rest.
Also use a Qt::PreciseTimer so Qt doesn't try to coalesce the scheduler
timer with other timers to save energy.
The old parser threw a standard compile error in this case; the
AST-based parser threw an ICE, which is ultimately the same thing but
made it sound like the parser was at fault. And maybe it is, and we
should allow code like "local a; func a() {}" but that seems like it
should be a conscious design decision.
C4Value already handles refcounting properly for us, so we don't need to
do it manually. It might still be worth manually refcounting them
to avoid the boxing/unboxing overhead, but it's only needed at load and
unload so it's not a priority at the moment.
By using an extern error handler in the script engine, we can mock that
handler and make sure something that should fail actually does, instead
of having to parse log messages.
Redefining new breaks perfectly valid code, but only on MSVC and only in
one particular configuration (Debug). This is very annoying because it
means people not using MSVC, or even people doing Release builds, can
write standards-conforming code which then may fail to build for other
people.
Depending on the mood of the linker, the editor may have been
constructed before and destroyed after the system-wide string table
because they weren't defined in the same file. Destruction of the editor
tries to load some strings, which would then access the already
destroyed string table and thus crash.
They never worked properly in network mode because all users would see the changes.
EditorProps, EditorActions and shape delegates now provide the functionality to have custom object editing widgets.
This also fixes a bug with the selection callback causing the object list to act up.
Parsing a function expression inside another function failed to reset
the code generator target to the containing function, so all following
bytecode would still be appended to the nested function, leaving the
container broken.
It doesn't make a lot of sense to keep console pointers around while the
objects and scripts have already been deleted. Clear them earlier so we
don't have any dangling pointers.
* Engine would always open up in Fullscreen and then switch to Windowed
instead of just starting up as Windowed.
* Could not change resolution because bit depth or refresh rate did not match
* handle RefreshRate==0 as "any", just like windows
* Remember refresh rate in combo box that enumerates all the modes and
propagate to video mode setting instead of assuming all modes have the
same refresh rate.
* Report bit depth as 32 even if SDL tells us it's 24. Other parts of the
code require it to be equal to 32, but 24 works just fine.
* Changing from fullscreen to windowed when "Screen" was selected in
resolution combo box (i.e. iXRes==-1) makes the window tiny (0x0 pixels).
The last error is displayed in the GUI, so until now there was just a "(null)"
string there.
The whole (SDL) resolution switching code is completely broken as well, but
that's a different story...
If a local variable in a definition was set to a proplist inside the
Definition() callback, and that proplist contained cyclic references
then those references were leaked. Typically cyclic references for
script-created proplists are broken in
C4PropListScript::ClearScriptPropLists, however definition proplists
are changed to be static proplists in
C4PropList::FreezeAndMakeStaticRecursively.
To fix this, each script host maintains a list of proplists made static
by FreezeAndMakeStaticRecursively, and explicitly deletes all of these
proplists on Clear().
This leak also leads to an assertion failure inside
C4PropListScript::ClearScriptPropLists in debug mode, and can also be
observed by C4PropList::PropLists not being empty after game clear.
The definition in Objects.ocd/Helpers.ocd/UserAction.ocd constructs
cyclic proplists in its Definition() call. A simpler, more minimal way
to provoke the leak is the following (it provokes the leak but not the
assertion failure):
local bla;
func Definition(def)
{
bla = {};
bla.test = { Name="Test222" , Options = { Name="Test333" } };
bla.test.Options.Link = { Name="Test444", Blub=bla.test };
}
As carrier-grade NATs are becoming common, many players cannot host
Clonk games at all. The simple STUN-like netpuncher from Clonk Rage
which was removed three years ago is already effective against some
DS-Lite NATs.
With some extensions, we should be able to make it work with more
restrictive NATs as well.
This reverts commit 72002cc366.