The sorting of the room objects + walkbehinds used some old hack, which behavior
dependent on a "walkbehind method" setting. But this setting is now deprecated
(and software renderer does not make walk-behinds a separate object).
Instead use a custom "sprite entry id" tag to help with sorting objects with equal zorder
(baseline). This lets to use same sorting algorithm for everything.
Walk-behinds should always be sorted back in case of equal zorder, so they receive
id = INT32_MIN.
From upstream 3b195eba0aaba9765e4dbfe427a0ba980fc3a1f6
The previous attempt, using a boolean spritemodified array, proved to be having logical
loopholes. In simple words, because spritemodified flag was resetting each draw pass, it won't
affect objects that are temporarily not visible, and they failed to reupdate when becoming
visible again. This affected Software renderer.
Texture-based renderers have a different problem, where they fail to recognize when an old
sprite was deleted and a completely new dynamic sprite created accidentally with the same ID.
The cause was simply that the check for this was done inside sync_object_texture(), but
sync_object_texture itself was not called unless draw() function thought that object had
changed. So there has to be a check outside too...
Here I decided to reimplement notification mechanism, and use it for both types of renderers,
for the sake of more straightforward code logic. (Although, strictly speaking, texture-based
renderers could check their texture's "ref id" instead.)
The idea of a new implementation is this:
1. There's a map of "control blocks" per each active sprite (that is - sprite that was drawn as a
part of object). The "control block" is simply a integer with a sprite ID in it, allocated and
wrapped by shared_ptr.
2. When the ObjectTexture syncs its texture with a new sprite, the control block is retrieved (or
new created), and from now on it may be shared among multiple objects which display same
sprite.
3. When the sprite gets either updated or deleted two things happen: the previous control
block is assigned an "invalid value", serving as a marker, and then it is removed from the map,
left only if referenced by any ObjectTexture.
4. When checking whether texture needs to be re-synced we test the control block too, to see
if it was invalidated. In such case this tells us to call sync_object_texture() again.
NOTE that dynamic sprites that do not appear on screen, and are only used for drawing on
another surface, do not allocate control blocks, nor notify anything.
From upstream ab2dd5846075a73e3a3415c45c37fe6b37805964
Previous existing method ran through virtually all the game objects that may reference a sprite, and
checked each one of them. Those who did reference the modified dynamic sprite were marked for
update and/or had their draw caches cleared.
Furthermore, for safety reasons, the Graphic properties of these objects were reset to 0.
This process was slow under two conditions:
- if there are alot of objects (especially overlays which may be created at runtime in large quantities);
- if there are alot of temporary dynamic sprites created and deleted per game frame (for example,
when drawing something complicated).
The new method:
1. We no longer reset object properties, this turned to be a bad design. There's another safety fix done
in the SpriteCache, which returns a placeholder sprite for any invalid sprite ID. This should make things
simpler and faster.
2. For the texture-based renderers, it turned out that updating the shared texture entries was enough
to make objects using them redraw. So for these renderers we don't need to reset any more caches.
3. For software renderer, introduced a GameState::spritemodified vector of bools. Whenever a sprite is
modified or deleted, engine sets a corresponding flag in this vector, and that triggers an update at the
next draw pass for all the objects that still reference that sprite.
GUI PROBLEM: because GUIs rendering is still different from other objects, even in texture render
mode, they are still marked for update the old way.
This should be addressed separately in the future.
From upstream 0b84a21cfb486e3a9fa03e6c2b354750742ed3fd
and 3f70782761a698a69d31af77833c05bf38eb7394
This is less of an issue in 3.6.1 (as opposed to 3.6.0), where overlays keep their
container indexes if anything is removed in the middle; but still is meant to
dispose remaining data.
From upstream 61afb63adbd3de77e7d23c40f1f5600bc58e9599
This setting comes from the original mobile port of AGS, but it's not clear whether it was
useful. More importantly, there are issues with this:
1. It was never implemented in another hardware accelerated driver (Direct3D), being
exclusive to OpenGL.
2. It was never added to standard setup, so not very visible.
3. It's not clear whether it was working properly all this time. There were multiple changes to graphic renderers, and some of them may assume that rendering at "native resolution" is done at exactly, well, native resolution.
This is meant to skip certain groups of sprites when taking a "screenshot",
for instance when preparing a frozen game screen for the room transition
(fade-out etc).
Think of hiding mouse cursor and engine overlay (fps counter etc).
Partially from upstream b0cd961483dcee8ffff7543c429fcd3272b413d5
Prior to introduction of explicit Overlay.ZOrder property, overlays were not sorted at all, and were
drawn in the order of their storage in container, which coincidentally matched their order of creation.
After Overlay.ZOrder was added, and overlays are sorted among GUIs using qsort, there's a potential
issue of their drawing order being undefined (if two overlays have matching or unassigned ZOrder).
This became a real issue after modification of the overlays internal storage, which was done for
performance reasons.
The change introduces a global incrementing counter that assigns a "creation index" to Overlays, and
is used as a second factor during sorting, similar to how GUIs use their ID property.
From upstream 278dbc40e91a56a3728a567abb8620cc917729cb
Avoid query gfxDriver's properties all the time, instead save them once in init_draw_method() and use saved values.
From upstream db535512af65119d50ae3d6fb06c221d56f42d85
* Moved plugin API event constants to a separate header agsplugin_evts.h.
Engine should not include whole plugin API, this is unnecessary, and may
create naming conflicts.
* Moved SimulateMouseClick to mouse.cpp.
* Minor cleanup in agsplugin.cpp
From upstream 510293c1fd277d853544534423ceea27b8ae3e2d
Historically, neither Character.z (vertical offset), nor picture offsets (ones set by Character.LockViewAligned() and Character.LockViewOffset())
were not scaled along with the character's sprite.
Although it seems like that would be a right thing to do in a majority of practical applications of these properties.
This change introduces a separate zoom factor for these parameters. It's done separately to be able to maintain backwards compatibility.
In backwards mode this factor is always 100 (%), in the new mode it is always set equal to regular character's zoom (whether got from
a manual property, or a walkable area scaling).
The switch between modes is controlled by OPT_SCALECHAROFFSETS. This supposed to be always set in the new games. But this is also
a backup opportunity to disable this behavior, if a user finds it making it impossible to achieve a previously possible effect: in such case
one may disable this when compiling a game, or call SetGameOption(OPT_SCALECHAROFFSETS, 0) in script.
Code-wise, I had to move get_effective_y() method to CharacterExtras class, which makes more sense, as that's a runtime character class,
as opposed to CharacterInfo which is a game data serialization class, shared with the Editor.
There's still alot of potential for refactor and tidying the code, but I'd leave that for another task.
From upstream a2b0c88379f37fdaf44155e37f372b7de725db21
This "console" implementation has multiple issues, making it unusable in practice:
- saves and displays only few lines, cannot scroll back;
while multiple game messages may be printed per a single game frame;
- messages cannot be filtered at runtime;
- uses a game font of a fixed number, which in unreliable (as the font may not be suitable);
There's not much value in its code; if a new console will be wanted in the future, then it
would be best to reimplement one from scratch, but with a good planning first.
From upstream c303590efca4632fef0fb2ab3143faba6e605ba8
Keep ScreenOverlays in std::vector, but do not erase elements
in the middle and invalidate them instead. Record free indexes
in a helper stack.
When creating a new overlay, first check for the recorded free indexes.
Overlay's type now equals storage index.
This speeds up both creation/deletion of overlays, and their access.
Removed the gap between "fixed" overlay types and custom ones,
to save space. If we ever need more special overlays, these could
be created as custom and their ids saved in a variable (similar to
how background speech works). Previously present special overlay
types are left for backwards compatibility (and to simplify the transition).
From upstream f7d2f162fa55aa1b6f37195d890ebe047a204154
The spriteset's [] operator loads a sprite, but some operations may
omit that and check the preloaded information instead.
This also makes it more certain where the actual sprite's bitmap is necessary.
From upstream df30fc1edd30d4f334addaf7883286e745dea2c3