Compare commits

...
Author SHA1 Message Date
asarium 131d22c82a Add support for external subtitle files
This allows to use external subtile files (currently only SRT is
configured) for providing subtitles for movie files. This should be more
universal since it also supports container formats with no support for
subtitle streams.

To use this code the srt file needs to be named
"<movie name>-<language code>.srt" where the language code is the file
extension name specified in the localization table. For english the
"-..." part can be omitted.
2018-06-06 19:55:28 +02:00
Fabian Woltermann b848823a2f Merge pull request #1670 from asarium/feature/bitmapBlocks
Add new bmpman slot management system
2018-06-02 12:08:22 +02:00
Goober5000 04b0f5bb75 Merge pull request #1721 from asarium/fix/unicodeScramble
Fix scrambling unicode messages
2018-06-01 17:24:04 -04:00
Goober5000 fdbba84a5b Merge pull request #1733 from Goober5000/fix_issue_1708
fix issue #1708
2018-05-31 15:52:46 -04:00
asarium 079ad97987 Fix clang-tidy issues in Assertion macro 2018-05-30 10:00:42 +02:00
asarium 7ae276fe6a Fix scrambling unicode messages
The code did not account for unicode escape sequences when inserting
scrambling characters which distorted the text and fequently caused
invalid UTF-8 sequences to appear in the text. This fixes that by
using the text iterators already present in the game code. I needed to
rewrite the logic of this block a bit since the previous logic could not
be converted to the way we need to handle unicode sequences at the
moment.

This fixes #1720.
2018-05-30 10:00:42 +02:00
Goober5000 45ddc8ac44 Merge pull request #1729 from chief1983/lib/sdl208
lib/sdl208: Upgrade the included SDL libs to 2.0.8.
2018-05-29 18:57:48 -04:00
Goober5000 6fa422c5e7 fix issue #1708 2018-05-29 17:04:31 -04:00
Cliff Gordon 35c830062d lib/sdl208: Upgrade the included SDL libs to 2.0.8. 2018-05-29 08:39:28 -05:00
Goober5000 243a5bb473 Merge pull request #1702 from Goober5000/minor_sexp_subsystem_cleanup
minor sexp subsystem cleanup
2018-05-29 00:21:29 -04:00
asarium 09abbe1789 Add new bmpman slot management system
This changes how the bitmap slots are managed by the bmpman system.
Instead of allocating a fixed-size array when the game starts this will
manage multiple "blocks" of bitmap slots. When the engine runs out of
slots in the already allocated blocks it simply creates a new block and
allocates the new slot in that.

This removed the hard limit on how many bitmaps can be loaded at the
same time and should fix issues encountered by mods which use a lot of
bitmap slots (I'm looking at you Spoon).

This implements the idea described in #1503.
2018-05-28 09:51:15 +02:00
asarium ad52278a67 Fix clang-tidy issues in Assertion macro 2018-05-28 09:51:15 +02:00
m!m e0a9c88241 Merge pull request #1716 from asarium/build/clang-tidy-diff
Use clang-tidy-diff to only check changed lines
2018-05-27 18:00:25 +02:00
m!m f45dcfc09a Merge pull request #1732 from asarium/fix/appveyorQt
Fix Appveyor Qt build issue
2018-05-26 16:54:23 +02:00
asarium 2036ebd3a0 Fix Appveyor Qt build issue
Apparently, Appveyor has removed the Qt version 5.7 from their servers
which was used by FSO previously. I have updated the paths to use Qt
5.9.5 instead now but there is a problem with Visual Studio 2013 since
there is no 32-bit Qt version for that compiler installed in the
Appveyor system.

For that reason, I decided to use Visual Studio 2015 instead for the
32-bit builds which means that Visual Studio 2013 will not be tested by
Appveyor anymore. Since no one is using that compiler version anymore
that shouldn't be a big issue.

This should fix the CI issues seen on recent PRs and commits.
2018-05-26 14:05:30 +02:00
m!m 469270d4b6 Merge pull request #1701 from Goober5000/is_in_turret_fov
is-in-turret-fov sexp
2018-05-17 19:34:49 +02:00
m!m e59df5d83c Merge pull request #1726 from Goober5000/sexp_bitwise_tweak
make the set-bit and is-bit-set operators fail gracefully
2018-05-17 19:31:22 +02:00
Goober5000 880e03e5d1 requested changes from code review 2018-05-15 22:04:20 -04:00
Goober5000 c1196f8286 requested changes from code review 2018-05-15 21:56:39 -04:00
Goober5000 40cd9e4c07 make the set-bit and is-bit-set operators fail gracefully
These operators used to warn and return NAN if they were given a bit index out of range.  For FREDding convenience, out-of-range bit indexes are now a no-op.  This is particularly helpful in the situation where a FREDder needs to evaluate an extended bit array, one 32-bit chunk at a time, e.g.

0-31 bits: offset 0
32-63 bits: offset -32
64-95 bits: offset -64
96-127 bits: offset -96

Because the sexp system always evaluates every argument, three out of four branches were always evaluated with invalid bit indexes (negative or too large) even if the sexp logic only used one branch.  The new method silently bypasses this behavior.
2018-05-07 18:44:58 -04:00
MageKing17 a90e480b61 Merge pull request #1724 from asarium/fix/showShipViewerMode
Fix "show-ship" flag
2018-05-05 11:35:27 -07:00
asarium 142ae846f4 Fix "show-ship" flag
The viewer mode check seemed to be wrong but I am not entirely sure if I
fixed this correctly. The Viewer_mode variable is a big mess of bitflags
that are not very consistent in what they mean.
2018-05-05 12:25:44 +02:00
asarium 7a827dcb0e Enable all modernize tests by default
This will report the usage of old coding patterns in new code.
modernize-raw-string-literal is disabled since it doesn't work right
with strings with special escape sequences in them.
modernize-use-using is disabled since typedefs are more common in the
FSO code.
2018-05-04 10:03:22 +02:00
asarium 619cb607d0 Use clang-tidy-diff to only check changed lines
This will only check the lines that were changed by a commit or pull
request. This makes it possible to enable more clang-tidy checks without
having to fix all occurences of the warnings in the code base.

Please note that the changes do not work correctly with rebased branches
due to the way Travis CI supplies the commit range. Pull requests will
always be checked properly though.
2018-05-02 12:26:05 +02:00
m!m 56c34eee6d Merge pull request #1685 from asarium/build/clang-tidy-2
Enable and fix more clang-tidy warnings
2018-05-01 19:35:46 +02:00
Fabian Woltermann 379031534d Merge pull request #1718 from asarium/fix/1717
Fix fog rendering in forward renderer
2018-04-29 18:49:04 +02:00
asarium 64b08f51c0 Fix fog rendering in forward renderer
There were actually two bugs here that were fixed:
1. The model draw list code disabled the fog rendering when it thought
it was it deferred rendering mode but did not account for explicitly
disabling the deferred renderer.
2. The fog effect was applied to both the emissive color and the base
color simultaneously which caused visual errors when rendering fogged
objects using the deferred renderer.

This fixes #1717.
2018-04-28 13:53:09 +02:00
asarium adfa12a706 Disable clang-tidy in release mode
The unused parameter warning cannot be disabled easily in release mode
for clang-tidy so this needs to be done to avoid false-positived in
release mode.
2018-04-25 11:57:56 +02:00
asarium d71a589b0f Use CMake 3.8 to make sure clang-tidy warnings fail the build
Previous versions do not support failing the build if warnings should be
treated as errors.
2018-04-25 11:57:56 +02:00
asarium 5118d94d5d Update header filter regex in .clang-tidy 2018-04-25 11:57:56 +02:00
asarium 17179d5b0b Fix unreferenced local variable warning 2018-04-25 11:57:55 +02:00
asarium bd3632d1bf Enable remaining misc- checks and fix detected issues 2018-04-25 11:57:55 +02:00
asarium eeed22b91a Enable misc-unused-parameters
clang-tidy was used for fixing the warnings. It is not clear if this is
actually an improvement so this may still be disabled later.
2018-04-25 11:57:55 +02:00
asarium 48873185ce Another batch of misc- checks 2018-04-25 11:13:20 +02:00
asarium e28ebc2a6c Enable and fix misc-suspicious-string-compare check 2018-04-25 11:13:19 +02:00
asarium dcac9e7223 Enable more misc- checks 2018-04-25 11:12:41 +02:00
asarium 0b4ca71eba Enable modernize-deprecated-headers 2018-04-25 11:12:41 +02:00
asarium 24c3c439d5 Test clang-tidy issues in test code 2018-04-25 11:12:41 +02:00
m!m 706973cb6b Merge pull request #1672 from asarium/feature/typesafeIDs
Add typesafe handle types and use it in game sound system
2018-04-25 10:36:46 +02:00
Fabian Woltermann 91a5bfa74a Merge pull request #1707 from asarium/feature/persistentParticles
Improve handling of non-persistent particles
2018-04-25 10:14:39 +02:00
m!m 2721c452c4 Merge pull request #1680 from asarium/qtfred2_/eventDialog
Port event editor dialog code to qtFRED
2018-04-22 21:39:57 +02:00
m!m 1030e29ef7 Merge pull request #1703 from asarium/qtfred2_/missionSave
Port mission save code to qtFRED
2018-04-22 17:40:48 +02:00
asarium 8f06e338a4 Add typesafe handle types and use it in game sound system
This adds a new class which allows to create type safe resource handle
types. At the moment, the engine uses ints pretty much everywhere for
providing handles to resources created by the specific subsystems. Since
all ints are the same to the C/C++ typesystem it is perfectly legal to
pass a sound handle to the graphics API as a buffer handle which will
obviously cause issues.

This adds a new type called "ID" which is a wrapper class for a generic
handle but with added type safety. An instance of this class cannot be
passed to a function expecting another type of handle which provided
compile-time type safety for these APIs.

As an initial test I converted the game sound handles to this new type.
I already found a bug in the mainhall system thanks to this new type.
The mainhall used the game sound handles as sound instance handles which
probably meant that that specific code never really worked right. I
removed the code since there was no better alternative for fixing it.
2018-04-22 16:22:45 +02:00
asarium d1a6b48beb Improve handling of non-persistent particles
The current particle system uses dynamic allocation of particle
instances for keeping track of particle instances. This adds unnecessary
overhead in case the code does not need a handle to this particle which
is the case in pretty much all instances.

The new non-persistent particles are stored in a standard vector without
dynamic allocation which should make the processing steps using this
vector much faster and allow better scalability in case more particles
are used by a mission.
2018-04-22 16:22:28 +02:00
asarium ce8fc0a373 Try to close the window on Esc key presses
This will allow the user to cancel the operation or save their changes
instead of discarding them without question.
2018-04-22 16:21:55 +02:00
asarium 991f131376 Fix Clang warnings 2018-04-22 16:21:55 +02:00
asarium ed7917cb26 Port event handling part of Event editor code 2018-04-22 16:21:55 +02:00
asarium e6e6288423 Replace interface functions with qt signals 2018-04-22 16:21:55 +02:00
asarium 48a6361586 Port message handling code of event editor dialog 2018-04-22 16:21:55 +02:00
asarium 8a2faa8b99 Port mission save code to qtFRED
This is pretty much an exact copy of the mission save code of FRED2. I
removed the campaign save code for now since it requires some
interactions with the campaign editor which does not exist yet.
2018-04-22 16:21:41 +02:00
m!m 7d139f9e80 Merge pull request #1667 from asarium/build/teaci
Add TeaCI config file and fix MinGW warnings
2018-04-22 11:23:18 +02:00
m!m cf93aa43c5 Merge pull request #1709 from jg18/qtfred2_/shieldSystemDialog
Finish shield system editor dialog in qtFRED
2018-04-21 23:24:08 +02:00
asarium 89e3533106 Add TeaCI config file
TeaCI is a CI service which provides MinGW CI builds (in Docker
containers so no "real" Windows machines). This would be useful for
validating the Windows only code with additional GCC warnings. It would
also make sure that the MinGW setup we currently have continues to work.
2018-04-21 23:01:19 +02:00
m!m a3f9febdc4 Merge pull request #1668 from asarium/build/minGWFixes
Fix various issues detected by MinGW
2018-04-21 22:59:54 +02:00
jg18 3c738312de make corrections to shield system dialog based on feedback 2018-04-21 12:52:01 -07:00
jg18 363d6d3ba0 finish shield system editor dialog in qtFRED 2018-04-21 12:52:01 -07:00
niffiwan 5578825bf3 Merge pull request #1662 from asarium/fix/luaWaypointAPI
Fix Assert in Lua API when passing invalid name to mn.WaypointList
2018-04-21 23:31:51 +10:00
asarium 9b5710e8c3 Fix various issues detected by MinGW
This fixes various issues I found while trying to compile FSO in a cross
compilation setup using MinGW. This is a prerequisite for merging Tea-CI
support.
2018-04-21 15:13:25 +02:00
m!m b527dd5449 Merge pull request #1665 from asarium/fix/1664
Validate number of parsed briefing stages and icons
2018-04-21 12:47:26 +02:00
m!m 175668e2bb Merge pull request #1700 from asarium/qtfred2_/fixWindowsError
Fix Windows deployment issue
2018-04-21 12:45:55 +02:00
m!m cbf3052094 Merge pull request #1673 from asarium/build/ciFRED
Reenable FRED building for Appveyor
2018-04-21 12:45:34 +02:00
m!m 3507cf96d1 Merge pull request #1711 from asarium/fix/fredStaticInitializer
Fix crash on FRED startup in debug mode
2018-04-20 21:05:10 +02:00
asarium e624f6c1a8 Fix crash on FRED startup in debug mode
The crash was caused by a static initialization order problem where the
static initializer of the FRED app was called before the initializer of
the outwnd filter vector.

This fixes that by initializing the vector as soon as necessary through
the use of a function with a static variable.
2018-04-20 19:52:57 +02:00
asarium 371aad8f8c Fix warnings in FRED code 2018-04-20 14:46:21 +02:00
asarium cb3fd31db4 Reenable FRED building for Appveyor
Apparently this was also disabled accidentally when qtFRED was merged
into master.
2018-04-20 14:46:21 +02:00
niffiwan e2e7eac0c6 Merge pull request #1705 from asarium/qtfred2_/updatedReadme
Update qtFRED readme and add some documentation
2018-04-18 20:46:01 +10:00
asarium 80faaf88b0 Update qtFRED readme and add some documentation
This fixes #1696.
2018-04-18 11:41:29 +02:00
Goober5000 fb0f7dd7de minor sexp subsystem cleanup
Synchronize the two subsystem-of-ship checks in sexp.cpp and sexp_tree.cpp.  Mostly this is just adding OP_BEAM_FLOATING_FIRE to sexp_tree.cpp because whoever added that sexp forgot to add it there.
2018-04-15 18:49:37 -04:00
Goober5000 62aae9d793 add optional argument for distance/range 2018-04-15 18:24:58 -04:00
Goober5000 15663a3551 add is-in-turret-fov sexp
Returns true if the ship is in a turret's FOV, false otherwise.  Requested by JSRNerdo.  Uses the object_in_turret_fov internal function which is the same one used by the turret code when it checks whether it can fire.
2018-04-15 17:59:04 -04:00
m!m 6df837e7f3 Merge pull request #1686 from PeterMitsis/experiment
Minor clean up
2018-04-15 23:06:38 +02:00
asarium 512d08e443 Fix Windows deployment issue
The CMake code did not specify that qwindows.cll also needed to be
distributed with the application which caused errors for users who had
not installed Qt on their system.

This should make qtFRED redistributable without needing a QT
installation.
2018-04-15 19:35:06 +02:00
Peter Mitsis 504abeb305 ship: Remove unused routine ship_select_next_valid_secondary_bank()
Signed-off-by: Peter Mitsis <[email protected]>
2018-04-15 12:58:05 -04:00
Peter Mitsis 2ae2f2910c asteroid: Remove unused routine hud_target_asteroid()
Signed-off-by: Peter Mitsis <[email protected]>
2018-04-15 10:51:50 -04:00
Peter Mitsis 3b4fbde8e6 collide: Apply static keyword to applicable routines
Applying the 'static' keyword to applicable routines both informs the
developer where the routine is likely to be used as well as allows the
compiler to perform additional optimizations.

Signed-off-by: Peter Mitsis <[email protected]>
2018-04-14 19:57:04 -04:00
Peter Mitsis 2d01cd2366 shiphit: apply static keyword to applicable routines
Applies the 'static' keyword to applicable routines to both make it
more clear to the developer where such routines are likely to be used
as well as to provide additional information to the compiler so it can
make better optimizations.

Signed-off-by: Peter Mitsis <[email protected]>
2018-04-14 19:57:04 -04:00
Peter Mitsis 2beb136ecf shipfx: Apply static keyword to applicable routines
Applying the static keyword to applicable routines makes it both
more clear to the developer where those routines are likely to be
used as well as provide additional information to the compiler to
allow it to make better optimization choices.

Signed-off-by: Peter Mitsis <[email protected]>
2018-04-14 19:57:04 -04:00
Peter Mitsis c728cc40b2 ship: Apply static keyword to ship routines
Applies the 'static' keyword to various sihp related routines. This both
makes it more clear to the developer where those routines might be used
as well as allowing the compiler to leverage that knowledge and potentially
make additional optimizations.

Signed-off-by: Peter Mitsis <[email protected]>
2018-04-14 19:57:04 -04:00
Peter Mitsis d13ddb387f asteroid: Remove unused routines
Removes the following two routines as not only are they unused, but
they have been unused for years.
    get_debris_from_same_group()
    asteroid_get_random_in_cone()

Signed-off-by: Peter Mitsis <[email protected]>
2018-04-14 19:57:03 -04:00
Peter Mitsis 666c177dec Fix asteriod typo
Replaces instances of 'asteriod' with 'asteroid'.

Signed-off-by: Peter Mitsis <[email protected]>
2018-04-14 19:57:03 -04:00
Peter Mitsis d5ba2369a2 asteroid: Apply static keyword to asteroid routines
Applies the 'static' keyword to various asteroid routines. This both
makes it more clear to the developer where those routines might be used
as well as allowing the compiler to leverage that knowledge and potentially
make additional optimizations.

Signed-off-by: Peter Mitsis <[email protected]>
2018-04-14 19:57:03 -04:00
Peter Mitsis 7bf7a8fc66 keycontrol: Remove reference to hud_target_asteroid()
Removes the extern declaration of hud_target_asteroid() from
keycontrol.cpp as it is not used in that module.

Signed-off-by: Peter Mitsis <[email protected]>
2018-04-14 19:57:03 -04:00
Fabian Woltermann a3d2320f0a Merge pull request #1681 from asarium/build/clang-tidy
Add clang-tidy to Travis CI configuration
2018-04-14 11:48:30 +02:00
asarium 9d352ddc5f Fix .clang-tidy format 2018-04-13 16:26:57 +02:00
MageKing17 299e584284 Merge pull request #1684 from asarium/fix/1683
Set team_glow_enabled uniform to proper value
2018-04-13 07:13:48 -07:00
asarium 4f22b12ec6 Mark all external libraries as system includes 2018-04-13 15:40:11 +02:00
asarium 57985b5f1a Enable misc-new-delete-overloads 2018-04-13 12:10:24 +02:00
asarium 513115ceeb Enable misc-noexcept-move-constructor check 2018-04-13 12:10:24 +02:00
asarium 95acebfce8 Add misc-multiple-statement-macro check 2018-04-13 12:10:24 +02:00
asarium ca5605cfb4 Add misc-move-forwarding-reference check 2018-04-13 12:10:24 +02:00
asarium ea4e5f222d Make .clang-tidy easier to read 2018-04-13 12:10:22 +02:00
asarium 538afc73a2 Keep building on Travis CI until more errors have occured
This will make it easier to find warnings and clang-tidy notifications
since ninja won't stop after the first warning or error was reported.
2018-04-13 12:10:03 +02:00
asarium 16560326e7 Add more clang-tidy checks 2018-04-13 12:10:01 +02:00
asarium 68372b18a2 Enable performance clang-tidy warnings 2018-04-13 12:08:56 +02:00
asarium c6abe74f06 Replace noexcept with compatibility macro 2018-04-13 12:08:07 +02:00
asarium f1c79c2ca7 Fix override warnings produced by clang-tidy 2018-04-13 12:08:06 +02:00
asarium 7944eda1cb Add Clang-tidy support 2018-04-13 11:40:38 +02:00
asarium 1571caa95e Set team_glow_enabled uniform to proper value
This was missed when converting the model uniforms to a uniform buffer
and caused some issues with team colors. This sets that uniform to the
value it had before the uniform buffer changes.

This fixes #1683.
2018-04-13 10:36:32 +02:00
m!m 9f97ea909a Merge pull request #1669 from jg18/qtfred2_/fictionViewerDialog
Add fiction viewer dialog to qtFRED
2018-04-13 09:57:01 +02:00
MageKing17 7469558e97 Merge pull request #1676 from asarium/fix/jsonOutputEfxSupport
Write EFX support information to JSON output
2018-04-12 17:10:38 -07:00
jg18 6747c630af Finish up qtFRED fiction viewer dialog 2018-04-11 21:45:38 -07:00
jg18 d80d8dd08e Use SignalBlockers with fiction viewer dialog 2018-04-09 23:51:19 -07:00
jg18 5ebf806c72 fix CI error about unused variable 2018-04-09 23:51:19 -07:00
jg18 6d2d092cc6 wrapup fiction viewer dialog corrections 2018-04-09 23:51:18 -07:00
jg18 cafee9c66a Add qtFRED notice about multiple fiction viewer stages 2018-04-09 23:51:18 -07:00
jg18 8fc281c7be Fix bugs in qtFRED fiction viewer dialog 2018-04-09 23:51:02 -07:00
jg18 8cae09bfe8 Add fiction viewer dialog to qtFRED (WIP) 2018-04-09 23:43:10 -07:00
jg18 5c5e48847e Add qtFRED keyboard shortcut for fiction viewer dialog 2018-04-09 23:42:47 -07:00
Joshua Glatt ae17e3f4b7 Merge pull request #1679 from asarium/qtfred2_/initSystem
Copy original FRED initialization code
2018-04-09 08:08:27 -07:00
m!m ebfc904e52 Merge pull request #1678 from jg18/qtfred2_/guisGalore
Add GUIs for background, shield system, and voice acting editors to qtFRED
2018-04-09 09:47:24 +02:00
asarium f3a3ed982f Copy original FRED initialization code
This copies the original FRED code for initializing the individual game
systems to qtFRED. This should fix the various issues caused by missing
game system initialization calls.
2018-04-09 09:45:41 +02:00
jg18 fabf05454b Make corrections to background editor UI and add dialog shortcut 2018-04-08 21:12:35 -07:00
m!m d309644e53 Merge pull request #1677 from jg18/qtfred2_/blockUiUpdate
Add SignalBlockers to qtFRED
2018-04-08 10:56:37 +02:00
jg18 63b21893df add stub dialog implementations and more corrections 2018-04-07 23:58:43 -07:00
jg18 81f4c03364 corrections to new GUIs 2018-04-07 23:01:04 -07:00
jg18 3668ce67d5 Add SignalBlockers to qtFRED 2018-04-07 19:52:23 -07:00
asarium 28ddf7d8d2 Write EFX support information to JSON output
The initial JSON flags output lacked this information but it is needed
for proper support by the launcher. This adds a new entry in the JSON
structure without changing anything else so it does not require a new
output version.
2018-04-06 13:48:49 +02:00
jg18 b2d427fb00 Add .ui files for background, shield system, and voice acting editor dialogs 2018-04-01 15:31:46 -07:00
Fabian Woltermann 3a4d5788a8 Merge pull request #1675 from asarium/fix/textureDetail
Fix texture detail errors
2018-04-01 20:34:53 +02:00
asarium 7e3ca7eb46 Fix texture detail errors
When I made the texture array changes I forgot to test the texture
detail feature which caused some visual corruption when using a texture
detail which was less than the maximum. This should fix that.
2018-04-01 13:21:14 +02:00
Fabian Woltermann 95620e5de6 Merge pull request #1671 from asarium/fix/soundSetObjectSounds
Assign minimum and maximum value properly in RandomRange
2018-03-29 15:31:04 +02:00
asarium ae738abcf5 Assign minimum and maximum value properly in RandomRange
The minimum and maximum values were not initialized correctly which
caused code which relied on those values to fail unexpectedly.

This assigns the value properly and adds a documentation note which
clarifies when the values are valid.
2018-03-29 14:25:37 +02:00
Tyler Blount e3c815c194 Merge pull request #1657 from asarium/qtfred2_/sexpContextMenu
Add SEXP tree context menu building
2018-03-19 10:53:16 -06:00
asarium daca57de4c Add replace Variable implementation 2018-03-18 22:56:59 +01:00
asarium 5650199b04 Implement "Add paste" 2018-03-18 19:10:22 +01:00
asarium b1e392be2f Add support for adding typed data 2018-03-18 18:58:10 +01:00
asarium 9f0e21f941 Fix menu enablement status
Also added simple add Data implementations
2018-03-18 18:46:19 +01:00
asarium 5258066545 Validate number of parsed briefing stages and icons
This fixes two possible assertions and two possible buffer overflows
which could have been caused by a mission with wrong values for
$num_stages and $num_icons.

This fixes #1664.
2018-03-18 15:50:10 +01:00
asarium f740583547 Add add/replace/insert actions 2018-03-18 15:49:01 +01:00
asarium fd92813198 Add Cut/Copy/Paste action handlers 2018-03-18 10:35:28 +01:00
asarium fc87b129ac Add expand all action 2018-03-18 10:27:08 +01:00
asarium d5509411de Add data editing support 2018-03-18 10:27:02 +01:00
asarium a1d7ec7855 Add delete action handler 2018-03-17 17:37:56 +01:00
asarium 7d3bc7fc58 Add support for the start_mission parameter to qtFRED 2018-03-17 17:06:50 +01:00
asarium 6ed82d88a9 Fix minor issues in editor code 2018-03-17 17:04:13 +01:00
m!m 8b49ebf323 Merge pull request #1660 from The-E/feature/ogl_anisotropy
Make the OGL_Anisotropy setting more usable
2018-03-17 10:22:51 +01:00
Goober5000 4bcc85e963 Merge pull request #1661 from asarium/fix/booleanSexpCrash
Fix wrong return value when getting boolean value from Lua
2018-03-16 22:19:30 -04:00
asarium 55c1c3ce9d Fix wrong handle return type 2018-03-16 23:53:34 +01:00
asarium 2bddcf8344 Fix Assert in Lua API when passing invalid name to mn.WaypointLists
Since atoi return 0 on error the code tries to access the waypoint list
with index -1 which causes an assert in the lookup code. This fixes that
by using the error detection capabilities of strtol.
2018-03-16 23:53:19 +01:00
asarium 235391154e Fix wrong return value when getting boolean value from Lua
This is probably a bug from when I changed how those functions worked.
The function is supposed to return if it successfully retreived a value
from the Lua stack but instead of returning true if it was, it returned
the value it just retrieved. This works fine if that value is true but
causes issues if it was false.
2018-03-16 22:32:58 +01:00
Fabian Woltermann 1c5bf39e8d Use GL_max_anisotropy by default 2018-03-16 13:05:21 +01:00
Fabian Woltermann 0b3ff5e698 Make the anisotropy setting controllable via commandline 2018-03-16 08:14:35 +01:00
asarium 5c0e88dd60 Add actions to context menu 2018-03-15 14:18:35 +01:00
asarium 1498367e48 Add SEXP tree context menu building
This adds displaying the correct context menu for the qtFRED SEXP tree
widget. The actions are not implemented yet.
2018-03-14 11:46:59 +01:00
Fabian Woltermann a8747b7b93 Merge pull request #1656 from asarium/fix/noRuntimeDll
Disable building targets with runtime DLLs as default
2018-03-14 10:12:50 +01:00
asarium dadf58f6b1 Disable building targets with runtime DLLs as default
This caused issues for some users and was an accidental change
introduced by the qtFRED merge.
2018-03-14 09:16:51 +01:00
m!m e9a642673c Merge pull request #1654 from asarium/qtfred2_/sync
Merge qtFRED into the main branch
2018-03-12 10:21:44 +01:00
asarium 42fbc92d73 Don't build qtFRED for deploy builds 2018-03-11 13:45:27 +01:00
m!m 6141fc7f73 Merge pull request #1652 from The-E/fix/1623
Fix for 1623
2018-03-11 09:06:20 +01:00
asarium c1fd6e7026 Call processEvents from game_busy
That will avoid unresponsive application errors when loading a big
mission.
2018-03-11 08:49:34 +01:00
Tyler Blount 9114d94e0c Merge pull request #1650 from asarium/qtfred2_/sexpTree
Add initial support for displaying SEXPs in a tree widget
2018-03-10 16:15:09 -07:00
asarium 235234ea66 Fix some warnings 2018-03-10 18:30:55 +01:00
Fabian Woltermann 512887482a use correct array lookups (how did VS not find these....?) 2018-03-10 18:00:30 +01:00
Fabian Woltermann 04fd9679bd Fix mprintf calls 2018-03-10 14:06:12 +01:00
m!m 07a2f5a155 Merge pull request #1651 from TRBlount/fred/changeHeadaniExt
Make APNG the default file extension for the Event Editors head ani file dialog
2018-03-10 12:55:53 +01:00
Fabian Woltermann 85874105e3 Remove unnecessary early exit 2018-03-10 12:17:17 +01:00
Fabian Woltermann 248b70b780 Replace this assert with a proper exit path + debug log print 2018-03-10 12:11:17 +01:00
Fabian Woltermann f05a50f57b Merge pull request #1638 from The-E/feature/lighting_settings_rework
Reworks the lighting settings according to the discussion in #1634.
2018-03-10 08:57:56 +01:00
Fabian Woltermann a5fc5e322d Merge branch 'feature/lighting_settings_rework' of https://github.com/The-E/fs2open.github.com into feature/lighting_settings_rework 2018-03-10 08:16:46 +01:00
Fabian Woltermann 91c4884fd3 Use the correct index in the popup 2018-03-10 08:15:59 +01:00
Fabian Woltermann eaad5a01a2 Create a popup to notify people that shaders are being recompiled 2018-03-10 08:15:59 +01:00
Fabian Woltermann 905417b866 Use 32 as a default specPower value in the Blinn-Phong render path 2018-03-10 08:15:59 +01:00
asarium 5061a112db Set default shader uniforms every time the shader is compiled 2018-03-10 08:15:59 +01:00
Fabian Woltermann b7981c0ce4 Implemented callback and shader recompile, but there is still strange behaviour 2018-03-10 08:15:59 +01:00
Fabian Woltermann c0328bb4f5 Beams should always be rendered at lighting detail >= 2 2018-03-10 08:15:59 +01:00
Fabian Woltermann dd2074d91d Reworks the lighting settings according to the discussion in #1634.
This fixes #1634
2018-03-10 08:15:59 +01:00
TRBlount e7a8adb367 Make APNG default file for head ani selection 2018-03-09 16:11:57 -07:00
asarium 809ac2300d Turn modified state into a signal 2018-03-09 23:52:21 +01:00
Fabian Woltermann 8ea179781a Merge pull request #1610 from asarium/feature/windowIcon
Allow mods to specify the window icon
2018-03-09 20:06:54 +01:00
Fabian Woltermann 77768b3328 Merge pull request #1632 from asarium/opengl/betterDecals
Add normal map rendering to decals
2018-03-09 20:06:06 +01:00
Fabian Woltermann 873162690d Merge pull request #1649 from asarium/fix/1647
Fix rendering position of hardpoint models
2018-03-09 20:03:31 +01:00
Fabian Woltermann 5c5ce5e66a Use the correct index in the popup 2018-03-09 15:00:39 +01:00
Fabian Woltermann 7d54dd9a05 Create a popup to notify people that shaders are being recompiled 2018-03-09 14:57:40 +01:00
asarium eb322476b2 Add initial tree creation code to event editor
With these changes the event editor can now display the SEXP tree of a
mission. No other operations are supported at the moment.
2018-03-08 22:42:45 +01:00
asarium aadb22c9f1 Fix the rest of the SEXP tree code 2018-03-08 22:28:25 +01:00
asarium d4b0dc9cc2 Convert mask color to proper alpha channels for SEXP icons 2018-03-08 22:28:25 +01:00
asarium b7e703553b Port sexp tree 2018-03-08 22:28:25 +01:00
Tyler Blount 6b97dcfe60 Merge pull request #1648 from asarium/qtfred2_/sync
Sync qtfred branch
2018-03-08 12:05:57 -07:00
asarium 8099bb737b Fix rendering position of hardpoint models
The previous fix to the weapon orientation failed to account for the
change from local to global space for the weapon position. This fixes
that by rotating the model positions to world space before submitting
the render call.

This fixes #1647.
2018-03-08 11:57:34 +01:00
asarium 91d6d90c9b Merge branch 'master' into qtfred2_/sync 2018-03-08 10:34:00 +01:00
m!m e5e5d14108 Merge pull request #1646 from asarium/fix/1645
Avoid reusing model material instance when setting fog
2018-03-06 18:59:12 +01:00
asarium 4fa43ed639 Avoid reusing model material instance when setting fog
The rendering material used by the model render list was reused by
multiple draw call submissions so a non-transparent mesh would reset the
fog value set before which would break meshes submitted after that.

There are still some issues with how the fog is rendered which causes
differences between how opaque and transparent meshes are drawn but I
will fix that in another pull request.

This fixes #1645.
2018-03-06 17:34:29 +01:00
asarium 1ace8b3abc Reenable decals in nebulas
With the recent changes to how fog is handled in nebulas it is now
possible to render decals correctly in a nebula environment so there is
no need to disable decals when the mission is in a nebula.
2018-03-06 11:38:07 +01:00
asarium 520e532c56 Add normal map rendering to decals
This changes the decal system so that it is able to modify the normal
map of the scene. I tested this with some existing normal maps but I am
not entirely sure if the tangent matrix I construct uses the right
values so some additional testing with normal maps made specifically for
decals would be good.

This also fixed the issues introduced by the changes to how directional
lighting was handled. Now a decal can have a diffuse and a glow map. The
diffuse map is used to change the values of the color buffer and also
supports ambient lighting. The glow map renders into the emissive buffer
and should be used for effects that should not receive lighting.
2018-03-06 11:38:01 +01:00
Fabian Woltermann 9a9e088861 Merge pull request #1644 from asarium/opengl/nebulaPostProcessing
Improve handling of nebula fog for deferred lighting
2018-03-06 09:34:43 +01:00
asarium 39f24bce23 Improve handling of nebula fog for deferred lighting
The previous method of rendering nebula fog didn't work correctly with
deferred shading since it changed the color of the material which
obviously caused some issues when it received light from a beam or a
weapon. This wasn't very noticable before because the directional lights
were handled correctly but since all the lighting operations have been
moved into the deferred shading phase it is very obvious that something
is wrong with our nebula rendering.

This fixes that by introducing a new shader which does a fullscreen pass
after resolving all the lights. It applies the usual fog formula based
on the depth of the fragment but it can only use a fixed distance range.
FSO support specifying a range for every object type but the default
range I chose should work properly for all ship types.

The new code only applies to opaque meshes. Transparent meshes are
fogged using the standard formula.
2018-03-05 22:40:05 +01:00
m!m 3dd9bc8aef Merge pull request #1643 from asarium/fix/hudHardpointsStencil
Fix stencil rendering in hardpoint rendering
2018-03-05 17:00:46 +01:00
Fabian Woltermann 03aa479efc Merge pull request #1642 from asarium/fix/hardpointOrientation
Fix missile hardpoint orientation in HUD gauge
2018-03-05 14:37:25 +01:00
asarium 31931777bc Fix stencil rendering in hardpoint rendering
There were actually multiple issues here. The addition of color mask and
stencil state to the material system overwrote the state set by the
hardpoint renderer so the stencil buffer was never written or read
correctly. I fixed this by introducing three new model render flags
(there were a few open slots in the bit mask so I used those) which set
the correct state using the material system. That also makes setting up
the rendering environment much easier.

Second, gr_opengl_stencil_set used mixed up parameter values which were
probably broken when I introduced more detailed stencil state tracking.
I restored those values to how they were in 3.8.

This fixes the other issue reported in #1640.
2018-03-05 14:28:59 +01:00
Fabian Woltermann 59d0c561d6 Use 32 as a default specPower value in the Blinn-Phong render path 2018-03-05 09:06:43 +01:00
Fabian Woltermann ca55f4ea9c Merge pull request #1641 from asarium/fix/lazySoundLoading
Load unloaded sounds when trying to determine sound length
2018-03-05 08:28:24 +01:00
Fabian Woltermann 8c223afcd0 Merge pull request #1639 from asarium/opengl/unifiedGammaHandling
Move gamma correction into common header
2018-03-05 08:27:29 +01:00
Fabian Woltermann 4dc8c57d3c Merge pull request #1 from asarium/fix/shaderDefaultUniforms
Set default shader uniforms every time the shader is compiled
2018-03-05 08:02:51 +01:00
asarium 82f74d570b Fix missile hardpoint orientation in HUD gauge
The code previously used the matrix stack for handling the orientation
or the weapon models. That is no longer supported by the model renderer
(since it would make handling the transforms harder for no real reason).
I fixed the issue by passing the object orientation directory to the
model render function.

This is a fix for one of the problems mentioned in #1640.
2018-03-05 00:20:21 +01:00
asarium 8df4835d51 Set default shader uniforms every time the shader is compiled 2018-03-04 23:30:49 +01:00
asarium 5a5dbd0df2 Load unloaded sounds when trying to determine sound length
This can happen if a script tries to determine the length of a sound
before actually playing it. This fixes the assertion by loading the
sound when it is necessary.
2018-03-04 22:41:15 +01:00
Fabian Woltermann cc876f8bc3 Implemented callback and shader recompile, but there is still strange behaviour 2018-03-04 20:14:09 +01:00
m!m 45d09fd49b Merge pull request #1637 from The-E/feature/no_max_lights
Remove the MAX_LIGHTS define
2018-03-04 16:45:43 +01:00
m!m 6fcdabeb45 Merge pull request #1635 from asarium/fix/emissiveLightNebula
Handle emissive light properly in nebulas
2018-03-04 16:45:14 +01:00
Fabian Woltermann 2e632467f4 Beams should always be rendered at lighting detail >= 2 2018-03-04 16:31:03 +01:00
asarium 5c599fa9ee Move gamma correction into common header
This moves the constant definition and functions for converting from and
to linear color space into a single file that is included in all other
files.
2018-03-04 13:21:45 +01:00
asarium 6b654ce38a Handle emissive light properly in nebulas
The emissive part of the lighting was not using the fog values properly
so ships didn't rendered right in nebulas. This fixes that by applying
the standard fog color transform to the emissive part of the scene.
2018-03-04 12:29:01 +01:00
Fabian Woltermann 2cba774a33 Reworks the lighting settings according to the discussion in #1634.
This fixes #1634
2018-03-04 10:25:45 +01:00
Fabian Woltermann 32fec00e97 Remove the MAX_LIGHTS define 2018-03-04 08:55:21 +01:00
niffiwan 66c9baf893 Merge pull request #1626 from asarium/opengl/vertexInterfaceBlocks
Use vertex interface blocks for vertex shader attributes
2018-03-04 10:52:59 +10:00
niffiwan 1c04be91bb Merge pull request #1624 from asarium/cleanup/grFog
Remove gr_set_fog
2018-03-04 10:52:42 +10:00
m!m 6d52cab0a4 Merge pull request #1627 from asarium/fix/lineDrawList
Add a mechanism for batching line draw calls
2018-03-03 22:46:50 +01:00
Samuel Cho aa60a639fb Merge pull request #1633 from The-E/fix/team_colors_washed_out
Add SRGB adjustment to the team colors
2018-03-03 12:25:27 -08:00
asarium dfd9fe7610 Use vertex interface blocks for vertex shader attributes
This is a minor cleanup of how the engine passes vertex attribute data
from one shader stage to the next. The current code uses standalone
attribute variables which require a unique name over the entire shader
program which means that the variable names need to be different when a
geometry shader is used which makes the code more complicated and harder
to understand.
2018-03-03 19:34:18 +01:00
Fabian Woltermann ef0c6b5c78 this should do it 2018-03-03 16:33:00 +01:00
Fabian Woltermann a3f493d8c1 make the code more readable here 2018-03-03 15:16:40 +01:00
Fabian Woltermann b6981875a5 Address some feedback make it all work correctly 2018-03-03 15:04:46 +01:00
Fabian Woltermann 7c1147541d Add SRGB adjustment to the team colors, make the logic less weird. 2018-03-03 11:48:02 +01:00
niffiwan be9a881cb5 Merge pull request #1630 from niffiwan/bsp_opt
add small bsp tree optimisation
2018-03-01 21:45:58 +10:00
niffiwan 8f2aec3b9a add small bsp tree optimisation
don't add no_collide (& similar) submodels to the bsp trees
this has been in the fotg branch for ages without causing any apparant
issues
2018-03-01 20:00:59 +10:00
MageKing17 78abbf89e6 Merge pull request #1625 from Flip-Sandwich/master
Fixes electronics flag behavior with shockwaves
2018-02-27 19:09:32 -08:00
Fabian Woltermann 4de3451d6c Merge pull request #1628 from The-E/fix/lab-glowpoints
Make glowpoints in the lab work correctly
2018-02-26 12:16:33 +01:00
Fabian Woltermann 8f5f77fa42 Merge pull request #1622 from asarium/opengl/directionalDeferredLights
Use deferred shader for applying directional lights
2018-02-26 11:18:33 +01:00
Fabian Woltermann 354246caf4 Make sure that glowpoints attached to rotating subobjects actually do rotate in the lab 2018-02-26 09:49:13 +01:00
faceman 4797b29311 fixes shockwaves with electronics flagged weapons, properly this time 2018-02-26 15:42:54 +11:00
asarium 2e0253e301 Add a mechanism for batching line draw calls
The previous version used NanoVG which caused quite a serious FPS drop.
This adds a buffer batching class which groups line drawing operations
together and submits them to the GPU with a single draw call.
2018-02-25 19:55:41 +01:00
asarium 0d188fe076 Use deferred shader for applying directional lights
This moves all lighting operations into the deferred shading phase of
the rendering pipeline. Previously, directional lights were applied to
all objects while they were being rendered. This was probably done to
avoid doing multiple full screen passes later but caused some problems
since the color information in the G-buffers was not correct for doing
later lighting operations.

This was especially noticable in dark scenes where point lights would
appear to ignore the color of the rendered objects. This should be fixed
with these changes.

I did some performance testing and to my surprise this actually improves
performance in very demanding scenes. My guess would be that applying
the shadows while rendering the objects caused a lot of overdraw which
is not the case anymore since shadows are only computed for visible
pixels. In simple scenes the opposite happens which leads to decreased
performance in those cases but in my opinion the improvement in
demanding scenes outweights this performance decrease.
2018-02-25 12:43:45 +01:00
asarium c463709399 Remove gr_set_fog
Specifying the fog rendering options is now handled by the materials
system and the implementation of gr_set_fog was pretty much empty so I
removed it.
2018-02-24 19:37:39 +01:00
asarium 25357ce8a2 Allow mods to specify the window icon
This is mostly intended for total conversions to allow them to set
themselves apart from FS2 based mods. It uses the new in-memory
filesystem to support a default icon in case no icon was specified by
the mod.
2018-02-24 18:08:41 +01:00
MageKing17 9953c6a7c4 Merge pull request #1616 from The-E/1615_fix
Do not try to delete opengl buffers when we have no idea what they are
2018-02-23 09:33:20 -08:00
MageKing17 1db36b7ba5 Merge pull request #1619 from The-E/debug_filter_defaults
The extra debug filters really should not be enabled by default.
2018-02-23 09:25:31 -08:00
Fabian Woltermann 77b6648d22 Merge pull request #1613 from asarium/opengl/shaderIncludes
Add support for includes in shader files
2018-02-23 12:58:04 +01:00
Fabian Woltermann 09ca5d3dd6 Merge pull request #1621 from The-E/dockpoint_warning
Print out a warning if we can't find a dockpoint during missionparse
2018-02-21 08:36:35 +01:00
Fabian Woltermann 942f72d09a Print out a warning if we can't find either dockpoint 2018-02-20 16:47:02 +01:00
Fabian Woltermann ee27db60de The extra debug filters really should not be enabled by default. 2018-02-20 11:54:23 +01:00
MageKing17 66c0d27270 Merge pull request #1618 from MageKing17/bugfix/ai-profiles-parsing-end
Make AI profile tables actually stop parsing if #End is missing.
2018-02-18 15:10:44 -08:00
m!m 206364a113 Merge pull request #1617 from The-E/missile_lighting_no_export
Do not export -missile_lighting to launchers
2018-02-18 23:14:05 +01:00
MageKing17 ac9547d610 Make AI profile tables actually stop parsing if #End is missing.
By making parse_ai_profiles_tbl() actually check the return value of skip_to_start_of_string_either() (and break if the appropriate characters aren't found), AI profile tables should no longer keep parsing past the end of the file and into invalid memory, until they either find an "#End" in memory somewhere or just plain crash.

As a pleasant bonus, a missing "#End" should now generate an appropriate error message.
2018-02-18 13:13:18 -08:00
Fabian Woltermann 6534c0a3f6 Remove the -missile_lighting flag from the list of exported cmdline options 2018-02-18 22:12:29 +01:00
Fabian Woltermann cdeeee688d Merge pull request #1605 from Flip-Sandwich/subsysdamagefix
Negative damages no longer heal subsystems
2018-02-18 21:01:57 +01:00
Fabian Woltermann 8b5f257d0d Merge pull request #1614 from asarium/feature/luaLanguageFunctions
Add lua functions for accessing the current engine language
2018-02-18 20:59:23 +01:00
Fabian Woltermann b2652e0628 While working through the atexit table, this function somehow got called, leading to the debug_filter.cfg being altered, as explained in #1615 2018-02-18 19:55:44 +01:00
asarium 2eea0a6eb1 Add lua functions for accessing the current engine language
This can be used by scripts to implement language specific behavior.
2018-02-18 17:12:17 +01:00
m!m 67c67548fd Merge pull request #1611 from The-E/smooth_lab_cam
Make the lab's camera smoother
2018-02-18 16:05:33 +01:00
m!m 12e45e88fa Merge pull request #1612 from The-E/LabHelpText
Print a helpful reminder about the camera controls
2018-02-18 00:01:25 +01:00
Fabian Woltermann e2129355bf Remove the bloom printout, add a camera distance printout 2018-02-17 21:00:47 +01:00
m!m 857582a980 Merge pull request #1608 from The-E/LightTypeEnum
Use an enum class to mark light types
2018-02-17 19:24:51 +01:00
asarium c4dd593dd7 Move lighing functions into one file
There was a slight difference between the GGX function from the main
shader and the deferred shader. The deferred shader didn't use the
fresnel value stored in the G-buffer for some reason.
2018-02-17 19:07:26 +01:00
asarium 30404d4b04 Move shadow functions into separate shader file 2018-02-17 19:02:02 +01:00
asarium c8e3e01ca0 Add support for includes in shader files
This can be used for keeping code for common functionality in one file
(e.g. lighting functions). The code which detects include statements is
pretty simple so it may break if it is used in a more complicated.
Circular includes are detected and treated as an error.
2018-02-17 18:59:11 +01:00
Fabian Woltermann 16ed58f403 Print a helpful reminder about the camera controls 2018-02-17 16:25:15 +01:00
Fabian Woltermann 5ac2571efa Clamp the lab camera's phi component to [0.01, 3.13] to avoid locking issues 2018-02-17 11:56:26 +01:00
Fabian Woltermann 7dfa5b5739 move this variable initialization out of the switch statement 2018-02-17 10:46:59 +01:00
m!m 0178374b98 Merge pull request #1606 from The-E/NewLab
Use mission backgrounds in the F3 lab
2018-02-16 11:26:51 +01:00
Fabian Woltermann 738e4a8153 Remove unused variable 2018-02-16 09:49:11 +01:00
Fabian Woltermann 1a4181fb67 Merge pull request #1609 from Flip-Sandwich/master
Fixes beam behaviour with additive/cap/etc damage types
2018-02-16 09:47:32 +01:00
faceman 85c2b3a7f0 Removes a magic number from ship.cpp 2018-02-16 16:08:45 +11:00
faceman 508b8a176b Fixes beam behaviour with additive/cap/etc damage types 2018-02-16 15:12:25 +11:00
Fabian Woltermann ca313ae17f Addressing CI issues 2018-02-15 14:41:14 +01:00
Fabian Woltermann 87bb2cbcc7 Remove debris rendering for now 2018-02-15 14:19:59 +01:00
Fabian Woltermann 9e673ff7fe light_reset needs to be called on every frame.
this also adds a trace scope to sunspot processing
2018-02-15 11:09:53 +01:00
Fabian Woltermann 126b6718db Reset the background window when it's closed 2018-02-15 11:01:34 +01:00
Fabian Woltermann b0fc182fab Fix crash when switching between weapons and ships 2018-02-15 10:44:45 +01:00
Fabian Woltermann 158292afba We can't show tech or external models yet 2018-02-15 10:35:25 +01:00
Fabian Woltermann e334c1f736 Specify all values explicitly 2018-02-15 10:21:13 +01:00
Fabian Woltermann f6fa053d94 Addressing feedback 2018-02-15 10:17:32 +01:00
Fabian Woltermann 4e24fba7fa Make sure the index is always incremented 2018-02-15 10:09:37 +01:00
Fabian Woltermann 0ea638f520 Fix an uninitialized variable being stuffed into a vector 2018-02-15 10:05:46 +01:00
Fabian Woltermann d75ec93484 Merge pull request #1604 from Flip-Sandwich/master
Consistent beam damage per frame regardless of time acceleration
2018-02-14 20:11:18 +01:00
Fabian Woltermann 468a9f280a Merge pull request #1607 from asarium/fix/aiProfilesWarning
Don't include the default ai_profiles system in CFile
2018-02-14 20:10:15 +01:00
Fabian Woltermann 69f4fa60f5 Remove unused variables 2018-02-14 17:10:26 +01:00
Fabian Woltermann 95ed536225 change the light type to an enum class 2018-02-14 17:07:42 +01:00
asarium 96d3eebad9 Don't include the default ai_profiles system in CFile
This fixes a warning caused by parsing the default ai_profiles table
twice. The default table was moved out of the data/tables folder and
into a special builtin category which will not be included in CFile.
2018-02-14 16:45:04 +01:00
Fabian Woltermann 3b21b2469f A clean, up-to-date patch of the new lab code 2018-02-14 16:19:38 +01:00
Fabian Woltermann cbe1d20fcc Merge pull request #1310 from asarium/feature/inMemoryCfile
Add support for accessing default files with CFile
2018-02-14 11:45:34 +01:00
m!m 3d3bbb5dc4 Merge pull request #1602 from The-E/RadarRangeWarning
Downgrade the invalid radar range error in the plr reader code to a warning
2018-02-14 11:12:34 +01:00
asarium 4c5b1c679b Add support for accessing default files with CFile
This allows to use more complex file structures in the executable
without requiring that those exist as real files. The rest of the code
does not need to handle the difference between a default file and a real
file anymore which means that it's now possible to embed image files
into the executable since bmpman only needs to use the standard CFile
API.

I added two tests which check if the default file can be found and
opened and if a mod file overrides the default file which should always
be possible.
2018-02-14 11:02:59 +01:00
faceman 65941e2e84 forgot to specify that 0.0f is indeed a float 2018-02-14 11:04:54 +11:00
faceman 538adf1bf6 Negative damages should not heal subsystems IMO 2018-02-14 11:00:34 +11:00
faceman a6d8b6b5fa Consistent beam damage per frame regardless of time acceleration 2018-02-14 10:41:49 +11:00
Fabian Woltermann 7fb5f08530 Merge pull request #1603 from asarium/fix/shipSoundGhostCrash
Fix assertion failure in ship_get_sound
2018-02-13 09:42:39 +01:00
asarium ffad093153 Fix assertion failure in ship_get_sound
This assertion could be hit if the player died and the engine tried to
play a sound for the now destroyed ship. Since the existing code already
had a check for the case that the object is an observer I just added
another case for OBJ_GHOST.
2018-02-12 19:46:25 +01:00
Fabian Woltermann 6a73d8f9d0 Having an invalid radar range in the pilot file should not be a fatal error. 2018-02-12 12:08:13 +01:00
m!m a0a88128ef Merge pull request #1599 from The-E/DirectionalLightFix
Make sure directional lights are always rendered
2018-02-12 11:40:05 +01:00
Fabian Woltermann 6fad19c8bc More changes requested by CI 2018-02-12 10:40:56 +01:00
Fabian Woltermann 119b5d662b Addressing feedback and CI issues 2018-02-12 08:57:39 +01:00
Fabian Woltermann 0b612c2f1a Remove an unused #define 2018-02-10 14:20:45 +01:00
Fabian Woltermann 8aee62b818 Make sure directional lights are always rendered; this kinda spiralled out into a bit of general cleanup regarding the lighting code. 2018-02-10 14:09:32 +01:00
m!m 1314b8634a Merge pull request #1597 from asarium/fix/int_list_warning
Fix off-by-one error in stuff_int_list
2018-02-10 12:12:59 +01:00
asarium b557985e90 Fix off-by-one error in stuff_int_list 2018-02-10 10:54:12 +01:00
Fabian Woltermann 4f43a2edf3 Merge pull request #1594 from The-E/MissileLightingdefault
Remove the -missile_lighting commandline parameter
2018-02-09 09:35:16 +01:00
m!m 6083c89b45 Merge pull request #1596 from asarium/fix/parse_int_list_errors
Improve error messages in stuff_int_list
2018-02-08 21:57:15 +01:00
asarium eefba9159a Improve error messages in stuff_int_list
This also converts an assertion into a proper error message which would
contain the actual file and line number.
2018-02-08 19:48:10 +01:00
m!m 8fed2fcfe3 Merge pull request #1590 from The-E/OGLDebugMessageSpamFix
Reduce the amount of Debug message spam due to non-fatal OGL warnings
2018-02-08 19:12:06 +01:00
Fabian Woltermann d149dd18b5 Use correct bit math operator 2018-02-07 15:32:37 +01:00
Fabian Woltermann a7d624f82d Add -missile_lighting to the deprecated flags 2018-02-06 16:38:52 +01:00
m!m aaab3fa03b Merge pull request #1589 from The-E/DebugFilterFix
Fix for debug_filters defaulting to +Parse
2018-02-06 14:20:41 +01:00
Fabian Woltermann 0d51cb0d14 Merge branch 'MissileLightingdefault' of https://github.com/The-E/fs2open.github.com into MissileLightingdefault 2018-02-05 16:21:55 +01:00
Fabian Woltermann 1c56d9f497 Remove the -missile_lighting commandline parameter 2018-02-05 16:18:15 +01:00
Fabian Woltermann dfc8cd1168 Remove the -missile_lighting commandline parameter 2018-02-05 16:16:55 +01:00
Fabian Woltermann ccaa766474 Merge pull request #1486 from asarium/opengl/combinedVertexBuffers
Pack vertex and index data into one buffer
2018-02-04 16:16:45 +01:00
Fabian Woltermann 741c28d785 Merge pull request #1565 from asarium/ci/gcc7
Add GCC 7 configuration for Travis CI
2018-02-04 16:15:25 +01:00
Fabian Woltermann d73a21a579 Fix variable shadowing warning 2018-02-03 23:02:19 +01:00
Fabian Woltermann 5b8f4343a3 Since OGL debug messages are only useful for coders, most of the time, we shouldn't print them to the general log unless they're actually critical 2018-02-03 22:58:43 +01:00
Fabian Woltermann 310785a961 Somehow, this loop to search for an existing debug filter did not work correctly anymore? 2018-02-03 22:38:53 +01:00
Fabian Woltermann 9029aad64d Merge pull request #1586 from asarium/fix/1579_workaround
Add a workaround for clipping planes on NVIDIA
2018-01-30 20:58:07 +01:00
asarium acc018507b Pack vertex and index data into one buffer
This changes the model loading code such that all index and vertex data
is packed in a single GPU buffer for each data type (index and vertex
data are still in separate buffers). This reduces the amount of buffer
rebinding needed when rendering a scene which will reduce the CPU
overhead. Furthermore, this opens up possibilities of future
improvements for which it is beneficial if all data is in the same
buffer (e.g. MultiDrawIndirect rendering).

To manage where to put the data in the GPU buffer I implemented a
custom HeapAllocator which manages where data can be put. It uses a very
primitive first-fit algorithm but that is sufficient for this usage
type. This does add quite a lot of overhead while allocating GPU model
data (I did some tracing and some allocation calls took as long as
130ms).

This fixes #1457.
2018-01-27 13:54:36 +01:00
asarium 25698b4534 Add a workaround for clipping planes on NVIDIA 2018-01-27 13:40:04 +01:00
Fabian Woltermann a2f6897c43 Merge pull request #1581 from asarium/feature/luaVersionCheck
Add lua function for checking the engine version
2018-01-26 17:05:24 +01:00
Fabian Woltermann 0777f24f08 Merge pull request #1583 from The-E/JumpnodeNameAssertion
Improve the JumpNode::SetName assertion to be readable by non-coders
2018-01-22 10:28:11 +01:00
Fabian Woltermann ed45baa843 Improve the JumpNode::SetName assertion to be readable by non-coders 2018-01-21 23:38:58 +01:00
m!m 13ff2ec907 Merge pull request #1582 from asarium/fix/nanovgPerformance
Add simple NanoVG draw buffer for better performance
2018-01-20 20:51:49 +01:00
asarium e795327a3f Add simple NanoVG draw buffer for better performance
This improves the rendering performance of the target hotkey brackets a
bit which caused a significant slowdown previously.
2018-01-20 18:32:39 +01:00
asarium 3c238d61e2 Add lua function for checking the engine version
This can be used to check if an API function is available in the current
version of the engine without causing runtime errors.
2018-01-20 16:37:31 +01:00
m!m 2d3e7e54e8 Merge pull request #1534 from asarium/fix/fs2netdSigbus
Fix SIGBUS crash in fs2netd
2018-01-18 16:14:54 +01:00
Tyler Blount 8ba05c1c3d Merge pull request #1578 from SamuelCho/reflection_blur_fix
Fix gloss-dependent blurred reflections
2018-01-16 09:01:54 -07:00
Tyler Blount 277962974c Merge pull request #1576 from SamuelCho/specularFixes
Specular lighting shader fixes
2018-01-15 23:17:40 -07:00
SamuelCho eab5b8b40a Allocate additional immutable storage for glGenerateMipMap when generating cube map mip levels if there's only one level 2018-01-15 22:15:04 -08:00
SamuelCho 842554e237 Flipped specular minimum floor to be done before gamma correction. Adjusted minimum specular value to 0.03 from 0.04 since that's Substance Painter's minimum. Brought back fresnel factor from the Blinn Phong function since that's needed for retail models. 2018-01-15 13:47:48 -08:00
Fabian Woltermann 563dc35dea Merge pull request #1575 from ngld/fix/setSubspaceDrive
Fix set-subspace-drive on debug builds and make the sexp_val Assert more helpful
2018-01-14 11:21:16 +01:00
ngld 3fc6958f88 Fix set-subspace-drive on debug builds and make this Assert more helpful 2018-01-14 02:48:11 +01:00
Fabian Woltermann a886a1659c Merge pull request #1574 from asarium/opengl/decalSystem
Add screen space decal rendering system
2018-01-13 14:36:36 +01:00
asarium 99f69c903e Add screen space decal rendering system
This allows to render screen space decals into the deferred lighting
buffers no matter how complex the underlying geometry is.

Currently there is only limited support for using this in the engine.
Only weapon impact decals are supported at the moment for testing
purposes.
2018-01-12 17:09:49 +01:00
m!m 830fd70f9e Merge pull request #1573 from SamuelCho/ggx
Replaced Blinn-Phong BRDF with GGX BRDF
2018-01-12 09:49:54 +01:00
m!m c4ff34970f Merge pull request #1572 from MageKing17/bugfix/unicode-distance
Correct backwards arguments in unicode::num_codepoints().
2018-01-12 09:31:52 +01:00
SamuelCho f216b8bf7f Replaced Blinn-Phong BRDF with GGX BRDF 2018-01-11 22:25:43 -08:00
MageKing17 0ec2c7fef0 Correct backwards arguments in unicode::num_codepoints().
When Unicode_text_mode was false, unicode::num_codepoints() would return (the size_t equivalent of) a negative number, because it was checking the distance from end to start instead of the distance from start to end.
2018-01-11 20:40:42 -08:00
MageKing17 1f70fb2bf2 Merge pull request #1570 from niffiwan/fix/default_volumes_pilot_create
set default volumes on pilot create
2018-01-11 10:57:52 -08:00
niffiwan 304a6a3a0d define the defaults volumes correctly 2018-01-11 19:56:12 +10:00
m!m ec6bea233b Merge pull request #1569 from chief1983/lib/sdl207
Upgrade the included SDL libs to 2.0.7.
2018-01-11 10:28:58 +01:00
niffiwan 9e495d7f94 set default volumes on pilot create
previously newly created pilots inherited the volumes from the last
pilot
2018-01-11 12:08:28 +10:00
Cliff Gordon 0344fd6e35 lib/sdl207: Also update the hash to use the new SCP Prebuilt lib version. 2018-01-10 10:02:58 -06:00
Cliff b8b7d41786 lib/sdl207: Upgrade the included SDL libs to 2.0.7. 2018-01-09 19:43:52 -06:00
asarium 3410822d9d Add GCC 7 build configuration for Travis CI
There are a few new warnings in GCC7 so this makes sure that no warning
gets missed by our CI setup. The new configuration should be updated to
the newest GCC version whenever possible.
2018-01-09 10:36:33 +01:00
MageKing17 aea63832ed Merge pull request #1568 from asarium/fix/1561
Reset loaded ship object when closing the F3 lab
2018-01-07 15:45:54 -08:00
MageKing17 1ee1886a9a Merge pull request #1567 from asarium/feature/wingLuaParameter
Add support for passing various parameter types to Lua SEXPs
2018-01-07 15:45:27 -08:00
MageKing17 c0a8ceb48f Merge pull request #1566 from asarium/fix/invalidSexpException
Fix game crash when a lua SEXP is not initialized properly
2018-01-07 15:44:46 -08:00
MageKing17 6bdbbd5c40 Merge pull request #1564 from asarium/build/cleanupOpenALLibs
Remove unnecessary OpenAL binaries in main repository
2018-01-07 15:42:13 -08:00
MageKing17 c66839a9bf Merge pull request #1562 from asarium/fix/readyroomCrash
Reset campaign room text pointers when freeing campaign data
2018-01-07 15:39:26 -08:00
asarium 40ba3162dc Reset loaded ship object when closing the F3 lab
The crash described in #1561 was caused by a NULL ai profile. The
profile was not set because the lab system already had a loaded ship
object (see line 2230). These changes make sure that the loaded ship
object is deleted before closing the lab system which ensures that the
ai profile is set the next time the lab is initialized.

This fixes #1561.
2018-01-07 14:31:42 +01:00
asarium e81547ae88 Add support for weapon class SEXP parameters 2018-01-07 12:26:33 +01:00
asarium 7577018bd3 Add support for ship class SEXP parameters 2018-01-07 12:24:18 +01:00
asarium 2181512949 Add support for passing wing parameters to Lua SEXPs
This was requested by Axem on Discord.
2018-01-06 19:28:45 +01:00
asarium dff5e4c21d Fix game crash when a lua SEXP is not initialized properly
These changes make sure that this situation is detected properly and an
informative error message is shown.
2018-01-06 19:11:48 +01:00
Fabian Woltermann d7ea260607 Merge pull request #1546 from asarium/fix/wrongMemset
Fix two minor issues detected by GCC7 warnings
2018-01-05 14:53:51 +01:00
m!m 7f7ed74bd6 Merge pull request #1563 from asarium/feature/hudTracingScopes
Add tracing scopes for HUD rendering
2018-01-05 12:30:10 +01:00
m!m 0df6c22216 Merge pull request #1547 from asarium/build/ccache
Enable ccache when available
2018-01-05 12:20:30 +01:00
asarium e8ab065bde Remove unnecessary OpenAL binaries in main repository
This is now handled by the prebuilt packages and not needed anymore.
2018-01-05 12:16:18 +01:00
asarium f79b83c60b Enable ccache when available
This will automatically enable ccache when it is detected on the system
and use it for faster compilations.
2018-01-04 20:52:03 +01:00
Fabian Woltermann 3ab6e43254 Merge pull request #1558 from The-E/revert_1555
Revert changes from #1555
2018-01-04 20:24:08 +01:00
asarium abbef793fc Add tracing scopes for HUD rendering
While debugging a performance issue reported on Discord I noticed that
the HUD rendering code does not have any tracing scopes. This adds a few
tracing scopes to that code to make performance debugging a bit easier.
2018-01-04 20:19:10 +01:00
m!m bd85f61971 Merge pull request #1560 from The-E/fix_1559
Sanity checking in maybe_play_flyby_snd
2018-01-04 16:23:29 +01:00
asarium 47967cb72a Reset campaign room text pointers when freeing campaign data
Previously the campaign room caused a heap-use-after-free error
(detected by AddressSanitizer) when loading the campaign failed two
times. This fixes the error by resetting the text pointers to their
default values when freeing the campaign list data.
2018-01-04 14:41:42 +01:00
Fabian Woltermann 7f56037369 Fully revert this 2018-01-04 13:39:16 +01:00
Fabian Woltermann 659828c213 If no flyby sounds are defined for a species, do not attempt to play any. 2018-01-04 11:10:06 +01:00
Fabian Woltermann 2c4884595e Revert changes from #1555 2018-01-04 10:47:57 +01:00
Fabian Woltermann 1621bd169b Merge pull request #1556 from asarium/fix/1554
Make sure updating a texture uses the right texture unit
2018-01-04 09:16:08 +01:00
Fabian Woltermann c496a08ab1 Merge pull request #1557 from asarium/fix/1555
Use correct attachment for depth/stencil buffer
2018-01-03 19:46:38 +01:00
m!m 012e37afb9 Merge pull request #10 from The-E/fix/1555
This seems to stop the flood.
2018-01-03 18:37:59 +01:00
Fabian Woltermann 4fc1183622 If we change the depth and stencil attachments in one place, we need to change them in all places. 2018-01-03 16:09:22 +01:00
asarium 1eaa67bb5b Use correct attachment for depth/stencil buffer
This should be the correct way to set the combined depth/stencil buffer.
This has not been tested yet since I do not have a GPU which causes
these issues.

This fixes #1555.
2018-01-03 13:45:43 +01:00
asarium bf74f29634 Make sure updating a texture uses the right texture unit
The normally faster version that was used before misbehaved if that
texture unit already used the specified texture object which caused the
glTexSubImage3D to cause out of bounds issues some times.

This fixes #1554.
2018-01-03 13:33:03 +01:00
m!m 6159e13162 Merge pull request #1551 from asarium/feature/messageSexpParameters
Add ability for passing messages to scripted SEXPs
2018-01-03 11:52:05 +01:00
asarium 1bd09a91d3 Add ability for passing messages to scripted SEXPs 2018-01-01 19:40:35 +01:00
MageKing17 8cf0e8eb1d Merge pull request #1550 from chief1983/fix/1541_mac_chdir
Only change directory on MacOS when parent process path is /sbin/launchd.
2017-12-30 17:16:51 -08:00
chief1983 2dcb75057c fix/1541_mac_chdir: Only change directory on MacOS when parent process path is /sbin/launchd. 2017-12-30 16:39:34 -06:00
asarium d95f173f26 Fix another sprintf warning of GCC7 2017-12-28 10:52:56 +01:00
asarium 47b21f6792 Fix wrong usage of memset
This caused a warning in GCC7 which is fixed by this. This will also
initialize the array properly since the previous version may not have
worked correctly even if the entire array woudld have been written (on
all supported platform it would have worked since repeating -1 on all 4
bytes of an int will still produce -1).
2017-12-28 10:50:10 +01:00
m!m 5ec8896c4a Merge pull request #1545 from ngld/fix/waveFileMissing
Log a proper error message if WaveFile::Open tries to load a missing file
2017-12-28 10:26:10 +01:00
ngld 560b49158b Log a proper error message if WaveFile::Open tries to load a missing file 2017-12-28 00:33:16 +01:00
Fabian Woltermann c109dc6aca Merge pull request #1539 from asarium/fix/shipSexpParamters
Pass ship variables as actual handles to scripts
2017-12-25 17:40:30 +01:00
m!m 581e5b0242 Merge pull request #1543 from asarium/fix/unicodeSpeech
Convert speech text properly to wide string
2017-12-24 12:44:15 +01:00
asarium ace3fc619e Convert speech text properly to wide string
The previous code could only handle ASCII data correctly but this new
code is also able to handle UTF-8 data correctly by using the Windows
API function MultiByteToWideChar. Since the conversion only happens in
Windows-only code this is not a portability issue.

This fixes an issue reported on the forums where non-ASCII text was not
spoken correctly by the TTS system.
2017-12-23 20:30:55 +01:00
m!m 7d418d50ce Merge pull request #1542 from devnexen/ffmpeg_decoder_fix
this codec layer handling not present but only from a certain version.
2017-12-23 13:10:07 +01:00
David Carlier ebd24341d4 this codec layer handling not present but only from a certain version. 2017-12-23 08:49:52 +00:00
asarium e8c80dbefc Pass ship variables as actual handles to scripts
This was requested by Axem on the forums.
2017-12-22 09:26:24 +01:00
m!m 68e19a19c5 Merge pull request #1331 from asarium/feature/scriptedSEXPs
Add ability to dynamically add new SEXPs at runtime
2017-12-20 12:41:05 +01:00
asarium f780d9e22a Add ability to dynamically add new SEXPs at runtime
This add a system for adding generic instances of the DynamicSEXP class
to the SEXP system. The only implementation at the moment is the LuaSEXP
which is used by the mn.addSEXP lua API to allow Lua to add new SEXPs.

Since this requires that FRED also runs lua scripts I added a mod table
option to enable scripting in FRED. Since the current scripts are not
built with FRED in mind it would likely break all these scripts if FRED
would be opened with normal scripting enabled.

This fixes #1320.
2017-12-20 10:45:40 +01:00
m!m c5117cf55e Merge pull request #1538 from TRBlount/fix/apply_recoil
Remove second instance of apply recoil flag in Weapon_Info_Flags
2017-12-20 10:28:32 +01:00
TRBlount f9704ebd89 Remove second instance of apply recoil flag in Weapon_Info_Flags 2017-12-19 12:41:53 -07:00
Fabian Woltermann eb738b3ef7 Merge pull request #1518 from asarium/fix/additionalFFmpegLogging
Add additional logging output for FFmpeg library version
2017-12-18 21:31:29 +01:00
Fabian Woltermann f04debfb36 Merge pull request #1537 from asarium/fix/parsingCrash
Fix some FRED issues
2017-12-18 21:30:47 +01:00
asarium aa8fb89a17 Fix unreadable FRED tooltip
I forgot to set the alpha blend mode in the NanoVG changes which meant
that the code used additive blending by default which is not good if the
color in use is black. This sets the blend mode to the value that
corresponds to the values used by the NanoVG reference code.
2017-12-18 19:04:36 +01:00
asarium 44e5f89e41 Fix crash in parsing code
The `nullptr` check was removed by mistake.
2017-12-18 18:28:49 +01:00
Fabian Woltermann fee0b900de Merge pull request #1489 from asarium/opengl/betterModelClipping
Use built-in OpenGL clipping planes for model transforms
2017-12-16 10:43:01 +01:00
Fabian Woltermann 6b209223ee Merge pull request #1531 from asarium/build/bundleOpenAL
Include OpenAL Soft DLLs as part of the build
2017-12-16 10:42:30 +01:00
Fabian Woltermann cb06c73b6a Merge pull request #1527 from asarium/feature/scriptedXSTRs
Add support for translating strings in scripts
2017-12-16 10:33:48 +01:00
Fabian Woltermann 7ab8a96903 Merge pull request #1526 from asarium/feature/xstrStringVars
Add support for setting string variables from a XSTR
2017-12-16 10:33:06 +01:00
Fabian Woltermann a58376404d Merge pull request #1523 from asarium/feature/movieSubtitles
Add localized subtitle support to the video player
2017-12-16 10:32:31 +01:00
Fabian Woltermann cfe89f411b Merge pull request #1535 from chief1983/always_preload_snd
Always Preload Game Sounds
2017-12-11 19:34:57 +01:00
m!m 91c9417d3e Merge pull request #1424 from chief1983/fix/470_attempt_2
Fix for #470: Proposal 2
2017-12-11 00:05:45 +01:00
Cliff f37c519b79 always_preload_snd: Is there ever a good reason not to preload mission sounds at this point? 2017-12-10 13:18:58 -06:00
Cliff Gordon 4dd194f4d6 fix/470_attempt_2: One more thing missing. 2017-12-10 13:16:42 -06:00
Cliff Gordon b38367b22f fix/470_attempt_2: Some more cleanup from this being copied from a set of functions and structs. 2017-12-10 13:16:42 -06:00
Cliff Gordon 72517ff9a2 fix/470_attempt_2: I should probably read my examples closer. Just make these local variables since I didn't bring in the struct from the example as it was overkill for us. 2017-12-10 13:16:42 -06:00
Cliff Gordon c3e212094e fix/470_attempt_2: Try to fix SIGPIPE crash using Kroki's example. 2017-12-10 13:16:42 -06:00
asarium 5f7721f300 Fix SIGBUS crash in fs2netd
This was reported by chief1983 on Discord. The standalone server crashed
with a SIGBUS error caused by an invalid socket file handle in
FS2NetD_DataReady(). This should fix that by adding additional checks
where necessary to make sure that our socket is valid when the socket
functions are used.
2017-12-10 19:42:56 +01:00
Fabian Woltermann 9e9378dcb6 Merge pull request #1533 from asarium/fix/jpegInterfaceCrash
Fix crash when using JPEGs as interface bitmaps
2017-12-10 18:39:03 +01:00
asarium 9b9041513d Fix crash when using JPEGs as interface bitmaps 2017-12-10 13:29:16 +01:00
Fabian Woltermann 51aac78080 Merge pull request #1529 from asarium/cleanup/noParseEofChar
Replace the special EOF char value with a standard null byte
2017-12-10 12:39:56 +01:00
m!m 3dd21f6cb6 Merge pull request #1532 from z64555/fix/mpshield_hits
Moves player control check for modelpoint shields into…
2017-12-10 12:22:01 +01:00
z64555 a42b27c0b8 Moves player control check for modelpoint shields into hud_augment_shield_quadrant(). AI ships can now use shield_transfer() on quadrant indices larger than 3. 2017-12-08 15:01:10 -06:00
asarium ca73920b8e Replace the special EOF char value with a standard null byte
This was an issue since UTF-8 encoded text can contain -128 as part of
an encoding sequence which causes a lot of issues for the parsing code.
I could not find any indication why the original code didn't use null
bytes from the start and I also couldn't find any code that would break
because of this. If anyone knows why this was done like this please let
me know.
2017-12-07 14:42:01 +01:00
asarium 17374106d1 Include OpenAL Soft DLLs as part of the build
This will remove the dependency on a system version of OpenAL and also
enable the advanced sound code for everyone. This removes the ability to
use a custom OpenAL version but removing the only system dependency we
currently have is worth a lot more than being able to use a custom
OpenAL version.
2017-12-06 10:42:02 +01:00
asarium 6da5302d34 Add localized subtitle support to the video player
This adds support for displaying subtitles embedded in movie files. This
supports files with multiple subtitle streams where each stream contains
the subtitles for one language. When the movie file is opened, the
stream for the currently active language will be used and displayed.

This resolves one of the points mentioned in #1522.

This also depends on PR #1484.
2017-12-05 12:04:13 +01:00
asarium d0a1efacb8 Improve video player API
This moves all the cutscene specific code out of the movie player code
and into the cutscene code so that the movie player can be reused for
usage in other environments.

This is required for #1041 since an implementation of that feature would
reuse the movie player code of the cutscene code but without all the
main loop stuff.
2017-12-05 12:01:50 +01:00
MageKing17 8168099eac Merge pull request #1530 from asarium/fix/fredSpheres
Fix usage of wrong buffer handles in opengl_draw_sphere()
2017-12-05 00:56:31 -08:00
asarium ae943503cb Fix usage of wrong buffer handles in opengl_draw_sphere()
This fixes another issue reported by Trivial Psychic on the forums.
2017-12-04 18:06:37 +01:00
asarium 4368db845d Add support for setting string variables from a XSTR
This allows to set string variables to localized values which will make
translating missions much easier.

This resolves one of the points mentioned in #1522.
2017-12-04 13:12:30 +01:00
m!m c25163e265 Merge pull request #1528 from asarium/fix/labGhosting
Enable all color channels before doing a clear
2017-12-04 12:58:17 +01:00
asarium 4bf9277c10 Enable all color channels before doing a clear
If the previous rendering operation left the color mask in any other
state than completely enabled then the clear will only affect the
enabled channels. This makes sure that all channels are enabled before
doing the clear.

This fixes an issue reported on the forums:
https://www.hard-light.net/forums/index.php?topic=94200.msg1859118#msg1859118
2017-12-04 11:56:47 +01:00
asarium 0bcdf19851 Add mission load screen scripting hook
This also includes a scripting function for retrieving the title of the
current mission.

This resolves point 4 of #1522.
2017-12-03 18:51:06 +01:00
asarium c4095d1af1 Add support for translating strings in scripts
This allows to use the XSTR mechanism in script to make translating
script text possible. This is compatible with the existing XSTR format
so automatic tstrings.tbl generator tools should work fine with this.

This resolves point 2 of #1522.
2017-12-03 18:51:06 +01:00
MageKing17 5d8f779cff Merge pull request #1416 from asarium/feature/onlyUnicode
Add true Unicode support
2017-12-03 09:32:04 -08:00
m!m 6f2592e733 Merge pull request #1525 from asarium/fix/disappearingShipSelection
Add a few graphics debug scropes to the ship selection
2017-12-02 22:20:01 +01:00
asarium 528a43952e Add a few graphics debug scropes to the ship selection
I added these while investigating the issue which was fixed in the
last commit and more debug scopes are always useful.
2017-12-02 19:34:36 +01:00
m!m 62d1f1978b Merge pull request #1475 from asarium/opengl/genericNanoVG
Add a NanoVG renderer using the generic rendering API
2017-12-02 19:34:01 +01:00
asarium b9b556c7a5 Add a NanoVG renderer using the generic rendering API
One of the main points of contention when adding the NanoVG based
TrueType text rendering was that it required an external Opengl
renderer which may interfere with our rendering engine by changing
OpenGL state without telling the rest of the engine. Since the rendering
interface for NanoVG is abstract and can be easily replaced, I did just
that and replaced it with an implementation that uses only generic
graphics functions without relying on the specific graphics API.

This will improve the interoperability of NanoVG with our engine and
should make later changes to the rendering engine easier since there is
no external rendering code which may interfere with our own code.
2017-12-02 18:31:00 +01:00
m!m 16b0db8eb9 Merge pull request #1524 from asarium/fix/3dSoundWarning
Only display 3D sound warnings for mods with 3.8.0 support
2017-12-02 17:20:43 +01:00
asarium 2c36ea35b4 Only display 3D sound warnings for mods with 3.8.0 support
This was an issue since a lot of mods used wrong sounds and after the
FFmpeg changes the code would display a warning for those sounds by
default. This will restore the old behavior of printing the warning to
the log where it is easier to ignore if the mod does not explicitly
support 3.8.0.
2017-12-01 12:06:23 +01:00
asarium 43e540cc4c Add true Unicode support
This adds proper Unicode support by allowing the parse system to read
UTF-8 encoded files. The new mode is controlled by a mod option which
allows older mods to continue using the legacy text encoding.

That option changes the behavior of several systems in FSO. It disallows
the usage of Volition fonts since they don't support Unicode encoding
and changes a few usages of special characters to their unicode
counterparts of generic rendering solutions.

This fixes #1415.
2017-11-30 13:26:20 +01:00
Fabian Woltermann 67627bd786 Merge pull request #1490 from asarium/opengl/vertexAttribBinding
Use OpenGL vertex array objects for better performance
2017-11-30 12:57:39 +01:00
m!m ea0c4b7b78 Merge pull request #1519 from asarium/build/fixAppimageLibraryPath
Fix LD_LIBRARY_PATH value in AppImage runs
2017-11-23 15:07:27 +01:00
Fabian Woltermann 29e56bb19a Merge pull request #1520 from asarium/fix/randomRangeWrongField
Fix wrong field usage in RandomRange
2017-11-23 15:05:13 +01:00
asarium 57da3e1ef6 Fix wrong field usage in RandomeRange 2017-11-23 12:53:30 +01:00
asarium 16ac19946f Fix LD_LIBRARY_PATH value in AppImage runs
The previous version used PATH instead of LD_LIBRARY_PATH which may have
caused some issues if the system is configured in a way that depends on
the value of LD_LIBRARY_PATH. It also broke launchers that tried to fix
library issues by changing LD_LIBRARY_PATH.
2017-11-22 11:31:04 +01:00
asarium e319b6f941 Use built-in OpenGL clipping planes for model transforms
This changes the batched transform code so that instead of using discard
in the fragment shader it uses the built-in clipping capabilities of
OpenGL for removing invisible sub models. This improves performance in
GPU-limited scenes by ~1ms if shadows are enabled.
2017-11-22 10:32:20 +01:00
asarium 8c88b68327 Use OpenGL vertex array objects for better performance
The original OpenGL Core changes only used a single vertex array object
for specifying the data layout of our vertex data. This uses the OpenGL
extension GL_ARB_vertex_attrib_binding to extend that so that each
vertex_layout uses a separate vertex array object which should improve
performance by reducing the CPU overhead while switching the vertex
layout. Since we need to use offsets into the vertex buffers at some
points this can not be done with the core functions since those do not
support specifying an offset when binding a vertex buffer.
GL_ARB_vertex_attrib_binding does support that and also features an
improved API for specifying the vertex layout. If that extension is not
available then the rendering engine will fall back to the current code.

In CPU intensive scenes I observed a frametime improvement of 1-2 ms.
2017-11-21 12:02:10 +01:00
asarium e75ed62692 Add additional logging output for FFmpeg library version
I had to debug some ffmpeg library issues and added these additional log
statements. They may be useful in the future.
2017-11-21 10:55:09 +01:00
MageKing17 748857ca2f Merge pull request #1517 from asarium/fix/1516
Fix PCX alpha color correction
2017-11-20 13:43:56 -08:00
m!m bff8231d87 Merge pull request #1509 from asarium/feature/jsonFlagPrinting
Add support for printing command line flags in JSON output
2017-11-20 22:10:33 +01:00
MageKing17 29087a3237 Merge pull request #1511 from asarium/build/gcc7Warnings
Fix new warnings generated by GCC 7
2017-11-20 12:20:30 -08:00
asarium a228a127e2 Fix PCX alpha color correction
This is a bugfix for an issue introduced in
72a797f732 which broke 8 bits-per-pixel
alpha bitmap reading.

This fixes #1516.
2017-11-20 13:17:22 +01:00
asarium 2692240ed9 Add additional information to JSON output 2017-11-19 13:27:56 +01:00
asarium a47dcc0548 Fix fall-through warnings introduced by GCC7 2017-11-19 12:12:42 +01:00
m!m 9fed19d4fc Merge pull request #1505 from MageKing17/feature/bmpman-usage
Add in-game BMPMAN usage display.
2017-11-19 11:56:03 +01:00
MageKing17 9446e61587 Add in-game BMPMAN usage display.
Can be enabled with the "-bmpmanusage" command-line option, toggled via the debug console, or toggled via a debug/cheat key combo (`+B).
2017-11-18 16:55:58 -08:00
MageKing17 1ffd0d3ef8 Merge pull request #1512 from asarium/feature/freddocsCfile
Search for fred docs using cfile
2017-11-18 14:50:43 -08:00
MageKing17 1a94018fb4 Merge pull request #1515 from MageKing17/bugfix/fred-close-exception
Avoid exception when closing FRED related to bm_release().
2017-11-18 14:49:14 -08:00
MageKing17 e8ef727a19 Avoid exception when closing FRED related to bm_release().
Now that BMPMAN dynamically allocates the bm_bitmaps array, and deallocates it in bm_close(), which is explicitly called by gr_close(), FRED generates an exception on close because of trying to release bitmap handles after bm_bitmaps has been deallocated and set to null. This is because gr_close() is called by CFREDView::OnDestroy(), but the mission textures aren't fully paged out until CMainFrame::OnClose() (well, technically, CMainFrame::OnClose() calls CFrameWnd::OnClose(), which calls CWinApp::CloseAllDocuments(), which calls CDocManager::CloseAllDocuments(), which calls CDocTemplate::CloseAllDocuments(), which calls CDocument::OnCloseDocument(), which calls CFREDDoc::DeleteContents(), which calls CFREDDoc::editor_init_mission(), which calls reset_mission(), which calls clear_mission(), which calls model_free_all(), which calls model_instance_free_all(), which calls model_unload() for every model, which calls model_page_out_textures(), which *finally* calls the crashing bm_release()). This commit moves the gr_close() call to CMainFrame::OnClose(), *after* it calls CFrameWnd::OnClose(), which avoids the exception as bm_bitmaps is still intact long enough for those final textures to be freed from it.
2017-11-18 04:38:03 -08:00
MageKing17 dfdfd59367 Merge pull request #1514 from MageKing17/feature/window-title
Window title overhaul.
2017-11-17 03:57:56 -08:00
asarium 4f7b718167 Fix sprintf warnings by checking the return value 2017-11-17 12:52:16 +01:00
MageKing17 b1046b1c1c Window title overhaul.
FSO now allows the window title to be specified via game_settings.tbl, some never-used function arguments were pruned at the same time, and fred.rc now receives version information (for the About dialogue and the title bar) from a cmake-generated header, so the version numbers get filled in properly. Speaking of FRED's About dialogue, it now displays the copyright symbol properly.
2017-11-17 02:51:36 -08:00
MageKing17 4663aed194 Merge pull request #1513 from MageKing17/bugfix/training-variable-timing
Move game_do_training_checks() to be right before goal processing.
2017-11-17 02:50:32 -08:00
MageKing17 a56432f5fc Move game_do_training_checks() to be right before goal processing.
In-mission events (SEXP chains that are used for directives and all mission logic) can sometimes call "training SEXPs", which depend on special variables set in the game_do_training_checks() function. However, this function was called near the end of game_frame(), well after mission_eval_goals() (which processes all mission events). This means that most training SEXPs wouldn't actually evaluate as true until the frame after whatever condition they were checking became fulfilled. This, combined with PR #1388 making the "targeted" SEXP actually use the appropriate variables (Players_target and Players_targeted_subsys), means that Diaspora's very first training mission's very first instruction (after launching from the launch tube, anyway) could not be completed, because the mission logic assumed that "key-pressed" and "targeted" would both return true on the same frame (which, after PR #1388, they did not).

This commit moves game_do_training_checks() to be called immediately before mission_eval_goals(), and therefore immediately after obj_move_all(), meaning Training_context_speed_set can become set the same frame the player's ship reaches the appropriate velocity and the relevant SEXPs can operate on the most up-to-date data available.
2017-11-16 23:26:05 -08:00
asarium 206ce536ec Search for fred docs using cfile
This will allow to put the FRED docs somewhere else instead of into the
root directory of a TC.
2017-11-14 23:15:58 +01:00
Fabian Woltermann d8ccf84452 Merge pull request #1482 from asarium/cleanup/sexpSCPString
Use SCP_strings and SCP_vectors in SEXP code
2017-11-14 09:35:44 +01:00
Fabian Woltermann bed9c13233 Merge pull request #1497 from z64555/cleanup/swarm_missiles
Refactors swarm_update_direction() a bit...
2017-11-14 09:34:30 +01:00
Fabian Woltermann 16993b236f Merge pull request #1479 from asarium/opengl/modelUniformBuffers
Use uniform buffer blocks for passing uniform data to shaders
2017-11-14 09:33:45 +01:00
Fabian Woltermann 94f8d547e0 Merge pull request #1487 from asarium/cleanup/modelVertexStruct
Use a C-struct for managing GPU model data layout
2017-11-14 09:32:48 +01:00
MageKing17 b6908d10c4 Merge pull request #1470 from asarium/fix/1469
Fix error line reported by Lua Errors
2017-11-13 16:31:16 -08:00
m!m a54aa24a64 Merge pull request #1510 from TRBlount/fix/motion_debris_load
Fix motion debris anim loading in mission-set-nebula sexp
2017-11-12 11:57:28 +01:00
MageKing17 d083089e1d Merge pull request #1508 from The-E/lab_fix_window_background
Fix window drawing in the F3 lab
2017-11-11 23:30:40 -08:00
MageKing17 338436d590 Merge pull request #1506 from MageKing17/bugfix/music-table-section-skipping
Fix music table parsing when a soundtrack needs to be skipped.
2017-11-11 23:27:58 -08:00
asarium 1d2f778b76 Add support for printing command line flags in JSON output
This will output the flags data in a better format than the current
binary format. For determining if the JSON output should be used this
uses an optional parameter for -get_flags. The command line parsing does
not cause an error if a parameter is specified for an option that does
not support them. This way, the launcher can just pass "json_v1" to the
option and an old build will just silently ignore it and use the binary
format.
2017-11-11 20:29:36 +01:00
Fabian Woltermann aad1bbbb05 The labviewer window background got its width and height mixed up in 6dbd7c34, this fixes that 2017-11-11 20:24:10 +01:00
TRBlount 1e4bede8c5 Fix motion debris anim loading 2017-11-11 10:34:28 -07:00
MageKing17 38b331dc92 Fix music table parsing when a soundtrack needs to be skipped.
For some reason, commit 8b43ed823c moved the consumption of the "#Soundtrack End" token out of parse_soundtrack(), when if a soundtrack needs to be skipped (e.g. because it's in a .tbm, flagged with +nocreate, and the original doesn't exist), it will skip straight past "#Soundtrack End" to reach the next "#Soundtrack Start". It also changed how music tables are parsed so that they'll skip any junk data that happens to be between sections, which is atypical of how tables are parsed. This commit changes both of these things: "Soundtrack End" is once again consumed near the end of parse_soundtrack(), and the while loop uses check_for_string() instead of skipping to the start of a section.
2017-11-09 15:08:40 -08:00
m!m d3965b1f9d Merge pull request #1502 from MageKing17/feature/tabled-bmpman-limit
Allow BMPMAN slot limit to be defined by mod table.
2017-11-09 09:23:20 +01:00
asarium 986099a495 Handle bmpman shutdown explicitly
This was previously done with atexit which caused issues if bmpman was
initialized more than once which is the case for the unit tests.
2017-11-07 15:43:27 -08:00
MageKing17 07ff605c58 Attempt to guarantee that bm_bitmaps will only be allocated once.
Even if bm_init() gets called more than once, for whatever reason. Unless bm_close() is called first, in which case it will re-allocate, potentially with a different MAX_BITMAPS (but it's okay, because there shouldn't be any active handles to worry about if bm_close() was called).
2017-11-07 15:33:36 -08:00
m!m a8171c118f Merge pull request #1500 from TRBlount/fix/directional_glows
Fix directional glow issues
2017-11-06 12:44:47 +01:00
TRBlount 4b9c7b19aa Add comment regarding the length and radius of a beam muzzle glow 2017-11-04 12:24:12 -06:00
TRBlount 33d2294a49 Fix ramp up/down sequence and basic size/positioning of directional glows 2017-11-04 12:16:06 -06:00
MageKing17 8e558b2095 Move MAX_BITMAPS to bmpman.cpp/.h, use error_display() for warnings.
Per discussion on the PR. Also corrected sizeof(bm_bitmaps) to sizeof(bm_bitmaps[0]) * MAX_BITMAPS.
2017-11-04 08:52:56 -07:00
MageKing17 703bfab587 Merge pull request #1504 from asarium/fix/defaultMaterialClipPlane
Fix Assertion failure when rendering clip planes using default material
2017-11-04 07:39:40 -07:00
MageKing17 344502c436 Merge pull request #1495 from asarium/feature/betterSoundSets
Add support for multiple sounds in one game sound entry
2017-11-04 06:53:10 -07:00
asarium ef06593ed7 Fix Assertion failure when rendering clip planes using default material
The texture array changes introduced the default material which is
similar to the passthrough shader but allows to use texture arrays. The
vertex shader is the same as for the passthrough shader so that shader
also supports clipping planes.
2017-11-04 14:42:50 +01:00
MageKing17 a22b336bfe Merge pull request #1493 from asarium/fix/particleDirection
Fix several oversights and bugs in the particle effect code
2017-11-04 05:05:43 -07:00
MageKing17 37b81efea4 Allow BMPMAN slot limit to be defined by mod table.
bm_init() now dynamically allocates the bm_bitmaps array, and MAX_BITMAPS can be changed by the mod table.
2017-11-02 16:37:57 -07:00
MageKing17 7c6f99c68b Merge pull request #1501 from TRBlount/fix/DRADIS_visuals
Make DRADIS blips use decaying alpha
2017-11-01 15:31:09 -07:00
TRBlount f7b7aaead3 Use std::abs() 2017-10-31 15:21:54 -06:00
TRBlount 80dcefa0fc Add comment specifying functionality 2017-10-31 13:31:43 -06:00
TRBlount 27a70d545d Update using time since last sweep. 2017-10-31 13:13:59 -06:00
TRBlount e4614f01ba Fix DRADIS blip alpha 2017-10-30 16:07:54 -06:00
Tyler Blount e2d8502a3e Merge pull request #1488 from asarium/fix/renderTargetError
Fix OpenGL function usage in opengl_make_render_target
2017-10-30 15:23:22 -06:00
Fabian Woltermann dee0cf600f Merge pull request #1499 from asarium/fix/linuxNightlyBuilds
Fix dependency issues when building libcurl for FTP deploy
2017-10-30 13:55:35 +01:00
asarium 6181c0b2f7 Fix dependency issues when building libcurl for FTP deploy 2017-10-29 11:20:39 +01:00
z64555 0f942afaae Simplify out-of-frame calls.
*Homing conditions are now consistant with in-frame checks
*Swarm missiles will now only change their homing pos during a change frame. This'll reduce their hit rate if SWARM_FRAME_STOP_SWARMING is too low, but will make their pathing more cinematic.
2017-10-22 14:42:33 -05:00
z64555 cdde87662a Refactors swarm_update_direction() a bit for readability and consistency.
* Changed stop distance to a stop frame. Frame was chosen instead of distance or time to ensure missiles won't appear to jerk twice in succession.
2017-10-22 02:00:01 -05:00
m!m 4e7f8fa92a Merge pull request #1496 from MageKing17/bugfix/music-parse-assertion
Fix misused assertion in music table parsing code.
2017-10-21 19:47:22 +02:00
MageKing17 867ebfed89 Fix misused assertion in music table parsing code.
The condition of an assertion doesn't exist in a release build, and assertions should never be used for bad data anyway.
2017-10-21 09:56:12 -07:00
asarium 0ff8a2c159 Add support for multiple sounds in one game sound entry
This adds support for specifying multiple sounds for a single game sound
entry. The engine then selects which sound will be played based on the
strategy provided by the game data. This required a few changes to some
of the game code since previously every game sound had exactly one sound
file attached to it. The most notable change is that it is no longer
possible to determine the exact duration a sound can have so instead the
new code computes the maximum duration a sound can have and uses that
where appropriate.

This also adds support for randomizing the pitch and volume of the sound
to provide a more varied experience even if only a single sound is used.

One possible issue that exists is that the "sequential" strategy only
works globally at the moment so if two sources use the same game sound
concurrently then the two sources will share the sequence of sounds
since there is no sound instance data at the moment. That can be added
in a future change but should not present a huge issue for most
use-cases.

Visual Studio on Appveyor somehow causes deprecation error on _our_
definition of vsprintf. I have no idea why these changes introduced this
warning but I won't debug Visual Studio compiler bugs that I can't
reproduce with my Visual Studio version so I just disabled those
warnings.
2017-10-17 10:57:22 +02:00
asarium 8272304cfa Remove global Snds and Snds_iface vector 2017-10-17 10:30:00 +02:00
asarium 0522566790 Replace direct usages of Snds vector with a function call
This will make it easier to validate the used handles and is generally
better since it doesn't require a global sounds vector.
2017-10-09 15:02:29 +02:00
MageKing17 59e7b10b73 Merge pull request #1494 from asarium/fix/ballisticSoundOutOfRange
Fix out-of-range vector access in ballistic sound code
2017-10-06 16:19:47 -07:00
asarium eb4cfeb256 Fix out-of-range vector access in ballistic sound code
The code probably tried to check if the sound is available but since the
sounds vector is not long enough if the sound is not specified in the
table it would cause an out-of-bounds failure if the sound was missing
from the table. Furthermore, the current code would only have worked if
the sound was preloaded since the id is -1 until the sound is loaded for
the first time.
2017-10-06 19:51:26 +02:00
asarium a7b1c00a84 Fix handling of relative source directions
Previously, the source orientation was always aligned to the world so it
couldn't adapt to a weapon that changes direction. This fixes that by
introducing a "relative" mode for source orientations that is enabled by
default and disabled if the direction is set explicitly.
2017-10-04 15:59:09 +02:00
asarium e484a84d97 Fix several oversights and bugs in the particle effect code
The particle sources of the beams were missing multiple properties
(direction and impact normals) and the generic shape effect didn't have
any way of controlling how long the source was active. This fixes that
by introducing an effect timing field similar to the single particle
effect.
2017-10-04 10:51:35 +02:00
MageKing17 bd2bb12ad3 Merge pull request #1492 from MageKing17/bugfix/shield-impact-sounds
Make shield impact sounds more intuitive.
2017-10-03 12:00:49 -07:00
MageKing17 c890c0af1f Make shield impact sounds more intuitive.
Shield impact sounds now re-use the shield quadrant calculated by the collision code instead of naively recalculating based on global hitpos, allowing the hull impact sound to play if the shot pierces shields or was fired from within the shield mesh, and simplifying the relevant calculations in the process.
2017-10-03 09:06:34 -07:00
m!m 9cda43afb2 Merge pull request #1491 from ashdnazg/mingw_fix_include
Add include <cinttypes> (fix mingw build)
2017-10-03 11:50:44 +02:00
Eshed 34b4321416 add include
required by PRIu64
2017-10-03 11:32:56 +03:00
asarium 3a18a88e30 Fix OpenGL function usage in opengl_make_render_target
The function previously used glFramebufferTexture3D which caused issues
on the Mesa drivers and probably also with other drivers. This fixes
that by using glFramebufferTextureLayer which is the right function for
this use case.
2017-09-26 14:10:56 +02:00
asarium 686bf15879 Ensure that init_render is called before rendering the scene
This was previously not enforced and some code did not call this
function at the correct time which caused crashes since data was not
initialized correctly. This adds a check to ensure that the function was
called and fixes the code that uses the model_draw_list.
2017-09-24 15:53:14 +02:00
asarium 22f0ba89a4 Use a C-struct for managing GPU model data layout
In previous versions of FSO the GPU data of a model was stored in
various different layouts depending on what data was required for
rendering that model. Since the transform batching code was added to the
model loading code this wasn't the case anymore since all data had to
use the same vertex stride even if the data wasn't used.

This made these changes possible where a standard C-struct is now used
for managing the layout of the data in GPU memory. This makes the code
easier to read and also easier to extend in the future since all layout
data is available in the struct.
2017-09-20 17:39:31 +02:00
Fabian Woltermann a3bf47991b Merge pull request #1485 from asarium/fix/1483
Ensure that viewport setting calls are valid
2017-09-16 19:27:13 +02:00
asarium 6af1768147 Ensure that viewport setting calls are valid
This fixes a CTD when FRED is started since the graphics function
pointers are not valid at that point which causes a null pointer
dereference when starting FRED. This fixes that by checking if the
graphics system has been initialized before calling that function.

This fixes #1483.
2017-09-16 18:24:13 +02:00
asarium 0d9fbd4725 Use SCP_strings and SCP_vectors in SEXP code
I split this from #1331 to make reviewing these two changesets easier.

These changes convert all usages of const char* to SCP_string in the
static SEXP arrays so that the dynamic SEXP system can use SCP_strings
instead of having to allocate the strings and then somehow figure out
which strings must be freed at the end of the program.

This also converts the SEXP arrays to vectors so that new SEXP operators
can be added at runtime later.
2017-09-14 11:11:52 +02:00
asarium c6975fda3c Use uniform buffer blocks for passing uniform data to shaders
This uses UBOs for building a buffer object of uniform data before
using that data to draw objects. This should reduce the CPU overhead by
reducing the amount of glUniform calls required for executing a single
draw call. This is especially useful if rendering is limited by the CPU
which should help performance for people with slower CPUs.

This fixes #910.
2017-09-13 11:54:16 +02:00
Fabian Woltermann 52baa1f115 Merge pull request #1480 from asarium/fix/movieScaling
Restore 2D matrix setting behavior
2017-09-12 12:19:39 +02:00
asarium d684dcea1b Restore 2D matrix setting behavior
This restores the behavior from before the matrix system changes. The
observed behavior is more or less the desired behavior sinde setting the
2D projection matrix resets the model matrix stack but it happens to
work with the previous movie code since the 2D matrix is not set if no
perspective projection matrix was set before. This would need to be
fixed if the movie player should ever work within a mission but for now
this will fix the reported bug.
2017-09-12 11:35:11 +02:00
Fabian Woltermann fa7f49f1e4 Merge pull request #1478 from asarium/opengl/externalLightManagment
Move light handling out of OpenGL code
2017-09-10 14:33:53 +02:00
Fabian Woltermann cc3dc5f566 Merge pull request #1476 from asarium/feature/pngScreenshots
Use PNG instead of TGA for saving screenshots
2017-09-10 14:33:27 +02:00
Fabian Woltermann 19c50412ba Merge pull request #1477 from asarium/opengl/gsInstancing
Use geometry shader instancing for shadow map rendering
2017-09-10 14:33:07 +02:00
asarium cdd391caa8 Move light handling out of OpenGL code
There is nothing specific to OpenGL in that code anymore since it's all
handled in the shaders at this point. This will make the lighting
information available in the normal graphics code which allows to use
those values when filling the uniform buffer for the model rendering.
2017-09-10 11:48:38 +02:00
asarium 4860f72678 Use geometry shader instancing for shadow map rendering
This provides ~10% to 20% of an improvement if shadows are enabled. The
required features are not available in our OpenGL target version so I
added a fallback meachanism that will continue to use the standard
instancing method.

With an RX 480 and these changes I can play/watch the BP2 Icarus
cutscene at a consistent 60FPS which wasn't possible before.
2017-09-09 21:14:25 +02:00
Fabian Woltermann 5ba33228cb Merge pull request #1473 from asarium/fix/1472
Only use 16 bit-per-pixel for PCX data loading
2017-09-09 20:48:18 +02:00
Fabian Woltermann b7f3fdbb98 Merge pull request #1471 from asarium/fix/unsupportedShadowFramebuffer
Add proper fallback path for unsupported shadow framebuffer
2017-09-09 20:47:38 +02:00
Fabian Woltermann 1bffdce6ef Merge pull request #1474 from asarium/opengl/externalMatrixStack
Move graphics matrix handling out of OpenGL code
2017-09-09 20:46:19 +02:00
asarium b130d526ff Use PNG instead of TGA for saving screenshots
This was requested by Axem for improving the usability of FSO
screenshots. This will remove the need to convert the TGA files to PNG
before uploading them to an online image hoster.
2017-09-09 18:28:55 +02:00
asarium 4c1ed2f66a Move graphics matrix handling out of OpenGL code
All transformations are now handled by shaders so there is nothing
special going on in the graphics API specific code anymore. Since model
uniform buffers require access to these matrices I moved the matrix
handling out of the graphics API code.
2017-09-05 12:36:32 +02:00
asarium d30a73a578 Only use 16 bit-per-pixel for PCX data loading
The PCX loader requires this or else the data isn't loaded correctly.
This matches what the code did before the texture array merge but it
only does it for PCX textures now since the other formats handle 32 and
24 bits per pixel correctly.

This fixes #1472.
2017-09-04 13:11:04 +02:00
Fabian Woltermann fa03117eaf Merge pull request #1323 from asarium/opengl/uniformBuffers
Use a uniform buffer object for storing deferred lighting data
2017-09-04 12:32:12 +02:00
asarium 2eb109dc49 Add proper fallback path for unsupported shadow framebuffer
If a 32-bit color shadow framebuffer is not supported this will first
try to fall back to 16-bit and if that still doesn't work it will
disable shadows completely. This should fix the rendering artifacts
reported on the forums here:
http://www.hard-light.net/forums/index.php?topic=93867.msg1854164#msg1854164
2017-09-04 12:02:49 +02:00
asarium bef57f7559 Fix error line reported by Lua Errors
This adds empty lines to the beginning of the Lua source passed to the
interpreter so that the interpreter sees the lines in the source as they
appear in the table.

This might slow down parsing a bit since get_line_num is quite slow but
it should not be noticable in most instances since the script tables
tend to be quite short.

This fixes #1469.
2017-09-04 10:56:39 +02:00
asarium b807c670db Use unsynchronized buffer mapping for updating uniform buffer
Since the system already tracks if a buffer is still in use by the GPU
the buffer updates can assume that there will be no synchronization
issues if the buffer is mapped into memory.
2017-09-03 12:40:33 +02:00
asarium 24b71441c0 Add debug scope to uniform buffer retiring function 2017-09-03 12:40:33 +02:00
asarium e47581ffa5 Add documentation to new classes 2017-09-03 12:40:33 +02:00
asarium c585314ff1 Use a uniform buffer object for storing deferred lighting data
This converts the deferred lighting shader to use uniform buffers for
the dynamic data sent to the GPU while rendering the lighting effects.
This doesn't affect performance but the deferred lighting code is a
nicely isolated piece of rendering code where I could test how the
rendering code could use the uniform buffers.

This is related to #910.
2017-09-03 12:40:33 +02:00
MageKing17 97d09ae6ad Merge pull request #1468 from asarium/cleanup/noStandaloneClippingPlanes
Remove graphics functions for explicit clipping planes
2017-09-02 08:44:30 -07:00
asarium 250bf919a7 Remove graphics functions for explicit clipping planes
The function implementations were empty anyway and the code that called
them wasn't used anymore.
2017-09-02 13:20:41 +02:00
MageKing17 f8dd06ccef Merge pull request #1467 from Goober5000/medal_button_hotspot
add field for setting the hotspot index of the exit button in the medals screen
2017-09-01 11:27:11 -07:00
Fabian Woltermann 67416cc8f6 Merge pull request #1447 from asarium/opengl/useExtensions
Only generate headers for OpenGL 3.2
2017-09-01 17:01:46 +02:00
Fabian Woltermann 7118697a35 Merge pull request #1454 from asarium/opengl/noImmediateDraws
Move immediate mode rendering into generic graphics code
2017-09-01 17:00:06 +02:00
Fabian Woltermann 095c1ebe2b Merge pull request #1458 from Goober5000/time_docked_fixes
several fixes to time-docked and time-undocked
2017-09-01 16:58:00 +02:00
Fabian Woltermann 8c89c19c7e Merge pull request #1155 from asarium/feature/debugWindowScrolling
Add scrolling support to new debug window
2017-09-01 16:37:10 +02:00
m!m ae3d06c54f Merge pull request #1328 from chief1983/libupgrade/sdl2_0_5
Upgrade included libSDL2 to 2.0.5
2017-09-01 15:04:54 +02:00
Cliff dbbb8af17b Avoid a potential crash when ff is enabled without a joystick. 2017-08-31 20:38:40 -05:00
Cliff Gordon a23830359a libupgrade/sdl2_0_5: joy_get_device is not defined, use this instead, thanks @ashdnazg 2017-08-31 19:56:15 -05:00
Cliff Gordon 31e572ec03 Revert "Allow force feedback to work again."
This reverts commit 19b5ee97f7.
2017-08-31 19:56:15 -05:00
Cliff Gordon 29b5c4bf7a libupgrade/sdl2_0_5: Attempt to migrate the MinGW support to the official libs using the filename they are published with. 2017-08-31 19:56:15 -05:00
Cliff Gordon 3811270a09 libupgrade/sdl2_0_5: Upgrade to SDL 2.0.5. 2017-08-31 19:56:15 -05:00
Cliff Gordon 64fc95ec8c libupgrade/sdl2_0_5: Remove old build system files from gitignore. 2017-08-31 19:56:15 -05:00
MageKing17 0c70672a84 Merge pull request #1461 from Goober5000/fix_emp_time_for_capship_turrets
make "same emp time for capships" actually work
2017-08-31 07:00:47 -07:00
Goober5000 67e6bcca9f make "same emp time for capships" actually work
Back when I added the "same emp time for capships" flag in SVN r9540, I neglected to multiply the EMP time by 1000, as the EMP disruption time for fighters is specified in seconds but the time for capships is specified in milliseconds.  So, using this flag would cause capships to suffer EMP disruption for almost no time at all.

This PR fixes that, and also extends the explosion-effect sexp to specify this parameter.  And I also cleaned up the fireball section by calling eval_num(n) just once instead of several times.
2017-08-31 04:16:15 -04:00
m!m 8de33ab56a Merge pull request #1464 from Goober5000/boolify_is_sexp_true
change is_sexp_true return type from int to bool
2017-08-31 10:06:47 +02:00
Goober5000 b786b8e230 fix another mismatch 2017-08-31 02:10:01 -04:00
Goober5000 9dc308331b fix some warnings I missed earlier 2017-08-30 16:03:15 -04:00
Goober5000 628ac86c3e Merge pull request #1465 from asarium/feature/dynamicTstrings
Looks good to me.
2017-08-30 12:23:20 -04:00
asarium dcee8a302e Remove limit for tstring table entries
Since 4500 strings are not enough for some mods there was a request for
removing that limit. I chose to use an unordered map for storing the
entries since the indices are not guaranteed to be sequential.

This fixes Mantis 3199.
2017-08-30 13:04:24 +02:00
Goober5000 c7673f0591 swap order of parameters to avoid short-circuiting 2017-08-29 20:25:04 -04:00
Goober5000 000d0c3a0d change |= and &= to be the more verbose and correct logical operators 2017-08-29 14:11:35 -04:00
Goober5000 ec19f9be98 change is_sexp_true return type from int to bool 2017-08-29 13:50:22 -04:00
Goober5000 3005a67573 Merge pull request #1459 from Goober5000/string_concatenate_block
add string-concatenate-block sexp
2017-08-29 13:49:18 -04:00
Goober5000 33d4a7efa7 more fiddling with string format arguments 2017-08-29 12:30:16 -04:00
MageKing17 6c4e03d9dc Merge pull request #1462 from Goober5000/fix_sexp_error_reporting
fix Assertion in sexp error reporting
2017-08-29 06:32:49 -07:00
m!m 537ee433de Merge pull request #1463 from Goober5000/fix_sound_coordinates
fix negative coordinates in play-sound-from-x
2017-08-29 09:54:20 +02:00
Goober5000 2cff45f2c5 fix negative coordinates in play-sound-from-x
When the OPF_NUMBER and OPF_POSITIVE behaviors were made more robust, it exposed a latent bug in the play-sound sexps.  These had OPF_POSITIVE where they should have had OPF_NUMBER.  With this fix, sounds can now play from all coordinates, positive or negative.
2017-08-28 19:12:40 -04:00
Goober5000 466e4c159f use SIZE_T_ARG 2017-08-28 18:39:01 -04:00
Goober5000 6c7de5120e improve warning messages per feedback 2017-08-28 14:40:44 -04:00
Goober5000 b2b0ba3630 to be pedantic, this happens at the very end of error-reporting mode 2017-08-28 14:26:34 -04:00
Goober5000 14dcff6f5f might as well restrict the test to only running during error-check mode 2017-08-28 14:23:53 -04:00
Goober5000 d826537485 fix Assertion in sexp error reporting
There is a bug where, when displaying an error message with a sexp node that contains a variable, the code will trigger an Assertion in the process of printing the error message.  This is because it tries to transcode the sexp variable from name to index, when that has already been done further up the pipeline.  This fixes that by adding a quick test to see if the expected variable name is an integer.
2017-08-28 14:17:02 -04:00
Cliff Gordon 95c0fad96f Merge pull request #1460 from asarium/fix/openglErrors
Readd accidentally removed OpenGL calls
2017-08-28 10:35:07 -05:00
MageKing17 85b3a30376 Merge pull request #1456 from Goober5000/is_docked_sexp
add is-docked sexp
2017-08-28 08:09:13 -07:00
asarium 3c347ae938 Readd accidentally removed OpenGL calls
I changed those lines in another PR and forgot to revert these before I
submitted it. This will fix the OpenGL errors that appeared when shadows
were enabled.
2017-08-28 16:53:50 +02:00
Fabian Woltermann 09b28f2219 Merge pull request #1453 from asarium/opengl/noRedundantActiveTexture
Avoid redundant glActiveTexture calls
2017-08-28 09:00:56 +02:00
Fabian Woltermann 3c0eec27de Merge pull request #1432 from asarium/qtfred2_/dev
Add most of the remaining menu action implementations
2017-08-28 08:59:41 +02:00
Fabian Woltermann 2fb078f32b Merge pull request #1455 from asarium/fix/deleteUnusedFile
Delete unused OpenGL video presenter
2017-08-28 08:57:26 +02:00
Goober5000 a19b3030b6 enhance warning messages 2017-08-27 18:01:14 -04:00
Goober5000 5095b1c57a several fixes to time-docked and time-undocked
Time-undocked will cause FSO to freeze unless you know what you're doing, so this PR fixes some gotcha areas.  Inspired by The E's rant on Discord which, while not 100% correct, did indicate some areas for improvement.

1) Set the default "number of times docked" argument to 1 when the sexp is created in FRED, same as with the has-[un]docked-delay sexps
2) Catch any <= 0 counts when the sexp is called in FRED and set them to 1.  (This was done for other sexps which used mission_log_get_time_indexed, but was not done for time-[un]docked for some reason.)
3) Add an assertion to mission_log_get_time_indexed as a last resort to guard against invalid counts.
2017-08-27 17:18:39 -04:00
Goober5000 ab14742f96 add is-docked sexp 2017-08-27 16:24:04 -04:00
asarium 492c4ba10a Delete unused OpenGL video presenter
The deletion of this file was missed in the cutscene changes.
2017-08-27 18:12:01 +02:00
asarium 999eb8a3f9 Add documentation to new functions 2017-08-27 17:32:58 +02:00
asarium 03aa75c39a Move immediate mode rendering into generic graphics code
Since this code is the same for all possible graphics backends it can be
moved outside the OpenGL implementation to simplify that code.
2017-08-27 17:14:02 +02:00
asarium 4f096c26b2 Avoid redundant glActiveTexture calls
This introduces a new function in the OpenGL state tracker which
combines setting the active texture unit and enabling a texture. The
reason this is a good idea is that this new function can filter out
unneeded calls to glActiveTexture if the texture is already enabled on
that specific unit. This happens very often when rendering several
submodels of a model which share their textures.

This is unlikely to yield significant performance improvements but
avoiding unneded OpenGL calls is always a good idea.
2017-08-27 13:46:44 +02:00
Goober5000 3db9fe9383 add field for setting the hotspot index of the exit button in the medals screen 2017-08-26 13:35:38 -04:00
Fabian Woltermann d1e236451f Merge pull request #1452 from asarium/fix/tgaLocking
Fix memory allocation in tga loading code
2017-08-26 18:11:11 +02:00
m!m 6cf7cb0843 Merge pull request #1450 from Goober5000/mantis_3174_fix
toss out the campaign savefile if we are restarting a previously finished campaign
2017-08-26 18:10:29 +02:00
asarium 2084eb01e8 Fix memory allocation in tga loading code
The code did not use the right method for calculating the required size
of the memory. This was never noticed before because the old OpenGL
texture loading code only used 16-bit textures for interface data but
the new code uses 32-bit textures which exhausted the available memory.

This was found and reported by @chief1983.
2017-08-26 17:08:26 +02:00
Goober5000 7d1365800f clean up old comments 2017-08-26 03:43:26 -04:00
Goober5000 66ce0acc17 toss out the campaign savefile if we are restarting a previously finished campaign 2017-08-26 03:38:20 -04:00
Fabian Woltermann c29954d672 Merge pull request #1449 from asarium/fix/arrayDetectionBug
Fix bug in texture array detection code
2017-08-25 19:55:49 +02:00
asarium f2d5246ccb Fix bug in texture array detection code
The code would have displayed the warning but didn't actually set the
flag to let the rest of the code know.
2017-08-25 18:22:34 +02:00
asarium b6dcc4f5ef Only generate headers for OpenGL 3.2
Since our target version is only OpenGL 3.2 all additional functionality
should only be used through their respective extensions to avoid
accidentially using a function not available in our minimum target
environment.
2017-08-25 18:18:17 +02:00
Fabian Woltermann bd62ceeeb0 Merge pull request #1318 from asarium/opengl/textureArrays
Use OpenGL texture arrays for animations
2017-08-25 18:00:56 +02:00
asarium f1bf0a411c Use OpenGL texture arrays for animations
This converts all usages of bmpman textures to OpenGL texture arrays.
That means that all frames of an animation are stored in a single OpenGL
texture object and can be accessed at the same time in a single draw
call. This should significantly reduce the overhead of drawing lots of
particles since all particles of a single animation can be drawn with a
single draw call.

This fixes #1169.
2017-08-25 11:31:02 +02:00
asarium 28898ca8e3 Add scrolling support to new debug window 2017-08-25 09:51:09 +02:00
MageKing17 3acdf3e801 Merge pull request #1399 from asarium/fix/1306
Use unique_ptr for storing HUD gauge pointers
2017-08-24 09:23:54 -07:00
MageKing17 f1101bee5d Merge pull request #1414 from asarium/feature/targettedFSOVersion
Add mod table setting for specifying targetted FSO version
2017-08-24 09:21:58 -07:00
MageKing17 e617f0cc41 Merge pull request #1435 from asarium/fix/ffGlobalGain
Add config option for setting the FF strength
2017-08-24 09:09:55 -07:00
MageKing17 7c9f73fbdc Merge pull request #1444 from asarium/fix/travisSourceCompression
Actually compress the source archive
2017-08-24 09:09:10 -07:00
Fabian Woltermann c36b47a35c Merge pull request #1290 from asarium/opengl/simplifyGrInterface
Move 2D drawing functions to a generic implementation
2017-08-24 17:41:32 +02:00
m!m 8d0b0a76f2 Merge pull request #1446 from MageKing17/bugfix/cmeasure-timer-interval-init
Explicitly initialize cmeasure_timer_interval to 0.
2017-08-24 17:21:05 +02:00
MageKing17 36e5afe1be Explicitly initialize cmeasure_timer_interval to 0.
If we rely on uninitialized values, we're likely to wind up with countermeasures that are only ever active for a single frame.
2017-08-24 04:54:42 -07:00
m!m 20398150d8 Merge pull request #647 from MageKing17/feature/countermeasure-pulse-interval
Allow countermeasures to pulse at regular intervals instead of globally.
2017-08-24 10:38:41 +02:00
m!m e085cc20ab Merge pull request #1445 from MageKing17/bugfix/beam-sound-unpause
Actually unpause 3D beam sounds correctly.
2017-08-24 09:25:33 +02:00
asarium 6b5869853c Correctly handle alpha blending for gr_flash_alpha 2017-08-23 14:42:54 +02:00
asarium a6411cc1d3 Add documentation for drawing functions 2017-08-23 14:42:54 +02:00
asarium bd4427a832 Reformat 2017-08-23 14:42:54 +02:00
asarium 6dbd7c34e6 Clean up a few remaining functions 2017-08-23 14:42:54 +02:00
asarium 7a3029d1e3 Remove unused gr_screen API functions 2017-08-23 14:42:54 +02:00
asarium 1bca5f128d Convert curve and circle functions 2017-08-23 14:42:54 +02:00
asarium 6bbb6be880 Move line drawing functions to generic implementation 2017-08-23 14:42:54 +02:00
asarium c1c2b72ef0 Move gr_string out of OpenGL code 2017-08-23 14:42:54 +02:00
asarium 1aa85d236e Begin moving 2D functions to a generic implementation
Thanks to the new material system, it's now possible to easily make the
2D functions independent of the underlying graphics API which allows to
reduce the size of the gr_screen 2D API.
2017-08-23 14:42:54 +02:00
MageKing17 1afc5eec13 Actually unpause 3D beam sounds correctly.
beam_pause_sounds() "pauses" looping beam sounds by setting their volume to 0; beam_unpause_sounds() "unpaused" by calling beam_recalc_sounds(), which only set the volume correctly when -no_3d_sound is set; 3D sound updates the sound's position without changing its volume. This PR just makes beam_unpause_sounds() perform the inverse operation of beam_pause_sounds() if 3D sounds are enabled.
2017-08-23 05:03:25 -07:00
Fabian Woltermann 759c9b1148 Merge pull request #1439 from asarium/opengl/genericVideoDisplay
Remove OpenGL code from cutscene presenter
2017-08-23 14:02:53 +02:00
Fabian Woltermann 47bb378342 Merge pull request #1438 from asarium/fix/aabitmapRemapping
Move 4 bit color conversion out of graphics code
2017-08-23 14:02:35 +02:00
m!m 0b3dad8dc0 Merge pull request #1308 from niffiwan/feature/tint_shader
Add colour-configurable tint shader
2017-08-23 12:53:50 +02:00
m!m 13e601a523 Merge pull request #1372 from MageKing17/feature/avx2-build-support
Add AVX2 to the list of supported MSVC compiler optimizations.
2017-08-23 12:50:16 +02:00
MageKing17 5de1b684f4 Merge pull request #1442 from asarium/fix/noWarningStacktrace
Remove stack trace from warning dialogs
2017-08-23 03:46:21 -07:00
asarium c5dcaf88d8 Actually compress the source archive
The previous command simply created a tar with a tar.gz ending which is
wrong. This fixes that.
2017-08-23 12:45:47 +02:00
MageKing17 55558cc608 Merge pull request #1437 from asarium/fix/unixSources
Build Unix source package before configuring
2017-08-23 03:44:43 -07:00
MageKing17 addc3ef383 Allow countermeasures to pulse at regular intervals instead of globally.
Adds a new "+Pulse Interval:" countermeasure field that enables the new behavior; all countermeasures that don't have this field defined still use the old behavior of the global frame counter.

This changes countermeasure logic quite a bit, but I attempted to mitigate performance implications by re-using an existing traversal of the object list in order to build the list of active countermeasures each frame. If any countermeasures are actively pulsing in a frame, the object list is traversed again, looking for homing weapons. Each homing weapon then goes through the active countermeasure list and checks to see if it got decoyed. Most of this central logic is unchanged from the old behavior, although no longer separated into two functions, and it should be more efficient since it's using a prepared list of active countermeasures instead of traversing the object list looking for countermeasures for every homing missile (which are themselves found by traversing the object list).
2017-08-23 03:39:48 -07:00
MageKing17 2c1abf78d1 Merge pull request #1443 from asarium/build/versionBump
Bump development version after final release
2017-08-23 03:37:14 -07:00
asarium 77c950ccd4 Bump development version after final release 2017-08-23 09:48:36 +02:00
asarium b160184f5b Remove stack trace from warning dialogs
It serves no purpose there since it's a message specifically designed to
be seen by modders and most times the stack trace doesn't even contain
useful information since there are no debug symbols present.
2017-08-23 00:02:28 +02:00
asarium f8d0a9bc7d Remove most remaining OpenGL header includes 2017-08-18 17:53:23 +02:00
asarium 72fa41a284 Use the generic rendering interface for cutscenes 2017-08-18 17:53:23 +02:00
asarium 72a797f732 Move 4 bit color conversion out of graphics code
Currently, the graphics code does some color remapping on 8
bit-per-pixel textures since those textures use special 4-bit pixel
values. These changes move that conversion out of the graphics code and
into the image loading/font bitmap creation code.

The reason this is needed is because this conversion breaks 8-bit
textures that try to use the full range of colors. I need to do exactly
that for moving the cutscene renderer to our generic rendering interface
which I can't do at the moment since the existing color conversion
corrupts the video data.

I have tested this with retail data and could not find any visual
changes after applying these changes.
2017-08-16 17:20:32 +02:00
asarium 2b0ec7161a Build Unix source package before configuring
The previous version included the make files which increased the size of
the package.
2017-08-15 10:18:09 +02:00
asarium 90c23c007c Add config option for setting the FF strength 2017-08-10 10:09:02 +02:00
asarium 4648721674 Add mod table parsing to qtfred initializers 2017-08-04 20:04:54 +02:00
asarium ae4a7319e5 Add About dialog 2017-08-04 15:13:16 +02:00
asarium 3c7f7f9df0 Add error checker action 2017-08-04 14:13:47 +02:00
asarium e11250f7e8 Add subsystem selection actions 2017-08-04 13:28:36 +02:00
asarium 24dec72f41 Add control object action 2017-08-04 10:55:50 +02:00
asarium 89c36b68c7 Add Align object action 2017-08-04 10:54:56 +02:00
asarium e66d9d1246 Add Level object action 2017-08-04 10:53:27 +02:00
asarium 789135516e Add Misc menu shortcuts 2017-08-04 10:53:27 +02:00
asarium 91b61d446f Add group action support 2017-08-04 10:53:27 +02:00
asarium 8e5aafb6e5 Add delete actions 2017-08-04 10:53:27 +02:00
asarium cb0080bfc1 Add actions for hiding and showing toolbar and statusbar 2017-08-04 10:53:27 +02:00
asarium a03180c46e Add Save camera position action 2017-08-04 10:53:27 +02:00
asarium a18fdd2112 Add support for hiding specific teams 2017-08-04 10:53:27 +02:00
asarium 7c81ac1d86 Improve waypoint dialog layout and behavior
The dialog is not resizable anymore and the combobox is disabled if
there are no entries.
2017-08-04 10:53:27 +02:00
asarium bc7414c403 Improve window title handling 2017-08-04 10:53:27 +02:00
asarium a7418d6dde Add documentation to runAfterInit 2017-08-04 10:53:27 +02:00
m!m f83c2e9cdc Merge pull request #1431 from asarium/qtfred2_/sync
Sync qtFRED branch
2017-08-04 10:52:53 +02:00
asarium 965a327630 Merge branch 'master' into qtfred2_/sync 2017-08-04 09:09:32 +02:00
Tyler Blount c9bb3f4caa Merge pull request #1428 from asarium/qtfred2_/dev
Add ship selection dialog
2017-08-02 01:12:36 -06:00
asarium 3e1b020bf5 Add local rotate action 2017-07-31 13:02:56 +02:00
asarium 60d6aaccec Add orbit rotate functionality 2017-07-31 12:57:28 +02:00
asarium 18a957e8bf Fix list selection 2017-07-31 10:20:55 +02:00
asarium ad7bddfd41 Copy old mission load code to qtFRED 2017-07-30 17:50:56 +02:00
asarium a90d859891 Add object selection dialog 2017-07-30 17:37:35 +02:00
asarium 841872aae0 Add mod table setting for specifying targetted FSO version
This adds a small system for letting a mod specify which version of FSO
was designed for. That would allow us to introduce code which would
normally break backwards-compatibility by putting it in an if block
which checks if the mod supports the FSO version which ontroduced the
behavioral change.

There is currently no code which uses the new functions yet so I added a
few tests to verify that the options do what they are designed to do.

This fixes #1389.
2017-07-14 20:09:29 +02:00
m!m 9b1e9600ce Merge pull request #1410 from asarium/qtfred2_/dev
Add form and disband wing actions
2017-07-10 09:44:25 +02:00
asarium 07a806e01f Clear mission on load 2017-07-09 13:25:38 +02:00
asarium ccd33eb50f Add zoom toolbar actions 2017-07-09 13:23:53 +02:00
asarium 1805c77f7c Add disband wing action and update enabled status 2017-07-09 12:46:26 +02:00
asarium 481ebec316 Add form wing action
This also introduces the new generic dialog system which should allow
the mission code to open specific dialogs without depending on the
actual Qt implementation.
2017-07-09 10:25:06 +02:00
m!m 99d8b19ee8 Merge pull request #1408 from TRBlount/qtfred2_dialogs
Add Mission Specs Editor
2017-07-08 11:12:35 +02:00
TRBlount 5adc3216df Fix CI compilation on Linux and Windows Debug 2017-07-08 02:21:18 -06:00
TRBlount 55f39e088d Use Dialog Provider and fix some model functions 2017-07-08 02:04:36 -06:00
TRBlount 71b572b7f4 Fix CI issues 2017-07-07 17:58:18 -06:00
TRBlount c1908669d9 Finish Custom Wing Name Editor 2017-07-07 16:31:29 -06:00
TRBlount a9d25fd18d Add Custom Wing Model 2017-07-07 14:37:00 -06:00
TRBlount 72c5d17739 Add Custom Wing dialog 2017-07-07 13:59:53 -06:00
TRBlount ecf10d8227 Fix comments and add Command Messages 2017-07-07 04:18:11 -06:00
TRBlount 8ab448dd70 Move to modification system
Alerts the user whenever they have unsaved changes
2017-07-07 03:16:21 -06:00
TRBlount ea53cff723 Add Mission Spec Model 2017-07-07 02:37:58 -06:00
TRBlount 407888641c Modify UI to use correct components
Some misuse of Spin Boxes and Line Edits
2017-07-05 18:40:36 -06:00
TRBlount ac554f24c2 Fix include formatting and Combo Box issues 2017-07-05 02:27:42 -06:00
TRBlount 56670b2ed7 Figure out QFileDialogs, issues with AI Profile Box 2017-07-05 02:19:16 -06:00
TRBlount 7e26955853 Figure out text cursors 2017-07-04 19:30:54 -06:00
TRBlount c085eef9a0 Update UI file and setup mission flags 2017-07-04 02:15:14 -06:00
TRBlount 8061125d84 Continue implementation
Some data actually saves now
2017-07-03 08:21:48 -06:00
asarium 72013d4c31 Use unique_ptr for storing HUD gauge pointers
The previous system used naked pointers which probably worked fine but
this should give us some extra memory-leak security.
2017-07-03 12:52:39 +02:00
TRBlount 93b1c0df17 Get dialog to close on accepted and rejected 2017-07-03 00:55:31 -06:00
TRBlount 41f889e55d Add Mission Spec Editor and begin implementation 2017-07-02 17:46:00 -06:00
Goober5000 416d45d060 deprecate string-concatenate since it's now redundant 2017-07-01 23:05:48 -04:00
Goober5000 18be4e854c add string-concatenate-block, which is a better design than the original string-concatenate 2017-07-01 23:05:48 -04:00
Tyler Blount 7d92178777 Merge pull request #1398 from asarium/qtfred2_/dev
Add object orientation editor
2017-07-01 16:54:35 -06:00
asarium ac69bd5712 Remove dialog test code 2017-07-01 23:47:15 +02:00
asarium d6b6ea715a Add Object orientation and location editor 2017-07-01 23:42:04 +02:00
asarium 8c59b06b59 Add form for object orientation editor 2017-06-29 08:57:13 +02:00
Tyler Blount e59d31d66e Merge pull request #1392 from asarium/qtfred2_/dev
Add waypoint editor
2017-06-28 01:28:31 -06:00
asarium 19c01563ca Add missing files 2017-06-28 08:52:28 +02:00
asarium 80f1f50582 Add edit popup menu and double click handling 2017-06-27 23:47:36 +02:00
asarium a057e111ba Add fully working waypoint editor
This is the first editor that is functional and uses.
2017-06-27 23:44:43 +02:00
asarium b45998b58d Add waypoint editor dialog form 2017-06-27 23:35:55 +02:00
m!m 472a3f09f7 Merge pull request #1380 from TRBlount/qtfred2_dialogs
Add Team Loadout and Mission Objective editors
2017-06-20 08:48:06 +02:00
TRBlount d6c4ff374c Update Team Loadout and Mission Objective Editors
Changes the above editors to use dialog button boxes and spacer widgets
instead of min/max sizes.
2017-06-18 00:57:23 -06:00
TRBlount b14c12befa Add Mission Goal and Team Loadout Dialogs 2017-06-18 00:57:23 -06:00
Tyler Blount 2d7606740a Merge pull request #1377 from asarium/qtfred2_/dev
Add object creation and drag movement of ships
2017-06-18 00:57:00 -06:00
asarium 1712a42807 Add abstracted dialog system 2017-06-17 15:52:36 +02:00
asarium f811d7591f Remove the need to specify the editor pointer 2017-06-14 17:56:30 +02:00
asarium 7e9f0c8e6f Connect toolbar button for showing distances 2017-06-14 17:46:33 +02:00
asarium 255814dd4f Fix warning 2017-06-13 11:38:10 +02:00
asarium e076aa6990 Add briefing editor to main window and fix layout 2017-06-13 11:14:16 +02:00
asarium 16d48fbf1b Port object moving and creation code 2017-06-13 10:56:44 +02:00
Tyler Blount 937de9355b Merge pull request #1373 from asarium/qtfred2_/dev
qtFRED development changes
2017-06-12 00:57:55 -06:00
asarium 947b25e2cc Add executable icon 2017-06-11 23:20:02 +02:00
asarium e6f92f316a Move Briefing editor dialog to correct folder 2017-06-11 22:08:42 +02:00
asarium f65de9bb43 Fix compilation warning 2017-06-11 20:04:42 +02:00
asarium 956e908b6e Separate editor viewport state into separate class
This moves all the data related to the editor state that is not directly
connected to the renderer into its own class and file. This should
resemble the fredrenderer <-> fredview separation in the original FRED.
2017-06-11 20:04:41 +02:00
asarium 0442c1c6ac Fix case of Editor file 2017-06-11 20:04:40 +02:00
asarium 1a3b14316d Move init and shutdown stuff out of editor.cpp 2017-06-11 20:04:38 +02:00
asarium 350e8a2cf5 Add various selection modes including box selection 2017-06-11 20:04:37 +02:00
asarium 4cd9993640 Add Event dialog code 2017-06-11 20:04:36 +02:00
asarium 41137fedbd Begin adding dialog infrastructure 2017-06-11 20:04:34 +02:00
asarium 52901e7351 Add viewpoint status label 2017-06-11 20:04:33 +02:00
MageKing17 526076f8ff Add AVX2 to the list of supported MSVC compiler optimizations.
Also adds AVX2 autodetection so that AVX2-capable processors will generate AVX2 projects by default. To my surprise, there is actually a noticeable performance increase between AVX and AVX2 builds.
2017-06-10 14:19:19 -07:00
m!m 8236a7d7f8 Merge pull request #1370 from TRBlount/Briefing_Editor
Add Briefing Editor Dialog
2017-06-10 11:42:44 +02:00
Tyler Blount 70e63dcf6c Fix include casing 2017-06-10 02:45:47 -06:00
TRBlount 557ff6be1d Add Briefing Editor Dialog 2017-06-10 01:37:16 -06:00
m!m 95896e6ec7 Merge pull request #1369 from asarium/qtfred2_/dev
Update qtFRED development files
2017-06-10 09:22:34 +02:00
asarium e6acd9a313 Add current ship control mode
Also fixed infinite recursion in key handler.
2017-06-09 23:16:06 +02:00
asarium c1cb978687 Fix context menu of RenderWindow 2017-06-09 18:58:53 +02:00
asarium 51698af1b0 Add viewpoint switching 2017-06-09 13:57:30 +02:00
asarium 9d3659cf88 Fix UI file compilation 2017-06-09 11:34:52 +02:00
asarium 3eddce06dd Add buddies settings to EventDialog form 2017-06-09 11:19:11 +02:00
asarium 9c75a2178c Remove unneeded variable name parameter in CMake config 2017-06-09 11:05:17 +02:00
asarium d26253c5f8 Add an application icon
It's currently the normal FRED icon.
2017-06-09 10:55:28 +02:00
asarium 6b5cac174a Add dialogs folder 2017-06-09 10:11:51 +02:00
asarium 1f39915a5e Add Event editor dialog form 2017-06-09 10:07:02 +02:00
asarium d60306288b Rebind movement speed shortcuts to fix camera movement 2017-06-09 10:06:55 +02:00
asarium 305e71e290 Copy display_distances code to fix rendering bug 2017-06-08 22:55:20 +02:00
asarium befe668c8b Remove deleted file from CMake config 2017-06-08 19:28:42 +02:00
asarium 25e87fb8a0 Use a timer with a 5 millisecond interval for our idle function
It uses less resources than the 0-interval timer.
2017-06-08 19:22:21 +02:00
asarium 9a11f232f6 Call super function in event filter 2017-06-08 19:11:01 +02:00
asarium 49a37ccf91 Fix view speed changing 2017-06-08 19:08:52 +02:00
asarium ee8d03b4cf Fix onIdle behavior 2017-06-08 19:07:02 +02:00
asarium 16b80faaaf Fix Travis CI warnings 2017-06-08 18:42:13 +02:00
asarium 0f7810fdb4 Add support for changing movement speed 2017-06-08 16:19:30 +02:00
asarium f85dfbb048 Add support for hiding objects
Also cleaned up some parameter handling
2017-06-08 15:32:47 +02:00
asarium 96ed407dd7 Fix endless loop 2017-06-08 13:04:36 +02:00
asarium cd7cf82430 Use render widget as focus proxy to redirect key events 2017-06-08 13:00:14 +02:00
asarium cff16f7b0b Remove object iterator 2017-06-08 12:49:06 +02:00
asarium 1a08bfa3e7 Handle window activation and deactivation 2017-06-08 12:39:45 +02:00
asarium dbc52e2aa7 Add handling of different cursor modes 2017-06-08 12:21:12 +02:00
asarium b1725bae76 Separate RenderWidget and RenderWindow
RenderWindow now only handled rendering and RenderWidget handles GUI
interaction by intercepting all GUI events for the RenderWindow.
2017-06-08 11:08:00 +02:00
asarium 4b10c61a5f Add initial cursor handling 2017-06-08 09:39:28 +02:00
asarium c18220048d Add handling of control constain buttons 2017-06-07 18:53:19 +02:00
asarium 08b8c1d768 Permanently create view popup menu 2017-06-07 17:56:39 +02:00
asarium 0f6a61894a Prevent context menu on the toolbar 2017-06-07 17:22:19 +02:00
asarium 3345aee144 Add viewport context menu
Still not complete but most actions are there already
2017-06-07 17:20:10 +02:00
asarium 207d3e6eba Continually update the view settings 2017-06-07 16:09:36 +02:00
asarium 8be0a19a98 Use a more elegant signal-slot solution for view option handling 2017-06-07 13:02:05 +02:00
asarium b517a47f81 Handle view settings updates 2017-06-07 12:35:51 +02:00
asarium 4afd5d9d1c Use normal event handler instead of event filter for shortcut override 2017-06-07 12:05:56 +02:00
asarium 7eaff0e63f Synchronize view settings with renderer settings 2017-06-07 10:52:10 +02:00
asarium 755df8c38b Fix crash when there is no valid filename 2017-06-07 10:51:56 +02:00
m!m 8357964e53 Merge pull request #1365 from asarium/qtfred2_/dev
Further qtFRED development
2017-06-07 10:38:54 +02:00
asarium e10b431735 Reformat FredView to fix GCC whitespace warning 2017-06-07 09:34:22 +02:00
asarium be5d7cc2cd Move most view parameters into the view struct 2017-06-06 23:42:41 +02:00
asarium 2e016ccffb Add support for storing recent files 2017-06-06 22:52:07 +02:00
asarium 4305649a64 Use standard key combinations for common actions 2017-06-06 22:51:42 +02:00
asarium 27c971a92b Actually fix MSVC 2013 compilation 2017-06-06 10:12:35 +02:00
asarium 1e1c8c7cb8 Actually add event based redrawing 2017-06-06 10:07:00 +02:00
asarium 94bb727ebe Fix MSVC 2013 compilation 2017-06-06 09:45:37 +02:00
m!m 884259fc14 Merge pull request #1360 from asarium/qtfred2_/editorSignals
Add signals to Editor class and implement window title switching
2017-06-05 21:47:19 +02:00
asarium 0b6a3115a7 Load debug filer file at startup 2017-06-05 19:13:52 +02:00
asarium ec6a786654 Create default ship on mission start 2017-06-05 18:02:16 +02:00
asarium a3744d8818 Fix installation step for FastDebug 2017-06-05 14:51:09 +02:00
asarium 5dc0c0d98d Add the Qt main code to fix compilation issues with FastDebug
This also removed the need to link the runtime dynamically.
2017-06-05 00:34:36 +02:00
asarium ad6551cf38 Override shortcuts when the key is on the key pad
This fixes the movement speed shortcuts
2017-06-04 15:57:12 +02:00
asarium 1cdc0840be Connect Open and New actions 2017-06-04 14:00:28 +02:00
asarium e7f619d65e Refactor render handling and editor separation 2017-06-04 13:44:22 +02:00
asarium 3ddc93fd9d Remove speed shortcuts to fix cmaera controls for now 2017-06-03 11:01:02 +02:00
asarium 6b32bdb732 Make sure our viewport is in use when updating the window 2017-06-02 22:21:09 +02:00
asarium cabc6f6412 Add organization and application names 2017-06-02 19:40:14 +02:00
asarium 164e20ef96 Remove usage of Qt in editor code 2017-06-02 19:24:12 +02:00
asarium d18b97014e Fix Unix compilation 2017-06-02 17:20:28 +02:00
asarium abdf713944 Add manifest for Windows 2017-06-02 17:16:54 +02:00
asarium 24a3369e9d Make sure member is initialied with a valid value 2017-06-01 23:47:32 +02:00
asarium cb94183629 Implement user name retrieval on Windows 2017-06-01 23:47:15 +02:00
asarium 7ecfa209ca Add Ship class combo box
This is still a few features of the old combobox.
2017-06-01 22:57:42 +02:00
asarium 22105d1e3e Use FredView as the new main window 2017-06-01 21:46:12 +02:00
asarium 588659a367 Rename frmFRED to match the name of the original FRED name 2017-06-01 11:40:49 +02:00
z64555 423d14c24a Add (another) UI for main window, mainwindow.ui is slated to be removed. 2017-06-01 11:27:42 +02:00
asarium 2f44c3242f Convert XPM to PNG and add images to resources 2017-06-01 11:19:14 +02:00
z64555 1167a4edcb Include art assets for UI 2017-06-01 11:04:40 +02:00
asarium 862010b4e0 Fix Qt config for mac 2017-06-01 10:46:02 +02:00
asarium 95dff1dacf Port mission clear code to qtfred 2017-06-01 10:40:43 +02:00
asarium bc38232f3a Use Qt 5.7 for Travis 2017-05-31 21:55:51 +02:00
asarium a29708ea89 Reformatted FredRenderer 2017-05-31 18:24:08 +02:00
asarium baeb9ac78b Improve handling of fredGlobals 2017-05-31 10:02:37 +02:00
asarium 211b9c9d71 Install custom Qt message handler 2017-05-31 09:44:55 +02:00
asarium 4c05a103fa Improve startup window display
Windows will now only be displayed once startup is complete and not when
the graphics code is initialized.
2017-05-31 00:29:42 +02:00
asarium 540e52ffbc Forward unused keyboard event to render window 2017-05-31 00:08:43 +02:00
m!m 0fc55babaf Merge pull request #1356 from asarium/qtfred2
Initial QtFRED source code
2017-05-29 10:10:54 +02:00
asarium 4ce085cd49 Add signals to Editor class and implement window title switching 2017-05-29 09:18:15 +02:00
asarium 3edb4575d3 Fix Visual Studio 2015 compiler bug 2017-05-28 22:50:25 +02:00
asarium 26af516704 Fix gtest variable for forced shared crt 2017-05-28 18:59:18 +02:00
asarium 668dccf925 Use dynamic runtime and disable FRED compilation 2017-05-28 14:34:35 +02:00
asarium acdf88fdeb Set focus policy for render widget 2017-05-28 14:28:59 +02:00
asarium 577c49eedb Add appveyor qt configuration 2017-05-28 14:08:55 +02:00
asarium 9cd3d80b81 Change setOption usage for Qt 5.2 compatibility 2017-05-28 13:51:48 +02:00
asarium e8316662b8 Improve update behavior 2017-05-28 13:23:59 +02:00
asarium 6a82c1eee7 Reformat file 2017-05-28 13:04:49 +02:00
asarium a309cb51b1 Add assertions for making sure a renderer exists 2017-05-28 13:02:28 +02:00
asarium af60cefbd5 Include QWidget header to fix compilation 2017-05-28 12:35:01 +02:00
asarium 8e2b1f354a Add message if dynamic runtime is not enabled 2017-05-28 12:32:02 +02:00
asarium 1d3ee16198 Remove unused field and fix brace warning
The fields were also unused by the previous FRED renderer so we are not
simply missing the code that used them.
2017-05-28 11:39:26 +02:00
asarium cb7f2a5dfd Remove unused include 2017-05-28 11:23:51 +02:00
asarium 18a621764c Fix warnings in FredRenderer 2017-05-28 10:48:35 +02:00
asarium 22c7e31c8a Merge branch 'fix/openglIncludes' into qtfred2 2017-05-28 10:36:01 +02:00
asarium 00ff9e8751 Correct message referencing wxFRED 2017-05-28 10:32:15 +02:00
asarium ba26f6e221 Add Travis CI configuration 2017-05-28 10:21:28 +02:00
asarium ed01e155f6 Fix typo 2017-05-28 09:58:17 +02:00
asarium cd110bb2c1 Some minor improvements to the main function 2017-05-28 09:30:00 +02:00
asarium 2c30dbcda6 Add better control of viewport destruction order 2017-05-27 23:51:39 +02:00
asarium 160d49fa82 Remove unused function 2017-05-27 23:03:27 +02:00
asarium 431ad4144f Fix Visual Studio uni test compilation with shared runtime 2017-05-27 23:03:00 +02:00
asarium 2555d11427 Use lambda instead of std::bind 2017-05-27 21:52:54 +02:00
asarium e1882fc314 Add better mechanism for specifying Qt install root 2017-05-27 21:52:30 +02:00
asarium 2804b5d9d3 Update rendering handling. 2017-05-27 20:39:24 +02:00
asarium 2bbe201130 Various changes while trying to find cause for shutdown crash 2017-05-27 19:04:36 +02:00
asarium bbbc08fa87 Fix borders around render widget 2017-05-27 19:04:21 +02:00
asarium a8def1e1b3 Improve CMake setup, now has proper source folder support 2017-05-27 19:02:53 +02:00
asarium 987a442dd6 Reorganize QtFRED file structure 2017-05-27 13:26:30 +02:00
asarium 09d39da97c Remove unneeded renderer initialization 2017-05-27 13:14:11 +02:00
asarium 0a2e6f581b Add commandline parsing
Also fixed some initialization inconsistencies
2017-05-27 11:37:45 +02:00
asarium 98cde8f21f Fix XSTR related crash when loading a mission 2017-05-27 11:05:42 +02:00
asarium 9d22d75ba8 Add claifying comment in main 2017-05-27 11:05:29 +02:00
asarium df095e6bdf Fix various Qt and rendering issues
Now this is actually able to show the mission grid (but mission loading
still fails).
2017-05-27 09:55:06 +02:00
asarium 243f7f7ce8 Disable memcpy checks if third party libraries are used 2017-05-25 23:46:10 +02:00
asarium 32b6696162 Fix qtfred code 2017-05-25 23:42:44 +02:00
asarium ac8befa4e6 Reimport previous qtfred source 2017-05-25 23:42:32 +02:00
niffiwan e003d08249 Fix lua function documentation 2017-03-20 20:37:38 +10:00
niffiwan c8baf8b344 Don't assume sexp will have all RGB supplied
Fix annoying clang pedantry with union aggregate init lists
2017-03-19 16:01:20 +10:00
niffiwan b5f75af66e Allow tint shader to be controlled by sexp & lua
i.e. the RGB values can be set/changed
2017-03-19 12:52:51 +10:00
niffiwan 25415342ea Add colour-configurable tint shader
FotG needs a tint shader for a feature; basically toggle screen tinting
when a key is pressed as a visual indicator of which mode your ship it
in. Was previously done in a custom shader.
2017-03-12 22:04:33 +10:00
898 changed files with 85354 additions and 21975 deletions

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
---
Checks: "-*,\
modernize-*,\
-modernize-raw-string-literal,\
-modernize-use-using,\
performance-*,\
-performance-type-promotion-in-math-fn,\
misc-*,\
-misc-macro-parentheses,\
-misc-misplaced-widening-cast,\
-misc-static-assert,\
"
WarningsAsErrors: ''
HeaderFilterRegex: 'code/.*$|freespace2/.*$|qtfred/.*$|test/src/.*$|build/.*$'
AnalyzeTemporaryDtors: false
CheckOptions:
- key: 'misc-assert-side-effect.AssertMacros'
value: 'assert,Assert,Assertion'
- key: 'modernize-use-emplace.ContainersWithPushBack'
value: 'std::vector;std::deque;std::list;SCP_vector;SCP_deque;SCP_list'
...
+21
View File
@@ -0,0 +1,21 @@
build:
image: teaci/msys$$arch
pull: true
shell: mingw$$arch
commands:
- git submodule update --init --recursive
- if [ $$arch = 32 ]; then target=i686; fi
- if [ $$arch = 64 ]; then target=x86_64; fi
- pacman -S --needed --noconfirm --noprogressbar mingw-w64-${target}-pkg-config mingw-w64-${target}-cmake
- mkdir build && cd build
- cmake -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=$$CONFIGURATION -DFSO_USE_SPEECH=OFF -DFSO_USE_VOICEREC=OFF -DFSO_FATAL_WARNINGS=ON -DFSO_BUILD_FRED2=OFF ..
- make -j$(nproc) all
matrix:
arch:
- 64
- 32
CONFIGURATION:
- Debug
- Release
+4 -30
View File
@@ -1,33 +1,3 @@
*.o
*.a
.dirstamp
libtool
ltmain.sh
m4/libtool.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
compile
.deps/
code/.deps/
Makefile
Makefile.in
aclocal.m4
autom4te.cache/
config.*
code/fs2_open_*
code/wxFRED2_*
configure
depcomp
install-sh
missing
.svn
*.layout
projects/Xcode/Frameworks/
#========
#OS junk files
[Tt]humbs.db
*.DS_Store
@@ -286,3 +256,7 @@ CMakeSettings.json
# Weird files created by Linux
.fuse_hidden*
# This gets ignored by one of the rules above for some reason...
!/code/scripting/lua/LuaConvert.h
!/code/debugconsole/
-3
View File
@@ -1,6 +1,3 @@
[submodule "cmake/external/cotire"]
path = cmake/external/cotire
url = https://github.com/sakra/cotire.git
[submodule "cmake/external/rpavlik-cmake-modules"]
path = cmake/external/rpavlik-cmake-modules
url = https://github.com/asarium/cmake-modules.git
+45 -12
View File
@@ -3,7 +3,8 @@ sudo: required
dist: trusty
cache:
directories:
- $HOME/cmake
- $HOME/cmake-3.8
- $HOME/.ccache
addons:
apt:
packages: &global_deps
@@ -16,6 +17,7 @@ addons:
- libjansson-dev
- libsdl2-dev
- valgrind
- qt57base
coverity_scan:
project:
name: "scp-fs2open/fs2open.github.com"
@@ -69,19 +71,36 @@ matrix:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-trusty'
packages:
- g++-5
- *global_deps
- g++-5
- os: linux
env: CONFIGURATION="Debug" CC=clang-3.6 CXX=clang++-3.6
env: CONFIGURATION="Debug" CC=gcc-7 CXX=g++-7
addons:
apt:
sources:
- llvm-toolchain-precise
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-trusty'
packages:
- clang-3.6
- libc++-dev
- g++-7
- *global_deps
- os: linux
env: CONFIGURATION="Debug" CC=clang-4.0 CXX=clang++-4.0 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- sourceline: 'ppa:beineri/opt-qt571-trusty'
packages:
- *global_deps
- clang-4.0
- clang-tidy-4.0
- libc++-dev
script:
- ./ci/travis/script.sh
- ./ci/travis/clang_tidy.sh
- os: osx
env: CONFIGURATION="Debug"
@@ -91,19 +110,32 @@ matrix:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-trusty'
packages:
- g++-5
- *global_deps
- g++-5
- os: linux
env: CONFIGURATION="Release" CC=clang-3.6 CXX=clang++-3.6
env: CONFIGURATION="Release" CC=gcc-7 CXX=g++-7
addons:
apt:
sources:
- llvm-toolchain-precise
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-trusty'
packages:
- clang-3.6
- libc++-dev
- g++-7
- *global_deps
- os: linux
env: CONFIGURATION="Release" CC=clang-4.0 CXX=clang++-4.0
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- sourceline: 'ppa:beineri/opt-qt571-trusty'
packages:
- *global_deps
- clang-4.0
- libc++-dev
- os: osx
env: CONFIGURATION="Release"
before_install:
@@ -117,8 +149,9 @@ before_install:
- "./ci/travis/before_install.sh"
install:
- "./ci/travis/install.sh"
- export PATH=$HOME/cmake/bin:$PATH
- export PATH=$HOME/cmake-3.6/bin:$PATH
before_script:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then QT_ENV_SCRIPT=$(find /opt -name 'qt*-env.sh'); source $QT_ENV_SCRIPT; fi
- "./ci/travis/before_script.sh"
script:
- if [ "$BUILD_DEPLOYMENT" = true ] ; then ./ci/travis/release.sh ; else ./ci/travis/script.sh ; fi
+20 -7
View File
@@ -40,6 +40,14 @@ set(CMAKE_CONFIGURATION_TYPES Debug Release FastDebug CACHE STRING "Available co
PROJECT(FS2_Open)
find_program(CCACHE_PROGRAM ccache)
# Currently only GCC support ccache properly without generating additional warnings
if(CCACHE_PROGRAM AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
message(STATUS "Using ccache for compilation: ${CCACHE_PROGRAM}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CCACHE_PROGRAM}")
endif()
IF(CMAKE_CROSSCOMPILING)
SET(IMPORT_EXE_DIR "IMPORT_EXE_DIR-NOTFOUND" CACHE FILEPATH "Required for a cross compiling build, point to binary directory of a cmake build for the real OS")
INCLUDE(${IMPORT_EXE_DIR}/ImportExecutables.cmake)
@@ -53,7 +61,7 @@ endif()
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/finder")
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/rpavlik-cmake-modules")
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/cotire/CMake")
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/cotire")
IF(RESET_INSTALL_PREFIX)
IF(NOT $ENV{FS2PATH} STREQUAL "")
@@ -85,7 +93,7 @@ OPTION(FSO_BUILD_TESTS "Build unit tests" OFF)
OPTION(FSO_DEVELOPMENT_MODE "Generate binaries in development mode, only use if you know what you're doing!" OFF)
OPTION(FSO_BUILD_WXFRED2 "Build wxFRED2 binary" OFF)
OPTION(FSO_BUILD_QTFRED "Build qtFRED2 binary" OFF)
IF(WIN32 OR APPLE)
# On windows and mac the default should be to always build the included libraries
@@ -108,6 +116,8 @@ SET(FSO_RUN_ARGUMENTS "" CACHE STRING "Additional arguments passed to a generate
option(FSO_INSTALL_DEBUG_FILES "Install some debug files (currently only PDB files on windows)" OFF)
option(ENABLE_COTIRE "Enable cotire for faster compilation. Enabled by default." ON)
MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG)
MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS)
MARK_AS_ADVANCED(FORCE FSO_USE_OPENALSOFT)
@@ -115,6 +125,7 @@ MARK_AS_ADVANCED(FORCE FSO_USE_LUAJIT)
MARK_AS_ADVANCED(FORCE FSO_DEVELOPMENT_MODE)
MARK_AS_ADVANCED(FORCE FSO_FATAL_WARNINGS)
mark_as_advanced(FORCE FSO_INSTALL_DEBUG_FILES)
mark_as_advanced(FORCE ENABLE_COTIRE)
# Include cotire file from https://github.com/sakra/cotire/
include(cotire)
@@ -134,6 +145,8 @@ if(FSO_BUILD_APPIMAGE)
include(appimage)
endif()
include(clang-tidy)
# This includes source code for some tools, either used in the build or also for something else
ADD_SUBDIRECTORY(tools)
@@ -147,9 +160,9 @@ IF(FSO_BUILD_FRED2)
ADD_SUBDIRECTORY(fred2)
ENDIF(FSO_BUILD_FRED2)
IF(FSO_BUILD_WXFRED2)
ADD_SUBDIRECTORY(wxfred2)
ENDIF(FSO_BUILD_WXFRED2)
IF(FSO_BUILD_QTFRED)
ADD_SUBDIRECTORY(qtfred)
ENDIF()
if(FSO_BUILD_TESTS)
add_subdirectory(test)
@@ -176,12 +189,12 @@ include(doxygen)
# Print used options to log
IF (WIN32)
message(STATUS "Building FRED2: ${FSO_BUILD_FRED2}")
message(STATUS "Using text to speech: ${FSO_USE_SPEECH}")
message(STATUS "Using voice recogition: ${FSO_USE_VOICEREC}")
message(STATUS "Building FRED2: ${FSO_BUILD_FRED2}")
elseif(UNIX)
message(STATUS "Building AppImage: ${FSO_BUILD_APPIMAGE}")
ENDIF()
message(STATUS "Building FSO tools: ${FSO_BUILD_TOOLS}")
message(STATUS "Building wxFRED: ${FSO_BUILD_WXFRED2}")
message(STATUS "Building qtFRED: ${FSO_BUILD_QTFRED}")
message(STATUS "Fatal warnings: ${FSO_FATAL_WARNINGS}")
+5 -2
View File
@@ -1,4 +1,5 @@
version: 1.0.0.{build}
image: Visual Studio 2015
configuration:
- Debug
- Release
@@ -6,11 +7,13 @@ clone_depth: 10
environment:
matrix:
- BuildID: 0
CMAKE_GENERATOR: Visual Studio 12 2013
PlatformToolset: v120_xp
CMAKE_GENERATOR: Visual Studio 14 2015
PlatformToolset: v140_xp
QT_DIR: C:\Qt\5.9.5\msvc2015
- BuildID: 1
CMAKE_GENERATOR: Visual Studio 14 2015 Win64
PlatformToolset: v140_xp
QT_DIR: C:\Qt\5.9.5\msvc2015_64
before_build:
- git submodule update --init --recursive
build_script:
+8
View File
@@ -4,6 +4,7 @@ class BuildConfig {
[string]$PackageType
[string]$Toolset
[string]$SimdType
[string]$QtDir
[Bool]$SourcePackage
}
@@ -13,6 +14,7 @@ $NightlyConfigurations = @(
PackageType="Win64";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9.5\msvc2015_64";
SourcePackage=$false;
},
[BuildConfig]@{
@@ -20,6 +22,7 @@ $NightlyConfigurations = @(
PackageType="Win32";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9.5\msvc2015";
SourcePackage=$false;
}
)
@@ -29,6 +32,7 @@ $ReleaseConfigurations = @(
PackageType="Win32";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9.5\msvc2015";
SourcePackage=$true;
}
[BuildConfig]@{
@@ -36,6 +40,7 @@ $ReleaseConfigurations = @(
PackageType="Win32-AVX";
Toolset="v140_xp";
SimdType="AVX";
QtDir="C:\Qt\5.9.5\msvc2015";
SourcePackage=$false;
}
[BuildConfig]@{
@@ -43,6 +48,7 @@ $ReleaseConfigurations = @(
PackageType="Win64";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9.5\msvc2015_64";
SourcePackage=$false;
}
[BuildConfig]@{
@@ -50,6 +56,7 @@ $ReleaseConfigurations = @(
PackageType="Win64-AVX";
Toolset="v140_xp";
SimdType="AVX";
QtDir="C:\Qt\5.9.5\msvc2015_64";
SourcePackage=$false;
}
)
@@ -141,6 +148,7 @@ if ($DeployBuild) {
Push-AppveyorArtifact "$($PackageName)-builds-$($buildConfig.PackageType).zip"
} else {
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="ON" -DFSO_BUILD_TESTS="ON" -DMSVC_SIMD_INSTRUCTIONS=SSE2 `
-DFSO_BUILD_QTFRED=ON -DQT5_INSTALL_ROOT="$env:QT_DIR" -DFSO_BUILD_FRED2="ON" `
-G "$Env:CMAKE_GENERATOR" -T "$Env:PlatformToolset" ..
cmake --build . --config "$Env:CONFIGURATION" -- /verbosity:minimal
+1 -14
View File
@@ -2,20 +2,7 @@
if ([System.Convert]::ToBoolean($env:ReleaseBuild) -Or [System.Convert]::ToBoolean($env:NightlyBuild) -Or [System.Convert]::ToBoolean($env:TestBuild)) {
# Skip tests for deployment
exit 0
} else {
# Appveyor doesn't have OpenAL so copy our DLLs to the output FOLDER
$arch=""
if ($Env:CMAKE_GENERATOR -Match "Win64") {
$arch="win64"
} else {
$arch="win32"
}
$dllPath = "$Env:APPVEYOR_BUILD_FOLDER\lib\openal\libs\$arch\OpenAL32.dll"
$copyDestination = "$pwd\bin\$Env:CONFIGURATION\"
write "Copying OpenAL DLL..."
Copy-Item "$dllPath" "$copyDestination"
} else {
write "Running unit tests..."
# Run unit tests
&"$pwd\bin\$Env:CONFIGURATION\unittests.exe" --gtest_shuffle 2>&1
+8 -3
View File
@@ -6,6 +6,11 @@ mkdir -p build
cd build
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
if [ "$RELEASE_BUILD" = true ]; then
PARENT_DIR="$(basename $PWD)"
(cd .. && tar -czvf /tmp/builds/$PACKAGE_NAME-source-Unix.tar.gz --exclude-vcs "$PARENT_DIR")
fi
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
@@ -15,7 +20,7 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
export CXXFLAGS
export CFLAGS
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON"
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON $CMAKE_OPTIONS"
if [ "$BUILD_DEPLOYMENT" = true ]; then
for config in $BUILD_CONFIGS
do
@@ -27,12 +32,12 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
cd ..
done
else
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON ..
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=ON ..
fi
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
if [ "$BUILD_DEPLOYMENT" = true ]; then
cmake -G "Xcode" -DFSO_FATAL_WARNINGS=ON -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_INSTALL_PREFIX="/tmp/release" ..
else
cmake -G "Xcode" ..
cmake -G "Xcode" $CMAKE_OPTIONS ..
fi
fi
+1 -1
View File
@@ -49,7 +49,7 @@ if ([ "$RELEASE_BUILD" = true ] || [ "$NIGHTLY_BUILD" = true ] || [ "$TEST_BUILD
fi
if [ "$BUILD_DEPLOYMENT" = true ]; then
if ([ "$TRAVIS_OS_NAME" = "linux" ] && (! [[ "$CC" =~ ^gcc.*$ ]])); then
if ([ "$TRAVIS_OS_NAME" = "linux" ] && (! [[ "$CC" =~ ^gcc-5.*$ ]])); then
echo "Skipping non-release compiler";
exit 0;
fi
+141
View File
@@ -0,0 +1,141 @@
#!/usr/bin/env python
#
#===- clang-tidy-diff.py - ClangTidy Diff Checker ------------*- python -*--===#
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===------------------------------------------------------------------------===#
r"""
ClangTidy Diff Checker
======================
This script reads input from a unified diff, runs clang-tidy on all changed
files and outputs clang-tidy warnings in changed lines only. This is useful to
detect clang-tidy regressions in the lines touched by a specific patch.
Example usage for git/svn users:
git diff -U0 HEAD^ | clang-tidy-diff.py -p1
svn diff --diff-cmd=diff -x-U0 | \
clang-tidy-diff.py -fix -checks=-*,modernize-use-override
"""
import argparse
import json
import re
import subprocess
import sys
def main():
parser = argparse.ArgumentParser(description=
'Run clang-tidy against changed files, and '
'output diagnostics only for modified '
'lines.')
parser.add_argument('-clang-tidy-binary', metavar='PATH',
default='clang-tidy',
help='path to clang-tidy binary')
parser.add_argument('-p', metavar='NUM', default=0,
help='strip the smallest prefix containing P slashes')
parser.add_argument('-regex', metavar='PATTERN', default=None,
help='custom pattern selecting file paths to check '
'(case sensitive, overrides -iregex)')
parser.add_argument('-iregex', metavar='PATTERN', default=
r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc)',
help='custom pattern selecting file paths to check '
'(case insensitive, overridden by -regex)')
parser.add_argument('-fix', action='store_true', default=False,
help='apply suggested fixes')
parser.add_argument('-checks',
help='checks filter, when not specified, use clang-tidy '
'default',
default='')
parser.add_argument('-path', dest='build_path',
help='Path used to read a compile command database.')
parser.add_argument('-extra-arg', dest='extra_arg',
action='append', default=[],
help='Additional argument to append to the compiler '
'command line.')
parser.add_argument('-extra-arg-before', dest='extra_arg_before',
action='append', default=[],
help='Additional argument to prepend to the compiler '
'command line.')
parser.add_argument('-quiet', action='store_true', default=False,
help='Run clang-tidy in quiet mode')
clang_tidy_args = []
argv = sys.argv[1:]
if '--' in argv:
clang_tidy_args.extend(argv[argv.index('--'):])
argv = argv[:argv.index('--')]
args = parser.parse_args(argv)
# Extract changed lines for each file.
filename = None
lines_by_file = {}
for line in sys.stdin:
match = re.search('^\+\+\+\ \"?(.*?/){%s}([^ \t\n\"]*)' % args.p, line)
if match:
filename = match.group(2)
if filename == None:
continue
if args.regex is not None:
if not re.match('^%s$' % args.regex, filename):
continue
else:
if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
continue
match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
if match:
start_line = int(match.group(1))
line_count = 1
if match.group(3):
line_count = int(match.group(3))
if line_count == 0:
continue
end_line = start_line + line_count - 1;
lines_by_file.setdefault(filename, []).append([start_line, end_line])
if len(lines_by_file) == 0:
print("No relevant changes found.")
sys.exit(0)
line_filter_json = json.dumps(
[{"name" : name, "lines" : lines_by_file[name]} for name in lines_by_file],
separators = (',', ':'))
quote = "";
if sys.platform == 'win32':
line_filter_json=re.sub(r'"', r'"""', line_filter_json)
else:
quote = "'";
# Run clang-tidy on files containing changes.
command = [args.clang_tidy_binary]
command.append('-line-filter=' + quote + line_filter_json + quote)
if args.fix:
command.append('-fix')
if args.checks != '':
command.append('-checks=' + quote + args.checks + quote)
if args.quiet:
command.append('-quiet')
if args.build_path is not None:
command.append('-p=%s' % args.build_path)
command.extend(lines_by_file.keys())
for arg in args.extra_arg:
command.append('-extra-arg=%s' % arg)
for arg in args.extra_arg_before:
command.append('-extra-arg-before=%s' % arg)
command.extend(clang_tidy_args)
sys.exit(subprocess.call(' '.join(command), shell=True))
if __name__ == '__main__':
main()
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -e
if ! git rev-list $TRAVIS_COMMIT_RANGE 2>1 >/dev/null; then
echo "\$TRAVIS_COMMIT_RANGE ($TRAVIS_COMMIT_RANGE) is not valid for this build (probably caused by a rebase)."
exit 0
fi
cd "$TRAVIS_BUILD_DIR"
echo "Running clang-tidy on changed files"
git diff -U0 --no-color $TRAVIS_COMMIT_RANGE | \
$TRAVIS_BUILD_DIR/ci/travis/clang-tidy-diff.py -path "$TRAVIS_BUILD_DIR/build" -p1 \
-regex 'code/.*$|freespace2/.*$|qtfred/.*$|test/src/.*$|build/.*$|tools/.*' \
-clang-tidy-binary /usr/bin/clang-tidy-4.0 2>/dev/null | \
tee clang-tidy-output.txt
if [[ -n $(grep "warning: " clang-tidy-output.txt) ]] || [[ -n $(grep "error: " clang-tidy-output.txt) ]]; then
echo "Errors or warnings were detected in the clang-tidy output!"
exit 1
else
echo -e "\033[1;32m\xE2\x9C\x93 passed:\033[0m clang-tidy test succeeded";
fi
+1 -1
View File
@@ -26,8 +26,8 @@ if [[ ! "$(curl -V)" == *"sftp"* ]]; then
cd ..
dpkg -l | grep curl
ls -al
sudo dpkg -i curl*.deb
sudo dpkg -i libcurl3*.deb
sudo dpkg -i curl*.deb
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew install curl --with-libssh2
export PATH="/usr/local/opt/curl/bin:$PATH"
+5 -7
View File
@@ -4,16 +4,14 @@ set -ex
FILENAME=
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
if [ ! -d "$HOME/cmake/bin" ]; then
if [ ! -d "$HOME/cmake-3.8/bin" ]; then
# If the cache does not currently contain CMake then download and install it
FILENAME=cmake-3.4.3-Linux-x86_64
mkdir -p $HOME/cmake-3.8/
mkdir -p $HOME/cmake/
wget -O /tmp/cmake.tar.gz --no-check-certificate https://www.cmake.org/files/v3.4/$FILENAME.tar.gz
tar -xzf /tmp/cmake.tar.gz -C $HOME/cmake/ --strip-components=1
wget -O /tmp/cmake.tar.gz --no-check-certificate https://cmake.org/files/v3.8/cmake-3.8.2-Linux-x86_64.tar.gz
tar -xzf /tmp/cmake.tar.gz -C $HOME/cmake-3.8/ --strip-components=1
fi
export PATH=$HOME/cmake/bin:$PATH
export PATH=$HOME/cmake-3.8/bin:$PATH
cd $HOME
-5
View File
@@ -4,11 +4,6 @@ set -ex
mkdir -p /tmp/builds
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
if [ "$RELEASE_BUILD" = true ]; then
PARENT_DIR="$(basename $PWD)"
(cd .. && tar cvf /tmp/builds/$PACKAGE_NAME-source-Unix.tar.gz --exclude-vcs "$PARENT_DIR")
fi
cd build
for config in $BUILD_CONFIGS
do
+1 -1
View File
@@ -5,7 +5,7 @@ set -e
cd build
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
ninja all
ninja -k 20 all
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
+1 -1
View File
@@ -1,4 +1,4 @@
#!/bin/sh
HERE=$(dirname $(readlink -f "${0}"))
export LD_LIBRARY_PATH="${HERE}"/lib:$PATH
export LD_LIBRARY_PATH="${HERE}"/lib:"$LD_LIBRARY_PATH"
"${HERE}"/bin/$<TARGET_FILE_NAME:Freespace2> $@
+3
View File
@@ -1,6 +1,9 @@
include(WriteCompilerDetectionHeader)
set(CMAKE_CXX_STANDARD_REQUIRED 11)
set(CMAKE_CXX_STANDARD 11)
set(REQUIRED_CXX_FEATURES cxx_rvalue_references cxx_nullptr)
get_property(CMAKE_CXX_KNOWN_FEATURES GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
+37
View File
@@ -0,0 +1,37 @@
option(ENABLE_CLANG_TIDY "Enable source code checking using clang-tidy" OFF)
find_program(
CLANG_TIDY_EXE
NAMES "clang-tidy"
DOC "Path to clang-tidy executable"
)
function(enable_clang_tidy target)
# Not enabled in this configuration
endfunction()
if(NOT ENABLE_CLANG_TIDY)
return()
endif()
if(NOT EXISTS "${CLANG_TIDY_EXE}")
message(SEND_ERROR "clang-tidy: Could not find clang-tidy executable (value of variable is \"${CLANG_TIDY_EXE}\".")
return()
endif()
if(CMAKE_VERSION VERSION_LESS "3.6.0")
message(SEND_ERROR "Clang-tidy support requires CMake 3.6")
return()
endif()
message(STATUS "clang-tidy: Using \"${CLANG_TIDY_EXE}\"")
function(enable_clang_tidy target)
SET(TIDY_OPTIONS "${CLANG_TIDY_EXE}")
if(FSO_FATAL_WARNINGS)
set(TIDY_OPTIONS "${TIDY_OPTIONS};-warnings-as-errors=*")
endif()
set_target_properties(${target} PROPERTIES CXX_CLANG_TIDY "${TIDY_OPTIONS}")
endfunction()
+8 -1
View File
@@ -27,6 +27,7 @@ int main( int argc, char* argv[] )
int SSE = false;
int SSE2 = false;
int AVX = false;
int AVX2 = false;
int info[4];
cpuid(info, 0);
@@ -40,8 +41,14 @@ int main( int argc, char* argv[] )
AVX = (info[2] & ((int)1 << 28)) != 0;
}
if (nIds >= 7){
cpuid(info,0x00000007);
AVX2 = (info[1] & ((int)1 << 5)) != 0;
}
if(AVX)
if (AVX2)
std::cout << "AVX2";
else if(AVX)
std::cout << "AVX";
else if(SSE2)
std::cout << "SSE2";
Submodule cmake/external/cotire deleted from 40a46bf2fb.
+4054
View File
File diff suppressed because it is too large. Load diff
+9
View File
@@ -0,0 +1,9 @@
#ifndef __FREDRC_H
#define __FREDRC_H
#define ABOUT_LINE_1 "FRED2_OPEN - FreeSpace Editor, Version @FSO_PRODUCT_VERSION_STRING@ OpenGL"
#define MAINFRAME_CONTENTS "FRED2_OPEN @FSO_PRODUCT_VERSION_STRING@ - FreeSpace2 Mission Editor\nUntitled\nFRED2\nFreeSpace2 Missions (*.fs2)\n.fs2\nFreeSpace2Mission\nFreeSpace2 Mission"
#endif // __FREDRC_H
+3 -1
View File
@@ -1,5 +1,7 @@
include(platformChecks)
include(Cxx11)
include(platformChecks)
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/project.h.in ${GENERATED_SOURCE_DIR}/project.h)
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/fred_rc.h.in ${GENERATED_SOURCE_DIR}/fred_rc.h)
+8 -2
View File
@@ -15,9 +15,9 @@ CHECK_INCLUDE_FILE_CXX("cxxabi.h" HAVE_CXXAPI_H)
CHECK_TYPE_SIZE("max_align_t" MAX_ALIGN_T)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(CMAKE_REQUIRED_FLAGS "-std=c++11") # required for g++ <= 5
endif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
endif()
set(CMAKE_EXTRA_INCLUDE_FILES "cstddef")
CHECK_TYPE_SIZE("std::max_align_t" STD_MAX_ALIGN_T LANGUAGE CXX)
@@ -25,6 +25,9 @@ set(CMAKE_EXTRA_INCLUDE_FILES "type_traits")
CHECK_TYPE_SIZE("std::is_trivially_copyable<int>" STD_IS_TRIVIALLY_COPYABLE LANGUAGE CXX)
set(CMAKE_EXTRA_INCLUDE_FILES)
CHECK_TYPE_SIZE("char32_t" CHAR32_T LANGUAGE CXX)
CHECK_TYPE_SIZE("U'b'" UNICODE_CHAR_LITERAL LANGUAGE CXX)
set(CMAKE_REQUIRED_FLAGS)
@@ -38,5 +41,8 @@ CHECK_FUNCTION_EXISTS(strlwr HAVE_STRLWR)
CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H)
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
check_symbol_exists(_snprintf "stdio.h" HAVE__SNPRINTF)
set(PLATFORM_CHECK_HEADER "${GENERATED_SOURCE_DIR}/platformChecks.h")
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/platformChecks.h.in "${PLATFORM_CHECK_HEADER}")
+7
View File
@@ -9,6 +9,7 @@
#cmakedefine HAVE_STD_MAX_ALIGN_T
#cmakedefine HAVE_STD_IS_TRIVIALLY_COPYABLE
#cmakedefine HAVE_STD_IS_TRIVIALLY_COPYABLE_ARRAY
#cmakedefine01 IS_64BIT
@@ -21,4 +22,10 @@
#cmakedefine01 HAVE_STRINGS_H
#cmakedefine01 HAVE_CHAR32_T
#cmakedefine01 HAVE_UNICODE_CHAR_LITERAL
#cmakedefine01 HAVE_SNPRINTF
#cmakedefine01 HAVE__SNPRINTF
#endif // __PLATFORM_CHECKS_H__
+1 -3
View File
@@ -73,14 +73,12 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-char-subscripts")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-parameter")
check_cxx_compiler_flag(-Wshift-negative-value SUPPORTS_SHIFT_NEGATIVE_VALUE)
if(SUPPORTS_SHIFT_NEGATIVE_VALUE)
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-shift-negative-value")
endif()
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable")
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-parameter")
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
+3 -4
View File
@@ -85,9 +85,7 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-deprecated -Wno-char-subscripts")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-parameter")
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered")
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
@@ -105,6 +103,7 @@ set(CMAKE_EXE_LINKER_FLAGS "")
IF (MINGW)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++ -Wl,--enable-auto-import")
target_compile_definitions(compiler INTERFACE __USE_MINGW_ANSI_STDIO=1)
ENDIF(MINGW)
if (SANITIZE_FLAGS)
@@ -131,4 +130,4 @@ if (FSO_FATAL_WARNINGS)
endif()
# Always define this to make sure that the fixed width format macros are available
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS)
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS=1)
+3 -1
View File
@@ -33,7 +33,9 @@ set(WARNING_FLAGS
/wd4311 # Disables warnings about casting pointer types to ints. The funny thing is these warnings can't be resolved, just disabled... - m!m
/wd4302 # Same as above - m!m
/wd4366 # The result of the unary '&' operator may be unaligned - m!m
/wd4592 # "symbol will be dynamically initialized" is being generated by a compiler bug, see https://stackoverflow.com/a/34027257 for an explanation - m!m
$<$<CONFIG:Release>:/wd4101> # In release mode there are unreferenced variables because debug needs them
/wd4995 # "'vsprintf': name was marked as #pragma deprecated" is being caused by our custom definition of vsprintf. I have no idea what causes this or how to fix it - m!m
)
target_compile_options(compiler INTERFACE ${WARNING_FLAGS})
@@ -88,7 +90,7 @@ ENDIF(MSVC_USE_RUNTIME_DLL)
INCLUDE(MSVCMultipleProcessCompile)
# Visual Studio supports compiling for multiple vector instruction sets
SET(POSSIBLE_INSTUCTION_SETS "" SSE SSE2 AVX)
SET(POSSIBLE_INSTUCTION_SETS "" SSE SSE2 AVX AVX2)
if (NOT DEFINED MSVC_SIMD_INSTRUCTIONS)
detect_simd_instructions(MSVC_DETECTED_SIMD_INSTRUCTIONS)
+34 -4
View File
@@ -10,7 +10,7 @@ FUNCTION(ADD_IMPORTED_LIB NAME INCLUDES LIBS)
target_link_libraries(${NAME} INTERFACE "${LIBS}")
target_include_directories(${NAME} INTERFACE "${INCLUDES}")
target_include_directories(${NAME} SYSTEM INTERFACE "${INCLUDES}")
ENDFUNCTION(ADD_IMPORTED_LIB)
MACRO(PKG_CONFIG_LIB_RESOLVE NAME OUTVAR)
@@ -141,10 +141,12 @@ macro(set_if_not_defined VAR VALUE)
endmacro(set_if_not_defined)
macro(configure_cotire target)
# Disable unity build as it doesn't work well for us
set_target_properties(${target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
if(ENABLE_COTIRE)
# Disable unity build as it doesn't work well for us
set_target_properties(${target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
cotire(${target})
cotire(${target})
endif()
endmacro(configure_cotire)
macro(add_target_copy_files)
@@ -195,3 +197,31 @@ function(suppress_warnings _target)
target_compile_options(${_target} PRIVATE "-w")
endif()
endfunction(suppress_warnings)
function(list_target_dependencies _target _out_var)
set(out_list)
set(work_libs ${_target})
list(LENGTH work_libs libs_length)
while(libs_length GREATER 0)
list(GET work_libs 0 current)
list(REMOVE_AT work_libs 0)
list(APPEND out_list ${current})
get_target_property(current_libs ${current} INTERFACE_LINK_LIBRARIES)
if(current_libs)
foreach(lib ${current_libs})
if (TARGET ${lib})
list(APPEND work_libs ${lib})
endif (TARGET ${lib})
endforeach(lib)
endif(current_libs)
list(LENGTH work_libs libs_length)
endwhile(libs_length GREATER 0)
list(REMOVE_DUPLICATES out_list)
set(${_out_var} ${out_list} PARENT_SCOPE)
endfunction(list_target_dependencies)
+2 -2
View File
@@ -7,8 +7,8 @@ if (EXISTS "${PROJECT_SOURCE_DIR}/version_override.cmake")
endif()
set_if_not_defined(FSO_VERSION_MAJOR 3)
set_if_not_defined(FSO_VERSION_MINOR 7)
set_if_not_defined(FSO_VERSION_BUILD 5)
set_if_not_defined(FSO_VERSION_MINOR 8)
set_if_not_defined(FSO_VERSION_BUILD 1)
# A numeric revision e.g. the CI build number
set_if_not_defined(FSO_VERSION_REVISION 0)
+20 -4
View File
@@ -21,7 +21,7 @@ TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${GENERATED_SOURCE_DIR}/code)
target_link_libraries(code PUBLIC OpenGL)
TARGET_LINK_LIBRARIES(code PUBLIC ${OPENAL_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC openal)
TARGET_LINK_LIBRARIES(code PUBLIC ${LUA_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC ${PNG_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC ${JPEG_LIBS})
@@ -30,11 +30,15 @@ TARGET_LINK_LIBRARIES(code PUBLIC sdl2)
TARGET_LINK_LIBRARIES(code PUBLIC ffmpeg)
TARGET_LINK_LIBRARIES(code PUBLIC utfcpp)
TARGET_LINK_LIBRARIES(code PUBLIC platform)
TARGET_LINK_LIBRARIES(code PUBLIC compiler)
target_link_libraries(code PUBLIC md5)
enable_clang_tidy(code)
IF (FSO_USE_SPEECH)
find_package(Speech REQUIRED)
target_link_libraries(code PUBLIC speech)
@@ -53,13 +57,25 @@ IF(FSO_BUILD_TOOLS)
ADD_SUBDIRECTORY(cfileextractor)
ENDIF(FSO_BUILD_TOOLS)
set_target_properties(code PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "prefix_header.h")
if (ENABLE_COTIRE)
set_target_properties(code PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h")
else()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:/FI ${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
ELSE()
MESSAGE("Unknown compiler for global includes. This will probably break the build.")
ENDIF()
endif()
include(util)
configure_cotire(code)
include(../cmake/Cxx11.cmake)
# Ensure that Xcode generates debug symbols on macOS for Debug builds
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES")
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=Debug] "NO")
+2 -1
View File
@@ -498,7 +498,8 @@ void parse_ai_profiles_tbl(const char *filename)
}
// find next valid option
skip_to_start_of_string_either("$", "#");
if (!skip_to_start_of_string_either("$", "#"))
break;
saved_Mp = Mp;
}
}
+4 -4
View File
@@ -714,7 +714,7 @@ extern void maybe_cheat_fire_synaptic(object *objp, ai_info *aip);
// dist_to_enemy => distance (in m) to attack point on current target
// dot_to_enemy => dot product between fvec of Pl_objp and vector from Pl_objp to attack point
//
void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *firing_pos, vec3d *enemy_pos, vec3d *enemy_vel)
void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d * /*firing_pos*/, vec3d * /*enemy_pos*/, vec3d * /*enemy_vel*/)
{
ai_info *aip;
ship_weapon *swp;
@@ -1153,7 +1153,7 @@ void ai_big_chase()
}
}
void ai_big_ship(object *objp)
void ai_big_ship(object * /*objp*/)
{
// do nothing
}
@@ -1228,7 +1228,7 @@ void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_t
// check to see if Pl_objp has gotten too close to attacking point.. if so, break off by entering
// AIS_STRAFE_RETREAT
int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos)
int ai_big_strafe_maybe_retreat(float /*dist*/, vec3d *target_pos)
{
ai_info *aip;
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
@@ -1704,7 +1704,7 @@ void ai_big_strafe()
//
// Check if weapon_objnum was fired by Pl_objp's target, and whether Pl_objp's target is a big ship, if
// so, enter AIM_STRAFE
int ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int consider_target_only)
int ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int /*consider_target_only*/)
{
ai_info *aip;
ship_info *sip;
+28 -20
View File
@@ -68,7 +68,7 @@
#include "weapon/swarm.h"
#include "weapon/weapon.h"
#include <map>
#include <limits.h>
#include <climits>
#ifdef _MSC_VER
@@ -1132,7 +1132,7 @@ void ai_update_danger_weapon(int attacked_objnum, int weapon_objnum)
// If rvec != NULL, use it to match bank by calling vm_matrix_interpolate.
// (rvec defaults to NULL)
void ai_turn_towards_vector(vec3d *dest, object *objp, float frametime, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec, int sexp_flags)
void ai_turn_towards_vector(vec3d *dest, object *objp, float /*frametime*/, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec, int sexp_flags)
{
matrix curr_orient;
vec3d vel_in, vel_out, desired_fvec, src;
@@ -3453,7 +3453,7 @@ float compute_time_to_enemy(float dist_to_enemy, object *pobjp)
// incorrect, not having been divided by distance.
// If *dot is > 0.0f, then tts is computed. This is the time it will take object
// *objp to get to *pos, assuming it moves right at it.
void fds_aux(float *dot, float *tts, vec3d *pos, float dtime, object *objp)
void fds_aux(float *dot, float *tts, vec3d *pos, float /*dtime*/, object *objp)
{
vec3d v2s;
@@ -5234,7 +5234,7 @@ vec3d G_predicted_pos, G_fire_pos;
// Else
// Select Any ol' weapon.
// Returns primary_bank index.
int ai_select_primary_weapon_OLD(object *objp, object *other_objp, Weapon::Info_Flags flags)
int ai_select_primary_weapon_OLD(object *objp, object * /*other_objp*/, Weapon::Info_Flags flags)
{
ship *shipp = &Ships[objp->instance];
ship_weapon *swp = &shipp->weapons;
@@ -6052,7 +6052,7 @@ int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip)
// Fire a secondary weapon.
// Maybe choose to fire a different one.
// priority1 and priority2 are optional parameters with defaults = -1
int ai_fire_secondary_weapon(object *objp, int priority1, int priority2)
int ai_fire_secondary_weapon(object *objp, int /*priority1*/, int /*priority2*/)
{
ship_weapon *swp;
ship *shipp;
@@ -6546,7 +6546,7 @@ void ai_chase_ct()
/**
* ATTACK submode handler for chase mode.
*/
void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, float dist_to_enemy)
void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, float /*dist_to_enemy*/)
{
vec3d _pep;
float dot_to_enemy, dot_from_enemy;
@@ -6755,7 +6755,7 @@ void attack_set_accel(ai_info *aip, ship_info *sip, float dist_to_enemy, float d
// Pl_objp (aip) tries to get behind En_objp.
// New on 2/21/98: If this ship can move backwards and slide, maybe do that to get behind.
void get_behind_ship(ai_info *aip, ship_info *sip, float dist_to_enemy)
void get_behind_ship(ai_info *aip, ship_info *sip, float /*dist_to_enemy*/)
{
vec3d new_pos;
float dot;
@@ -10395,6 +10395,7 @@ void ai_get_dock_goal_indexes(object *objp, ai_info *aip, ai_goal *aigp, object
case AIS_DOCK_2:
case AIS_DOCK_3:
Warning(LOCATION, "Normally dock indexes should be calculated for only AIS_DOCK_0 and AIS_UNDOCK_0. Trace out and debug.");
FALLTHROUGH;
case AIS_DOCK_0:
{
// get them from the active goal
@@ -10412,6 +10413,7 @@ void ai_get_dock_goal_indexes(object *objp, ai_info *aip, ai_goal *aigp, object
case AIS_UNDOCK_1:
case AIS_UNDOCK_2:
Warning(LOCATION, "Normally dock indexes should be calculated for only AIS_DOCK_0 and AIS_UNDOCK_0. Trace out and debug.");
FALLTHROUGH;
case AIS_UNDOCK_0:
{
// get them from the guy I'm docked to
@@ -10478,9 +10480,11 @@ void ai_cleanup_dock_mode_subjective(object *objp)
case AIS_UNDOCK_0:
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKED, docker_index, -1);
model_anim_start_type(goal_shipp, TRIGGER_TYPE_DOCKED, dockee_index, -1);
FALLTHROUGH;
case AIS_UNDOCK_1:
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKING_STAGE_3, docker_index, -1);
model_anim_start_type(goal_shipp, TRIGGER_TYPE_DOCKING_STAGE_3, dockee_index, -1);
FALLTHROUGH;
case AIS_UNDOCK_2:
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKING_STAGE_2, docker_index, -1);
model_anim_start_type(goal_shipp, TRIGGER_TYPE_DOCKING_STAGE_2, dockee_index, -1);
@@ -10490,9 +10494,11 @@ void ai_cleanup_dock_mode_subjective(object *objp)
case AIS_DOCK_4A:
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKED, docker_index, -1);
model_anim_start_type(goal_shipp, TRIGGER_TYPE_DOCKED, dockee_index, -1);
FALLTHROUGH;
case AIS_DOCK_3:
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKING_STAGE_3, docker_index, -1);
model_anim_start_type(goal_shipp, TRIGGER_TYPE_DOCKING_STAGE_3, dockee_index, -1);
FALLTHROUGH;
case AIS_DOCK_2:
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKING_STAGE_2, docker_index, -1);
model_anim_start_type(goal_shipp, TRIGGER_TYPE_DOCKING_STAGE_2, dockee_index, -1);
@@ -10833,7 +10839,7 @@ void ai_dock()
if (aip->submode == AIS_DOCK_3) {
// Play a ship docking attach sound
snd_play_3d( &Snds[SND_DOCK_ATTACH], &Pl_objp->pos, &View_position );
snd_play_3d( gamesnd_get_game_sound(GameSounds::DOCK_ATTACH), &Pl_objp->pos, &View_position );
// start the dock animation
model_anim_start_type(shipp, TRIGGER_TYPE_DOCKED, docker_index, 1);
@@ -10960,7 +10966,7 @@ void ai_dock()
ai_find_path(Pl_objp, OBJ_INDEX(goal_objp), path_num, 0);
// Play a ship docking detach sound
snd_play_3d( &Snds[SND_DOCK_DETACH], &Pl_objp->pos, &View_position );
snd_play_3d( gamesnd_get_game_sound(GameSounds::DOCK_DETACH), &Pl_objp->pos, &View_position );
aip->submode = AIS_UNDOCK_1;
aip->submode_start_time = Missiontime;
@@ -10980,7 +10986,7 @@ void ai_dock()
// play the depart sound, but only once, since this mode is called multiple times per frame
if ( !(aigp->flags[AI::Goal_Flags::Depart_sound_played]))
{
snd_play_3d( &Snds[SND_DOCK_DEPART], &Pl_objp->pos, &View_position );
snd_play_3d( gamesnd_get_game_sound(GameSounds::DOCK_DEPART), &Pl_objp->pos, &View_position );
aigp->flags.set(AI::Goal_Flags::Depart_sound_played);
}
@@ -11379,7 +11385,7 @@ float gwlr_1(object *objp, ai_info *aip)
/**
* Compute the largest radius of a ship forming on *objp's wing.
*/
float gwlr_object_1(object *objp, ai_info *aip)
float gwlr_object_1(object *objp, ai_info * /*aip*/)
{
float max_radius;
object *o;
@@ -12185,7 +12191,7 @@ void ai_maybe_launch_cmeasure(object *objp, ai_info *aip)
}
// --------------------------------------------------------------------------
void ai_preprocess_ignore_objnum(object *objp, ai_info *aip)
void ai_preprocess_ignore_objnum(object * /*objp*/, ai_info *aip)
{
if (aip->ai_flags[AI::AI_Flags::Temporary_ignore])
{
@@ -12376,6 +12382,7 @@ void ai_maybe_evade_locked_missile(object *objp, ai_info *aip)
case AIM_DOCK: // Ships in dock mode can evade iif they are not currently repairing or docked.
if (object_is_docked(objp) || (aip->ai_flags[AI::AI_Flags::Repairing, AI::AI_Flags::Being_repaired]))
break;
FALLTHROUGH;
case AIM_GUARD:
// If in guard mode and far away from guard object, don't pursue guy that hit me.
if ((aip->guard_objnum != -1) && (aip->guard_signature == Objects[aip->guard_objnum].signature)) {
@@ -12383,6 +12390,7 @@ void ai_maybe_evade_locked_missile(object *objp, ai_info *aip)
return;
}
}
FALLTHROUGH;
case AIM_EVADE:
case AIM_GET_BEHIND:
case AIM_STAY_NEAR:
@@ -13016,7 +13024,7 @@ void ai_execute_behavior(ai_info *aip)
ship *shipp = &Ships[aip->shipnum];
ship_info *sip = &Ship_info[shipp->ship_info_index];
if (strnicmp(shipp->ship_name, INSTRUCTOR_SHIP_NAME, strlen(INSTRUCTOR_SHIP_NAME))) {
if (strnicmp(shipp->ship_name, INSTRUCTOR_SHIP_NAME, strlen(INSTRUCTOR_SHIP_NAME)) != 0) {
if (sip->is_big_or_huge()) {
aip->mode = AIM_NONE;
} else {
@@ -13433,7 +13441,7 @@ void ai_warp_out(object *objp)
// Return object index of weapon that could produce a shockwave that should be known about to *objp.
// Return nearest one.
int ai_find_shockwave_weapon(object *objp, ai_info *aip)
int ai_find_shockwave_weapon(object *objp, ai_info * /*aip*/)
{
missile_obj *mo;
float nearest_dist = 999999.9f;
@@ -13499,7 +13507,7 @@ void ai_announce_ship_dying(object *dying_objp)
// Return object index of weapon that could produce a shockwave that should be known about to *objp.
// Return nearest one.
int ai_find_shockwave_ship(object *objp, ai_info *aip)
int ai_find_shockwave_ship(object *objp, ai_info * /*aip*/)
{
ship_obj *so;
float nearest_dist = 999999.9f;
@@ -14150,7 +14158,7 @@ void ai_frame(int objnum)
}
}
void ai_control_info_check( object *obj, ai_info *aip )
void ai_control_info_check( object * /*obj*/, ai_info *aip )
{
if(aip->ai_override_flags.none_set())
return;
@@ -14789,7 +14797,7 @@ int firing_aspect_seeking_bomb(object *objp)
// *objp collided with big ship *big_objp at global point *collide_pos
// Make it fly away from the collision point.
// collision_normal is NULL, when a collision is imminent and we just want to bug out.
void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collide_pos, vec3d *collision_normal)
void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d * /*collide_pos*/, vec3d *collision_normal)
{
ai_info *aip;
@@ -14880,7 +14888,7 @@ void ai_update_lethality(object *pship_obj, object *other_obj, float damage)
/**
* Object *objp_ship was hit by either weapon *objp_weapon or collided into by ship hit_objp at point *hitpos.
*/
void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_quadrant, vec3d *hit_normal)
void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int /*shield_quadrant*/, vec3d *hit_normal)
{
int hitter_objnum = -2;
object *objp_hitter = NULL;
@@ -15182,7 +15190,7 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_
// the parameter 'method' is used to tell is this ship was destroyed or it departed normally.
// This function will get called in either case, and there are things that should be done if
// the ship actually gets destroyed which shouldn't get done if it departed.
void ai_ship_destroy(int shipnum, Ship::Exit_Flags method)
void ai_ship_destroy(int shipnum, Ship::Exit_Flags /*method*/)
{
int objnum;
object *other_objp;
@@ -15502,7 +15510,7 @@ int ai_return_path_num_from_dockbay(object *dockee_objp, int dockbay_index)
/**
* Actually go ahead and fire the synaptics.
*/
void cheat_fire_synaptic(object *objp, ship *shipp, ai_info *aip)
void cheat_fire_synaptic(object *objp, ship *shipp, ai_info * /*aip*/)
{
ship_weapon *swp;
swp = &shipp->weapons;
+3 -3
View File
@@ -414,7 +414,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
if ( purge_ai_mode == AI_GOAL_CHASE_SHIP_CLASS ) {
// if the target of the purge goal is the same class of ship we are concerned about, then we have a match;
// if it is not, then we can continue (see standard ship check below)
if ( stricmp(purge_goal->target_name, Ship_info[Ships[ship_index].ship_info_index].name) )
if ( stricmp(purge_goal->target_name, Ship_info[Ships[ship_index].ship_info_index].name) != 0 )
continue;
}
// standard goals operating on either wings or ships
@@ -426,7 +426,7 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
// don't match, we can continue; if the wing is valid, don't process if the wing numbers
// are different.
if ( purge_wing == -1 ) {
if ( stricmp(purge_goal->target_name, name ) )
if ( stricmp(purge_goal->target_name, name ) != 0 )
continue;
} else if ( purge_wing != wingnum )
continue;
@@ -1263,7 +1263,7 @@ void ai_add_wing_goal_sexp(int sexp, int type, int wingnum)
// this name can be a shipname or a wingname)
// docker_point and dockee_point are used for the AI_GOAL_DOCK command to tell two ships where to dock
// immediate means to process this order right away
void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate )
void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*docker_point*/, int /*dockee_point*/, int immediate )
{
int gindex;
ai_goal *aigp;
+6 -6
View File
@@ -24,7 +24,7 @@
#include "weapon/swarm.h"
#include "weapon/weapon.h"
#include <limits.h>
#include <climits>
// How close a turret has to be point at its target before it
@@ -243,7 +243,7 @@ int bomb_headed_towards_ship(object *bomb_objp, object *ship_objp)
* @note All non-negative return values are expressed in what I like to call "widx"s.
* @return -1 if unable to find a weapon for the target at all.
*/
int turret_select_best_weapon(ship_subsys *turret, object *target)
int turret_select_best_weapon(ship_subsys *turret, object * /*target*/)
{
//TODO: Fill this out with extraodinary gun-picking algorithms
if(turret->weapons.num_primary_banks > 0)
@@ -2048,10 +2048,10 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
}
}
if ( wip->launch_snd != -1 ) {
if ( wip->launch_snd.isValid() ) {
// Don't play turret firing sound if turret sits on player ship... it gets annoying.
if ( parent_objnum != OBJ_INDEX(Player_obj) || (turret->flags[Ship::Subsystem_Flags::Play_sound_for_player]) ) {
snd_play_3d( &Snds[wip->launch_snd], turret_pos, &View_position );
snd_play_3d( gamesnd_get_game_sound(wip->launch_snd), turret_pos, &View_position );
}
}
}
@@ -2135,10 +2135,10 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
}
// maybe sound
if ( Weapon_info[tsi->weapon_class].launch_snd != -1 ) {
if ( Weapon_info[tsi->weapon_class].launch_snd.isValid() ) {
// Don't play turret firing sound if turret sits on player ship... it gets annoying.
if ( tsi->parent_objnum != OBJ_INDEX(Player_obj) ) {
snd_play_3d( &Snds[Weapon_info[tsi->weapon_class].launch_snd], &turret_pos, &View_position );
snd_play_3d( gamesnd_get_game_sound(Weapon_info[tsi->weapon_class].launch_snd), &turret_pos, &View_position );
}
}
+2 -2
View File
@@ -274,9 +274,9 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
percent_through = instance->time_elapsed / time;
if(instance->direction == ANIM_DIRECT_FORWARD)
new_frame_num = instance->start_at - 1 + fl2i(percent_through * n_frames + 0.5f);
new_frame_num = instance->start_at - 1 + (int) lround(percent_through * n_frames);
else
new_frame_num = instance->start_at - 1 - fl2i(percent_through * n_frames + 0.5f);
new_frame_num = instance->start_at - 1 - (int) lround(percent_through * n_frames);
frame_save = instance->frame_num;
+16 -2
View File
@@ -512,7 +512,14 @@ int unpack_pixel(anim_instance *ai, ubyte *data, ubyte pix, int aabitmap, int bp
bit_16 = (ushort)pix;
break;
case 8:
bit_8 = pix;
// 8 bit-per-pixel aa bitmaps are a bit special since they only use value in the range [0, 15] where 15 wraps
// around back to 0. Since the rest of the code expects the value to be in the range [0, 255] the pixel value
// needs to be adjusted here. By muliplying the value with 17 the original range [0, 15] is mapped to [0, 255]
if (pix >= 15) {
bit_8 = 0;
} else {
bit_8 = (ubyte)(pix * 17);
}
break;
default:
Int3();
@@ -596,7 +603,14 @@ int unpack_pixel_count(anim_instance *ai, ubyte *data, ubyte pix, int count = 0,
bit_16 = (ushort)pix;
break;
case 8 :
bit_8 = pix;
// 8 bit-per-pixel aa bitmaps are a bit special since they only use value in the range [0, 15] where 15 wraps
// around back to 0. Since the rest of the code expects the value to be in the range [0, 255] the pixel value
// needs to be adjusted here. By muliplying the value with 17 the original range [0, 15] is mapped to [0, 255]
if (pix >= 15) {
bit_8 = 0;
} else {
bit_8 = (ubyte)(pix * 17);
}
break;
default :
Int3();
+40 -102
View File
@@ -76,7 +76,7 @@ float Asteroid_icon_closeup_zoom;
/**
* Force updating of pair stuff for asteroid *objp.
*/
void asteroid_update_collide(object *objp)
static void asteroid_update_collide(object *objp)
{
// Asteroid has wrapped, update collide objnum and flags
Asteroids[objp->instance].collide_objnum = -1;
@@ -87,7 +87,7 @@ void asteroid_update_collide(object *objp)
/**
* Clear out the ::Asteroid_obj_list
*/
void asteroid_obj_list_init()
static void asteroid_obj_list_init()
{
int i;
@@ -101,7 +101,7 @@ void asteroid_obj_list_init()
* Add a node from the Asteroid_obj_list.
* Only called from ::weapon_create()
*/
int asteroid_obj_list_add(int objnum)
static int asteroid_obj_list_add(int objnum)
{
int index;
@@ -123,7 +123,7 @@ int asteroid_obj_list_add(int objnum)
* Remove a node from the Asteroid_obj_list.
* Only called from ::weapon_delete()
*/
void asteroid_obj_list_remove(object * obj)
static void asteroid_obj_list_remove(object * obj)
{
int index = obj->instance;
@@ -138,7 +138,7 @@ void asteroid_obj_list_remove(object * obj)
/**
* Prevent speed from getting too huge so it's hard to catch up to an asteroid.
*/
float asteroid_cap_speed(int asteroid_info_index, float speed)
static float asteroid_cap_speed(int asteroid_info_index, float speed)
{
float max, double_max;
@@ -164,7 +164,7 @@ float asteroid_cap_speed(int asteroid_info_index, float speed)
* Sum together the following: 1 inside x, 2 inside y, 4 inside z
* inside only when sum = 7
*/
int asteroid_in_inner_bound_with_axes(asteroid_field *asfieldp, vec3d *pos, float delta)
static int asteroid_in_inner_bound_with_axes(asteroid_field *asfieldp, vec3d *pos, float delta)
{
Assert(asfieldp->has_inner_bound);
@@ -188,7 +188,7 @@ int asteroid_in_inner_bound_with_axes(asteroid_field *asfieldp, vec3d *pos, floa
* Check if asteroid is within inner bound
* @return 0 if not inside or no inner bound, 1 if inside inner bound
*/
int asteroid_in_inner_bound(asteroid_field *asfieldp, vec3d *pos, float delta) {
static int asteroid_in_inner_bound(asteroid_field *asfieldp, vec3d *pos, float delta) {
if (!asfieldp->has_inner_bound) {
return 0;
@@ -202,7 +202,7 @@ int asteroid_in_inner_bound(asteroid_field *asfieldp, vec3d *pos, float delta) {
*
* Moves to the other side of the inner box a distance delta from edge of box
*/
void inner_bound_pos_fixup(asteroid_field *asfieldp, vec3d *pos)
static void inner_bound_pos_fixup(asteroid_field *asfieldp, vec3d *pos)
{
if (!asteroid_in_inner_bound(asfieldp, pos, 0)) {
return;
@@ -446,7 +446,7 @@ void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec)
/**
* Load in an asteroid model
*/
void asteroid_load(int asteroid_info_index, int asteroid_subtype)
static void asteroid_load(int asteroid_info_index, int asteroid_subtype)
{
int i;
asteroid_info *asip;
@@ -487,26 +487,12 @@ void asteroid_load(int asteroid_info_index, int asteroid_subtype)
}
}
/**
* Randomly choose a debris model within the current group
*/
int get_debris_from_same_group(int index) {
int group_base, group_offset;
group_base = (index / NUM_DEBRIS_SIZES) * NUM_DEBRIS_SIZES;
group_offset = index - group_base;
// group base + offset
// offset is formed by adding 1 or 2 (since 3 in model group) and mapping back in the 0-2 range
return group_base + ((group_offset + rand()%(NUM_DEBRIS_SIZES-1) + 1) % NUM_DEBRIS_SIZES);
}
/**
* Returns a weight that depends on asteroid size.
*
* The weight is then used to determine the frequencty of different sizes of ship debris
*/
int get_debris_weight(int ship_debris_index)
static int get_debris_weight(int ship_debris_index)
{
int size = ship_debris_index % NUM_DEBRIS_SIZES;
switch (size)
@@ -626,7 +612,7 @@ void asteroid_create_all()
}
/**
* Init asteriod system for the level, called from ::game_level_init()
* Init asteroid system for the level, called from ::game_level_init()
*/
void asteroid_level_init()
{
@@ -645,7 +631,7 @@ void asteroid_level_init()
*
* @return !0 if asteroid should be wrapped, 0 otherwise.
*/
int asteroid_should_wrap(object *objp, asteroid_field *asfieldp)
static int asteroid_should_wrap(object *objp, asteroid_field *asfieldp)
{
if ( MULTIPLAYER_CLIENT )
return 0;
@@ -690,7 +676,7 @@ int asteroid_should_wrap(object *objp, asteroid_field *asfieldp)
/**
* Wrap an asteroid from one end of the asteroid field to the other
*/
void asteroid_wrap_pos(object *objp, asteroid_field *asfieldp)
static void asteroid_wrap_pos(object *objp, asteroid_field *asfieldp)
{
if (objp->pos.xyz.x < asfieldp->min_bound.xyz.x) {
objp->pos.xyz.x = asfieldp->max_bound.xyz.x + (objp->pos.xyz.x - asfieldp->min_bound.xyz.x);
@@ -727,7 +713,7 @@ void asteroid_wrap_pos(object *objp, asteroid_field *asfieldp)
*
* @return !0 if this asteroid is a target for any ship, otherwise return 0
*/
int asteroid_is_targeted(object *objp)
static int asteroid_is_targeted(object *objp)
{
ship_obj *so;
object *ship_objp;
@@ -748,7 +734,7 @@ int asteroid_is_targeted(object *objp)
/**
* Create an asteroid that will hit object *objp in delta_time seconds
*/
void asteroid_aim_at_target(object *objp, object *asteroid_objp, float delta_time)
static void asteroid_aim_at_target(object *objp, object *asteroid_objp, float delta_time)
{
vec3d predicted_center_pos;
vec3d rand_vec;
@@ -776,7 +762,7 @@ void asteroid_aim_at_target(object *objp, object *asteroid_objp, float delta_tim
*
* @param count asteroids already targeted on
*/
void maybe_throw_asteroid(int count)
static void maybe_throw_asteroid(int count)
{
if (!timestamp_elapsed(Next_asteroid_throw)) {
return;
@@ -850,7 +836,7 @@ void asteroid_delete( object * obj )
* See if we should reposition the asteroid.
* Only reposition if oustide the bounding volume and the player isn't looking towards the asteroid.
*/
void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
static void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
{
// passive field does not wrap
if (asfieldp->field_type == FT_PASSIVE) {
@@ -903,7 +889,7 @@ void asteroid_maybe_reposition(object *objp, asteroid_field *asfieldp)
}
}
void lerp(float *goal, float f1, float f2, float scale)
static void lerp(float *goal, float f1, float f2, float scale)
{
*goal = (f2 - f1) * scale + f1;
}
@@ -1207,7 +1193,7 @@ void asteroid_render(object * obj, model_draw_list *scene)
/**
* Create a normalized vector generally in the direction from *hitpos to other_obj->pos
*/
void asc_get_relvec(vec3d *relvec, object *other_obj, vec3d *hitpos)
static void asc_get_relvec(vec3d *relvec, object *other_obj, vec3d *hitpos)
{
vec3d tvec, rand_vec;
int count = 0;
@@ -1229,7 +1215,7 @@ void asc_get_relvec(vec3d *relvec, object *other_obj, vec3d *hitpos)
/**
* Return multiplier on asteroid radius for fireball
*/
float asteroid_get_fireball_scale_multiplier(int num)
static float asteroid_get_fireball_scale_multiplier(int num)
{
if (Asteroids[num].flags & AF_USED) {
asteroid_info *asip = &Asteroid_info[Asteroids[num].asteroid_type];
@@ -1258,7 +1244,7 @@ float asteroid_get_fireball_scale_multiplier(int num)
* Create asteroid explosion
* @return expected time for explosion anim to last, in seconds
*/
float asteroid_create_explosion(object *objp)
static float asteroid_create_explosion(object *objp)
{
int fireball_objnum;
float explosion_life, fireball_scale_multiplier;
@@ -1290,37 +1276,37 @@ float asteroid_create_explosion(object *objp)
/**
* Play sound when asteroid explodes
*/
void asteriod_explode_sound(object *objp, int type, int play_loud)
static void asteroid_explode_sound(object *objp, int type, int play_loud)
{
int sound_index = -1;
gamesnd_id sound_index;
float range_factor = 1.0f; // how many times sound should traver farther than normal
if (type % NUM_DEBRIS_SIZES <= 1)
{
sound_index = SND_ASTEROID_EXPLODE_SMALL;
sound_index = gamesnd_id(GameSounds::ASTEROID_EXPLODE_SMALL);
range_factor = 5.0;
}
else
{
sound_index = SND_ASTEROID_EXPLODE_LARGE;
sound_index = gamesnd_id(GameSounds::ASTEROID_EXPLODE_LARGE);
range_factor = 10.0f;
}
Assert(sound_index != -1);
Assert(sound_index.isValid());
if ( !play_loud ) {
range_factor = 1.0f;
}
snd_play_3d( &Snds[sound_index], &objp->pos, &Eye_position, objp->radius, NULL, 0, 1.0f, SND_PRIORITY_MUST_PLAY, NULL, range_factor );
snd_play_3d( gamesnd_get_game_sound(sound_index), &objp->pos, &Eye_position, objp->radius, NULL, 0, 1.0f, SND_PRIORITY_MUST_PLAY, NULL, range_factor );
}
/**
* Do the area effect for an asteroid exploding
*
* @param asteroid_objp object pointer to asteriod causing explosion
* @param asteroid_objp object pointer to asteroid causing explosion
*/
void asteroid_do_area_effect(object *asteroid_objp)
static void asteroid_do_area_effect(object *asteroid_objp)
{
object *ship_objp;
float damage, blast;
@@ -1382,7 +1368,7 @@ void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, f
explosion_life = asteroid_create_explosion(pasteroid_obj);
asteriod_explode_sound(pasteroid_obj, asp->asteroid_type, play_loud_collision);
asteroid_explode_sound(pasteroid_obj, asp->asteroid_type, play_loud_collision);
asteroid_do_area_effect(pasteroid_obj);
asp->final_death_time = timestamp( fl2i(explosion_life*1000.0f)/5 ); // Wait till 30% of vclip time before breaking the asteroid up.
@@ -1432,35 +1418,6 @@ void asteroid_level_close()
DCF_BOOL2(asteroids, Asteroids_enabled, "enables or disables asteroids", "Usage: asteroids [bool]\nTurns asteroid system on/off. If nothing passed, then toggles it.\n");
void hud_target_asteroid()
{
int i;
int start_index = 0, end_index = MAX_ASTEROIDS;
if (Player_ai->target_objnum != -1) {
if (Objects[Player_ai->target_objnum].type == OBJ_ASTEROID) {
start_index = Objects[Player_ai->target_objnum].instance+1;
end_index = start_index-1;
if (end_index < 0)
end_index = MAX_ASTEROIDS;
}
}
i = start_index;
while (i != end_index) {
if (i == MAX_ASTEROIDS)
i = 0;
if (Asteroids[i].flags & AF_USED) {
Assert(Objects[Asteroids[i].objnum].type == OBJ_ASTEROID);
set_target_objnum( Player_ai, Asteroids[i].objnum);
break;
}
i++;
}
}
/**
* Return the number of active asteroids
*/
@@ -1473,7 +1430,7 @@ int asteroid_count()
* See if asteroid should split up.
* We delay splitting up to allow the explosion animation to play for a bit.
*/
void asteroid_maybe_break_up(object *pasteroid_obj)
static void asteroid_maybe_break_up(object *pasteroid_obj)
{
asteroid *asp;
asteroid_info *asip;
@@ -1595,26 +1552,7 @@ void asteroid_maybe_break_up(object *pasteroid_obj)
}
}
int asteroid_get_random_in_cone(vec3d *pos, vec3d *dir, float ang, int danger)
{
int idx;
vec3d asteroid_dir;
// just pick the first asteroid which satisfies our condition
for(idx=0; idx<Num_asteroids; idx++){
vm_vec_sub(&asteroid_dir, &Objects[Asteroids[idx].objnum].pos, pos);
vm_vec_normalize_quick(&asteroid_dir);
// if it satisfies the condition
if(vm_vec_dot(dir, &asteroid_dir) >= ang){
return idx;
}
}
return -1;
}
void asteroid_test_collide(object *pasteroid_obj, object *pship_obj, mc_info *mc, bool lazy = false)
static void asteroid_test_collide(object *pasteroid_obj, object *pship_obj, mc_info *mc, bool lazy = false)
{
float asteroid_ray_dist;
vec3d asteroid_fvec, terminus;
@@ -1656,7 +1594,7 @@ void asteroid_test_collide(object *pasteroid_obj, object *pship_obj, mc_info *mc
*
* @return !0 if the asteroid will collide with the escort
*/
int asteroid_will_collide(object *pasteroid_obj, object *escort_objp)
static int asteroid_will_collide(object *pasteroid_obj, object *escort_objp)
{
mc_info mc;
mc_info_init(&mc);
@@ -1674,7 +1612,7 @@ int asteroid_will_collide(object *pasteroid_obj, object *escort_objp)
* Warn if asteroid on collision path with ship
* @return !0 if we should warn about asteroid hitting ship, otherwise return 0
*/
int asteroid_valid_ship_to_warn_collide(ship *shipp)
static int asteroid_valid_ship_to_warn_collide(ship *shipp)
{
if ( !(Ship_info[shipp->ship_info_index].is_big_or_huge()) ) {
return 0;
@@ -1696,7 +1634,7 @@ int asteroid_valid_ship_to_warn_collide(ship *shipp)
* See if asteroid will collide with a large ship on the escort list in the next
* ASTEROID_MIN_COLLIDE_TIME seconds.
*/
void asteroid_update_collide_flag(object *asteroid_objp)
static void asteroid_update_collide_flag(object *asteroid_objp)
{
int i, num_escorts, escort_objnum, will_collide=0;
ship *escort_shipp;
@@ -1735,7 +1673,7 @@ void asteroid_update_collide_flag(object *asteroid_objp)
/**
* Ensure that the collide objnum for the asteroid is still valid
*/
void asteroid_verify_collide_objnum(asteroid *asp)
static void asteroid_verify_collide_objnum(asteroid *asp)
{
if ( asp->collide_objnum >= 0 ) {
if ( Objects[asp->collide_objnum].signature != asp->collide_objsig ) {
@@ -1815,7 +1753,7 @@ float asteroid_time_to_impact(object *asteroid_objp)
/**
* Read in a single asteroid section from asteroid.tbl
*/
void asteroid_parse_section(asteroid_info *asip)
static void asteroid_parse_section(asteroid_info *asip)
{
required_string("$Name:");
stuff_string(asip->name, F_NAME, NAME_LENGTH);
@@ -1915,7 +1853,7 @@ to do with the debris of ships that explode, however these
are the same debris and asteroids that get flung at a ship
that is being protected.
*/
void asteroid_parse_tbl()
static void asteroid_parse_tbl()
{
char impact_ani_file[MAX_FILENAME_LEN];
@@ -2066,7 +2004,7 @@ void asteroid_parse_tbl()
/**
* Return number of asteroids expected to collide with a ship.
*/
int count_incident_asteroids()
static int count_incident_asteroids()
{
object *asteroid_objp;
int count;
@@ -2090,7 +2028,7 @@ int count_incident_asteroids()
* Pick object to throw asteroids at.
* Pick any capital or big ship inside the bounds of the asteroid field.
*/
int set_asteroid_throw_objnum()
static int set_asteroid_throw_objnum()
{
if (Asteroid_field.num_initial_asteroids < 1)
return -1;
-1
View File
@@ -163,7 +163,6 @@ int asteroid_collide_objnum(object *asteroid_objp);
float asteroid_time_to_impact(object *asteroid_objp);
void asteroid_show_brackets();
void asteroid_target_closest_danger();
int asteroid_get_random_in_cone(vec3d *pos, vec3d *dir, float ang, int danger = 0);
// need to extern for multiplayer
void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec);
+2 -2
View File
@@ -1231,7 +1231,7 @@ void send_autopilot_msg(char *msg, char *snd)
audio_handle = -1;
}
if (msg[0] != '\0' && strcmp(msg, "none"))
if (msg[0] != '\0' && strcmp(msg, "none") != 0)
change_message("autopilot builtin message", msg, -1, 0);
// load sound
@@ -1246,7 +1246,7 @@ void send_autopilot_msg(char *msg, char *snd)
audiostream_play(audio_handle, (Master_event_music_volume * aav_music_volume), 0);
}
if (msg[0] != '\0' && strcmp(msg, "none"))
if (msg[0] != '\0' && strcmp(msg, "none") != 0)
message_training_queue("autopilot builtin message", timestamp(0), 5); // display message for five seconds
}
+38 -9
View File
@@ -23,6 +23,16 @@
#include "bmpman/bmpman.h"
#include <array>
/**
* @brief Container class for graphics API specific bitmap data
*/
class gr_bitmap_info {
public:
virtual ~gr_bitmap_info() = 0;
};
union bm_extra_info {
struct {
// Stuff needed for animations
@@ -31,6 +41,7 @@ union bm_extra_info {
int keyframe; //!< used for animations -- keyframe info
float total_time; //!< used for animations -- total animation time (not always derived from num_frames/fps)
ubyte fps; //!< used for animations -- frames per second
bool is_array; //!< Flag for if all frames of an animation have the same size which means that it can be put into a texture array
struct {
// stuff for static animations
@@ -89,17 +100,35 @@ struct bitmap_entry {
#endif
};
extern bitmap_entry bm_bitmaps[MAX_BITMAPS];
struct bitmap_slot {
bitmap_entry entry;
gr_bitmap_info* gr_info = nullptr;
};
// image specific lock functions
void bm_lock_ani( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_dds( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_png( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_apng( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_jpg( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_pcx( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_tga( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_user( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_ani( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_dds( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_png( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_apng( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_jpg( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_pcx( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_tga( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
void bm_lock_user( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
const size_t BM_BLOCK_SIZE = 4096;
extern SCP_vector<std::array<bitmap_slot, BM_BLOCK_SIZE>> bm_blocks;
bitmap_slot* bm_get_slot(int handle, bool separate_ani_frames = true);
inline bitmap_entry* bm_get_entry(int handle, bool separate_ani_frames = true) {
return &bm_get_slot(handle, separate_ani_frames)->entry;
}
template<typename T>
T* bm_get_gr_info(int handle, bool separate_ani_frames = true) {
return static_cast<T*>(bm_get_slot(handle, separate_ani_frames)->gr_info);
}
#endif // __BM_INTERNAL_H__
+886 -722
View File
File diff suppressed because it is too large. Load diff
+74 -47
View File
@@ -32,21 +32,6 @@
* @{
*/
/**
* @brief How many bitmaps the game can handle
*
* @attention MAX_BITMAPS shouldn't need to be bumped again. With the fixed bm_release() and it's proper use even the
* largest missions should stay under this number. With the largest retail missions and wasteful content we should
* still have about 20% of the slots free. If it still goes over then it's something the artists need to fix.
* For instance the Terran Mara fighter, with -spec and -glow and using the Shinepack, needs 117 bitmap slots alone.
* 111 of those is just for the glowmaps. This number can be greatly reduced if the number of ani frames for another
* LOD than LOD0 has fewer or no ani frames. A 37 frame glow ani for LOD2 is little more than a waste of resources.
* Future reports of texture corruption should be initially approached with content as the cause and not code.
* If anything we could/should reduce MAX_BITMAPS in the future. Where it's at now should accomidate even the
* largest mods. -- Taylor
*/
#define MAX_BITMAPS 4750
// Flag positions for bitmap.flags
// ***** NOTE: bitmap.flags is an 8-bit value, no more BMP_TEX_* flags can be added unless the type is changed!! ******
#define BMP_AABITMAP (1<<0) //!< antialiased bitmap
@@ -56,6 +41,7 @@
#define BMP_TEX_DXT3 (1<<4) //!< dxt3 compressed 8r8g8b4a (32bit)
#define BMP_TEX_DXT5 (1<<5) //!< dxt5 compressed 8r8g8b8a (32bit)
#define BMP_TEX_CUBEMAP (1<<6) //!< a texture made for cubic environment map
#define BMP_MASK_BITMAP (1<<7) //!< a bitmap that will be used for masking mouse interaction. Typically not used in render operations
// Combined flags
#define BMP_TEX_COMP ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 ) //!< Compressed textures
@@ -112,6 +98,10 @@ struct bitmap
*/
};
// Forward definition for the graphics API
struct bitmap_entry;
struct bitmap_slot;
extern size_t bm_texture_ram; //!< how many bytes of textures are used.
extern int Bm_paging; //!< Bool type that indicates if BMPMAN is currently paging.
@@ -140,22 +130,6 @@ void bm_init();
*/
void bm_close();
/**
* Gets the cache slot of the bitmap indexed by handle.
*
* @details if the bitmap is an ani, gets the first frame
*
* @returns The cache slot index of the bitmap if handle is valid
*
* @note If the handle is invalid, an Assert() fails
*/
int bm_get_cache_slot(int bitmap_id, int separate_ani_frames);
/**
* @brief Gets the next available bitmap slot.
*/
int bm_get_next_handle();
#define BMP_FLAG_RENDER_TARGET_STATIC (1<<0)
#define BMP_FLAG_RENDER_TARGET_DYNAMIC (1<<1)
#define BMP_FLAG_CUBEMAP (1<<2)
@@ -409,13 +383,6 @@ void bm_get_filename(int bitmapnum, char *filename);
*/
const char *bm_get_filename(int handle);
/**
* @brief Loads all data for all bitmaps that have been requested to be loaded
*
* @note This function is not defined.
*/
void bm_gfx_load_all();
/**
* @brief Unloads all used bitmaps, should only ever be called by game_shutdown()
*
@@ -434,15 +401,6 @@ void bm_unload_all();
*/
void bm_get_palette(int handle, ubyte *pal, char *name);
/**
* @brief Hack to get a pixel from a bitmap
*
* @details only works good in 8bpp mode
*
* @note This function is not defined.
*/
void bm_gfx_get_pixel(int bitmap, float u, float v, ubyte *r, ubyte *g, ubyte *b);
/**
* @brief (DEBUG) Gets memory size, in bytes, of the locked bitmaps
*
@@ -698,4 +656,73 @@ bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int
*/
int bm_get_anim_frame(const int frame1_handle, float elapsed_time, const float divisor = 0.0f, const bool loop = false);
/**
* @brief Determines if the given handle could be used in a texture array
*
* @param handle The handle to query the value for
* @return @c true if all frames have the same size, @c false otherwise. Always returns @c true for single images
*/
bool bm_is_texture_array(const int handle);
/**
* @brief Gets the base frame of the specified animation
*
* @details The base frame is the frame of the animation that should be used to determine if two animation frames can be
* used in the same draw call. Use this if you want to optimize your draw calls to make use of texture arrays.
*
* @param handle The handle of the animation to check. This may also be a single frame bitmap
* @param num_frames Optionally return the number of frames in the animation
* @return The bitmap handle of the base frame or -1 on error
*/
int bm_get_base_frame(const int handle, int* num_frames = nullptr);
/**
* @brief Get the array index of the specified bitmap
*
* This should be used when passing the array index to the GPU (e.g. when building uniform structs or streaming particle
* data)
*
* @param handle The handle of the bitmap
* @return The index into the array
*/
int bm_get_array_index(const int handle);
/**
* @brief Counts how many slots are used in bm_bitmaps
*
* This needs to iterate through all the slots in order to determine whether or not they're used, so shouldn't be used frivolously.
*
* @return The number of used slots
*/
int bmpman_count_bitmaps();
/**
* @brief Counts how many slots are available to the bmpman system
*
* Since the number of slots is dynamic now, this should be used for determining the total amount of available slots at
* the moment.
*
* @warning This is entirely for debugging and logging purposes. It should not be used in actual engine code.
*
* @return The number of available slots
*/
int bmpman_count_available_slots();
/**
* @brief Checks if the given filename is a valid effect or texture file name
*
* @note At least one of @c single_frame or @c animation must be true since the result would make no sense otherwise. It
* is also valid to set both parmeters to @c true.
*
* @todo This currently just tries to load the file but could be improved by not actually loading the file in the future.
*
* @param file The file name to check
* @param single_frame If set to @c true then single frames are valid files
* @param animation If set to @c true then animations are valid files
* @return @c true if the file name is valid, @c false otherwise
*/
bool bm_validate_filename(const SCP_string& file, bool single_frame, bool animation);
SDL_Surface* bm_to_sdl_surface(int handle);
#endif
+4 -4
View File
@@ -2,7 +2,7 @@
#include "globalincs/alphacolors.h"
#include "globalincs/linklist.h"
#include "globalincs/systemvars.h" //VM_FREECAMERA etc
#include "graphics/font.h"
#include "graphics/matrix.h"
#include "hud/hud.h" //hud_get_draw
#include "math/vecmat.h"
#include "mod_table/mod_table.h"
@@ -245,12 +245,12 @@ void camera::set_rotation_facing(vec3d *in_target, float in_rotation_time, float
set_rotation(&temp_matrix, in_rotation_time, in_rotation_acceleration_time, in_rotation_deceleration_time);
}
void camera::set_rotation_velocity(angles *in_rotation_rate, float in_acceleration_time)
void camera::set_rotation_velocity(angles * /*in_rotation_rate*/, float /*in_acceleration_time*/)
{
Error(LOCATION, "This function is disabled until further notice.");
}
void camera::do_frame(float in_frametime)
void camera::do_frame(float /*in_frametime*/)
{
}
@@ -802,7 +802,7 @@ void subtitle::clone(const subtitle &sub)
post_shaded = sub.post_shaded;
}
const subtitle &subtitle::operator=(const subtitle &sub)
subtitle& subtitle::operator=(const subtitle &sub)
{
if (this != &sub) {
if (image_id != -1) {
+1 -1
View File
@@ -143,7 +143,7 @@ public:
~subtitle();
subtitle(const subtitle &sub) { clone(sub); }
const subtitle &operator=(const subtitle &sub);
subtitle& operator=(const subtitle &sub);
void do_frame(float frametime);
bool is_post_shaded( ) { return post_shaded; }
+122 -84
View File
@@ -10,10 +10,10 @@
#define _CFILE_INTERNAL
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cerrno>
#include <sys/stat.h>
#ifdef _WIN32
@@ -48,49 +48,56 @@ char Cfile_user_dir_legacy[CFILE_ROOT_DIRECTORY_LEN] = "";
//
// Please make sure extensions are all lower-case, or we'll break unix compatibility
//
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
// What type this is Path Extensions Parent type
{ CF_TYPE_INVALID, NULL, NULL, CF_TYPE_INVALID },
// Root must be index 1!!
{ CF_TYPE_ROOT, "", ".mve .ogg", CF_TYPE_ROOT },
{ CF_TYPE_DATA, "data", ".cfg .txt", CF_TYPE_ROOT },
{ CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA },
{ CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA },
{ CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm", CF_TYPE_DATA },
{ CF_TYPE_SOUNDS, "data" DIR_SEPARATOR_STR "sounds", ".wav .ogg", CF_TYPE_DATA },
{ CF_TYPE_SOUNDS_8B22K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "8b22k", ".wav .ogg", CF_TYPE_SOUNDS },
{ CF_TYPE_SOUNDS_16B11K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "16b11k", ".wav .ogg", CF_TYPE_SOUNDS },
{ CF_TYPE_VOICE, "data" DIR_SEPARATOR_STR "voice", "", CF_TYPE_DATA },
{ CF_TYPE_VOICE_BRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "briefing", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_CMD_BRIEF, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "command_briefings", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_DEBRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "debriefing", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_PERSONAS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "personas", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_SPECIAL, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "special", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_TRAINING, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "training", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_MUSIC, "data" DIR_SEPARATOR_STR "music", ".wav .ogg", CF_TYPE_DATA },
{ CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg .mp4", CF_TYPE_DATA },
{ CF_TYPE_INTERFACE, "data" DIR_SEPARATOR_STR "interface", ".pcx .ani .dds .tga .eff .png .jpg", CF_TYPE_DATA },
{ CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf", CF_TYPE_DATA },
{ CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA },
{ CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA },
{ CF_TYPE_PLAYER_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "images", ".pcx .png .dds", CF_TYPE_PLAYERS },
{ CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds", CF_TYPE_PLAYERS },
{ CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css", CF_TYPE_PLAYERS },
{ CF_TYPE_MULTI_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "multi", ".plr", CF_TYPE_PLAYERS },
{ CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .bx", CF_TYPE_DATA }, //clr=cached color
{ CF_TYPE_MULTI_CACHE, "data" DIR_SEPARATOR_STR "multidata", ".pcx .png .dds .fs2 .txt", CF_TYPE_DATA },
{ CF_TYPE_MISSIONS, "data" DIR_SEPARATOR_STR "missions", ".fs2 .fc2 .ntl .ssv", CF_TYPE_DATA },
{ CF_TYPE_CONFIG, "data" DIR_SEPARATOR_STR "config", ".cfg .tbl .tbm .xml .csv", CF_TYPE_DATA },
{ CF_TYPE_DEMOS, "data" DIR_SEPARATOR_STR "demos", ".fsd", CF_TYPE_DATA },
{ CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA },
{ CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA },
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
// What type this is Path Extensions Parent
// type
{CF_TYPE_INVALID, NULL, NULL, CF_TYPE_INVALID},
// Root must be index 1!!
{CF_TYPE_ROOT, "", ".mve .ogg", CF_TYPE_ROOT},
{CF_TYPE_DATA, "data", ".cfg .txt", CF_TYPE_ROOT},
{CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
{CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA},
{CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA},
{CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm", CF_TYPE_DATA},
{CF_TYPE_SOUNDS, "data" DIR_SEPARATOR_STR "sounds", ".wav .ogg", CF_TYPE_DATA},
{CF_TYPE_SOUNDS_8B22K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "8b22k", ".wav .ogg", CF_TYPE_SOUNDS},
{CF_TYPE_SOUNDS_16B11K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "16b11k", ".wav .ogg", CF_TYPE_SOUNDS},
{CF_TYPE_VOICE, "data" DIR_SEPARATOR_STR "voice", "", CF_TYPE_DATA},
{CF_TYPE_VOICE_BRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "briefing", ".wav .ogg",
CF_TYPE_VOICE},
{CF_TYPE_VOICE_CMD_BRIEF, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "command_briefings", ".wav .ogg",
CF_TYPE_VOICE},
{CF_TYPE_VOICE_DEBRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "debriefing", ".wav .ogg",
CF_TYPE_VOICE},
{CF_TYPE_VOICE_PERSONAS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "personas", ".wav .ogg", CF_TYPE_VOICE},
{CF_TYPE_VOICE_SPECIAL, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "special", ".wav .ogg", CF_TYPE_VOICE},
{CF_TYPE_VOICE_TRAINING, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "training", ".wav .ogg", CF_TYPE_VOICE},
{CF_TYPE_MUSIC, "data" DIR_SEPARATOR_STR "music", ".wav .ogg", CF_TYPE_DATA},
{CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg .mp4 .srt", CF_TYPE_DATA},
{CF_TYPE_INTERFACE, "data" DIR_SEPARATOR_STR "interface", ".pcx .ani .dds .tga .eff .png .jpg", CF_TYPE_DATA},
{CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf", CF_TYPE_DATA},
{CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA},
{CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
{CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA},
{CF_TYPE_PLAYER_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "images", ".pcx .png .dds",
CF_TYPE_PLAYERS},
{CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds",
CF_TYPE_PLAYERS},
{CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css",
CF_TYPE_PLAYERS},
{CF_TYPE_MULTI_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "multi", ".plr", CF_TYPE_PLAYERS},
{CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .bx", CF_TYPE_DATA}, // clr=cached color
{CF_TYPE_MULTI_CACHE, "data" DIR_SEPARATOR_STR "multidata", ".pcx .png .dds .fs2 .txt", CF_TYPE_DATA},
{CF_TYPE_MISSIONS, "data" DIR_SEPARATOR_STR "missions", ".fs2 .fc2 .ntl .ssv", CF_TYPE_DATA},
{CF_TYPE_CONFIG, "data" DIR_SEPARATOR_STR "config", ".cfg .tbl .tbm .xml .csv", CF_TYPE_DATA},
{CF_TYPE_DEMOS, "data" DIR_SEPARATOR_STR "demos", ".fsd", CF_TYPE_DATA},
{CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
{CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
{CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA},
{CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA},
{CF_TYPE_FREDDOCS, "data" DIR_SEPARATOR_STR "freddocs", ".html", CF_TYPE_DATA},
};
#define CFILE_STACK_MAX 8
int cfile_inited = 0;
@@ -109,6 +116,7 @@ static const char *Cfile_cdrom_dir = NULL;
static int cfget_cfile_block();
static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE * fp, int type);
static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int type, size_t offset, size_t size);
static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const void* data, size_t size, int dir_type);
#if defined _WIN32
static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, HANDLE hFile, int type);
@@ -465,7 +473,7 @@ char *cf_add_ext(const char *filename, const char *ext)
size_t elen = strlen(ext);
Assert(flen < MAX_PATH_LEN);
strcpy_s(path, filename);
if ((flen < 4) || stricmp(path + flen - elen, ext)) {
if ((flen < 4) || stricmp(path + flen - elen, ext) != 0) {
Assert(flen + elen < MAX_PATH_LEN);
strcat_s(path, ext);
}
@@ -559,7 +567,7 @@ void cf_attrib(const char *filename, int set, int clear, int dir_type)
fclose(fp);
DWORD z = GetFileAttributes(longname);
SetFileAttributes(longname, z | set & ~clear);
SetFileAttributes(longname, z | (set & ~clear));
}
}
@@ -684,7 +692,7 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
Assert( mode != NULL );
// Can only open read-only binary files in memory mapped mode.
if ( (type & CFILE_MEMORY_MAPPED) && strcmp(mode,"rb") ) {
if ( (type & CFILE_MEMORY_MAPPED) && strcmp(mode,"rb") != 0 ) {
Int3();
return NULL;
}
@@ -763,16 +771,16 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
char copy_file_path[MAX_PATH_LEN]; // FIX change in memory from cf_find_file_location
strcpy_s(copy_file_path, file_path);
if ( cf_find_file_location( copy_file_path, dir_type, sizeof(longname) - 1, longname, &size, &offset, localize ) ) {
const void* file_data = nullptr;
if ( cf_find_file_location( copy_file_path, dir_type, sizeof(longname) - 1, longname, &size, &offset, localize, &file_data ) ) {
// Fount it, now create a cfile out of it
nprintf(("CFileDebug", "Requested file %s found at: %s\n", file_path, longname));
if ( type & CFILE_MEMORY_MAPPED ) {
// Can't open memory mapped files out of pack files
if ( offset == 0 ) {
// Can't open memory mapped files out of pack or memory files
if ( offset == 0 && file_data != nullptr ) {
#if defined _WIN32
HANDLE hFile;
@@ -790,18 +798,8 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
}
} else {
FILE *fp = fopen( longname, "rb" );
if ( fp ) {
if ( offset ) {
// Found it in a pack file
return cf_open_packed_cfblock(source, line, fp, dir_type, offset, size );
} else {
// Found it in a normal file
return cf_open_fill_cfblock(source, line, fp, dir_type);
}
}
// since cfopen_special already has all the code to handle the opening we can just use that here
return _cfopen_special(source, line, longname, mode, size, offset, file_data, dir_type);
}
}
@@ -820,7 +818,7 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
// returns: success ==> address of CFILE structure
// error ==> NULL
//
CFILE *_cfopen_special(const char* source, int line, const char *file_path, const char *mode, const size_t size, const size_t offset, int dir_type)
CFILE *_cfopen_special(const char* source, int line, const char *file_path, const char *mode, const size_t size, const size_t offset, const void* data, int dir_type)
{
if ( !cfile_inited) {
Int3();
@@ -836,19 +834,27 @@ CFILE *_cfopen_special(const char* source, int line, const char *file_path, cons
return NULL;
}
// "file_path" should already be a fully qualified path, so just try to open it
FILE *fp = fopen( file_path, "rb" );
if ( !fp )
return NULL;
if ( offset ) {
// it's in a pack file
return cf_open_packed_cfblock(source, line, fp, dir_type, offset, size);
} else {
// it's a normal file
return cf_open_fill_cfblock(source, line, fp, dir_type);
// In-Memory files are a bit different from normal files so we need to handle them separately
if (data != nullptr) {
return cf_open_memory_fill_cfblock(source, line, data, size, dir_type);
}
else {
// "file_path" should already be a fully qualified path, so just try to open it
FILE *fp = fopen(file_path, "rb");
if (fp) {
if (offset) {
// Found it in a pack file
return cf_open_packed_cfblock(source, line, fp, dir_type, offset, size);
}
else {
// Found it in a normal file
return cf_open_fill_cfblock(source, line, fp, dir_type);
}
}
}
return NULL;
}
@@ -922,7 +928,7 @@ int cfclose( CFILE * cfile )
cb = &Cfile_block_list[cfile->id];
result = 0;
if ( cb->data ) {
if ( cb->data && cb->mem_mapped ) {
// close memory mapped file
#if defined _WIN32
result = UnmapViewOfFile((void*)cb->data);
@@ -936,7 +942,8 @@ int cfclose( CFILE * cfile )
// FIXME: result is wrong after munmap() but it is successful
//result = munmap(cb->data, cb->data_length);
//Assert(result);
munmap(cb->data, cb->data_length);
// This const_cast is safe since the pointer returned by mmap was also non-const
munmap(const_cast<void*>(cb->data), cb->data_length);
if ( cb->fp != NULL)
result = fclose(cb->fp);
#endif
@@ -996,6 +1003,7 @@ static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE *fp, int t
cfp->id = cfile_block_index;
cfp->version = 0;
cfbp->data = NULL;
cfbp->mem_mapped = false;
cfbp->fp = fp;
cfbp->dir_type = type;
cfbp->max_read_len = 0;
@@ -1038,6 +1046,7 @@ static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int
cfp->version = 0;
cfbp->data = NULL;
cfbp->fp = fp;
cfbp->mem_mapped = false;
cfbp->dir_type = type;
cfbp->max_read_len = 0;
@@ -1083,6 +1092,7 @@ static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp
cfp->version = 0;
cfbp->max_read_len = 0;
cfbp->fp = NULL;
cfbp->mem_mapped = true;
#if defined _WIN32
cfbp->hInFile = hFile;
#endif
@@ -1117,6 +1127,37 @@ static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp
}
}
static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const void* data, size_t size, int dir_type)
{
int cfile_block_index;
cfile_block_index = cfget_cfile_block();
if ( cfile_block_index == -1 ) {
return NULL;
}
else {
CFILE *cfp;
Cfile_block *cfbp;
cfbp = &Cfile_block_list[cfile_block_index];
cfp = &Cfile_list[cfile_block_index];
cfp->id = cfile_block_index;
cfp->version = 0;
cfbp->max_read_len = 0;
cfbp->fp = NULL;
cfbp->mem_mapped = false;
cfbp->dir_type = dir_type;
cfbp->source_file = source;
cfbp->line_num = line;
cf_init_lowlevel_read_code(cfp, 0, size, 0 );
cfbp->data = data;
return cfp;
}
}
int cf_get_dir_type(CFILE *cfile)
{
return Cfile_block_list[cfile->id].dir_type;
@@ -1127,7 +1168,7 @@ int cf_get_dir_type(CFILE *cfile)
//
//
void *cf_returndata(CFILE *cfile)
const void *cf_returndata(CFILE *cfile)
{
Assert(cfile != NULL);
Cfile_block *cb;
@@ -1418,9 +1459,7 @@ int cfilelength( CFILE * cfile )
cb = &Cfile_block_list[cfile->id];
// TODO: return length of memory mapped file
Assert( !cb->data );
Assert(cb->fp != NULL);
Assert( !cb->mem_mapped );
// cb->size gets set at cfopen
@@ -1519,7 +1558,6 @@ int cfputc(int c, CFILE *cfile)
return result;
}
// cfputs() writes a string to a file
//
// returns: success ==> non-negative value
+11 -13
View File
@@ -13,7 +13,7 @@
#define __CFILE_H__
#include <time.h>
#include <ctime>
#include "globalincs/pstypes.h"
#include <stdexcept>
@@ -78,8 +78,9 @@ typedef struct {
#define CF_TYPE_INTEL_ANIMS 34
#define CF_TYPE_SCRIPTS 35
#define CF_TYPE_FICTION 36
#define CF_TYPE_FREDDOCS 37
#define CF_MAX_PATH_TYPES 37 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
#define CF_MAX_PATH_TYPES 38 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
// TRUE if type is specified and valid
@@ -139,7 +140,7 @@ CFILE *_cfopen(const char* source_file, int line, const char *filename, const ch
// like cfopen(), but it accepts a fully qualified path only (ie, the result of a cf_find_file_location() call)
// NOTE: only supports reading files!!
CFILE *_cfopen_special(const char* source_file, int line, const char *file_path, const char *mode,
const size_t size, const size_t offset, int dir_type = CF_TYPE_ANY);
const size_t size, const size_t offset, const void* data, int dir_type = CF_TYPE_ANY);
#define cfopen_special(...) _cfopen_special(LOCATION, __VA_ARGS__) // Pass source location to the function
// Flush the open file buffer
@@ -215,7 +216,7 @@ char *cfgets(char *buf, int n, CFILE *cfile);
int cfeof(CFILE *cfile);
// Return the data pointer associated with the CFILE structure (for memory mapped files)
void *cf_returndata(CFILE *cfile);
const void *cf_returndata(CFILE *cfile);
// get the 2 byte checksum of the passed filename - return 0 if operation failed, 1 if succeeded
int cf_chksum_short(const char *filename, ushort *chksum, int max_size = -1, int cf_type = CF_TYPE_ANY );
@@ -325,7 +326,7 @@ void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_
// size - File size
// offset - Offset into pack file. 0 if not a packfile.
// Returns: If not found returns 0.
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize = false);
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize = false, const void** data_out = nullptr);
// Searches for a file. Follows all rules and precedence and searches
// CD's and pack files. Searches all locations in order for first filename using ext filter list.
@@ -339,7 +340,7 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
// offset - Offset into pack file. 0 if not a packfile.
// Returns: If not found returns -1, else returns offset into ext_list.
// (NOTE: This function is exponentially slow, so don't use it unless truely needed!!)
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out = 0, char *pack_filename = NULL, size_t *size = NULL, size_t *offset = NULL, bool localize = false);
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out = 0, char *pack_filename = NULL, size_t *size = NULL, size_t *offset = NULL, bool localize = false, const void** data_out = nullptr);
// Functions to change directories
int cfile_chdir(const char *dir);
@@ -364,16 +365,13 @@ namespace cfile
{
}
cfile_error(const std::string &excuse) : m_excuse(excuse)
explicit cfile_error(const std::string &excuse) : m_excuse(excuse)
{
}
~cfile_error() throw()
{
}
~cfile_error() SCP_NOEXCEPT override {}
virtual const char *what() const throw()
{
const char *what() const SCP_NOEXCEPT override {
return m_excuse.c_str();
}
@@ -384,7 +382,7 @@ namespace cfile
class max_read_length : public cfile_error
{
public:
max_read_length(const std::string &excuse) : cfile_error(excuse)
explicit max_read_length(const std::string &excuse) : cfile_error(excuse)
{
}
+59 -41
View File
@@ -11,9 +11,9 @@
#define _CFILE_INTERNAL
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#ifdef _WIN32
#include <io.h>
@@ -74,18 +74,13 @@ int cfeof(CFILE *cfile)
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
int result;
result = 0;
// cfeof() not supported for memory-mapped files
Assert( !cb->data );
Assert(cb->fp != NULL);
int result = 0;
#if defined(CHECK_POSITION) && !defined(NDEBUG)
auto raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
if (cb->fp) {
auto raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
}
#endif
if (cb->raw_position >= cb->size ) {
@@ -109,14 +104,11 @@ int cftell( CFILE * cfile )
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
// Doesn't work for memory mapped files
Assert( !cb->data );
Assert(cb->fp != NULL);
#if defined(CHECK_POSITION) && !defined(NDEBUG)
auto raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
if (cb->fp) {
auto raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
}
#endif
// The rest of the code still uses ints, do an overflow check to detect cases where this fails
@@ -141,8 +133,7 @@ int cfseek( CFILE *cfile, int offset, int where )
// TODO: seek to offset in memory mapped file
Assert( !cb->data );
Assert( cb->fp != NULL );
Assert( !cb->mem_mapped );
size_t goal_position;
@@ -166,14 +157,22 @@ int cfseek( CFILE *cfile, int offset, int where )
// Make sure we don't seek beyond the end of the file
CAP(goal_position, cb->lib_offset, cb->lib_offset + cb->size);
int result = fseek(cb->fp, (long)goal_position, SEEK_SET );
Assertion(goal_position >= cb->lib_offset, "Invalid offset values detected while seeking! Goal was " SIZE_T_ARG ", lib_offset is " SIZE_T_ARG ".", goal_position, cb->lib_offset);
int result = 0;
if (cb->fp) {
// If we have a file pointer we can also seek in that file
result = fseek(cb->fp, (long)goal_position, SEEK_SET );
Assertion(goal_position >= cb->lib_offset, "Invalid offset values detected while seeking! Goal was " SIZE_T_ARG ", lib_offset is " SIZE_T_ARG ".", goal_position, cb->lib_offset);
}
// If we only have a data pointer this will do all the work
cb->raw_position = goal_position - cb->lib_offset;
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
#if defined(CHECK_POSITION) && !defined(NDEBUG)
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
if (cb->fp) {
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset == cb->raw_position);
}
#endif
return result;
@@ -197,13 +196,6 @@ int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
Cfile_block *cb = &Cfile_block_list[cfile->id];
// cfread() not supported for memory-mapped files
if(cb->data != NULL)
{
Warning(LOCATION, "Writing is not supported for mem-mapped files");
return 0;
}
if ( (cb->raw_position+size) > cb->size ) {
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
size = cb->size - cb->raw_position;
@@ -222,15 +214,24 @@ int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
}
}
size_t bytes_read = fread( buf, 1, size, cb->fp );
size_t bytes_read;
if (cb->data != nullptr) {
// This is a file from memory
bytes_read = size;
memcpy(buf, reinterpret_cast<const char*>(cb->data) + cb->raw_position, size);
} else {
bytes_read = fread( buf, 1, size, cb->fp );
}
if ( bytes_read > 0 ) {
cb->raw_position += bytes_read;
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
}
#if defined(CHECK_POSITION) && !defined(NDEBUG)
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
if (cb->fp) {
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
}
#endif
return (int)(bytes_read / elsize);
@@ -254,14 +255,31 @@ int cfread_lua_number(double *buf, CFILE *cfile)
return 0;
}
long orig_pos = ftell(cb->fp);
int items_read = fscanf(cb->fp, LUA_NUMBER_SCAN, buf);
cb->raw_position += ftell(cb->fp)-orig_pos;
size_t advance = 0;
int items_read;
if (cb->fp) {
long orig_pos = ftell(cb->fp);
items_read = fscanf(cb->fp, LUA_NUMBER_SCAN, buf);
advance = (size_t) (ftell(cb->fp)-orig_pos);
} else {
int read;
// %n returns the number of bytes currently read so we append that to the scan format at the end so it will return
// how many bytes we have consumed
items_read = sscanf(reinterpret_cast<const char*>(cb->data), LUA_NUMBER_SCAN "%n", buf, &read);
if (items_read == 2) {
// We need to correct the items read counter since we read one additional item
items_read = 1;
}
advance = (size_t) read;
}
cb->raw_position += advance;
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
#if defined(CHECK_POSITION) && !defined(NDEBUG)
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
if (cb->fp) {
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
}
#endif
return items_read;
+2 -1
View File
@@ -26,7 +26,8 @@ typedef struct Cfile_block {
int type; // CFILE_BLOCK_UNUSED, CFILE_BLOCK_USED
int dir_type; // directory location
FILE *fp; // File pointer if opening an individual file
void *data; // Pointer for memory-mapped file access. NULL if not mem-mapped.
const void *data; // Pointer for memory-mapped file access. NULL if not mem-mapped.
bool mem_mapped; // Flag for memory mapped files (if data is not null and this is false it means that it's an embedded file)
#ifdef _WIN32
HANDLE hInFile; // Handle from CreateFile()
HANDLE hMapFile; // Handle from CreateFileMapping()
+3 -3
View File
@@ -9,9 +9,9 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <algorithm>
+153 -36
View File
@@ -9,10 +9,10 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cerrno>
#include <sstream>
#include <algorithm>
@@ -37,12 +37,16 @@
#include "cfile/cfilesystem.h"
#include "cmdline/cmdline.h"
#include "globalincs/pstypes.h"
#include "def_files/def_files.h"
#include "localization/localize.h"
#include "osapi/osapi.h"
#include "parse/parselo.h"
#define CF_ROOTTYPE_PATH 0
#define CF_ROOTTYPE_PACK 1
enum CfileRootType {
CF_ROOTTYPE_PATH = 0,
CF_ROOTTYPE_PACK = 1,
CF_ROOTTYPE_MEMORY = 2,
};
// for a defined and specifically set location to get/send pilot/campaign files
SCP_string Pilot_file_path;
@@ -53,8 +57,8 @@ SCP_string Pilot_file_path;
// specifying cd-rom tree
// searching for pack files on CD-rom tree
typedef struct cf_root {
char path[CF_MAX_PATHNAME_LENGTH]; // Contains something like c:\projects\freespace or c:\projects\freespace\freespace.vp
int roottype; // CF_ROOTTYPE_PATH = Path, CF_ROOTTYPE_PACK =Pack file
char path[CF_MAX_PATHNAME_LENGTH]; // Contains something like c:\projects\freespace or c:\projects\freespace\freespace.vp
int roottype; // CF_ROOTTYPE_PATH = Path, CF_ROOTTYPE_PACK =Pack file, CF_ROOTTYPE_MEMORY=In memory
} cf_root;
// convenient type for sorting (see cf_build_pack_list())
@@ -79,13 +83,14 @@ static int Num_path_roots = 0;
// Created by searching all roots in order. This means Files is then sorted by precedence.
typedef struct cf_file {
char name_ext[CF_MAX_FILENAME_LENGTH]; // Filename and extension
int root_index; // Where in Roots this is located
int pathtype_index; // Where in Paths this is located
time_t write_time; // When it was last written
int size; // How big it is in bytes
int pack_offset; // For pack files, where it is at. 0 if not in a pack file. This can be used to tell if in a pack file.
char* real_name; // For real files, the full path
char name_ext[CF_MAX_FILENAME_LENGTH]; // Filename and extension
int root_index; // Where in Roots this is located
int pathtype_index; // Where in Paths this is located
time_t write_time; // When it was last written
int size; // How big it is in bytes
int pack_offset; // For pack files, where it is at. 0 if not in a pack file. This can be used to tell if in a pack file.
char* real_name; // For real files, the full path
const void* data; // For in-memory files, the data pointer
} cf_file;
#define CF_NUM_FILES_PER_BLOCK 512
@@ -510,6 +515,11 @@ void cf_build_root_list(const char *cdrom_dir)
}
// The final root is the in-memory root
root = cf_create_root();
memset(root->path, 0, sizeof(root->path));
root->roottype = CF_ROOTTYPE_MEMORY;
}
// Given a lower case list of file extensions
@@ -639,7 +649,7 @@ void cf_search_root_path(int root_index)
struct dirent *dir = nullptr;
while ((dir = readdir (parentDirP)) != nullptr) {
if (stricmp(search_name, dir->d_name)) {
if (stricmp(search_name, dir->d_name) != 0) {
continue;
}
@@ -836,7 +846,48 @@ void cf_search_root_pack(int root_index)
mprintf(( "%i files\n", num_files ));
}
void cf_search_memory_root(int root_index) {
int num_files = 0;
mprintf(( "Searching memory root ... " ));
auto default_files = defaults_get_all();
for (auto& default_file : default_files) {
// Pure built in files have an empty path_type string
if (strlen(default_file.path_type) <= 0) {
// Ignore pure builtin files. They should only be accessible with defaults_get_file
continue;
}
int pathtype = -1;
for (int i = 0; i < CF_MAX_PATH_TYPES; ++i) {
if (Pathtypes[i].path == nullptr) {
continue;
}
if (!strcmp(Pathtypes[i].path, default_file.path_type)) {
pathtype = i;
break;
}
}
Assertion(pathtype != -1, "Default file '%s%s%s' does not use a valid path type!",
default_file.path_type,
DIR_SEPARATOR_STR,
default_file.filename);
cf_file *file = cf_create_file();
strcpy_s( file->name_ext, default_file.filename );
file->root_index = root_index;
file->pathtype_index = pathtype;
file->write_time = time(nullptr); // Just assume that memory files were last written to just now
file->size = (int)default_file.size;
file->data = default_file.data;
num_files++;
}
mprintf(( "%i files\n", num_files ));
}
void cf_build_file_list()
{
@@ -851,6 +902,8 @@ void cf_build_file_list()
cf_search_root_path(i);
} else if ( root->roottype == CF_ROOTTYPE_PACK ) {
cf_search_root_pack(i);
} else if (root->roottype == CF_ROOTTYPE_MEMORY) {
cf_search_memory_root(i);
}
}
@@ -932,7 +985,7 @@ void cf_free_secondary_filelist()
*
* @return If not found returns 0.
*/
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize )
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize, const void** data_out )
{
int i;
uint ui;
@@ -1067,8 +1120,16 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
if (offset)
*offset = (size_t)f->pack_offset;
if (data_out)
*data_out = f->data;
if (pack_filename) {
if (f->pack_offset < 1) {
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
strncat(pack_filename, f->name_ext, max_out);
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
strncpy( pack_filename, f->real_name, max_out );
} else {
@@ -1092,8 +1153,16 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
if (offset)
*offset = (size_t)f->pack_offset;
if (data_out)
*data_out = f->data;
if (pack_filename) {
if (f->pack_offset < 1) {
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
strncat(pack_filename, f->name_ext, max_out);
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
strncpy( pack_filename, f->real_name, max_out );
} else {
@@ -1132,7 +1201,7 @@ extern char *stristr(char *str, const char *substr);
*
* @return If not found returns -1, else returns offset into ext_list.
*/
int cf_find_file_location_ext( const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize )
int cf_find_file_location_ext( const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize, const void** data_out)
{
int cur_ext, i;
uint ui;
@@ -1217,6 +1286,9 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
if (size)
*size = findstruct.size;
if (data_out)
*data_out = nullptr;
_findclose(findhandle);
if (offset)
@@ -1235,6 +1307,9 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
if (size)
*size = filelength( fileno(fp) );
if (data_out)
*data_out = nullptr;
fclose(fp);
if (offset)
@@ -1284,7 +1359,7 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
continue;
// ... check that we match the base filename
if ( strnicmp(f->name_ext, filespec, filespec_len) )
if ( strnicmp(f->name_ext, filespec, filespec_len) != 0 )
continue;
// ... make sure that it's one of our supported types
@@ -1334,15 +1409,25 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
if (offset)
*offset = f->pack_offset;
if (data_out)
*data_out = f->data;
if (pack_filename) {
if (f->pack_offset < 1) {
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
strncat(pack_filename, f->name_ext, max_out);
}
else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
strncpy( pack_filename, f->real_name, max_out );
} else {
strncpy(pack_filename, f->real_name, max_out);
}
else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
strncpy( pack_filename, r->path, max_out );
strncpy(pack_filename, r->path, max_out);
}
}
@@ -1362,15 +1447,25 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
if (offset)
*offset = f->pack_offset;
if (data_out)
*data_out = f->data;
if (pack_filename) {
if (f->pack_offset < 1) {
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
strncat(pack_filename, f->name_ext, max_out);
}
else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
strncpy( pack_filename, f->real_name, max_out );
} else {
strncpy(pack_filename, f->real_name, max_out);
}
else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
strncpy( pack_filename, r->path, max_out );
strncpy(pack_filename, r->path, max_out);
}
}
@@ -1432,6 +1527,7 @@ int cf_matches_spec(const char *filespec, const char *filename)
int (*Get_file_list_filter)(const char *filename) = NULL;
const char *Get_file_list_child = NULL;
int Skip_packfile_search = 0;
bool Skip_memory_files = false;
static bool verify_file_list_child()
{
@@ -1567,8 +1663,10 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
continue;
char fn[MAX_PATH];
snprintf(fn, MAX_PATH-1, "%s/%s", filespec, dir->d_name);
fn[MAX_PATH-1] = 0;
if (snprintf(fn, MAX_PATH, "%s/%s", filespec, dir->d_name) >= MAX_PATH) {
// Make sure the string is null terminated
fn[MAX_PATH-1] = 0;
}
struct stat buf;
if (stat(fn, &buf) == -1) {
@@ -1633,6 +1731,11 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
continue;
}
if (Skip_memory_files && f->data != nullptr) {
// If we want to skip memory files and this is a memory file then ignore it
continue;
}
if ( !Get_file_list_filter || (*Get_file_list_filter)(f->name_ext) ) {
//mprintf(( "Found '%s' in root %d path %d\n", f->name_ext, f->root_index, f->pathtype_index ));
@@ -1776,8 +1879,10 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
continue;
char fn[MAX_PATH];
snprintf(fn, MAX_PATH-1, "%s/%s", filespec, dir->d_name);
fn[MAX_PATH-1] = 0;
if (snprintf(fn, MAX_PATH, "%s/%s", filespec, dir->d_name) >= MAX_PATH) {
// Make sure the string is null terminated
fn[MAX_PATH-1] = 0;
}
struct stat buf;
if (stat(fn, &buf) == -1) {
@@ -1843,6 +1948,11 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
continue;
}
if (Skip_memory_files && f->data != nullptr) {
// If we want to skip memory files and this is a memory file then ignore it
continue;
}
if ( !Get_file_list_filter || (*Get_file_list_filter)(f->name_ext) ) {
//mprintf(( "Found '%s' in root %d path %d\n", f->name_ext, f->root_index, f->pathtype_index ));
@@ -1991,8 +2101,10 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
continue;
char fn[MAX_PATH];
snprintf(fn, MAX_PATH-1, "%s/%s", filespec, dir->d_name);
fn[MAX_PATH-1] = 0;
if (snprintf(fn, MAX_PATH, "%s/%s", filespec, dir->d_name) >= MAX_PATH) {
// Make sure the string is null terminated
fn[MAX_PATH-1] = 0;
}
struct stat buf;
if (stat(fn, &buf) == -1) {
@@ -2061,6 +2173,11 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
continue;
}
if (Skip_memory_files && f->data != nullptr) {
// If we want to skip memory files and this is a memory file then ignore it
continue;
}
if ( !Get_file_list_filter || (*Get_file_list_filter)(f->name_ext) ) {
//mprintf(( "Found '%s' in root %d path %d\n", f->name_ext, f->root_index, f->pathtype_index ));
@@ -2177,7 +2294,7 @@ int cf_create_default_path_string(char *path, uint path_max, int pathtype, const
// filename - optional, if set, tacks the filename onto end of path.
// Output: path - Fully qualified pathname.
//Returns 0 if the result would be too long (invalid result)
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename, bool localize )
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename, bool /*localize*/ )
{
#ifdef SCP_UNIX
if ( filename && strpbrk(filename,"/") ) {
+303 -70
View File
@@ -23,6 +23,9 @@
#include "globalincs/pstypes.h"
#include "osapi/osapi.h"
#include "cfile/cfilesystem.h"
#include "sound/speech.h"
#include "sound/openal.h"
#include "io/joy.h"
#ifdef _WIN32
#include <io.h>
@@ -36,8 +39,11 @@
#include <dirent.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <jansson.h>
// Stupid windows workaround...
#ifdef MessageBox
@@ -60,6 +66,11 @@ const char *cmdline_arg_types[] =
"STRING",
};
enum class flag_output_type {
Binary,
Json_V1,
};
// variables
class cmdline_parm {
public:
@@ -78,6 +89,7 @@ public:
float get_float();
char *str();
bool check_if_args_is_valid();
bool has_param();
};
static cmdline_parm Parm_list(NULL, NULL, AT_NONE);
@@ -148,7 +160,6 @@ Flag exe_params[] =
{ "-noenv", "Disable environment maps", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-env", },
{ "-nomotiondebris", "Disable motion debris", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomotiondebris",},
{ "-noscalevid", "Disable scale-to-window for movies", true, 0, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noscalevid", },
{ "-missile_lighting", "Apply lighting to missiles" , true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-missile_lighting", },
{ "-nonormal", "Disable normal maps", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-normal" },
{ "-no_emissive_light", "Disable emissive light from ships", true, 0, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_emissive_light" },
{ "-noheight", "Disable height/parallax maps", true, EASY_DEFAULT_MEM, EASY_MEM_ALL_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-height" },
@@ -177,7 +188,6 @@ Flag exe_params[] =
{ "-no_ap_interrupt", "Disable interrupting autopilot", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ap_interrupt", },
{ "-stretch_menu", "Stretch interface to fill screen", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stretch_menu", },
{ "-snd_preload", "Preload mission game sounds", true, EASY_MEM_ALL_ON, EASY_DEFAULT_MEM, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-snd_preload", },
{ "-nosound", "Disable all sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nosound", },
{ "-nomusic", "Disable music", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomusic", },
{ "-no_enhanced_sound", "Disable enhanced sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_enhanced_sound", },
@@ -205,7 +215,6 @@ Flag exe_params[] =
{ "-use_gldrawelements","Don't use glDrawRangeElements", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-use_gldrawelements", },
{ "-old_collision", "Use old collision detection system", true, EASY_DEFAULT, EASY_ALL_ON, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-old_collision", },
{ "-gl_finish", "Fix input lag on some ATI+Linux systems", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-gl_finish", },
{ "-no_batching", "Disable batched model rendering", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
{ "-no_geo_effects", "Disable geometry shader for effects", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
{ "-set_cpu_affinity", "Sets processor affinity to config value", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
{ "-nograb", "Disables mouse grabbing", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nograb", },
@@ -218,6 +227,7 @@ Flag exe_params[] =
{ "-voicer", "Enable voice recognition", true, 0, EASY_DEFAULT, "Experimental", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-voicer", },
{ "-fps", "Show frames per second on HUD", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fps", },
{ "-bmpmanusage", "Show how many BMPMAN slots are in use", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-bmpmanusage", },
{ "-pos", "Show position of camera", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pos", },
{ "-window", "Run in window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-window", },
{ "-fullscreen_window", "Run in fullscreen window", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fullscreen_window", },
@@ -303,7 +313,6 @@ cmdline_parm spec_static_arg("-spec_static", "Adjusts suns contribution to specu
cmdline_parm spec_point_arg("-spec_point", "Adjusts laser weapons contribution to specular highlights", AT_FLOAT);
cmdline_parm spec_tube_arg("-spec_tube", "Adjusts beam weapons contribution to specular highlights", AT_FLOAT);
cmdline_parm ambient_factor_arg("-ambient_factor", "Adjusts ambient light applied to all parts of a ship", AT_INT); // Cmdline_ambient_factor
cmdline_parm missile_lighting_arg("-missile_lighting", NULL, AT_NONE); // Cmdline_missile_lighting
cmdline_parm env("-noenv", NULL, AT_NONE); // Cmdline_env
cmdline_parm glow_arg("-noglow", NULL, AT_NONE); // Cmdline_glow -- use Bobs glow code
cmdline_parm nomotiondebris_arg("-nomotiondebris", NULL, AT_NONE); // Cmdline_nomotiondebris -- Removes those ugly floating rocks -C
@@ -321,10 +330,10 @@ cmdline_parm fxaa_preset_arg("-fxaa_preset", "FXAA quality (0-9), requires -post
cmdline_parm fb_explosions_arg("-fb_explosions", NULL, AT_NONE);
cmdline_parm fb_thrusters_arg("-fb_thrusters", NULL, AT_NONE);
cmdline_parm flightshaftsoff_arg("-nolightshafts", NULL, AT_NONE);
cmdline_parm no_batching("-no_batching", NULL, AT_NONE);
cmdline_parm shadow_quality_arg("-shadow_quality", NULL, AT_INT);
cmdline_parm enable_shadows_arg("-enable_shadows", NULL, AT_NONE);
cmdline_parm no_deferred_lighting_arg("-no_deferred", NULL, AT_NONE); // Cmdline_no_deferred
cmdline_parm anisotropy_level_arg("-anisotropic_filter", NULL, AT_INT);
float Cmdline_clip_dist = Default_min_draw_distance;
float Cmdline_fov = 0.75f;
@@ -332,7 +341,6 @@ float Cmdline_ogl_spec = 80.0f;
int Cmdline_ambient_factor = 128;
int Cmdline_env = 1;
int Cmdline_mipmap = 0;
int Cmdline_missile_lighting = 0;
int Cmdline_glow = 1;
int Cmdline_nomotiondebris = 0;
int Cmdline_noscalevid = 0;
@@ -349,10 +357,10 @@ int Cmdline_fxaa_preset = 6;
extern int Fxaa_preset_last_frame;
bool Cmdline_fb_explosions = 0;
bool Cmdline_fb_thrusters = false;
bool Cmdline_no_batching = false;
extern bool ls_force_off;
int Cmdline_shadow_quality = 0;
int Cmdline_no_deferred_lighting = 0;
int Cmdline_aniso_level = 0;
// Game Speed related
cmdline_parm cache_bitmaps_arg("-cache_bitmaps", NULL, AT_NONE); // Cmdline_cache_bitmaps
@@ -393,11 +401,9 @@ int Cmdline_stretch_menu = 0;
// Audio related
cmdline_parm query_speech_arg("-query_speech", NULL, AT_NONE); // Cmdline_query_speech
cmdline_parm snd_preload_arg("-snd_preload", NULL, AT_NONE); // Cmdline_snd_preload
cmdline_parm voice_recognition_arg("-voicer", NULL, AT_NONE); // Cmdline_voice_recognition
int Cmdline_query_speech = 0;
int Cmdline_snd_preload = 0; // preload game sounds during mission load
int Cmdline_voice_recognition = 0;
int Cmdline_no_enhanced_sound = 0;
@@ -472,6 +478,7 @@ cmdline_parm dis_weapons("-dis_weapons", NULL, AT_NONE); // Cmdline_dis_weapons
cmdline_parm noparseerrors_arg("-noparseerrors", NULL, AT_NONE); // Cmdline_noparseerrors -- turns off parsing errors -C
cmdline_parm extra_warn_arg("-extra_warn", "Enable 'extra' warnings", AT_NONE); // Cmdline_extra_warn
cmdline_parm fps_arg("-fps", NULL, AT_NONE); // Cmdline_show_fps
cmdline_parm bmpmanusage_arg("-bmpmanusage", NULL, AT_NONE); // Cmdline_bmpman_usage
cmdline_parm pos_arg("-pos", NULL, AT_NONE); // Cmdline_show_pos
cmdline_parm stats_arg("-stats", NULL, AT_NONE); // Cmdline_show_stats
cmdline_parm save_render_targets_arg("-save_render_target", NULL, AT_NONE); // Cmdline_save_render_targets
@@ -497,11 +504,13 @@ char *Cmdline_start_mission = NULL;
int Cmdline_old_collision_sys = 0;
int Cmdline_dis_collisions = 0;
int Cmdline_dis_weapons = 0;
bool Cmdline_output_sexp_info = false;
int Cmdline_noparseerrors = 0;
#ifdef Allow_NoWarn
int Cmdline_nowarn = 0; // turn warnings off in FRED
#endif
int Cmdline_extra_warn = 0;
int Cmdline_bmpman_usage = 0;
int Cmdline_show_pos = 0;
int Cmdline_show_stats = 0;
int Cmdline_save_render_targets = 0;
@@ -522,7 +531,7 @@ bool Cmdline_show_video_info = false;
bool Cmdline_debug_window = false;
// Other
cmdline_parm get_flags_arg("-get_flags", "Output the launcher flags file", AT_NONE);
cmdline_parm get_flags_arg("-get_flags", "Output the launcher flags file", AT_STRING);
cmdline_parm output_sexp_arg("-output_sexps", NULL, AT_NONE); //WMC - outputs all SEXPs to sexps.html
cmdline_parm output_scripting_arg("-output_scripting", NULL, AT_NONE); //WMC
@@ -535,6 +544,8 @@ cmdline_parm deprecated_tbp_arg("-tbp", "Deprecated", AT_NONE);
cmdline_parm deprecated_jpgtga_arg("-jpgtga", "Deprecated", AT_NONE);
cmdline_parm deprecated_htl_arg("-nohtl", "Deprecated", AT_NONE);
cmdline_parm deprecated_brieflighting_arg("-brief_lighting", "Deprecated", AT_NONE);
cmdline_parm deprecated_sndpreload_arg("-snd_preload", "Deprecated", AT_NONE);
cmdline_parm deprecated_missile_lighting_arg("-missile_lighting", "Deprecated", AT_NONE);
int Cmdline_deprecated_spec = 0;
int Cmdline_deprecated_glow = 0;
@@ -544,6 +555,7 @@ int Cmdline_deprecated_tbp = 0;
int Cmdline_deprecated_jpgtga = 0;
int Cmdline_deprecated_nohtl = 0;
bool Cmdline_deprecated_brief_lighting = 0;
bool Cmdline_deprecated_missile_lighting = false;
#ifndef NDEBUG
// NOTE: this assumes that os_init() has already been called but isn't a fatal error if it hasn't
@@ -609,6 +621,11 @@ void cmdline_debug_print_cmdline()
{
mprintf(("Deprecated flag '-brief_lighting' found. Please remove from your cmdline.\n"));
}
if (Cmdline_deprecated_missile_lighting)
{
mprintf(("Deprecated flag '-missile_lighting' found. Please remove from your cmdline.\n"));
}
}
#endif
@@ -801,7 +818,7 @@ void os_validate_parms(int argc, char *argv[])
size_t sp = 0;
for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
// don't output deprecated flags
if (stricmp("deprecated", parmp->help)) {
if (stricmp("deprecated", parmp->help) != 0) {
sp = strlen(parmp->name);
if (parmp->arg_type != AT_NONE) {
atp = strlen(cmdline_arg_types[parmp->arg_type]);
@@ -1143,11 +1160,14 @@ char *cmdline_parm::str()
return args;
}
bool cmdline_parm::has_param() {
return args != nullptr;
}
#ifdef SCP_UNIX
// Return a vector with all filesystem names of "parent/dir" relative to parent.
// dir must not contain a slash.
static SCP_vector<SCP_string> unix_get_single_dir_names(SCP_string parent, SCP_string dir)
static SCP_vector<SCP_string> unix_get_single_dir_names(const SCP_string& parent, const SCP_string& dir)
{
SCP_vector<SCP_string> ret;
@@ -1170,7 +1190,7 @@ static SCP_vector<SCP_string> unix_get_single_dir_names(SCP_string parent, SCP_s
// Return a vector with all filesystem names of "parent/dir" relative to parent.
// Recurses to deal with slashes in dir.
static SCP_vector<SCP_string> unix_get_dir_names(SCP_string parent, SCP_string dir)
static SCP_vector<SCP_string> unix_get_dir_names(const SCP_string& parent, const SCP_string& dir)
{
size_t slash = dir.find_first_of("/\\");
@@ -1241,6 +1261,257 @@ static void handle_unix_modlist(char **modlist, size_t *len)
// external entry point into this modules
static json_t* json_get_v1() {
auto root = json_object();
{
auto version_obj = json_object();
json_object_set_new(version_obj, "full", json_string(FS_VERSION_FULL));
json_object_set_new(version_obj, "major", json_integer(FS_VERSION_MAJOR));
json_object_set_new(version_obj, "minor", json_integer(FS_VERSION_MINOR));
json_object_set_new(version_obj, "build", json_integer(FS_VERSION_BUILD));
json_object_set_new(version_obj, "has_revision", json_boolean(FS_VERSION_HAS_REVIS));
json_object_set_new(version_obj, "revision", json_integer(FS_VERSION_REVIS));
json_object_set_new(version_obj, "revision_str", json_string(FS_VERSION_REVIS_STR));
json_object_set_new(root, "version", version_obj);
}
{
auto easy_array = json_array();
for (auto& easy_flag : easy_flags) {
json_array_append_new(easy_array, json_string(easy_flag.name));
}
json_object_set_new(root, "easy_flags", easy_array);
}
{
auto flags_array = json_array();
for (auto& flag : exe_params) {
auto flag_obj = json_object();
json_object_set_new(flag_obj, "name", json_string(flag.name));
json_object_set_new(flag_obj, "description", json_string(flag.desc));
json_object_set_new(flag_obj, "fso_only", json_boolean(flag.fso_only));
json_object_set_new(flag_obj, "on_flags", json_integer(flag.on_flags));
json_object_set_new(flag_obj, "off_flags", json_integer(flag.off_flags));
json_object_set_new(flag_obj, "type", json_string(flag.type));
json_object_set_new(flag_obj, "web_url", json_string(flag.web_url));
json_array_append_new(flags_array, flag_obj);
}
json_object_set_new(root, "flags", flags_array);
}
{
auto caps_array = json_array();
json_array_append_new(caps_array, json_string("OpenAL"));
json_array_append_new(caps_array, json_string("No D3D"));
json_array_append_new(caps_array, json_string("New Sound"));
json_array_append_new(caps_array, json_string("SDL"));
json_object_set_new(root, "caps", caps_array);
}
{
auto voices_array = json_array();
auto voices = speech_enumerate_voices();
for (auto& voice : voices) {
json_array_append_new(voices_array, json_string(voice.c_str()));
}
json_object_set_new(root, "voices", voices_array);
}
{
auto resolution_array = json_array();
auto displays = gr_enumerate_displays();
for (auto& display : displays) {
auto display_obj = json_object();
json_object_set_new(display_obj, "index", json_integer(display.index));
json_object_set_new(display_obj, "name", json_string(display.name.c_str()));
json_object_set_new(display_obj, "x", json_integer(display.x));
json_object_set_new(display_obj, "y", json_integer(display.y));
json_object_set_new(display_obj, "width", json_integer(display.width));
json_object_set_new(display_obj, "height", json_integer(display.height));
auto modes_array = json_array();
for (auto& mode : display.video_modes) {
auto mode_obj = json_object();
json_object_set_new(mode_obj, "x", json_integer(mode.width));
json_object_set_new(mode_obj, "y", json_integer(mode.height));
json_object_set_new(mode_obj, "bits", json_integer(mode.bit_depth));
json_array_append_new(modes_array, mode_obj);
}
json_object_set_new(display_obj, "modes", modes_array);
json_array_append_new(resolution_array, display_obj);
}
json_object_set_new(root, "displays", resolution_array);
}
{
auto openal_obj = json_object();
auto openal_info = openal_get_platform_information();
json_object_set_new(openal_obj, "version_major", json_integer(openal_info.version_major));
json_object_set_new(openal_obj, "version_minor", json_integer(openal_info.version_minor));
json_object_set(openal_obj, "default_playback", json_string(openal_info.default_playback_device.c_str()));
json_object_set(openal_obj, "default_capture", json_string(openal_info.default_capture_device.c_str()));
{
auto playback_array = json_array();
for (auto& device : openal_info.playback_devices) {
json_array_append_new(playback_array, json_string(device.c_str()));
}
json_object_set_new(openal_obj, "playback_devices", playback_array);
}
{
auto capture_array = json_array();
for (auto& device : openal_info.capture_devices) {
json_array_append_new(capture_array, json_string(device.c_str()));
}
json_object_set_new(openal_obj, "capture_devices", capture_array);
}
{
auto efx_support_obj = json_object();
for (auto& pair : openal_info.efx_support) {
json_object_set_new(efx_support_obj, pair.first.c_str(), json_boolean(pair.second));
}
json_object_set_new(openal_obj, "efx_support", efx_support_obj);
}
json_object_set_new(root, "openal", openal_obj);
}
{
auto joystick_array = json_array();
auto joysticks = io::joystick::getJoystickInformations();
for (auto& info : joysticks) {
auto joystick_obj = json_object();
json_object_set_new(joystick_obj, "name", json_string(info.name.c_str()));
json_object_set_new(joystick_obj, "guid", json_string(info.guid.c_str()));
json_object_set_new(joystick_obj, "num_axes", json_integer(info.num_axes));
json_object_set_new(joystick_obj, "num_balls", json_integer(info.num_balls));
json_object_set_new(joystick_obj, "num_buttons", json_integer(info.num_buttons));
json_object_set_new(joystick_obj, "num_hats", json_integer(info.num_hats));
json_object_set_new(joystick_obj, "is_haptic", json_boolean(info.is_haptic));
json_array_append_new(joystick_array, joystick_obj);
}
json_object_set_new(root, "joysticks", joystick_array);
}
{
json_object_set_new(root, "pref_path", json_string(os_get_config_path().c_str()));
}
return root;
}
static void write_flags_file() {
FILE *fp = fopen("flags.lch","w");
if (fp == NULL) {
os::dialogs::Message(os::dialogs::MESSAGEBOX_ERROR, "Error creating flag list for launcher");
return;
}
int easy_flag_size = sizeof(EasyFlag);
int flag_size = sizeof(Flag);
int num_easy_flags = sizeof(easy_flags) / easy_flag_size;
int num_flags = sizeof(exe_params) / flag_size;
// Launcher will check its using structures of the same size
fwrite(&easy_flag_size, sizeof(int), 1, fp);
fwrite(&flag_size, sizeof(int), 1, fp);
fwrite(&num_easy_flags, sizeof(int), 1, fp);
fwrite(&easy_flags, sizeof(easy_flags), 1, fp);
fwrite(&num_flags, sizeof(int), 1, fp);
fwrite(&exe_params, sizeof(exe_params), 1, fp);
{
// cheap and bastardly cap check for builds
// (needs to be compatible with older Launchers, which means having
// this implies an OpenAL build for old Launchers)
ubyte build_caps = 0;
/* portej05 defined this always */
build_caps |= BUILD_CAPS_OPENAL;
build_caps |= BUILD_CAPS_NO_D3D;
build_caps |= BUILD_CAPS_NEW_SND;
build_caps |= BUILD_CAPS_SDL;
fwrite(&build_caps, 1, 1, fp);
}
fflush(fp);
fclose(fp);
}
static flag_output_type get_flags_output_type() {
Assertion(get_flags_arg.found(), "This function is only valid if -get_flags is present!");
if (!get_flags_arg.has_param()) {
// Default to binary mode
return flag_output_type::Binary;
}
SCP_string type(get_flags_arg.str());
if (type == "binary") {
return flag_output_type::Binary;
} else if (type == "json_v1") {
return flag_output_type::Json_V1;
} else {
// This is supposed to make it easy for the launcher to recognize an unsupported type
printf("OUTPUT TYPE NOT SUPPORTED!\n");
// Default to json in this case so that no flags.lch file is created
return flag_output_type::Json_V1;
}
}
static void write_flags() {
auto type = get_flags_output_type();
switch(type) {
case flag_output_type::Binary:
write_flags_file();
break;
case flag_output_type::Json_V1:
json_t* root = json_get_v1();
json_dumpf(root, stdout, JSON_INDENT(4));
json_decref(root);
break;
}
}
bool SetCmdlineParams()
// Sets externed variables used for communication cmdline information
{
@@ -1248,47 +1519,7 @@ bool SetCmdlineParams()
// DO THIS FIRST to avoid unrecognized flag warnings when just getting flag file
if ( get_flags_arg.found() ) {
FILE *fp = fopen("flags.lch","w");
if (fp == NULL) {
os::dialogs::Message(os::dialogs::MESSAGEBOX_ERROR, "Error creating flag list for launcher");
return false;
}
int easy_flag_size = sizeof(EasyFlag);
int flag_size = sizeof(Flag);
int num_easy_flags = sizeof(easy_flags) / easy_flag_size;
int num_flags = sizeof(exe_params) / flag_size;
// Launcher will check its using structures of the same size
fwrite(&easy_flag_size, sizeof(int), 1, fp);
fwrite(&flag_size, sizeof(int), 1, fp);
fwrite(&num_easy_flags, sizeof(int), 1, fp);
fwrite(&easy_flags, sizeof(easy_flags), 1, fp);
fwrite(&num_flags, sizeof(int), 1, fp);
fwrite(&exe_params, sizeof(exe_params), 1, fp);
{
// cheap and bastardly cap check for builds
// (needs to be compatible with older Launchers, which means having
// this implies an OpenAL build for old Launchers)
ubyte build_caps = 0;
/* portej05 defined this always */
build_caps |= BUILD_CAPS_OPENAL;
build_caps |= BUILD_CAPS_NO_D3D;
build_caps |= BUILD_CAPS_NEW_SND;
build_caps |= BUILD_CAPS_SDL;
fwrite(&build_caps, 1, 1, fp);
}
fflush(fp);
fclose(fp);
write_flags();
return false;
}
@@ -1541,6 +1772,11 @@ bool SetCmdlineParams()
Show_framerate = 1;
}
if (bmpmanusage_arg.found())
{
Cmdline_bmpman_usage = 1;
}
if(pos_arg.found())
{
Cmdline_show_pos = 1;
@@ -1667,7 +1903,7 @@ bool SetCmdlineParams()
Output_scripting_meta = true;
if (output_sexp_arg.found() ) {
output_sexps("sexps.html");
Cmdline_output_sexp_info = true;
}
if ( no_pbo_arg.found() )
@@ -1721,11 +1957,6 @@ bool SetCmdlineParams()
}
#endif
if ( snd_preload_arg.found() )
{
Cmdline_snd_preload = 1;
}
if ( env.found() ) {
Cmdline_env = 0;
}
@@ -1764,9 +1995,6 @@ bool SetCmdlineParams()
if ( rearm_timer_arg.found() )
Cmdline_rearm_timer = 1;
if ( missile_lighting_arg.found() )
Cmdline_missile_lighting = 1;
if ( save_render_targets_arg.found() )
Cmdline_save_render_targets = 1;
@@ -1801,11 +2029,6 @@ bool SetCmdlineParams()
Cmdline_fb_thrusters = true;
}
if ( no_batching.found() )
{
Cmdline_no_batching = true;
}
if ( postprocess_arg.found() )
{
Cmdline_postprocess = 1;
@@ -1841,6 +2064,11 @@ bool SetCmdlineParams()
Cmdline_no_deferred_lighting = 1;
}
if (anisotropy_level_arg.found())
{
Cmdline_aniso_level = anisotropy_level_arg.get_int();
}
if (frame_profile_write_file.found())
{
Cmdline_profile_write_file = true;
@@ -1926,6 +2154,11 @@ bool SetCmdlineParams()
Cmdline_deprecated_brief_lighting = 1;
}
if (deprecated_missile_lighting_arg.found())
{
Cmdline_deprecated_missile_lighting = true;
}
return true;
}
+3 -3
View File
@@ -62,7 +62,6 @@ extern float static_point_factor;
extern float static_tube_factor;
extern int Cmdline_ambient_factor;
extern int Cmdline_env;
extern int Cmdline_missile_lighting;
extern int Cmdline_glow;
extern int Cmdline_nomotiondebris;
extern int Cmdline_noscalevid; // disables fit-to-window for movies - taylor
@@ -77,10 +76,10 @@ extern bool Cmdline_fxaa;
extern int Cmdline_fxaa_preset;
extern bool Cmdline_fb_explosions;
extern bool Cmdline_fb_thrusters;
extern bool Cmdline_no_batching;
extern int Cmdline_shadow_quality;
extern int Cmdline_no_deferred_lighting;
extern int Cmdline_no_emissive;
extern int Cmdline_aniso_level;
// Game Speed related
extern int Cmdline_cache_bitmaps;
@@ -104,7 +103,6 @@ extern int Cmdline_stretch_menu;
// Audio related
extern int Cmdline_query_speech;
extern int Cmdline_snd_preload;
extern int Cmdline_voice_recognition;
extern int Cmdline_no_enhanced_sound;
@@ -146,8 +144,10 @@ extern char *Cmdline_start_mission;
extern int Cmdline_old_collision_sys;
extern int Cmdline_dis_collisions;
extern int Cmdline_dis_weapons;
extern bool Cmdline_output_sexp_info;
extern int Cmdline_noparseerrors;
extern int Cmdline_extra_warn;
extern int Cmdline_bmpman_usage;
extern int Cmdline_show_pos;
extern int Cmdline_show_stats;
extern int Cmdline_save_render_targets;
+1 -1
View File
@@ -92,7 +92,7 @@ void cmeasure_maybe_alert_success(object *objp)
if ( objp->parent == OBJ_INDEX(Player_obj) ) {
hud_start_text_flash(XSTR("Evaded", 1430), 800);
snd_play(&Snds[ship_get_sound(Player_obj, SND_MISSILE_EVADED_POPUP)]);
snd_play(gamesnd_get_game_sound(ship_get_sound(Player_obj, GameSounds::MISSILE_EVADED_POPUP)));
} else if ( Objects[objp->parent].flags[Object::Object_Flags::Player_ship] ) {
send_countermeasure_success_packet( objp->parent );
}
+47 -47
View File
@@ -356,7 +356,7 @@ DCF_BOOL(show_controls_info, Show_controls_info);
static int Axes_origin[JOY_NUM_AXES];
static int joy_get_unscaled_reading(int raw, int axn)
static int joy_get_unscaled_reading(int raw)
{
int rng;
@@ -615,7 +615,7 @@ int control_config_undo_last()
int i, z, tab;
if (!Config_item_undo) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return -1;
}
@@ -664,7 +664,7 @@ int control_config_undo_last()
free_undo_block();
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
return 0;
}
@@ -715,7 +715,7 @@ int control_config_remove_binding()
config_item_undo *ptr;
if (Selected_line < 0) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return -1;
}
@@ -723,7 +723,7 @@ int control_config_remove_binding()
if (z & JOY_AXIS) {
z &= ~JOY_AXIS;
if (Axis_map_to[z] < 0) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return -1;
}
@@ -731,13 +731,13 @@ int control_config_remove_binding()
Axis_map_to[z] = -1;
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Selected_item = -1;
return 0;
}
if ((Control_config[z].joy_id < 0) && (Control_config[z].key_id < 0)) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return -1;
}
@@ -755,7 +755,7 @@ int control_config_remove_binding()
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
Selected_item = -1;
return 0;
}
@@ -766,7 +766,7 @@ int control_config_clear_other()
config_item_undo *ptr;
if (Selected_line < 0) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return -1;
}
@@ -776,7 +776,7 @@ int control_config_clear_other()
z &= ~JOY_AXIS;
if (Axis_map_to[z] < 0) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return -1;
}
@@ -787,7 +787,7 @@ int control_config_clear_other()
}
if (!total) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return -1;
}
@@ -808,7 +808,7 @@ int control_config_clear_other()
}
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
return 0;
}
@@ -820,12 +820,12 @@ int control_config_clear_other()
}
}
if (!total) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return -1;
}
if ((Control_config[z].joy_id < 0) && (Control_config[z].key_id < 0)) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return -1;
}
@@ -850,7 +850,7 @@ int control_config_clear_other()
}
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
return 0;
}
@@ -867,7 +867,7 @@ int control_config_clear_all()
}
if (!total) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return -1;
}
@@ -888,7 +888,7 @@ int control_config_clear_all()
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(SND_RESET_PRESSED);
gamesnd_play_iface(InterfaceSounds::RESET_PRESSED);
return 0;
}
@@ -945,7 +945,7 @@ int control_config_do_reset()
}
if (!total && !cycling_presets) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return -1;
}
@@ -981,7 +981,7 @@ int control_config_do_reset()
control_config_conflict_check();
control_config_list_prepare();
gamesnd_play_iface(SND_RESET_PRESSED);
gamesnd_play_iface(InterfaceSounds::RESET_PRESSED);
return 0;
}
@@ -1026,10 +1026,10 @@ void control_config_scroll_screen_up()
}
Selected_item = -1;
gamesnd_play_iface(SND_SCROLL);
gamesnd_play_iface(InterfaceSounds::SCROLL);
} else {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
}
@@ -1042,10 +1042,10 @@ void control_config_scroll_line_up()
}
Selected_item = -1;
gamesnd_play_iface(SND_SCROLL);
gamesnd_play_iface(InterfaceSounds::SCROLL);
} else {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
}
@@ -1059,10 +1059,10 @@ void control_config_scroll_screen_down()
}
Selected_item = -1;
gamesnd_play_iface(SND_SCROLL);
gamesnd_play_iface(InterfaceSounds::SCROLL);
} else {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
}
@@ -1076,10 +1076,10 @@ void control_config_scroll_line_down()
}
Selected_item = -1;
gamesnd_play_iface(SND_SCROLL);
gamesnd_play_iface(InterfaceSounds::SCROLL);
} else {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
}
@@ -1091,13 +1091,13 @@ void control_config_toggle_modifier(int bit)
Assert(!(z & JOY_AXIS));
k = Control_config[z].key_id;
if (k < 0) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return;
}
control_config_bind_key(z, k ^ bit);
control_config_conflict_check();
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
void control_config_toggle_invert()
@@ -1118,7 +1118,7 @@ void control_config_do_bind()
game_flush();
// if ((Selected_line < 0) || (Cc_lines[Selected_line].cc_index & JOY_AXIS)) {
if (Selected_line < 0) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return;
}
@@ -1142,7 +1142,7 @@ void control_config_do_bind()
Search_mode = 0;
Last_key = -1;
Axis_override = -1;
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
void control_config_do_search()
@@ -1166,7 +1166,7 @@ void control_config_do_search()
Binding_mode = 0;
Search_mode = 1;
Last_key = -1;
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
void control_config_do_cancel(int fail = 0)
@@ -1189,9 +1189,9 @@ void control_config_do_cancel(int fail = 0)
Binding_mode = Search_mode = 0;
if (fail){
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
} else {
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
}
@@ -1206,13 +1206,13 @@ int control_config_accept()
}
if (i < NUM_TABS) {
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
return -1;
}
hud_squadmsg_save_keys(); // rebuild map for saving/restoring keys in squadmsg mode
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
gamesnd_play_iface(SND_COMMIT_PRESSED);
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
return 0;
}
@@ -1237,7 +1237,7 @@ void control_config_button_pressed(int n)
Tab = n;
Scroll_offset = Selected_line = 0;
control_config_list_prepare();
gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
gamesnd_play_iface(InterfaceSounds::SCREEN_MODE_PRESSED);
break;
case BIND_BUTTON:
@@ -1250,17 +1250,17 @@ void control_config_button_pressed(int n)
case SHIFT_TOGGLE:
control_config_toggle_modifier(KEY_SHIFTED);
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
case ALT_TOGGLE:
control_config_toggle_modifier(KEY_ALTED);
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
case INVERT_AXIS:
control_config_toggle_invert();
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
break;
case SCROLL_UP_BUTTON:
@@ -1281,7 +1281,7 @@ void control_config_button_pressed(int n)
case HELP_BUTTON:
launch_context_help();
gamesnd_play_iface(SND_HELP_PRESSED);
gamesnd_play_iface(InterfaceSounds::HELP_PRESSED);
break;
case RESET_BUTTON:
@@ -1799,7 +1799,7 @@ void control_config_do_frame(float frametime)
Scroll_offset = Selected_line = 0;
control_config_list_prepare();
gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
gamesnd_play_iface(InterfaceSounds::SCREEN_MODE_PRESSED);
break;
case KEY_TAB: // activate next tab
@@ -1810,7 +1810,7 @@ void control_config_do_frame(float frametime)
Scroll_offset = Selected_line = 0;
control_config_list_prepare();
gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
gamesnd_play_iface(InterfaceSounds::SCREEN_MODE_PRESSED);
break;
case KEY_LEFT:
@@ -1825,7 +1825,7 @@ void control_config_do_frame(float frametime)
}
}
gamesnd_play_iface(SND_SCROLL);
gamesnd_play_iface(InterfaceSounds::SCROLL);
break;
case KEY_RIGHT:
@@ -1837,7 +1837,7 @@ void control_config_do_frame(float frametime)
} else if (Selected_item > 1) {
Selected_item = -1;
}
gamesnd_play_iface(SND_SCROLL);
gamesnd_play_iface(InterfaceSounds::SCROLL);
break;
case KEY_BACKSP: // undo
@@ -1873,7 +1873,7 @@ void control_config_do_frame(float frametime)
Selected_item = 1;
}
gamesnd_play_iface(SND_USER_SELECT);
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
}
if (List_buttons[i].double_clicked()) {
@@ -2379,7 +2379,7 @@ void control_get_axes_readings(int *h, int *p, int *b, int *ta, int *tr)
*ta = 0;
if (Axis_map_to[3] >= 0) {
*ta = joy_get_unscaled_reading(axes_values[Axis_map_to[3]], Axis_map_to[3]);
*ta = joy_get_unscaled_reading(axes_values[Axis_map_to[3]]);
}
*tr = 0;
+5 -5
View File
@@ -7,8 +7,8 @@
*
*/
#include <stdio.h>
#include <stdarg.h>
#include <cstdio>
#include <cstdarg>
#include "cfile/cfile.h"
#include "controlconfig/controlsconfig.h"
@@ -201,7 +201,7 @@ config_item Control_config[CCFG_MAX + 1] = {
const char *Scan_code_text_german[] = {
"", "Esc", "1", "2", "3", "4", "5", "6",
"7", "8", "9", "0", "Akzent '", "Eszett", "R\x81""cktaste", "Tab",
"7", "8", "9", "0", "Akzent '", "Eszett", "R\x81""cktaste", "Tab", // NOLINT
"Q", "W", "E", "R", "T", "Z", "U", "I",
"O", "P", "\x9A", "+", "Eingabe", "Strg Links", "A", "S",
@@ -251,8 +251,8 @@ const char *Joy_button_text_german[] = {
};
const char *Scan_code_text_french[] = {
"", "\x90""chap", "1", "2", "3", "4", "5", "6",
"7", "8", "9", "0", "-", "=", "Fl\x82""che Ret.", "Tab",
"", "\x90""chap", "1", "2", "3", "4", "5", "6", // NOLINT
"7", "8", "9", "0", "-", "=", "Fl\x82""che Ret.", "Tab", // NOLINT
"Q", "W", "E", "R", "T", "Y", "U", "I",
"O", "P", "[", "]", "Entr\x82""e", "Ctrl Gauche", "A", "S",
+21
View File
@@ -14,6 +14,11 @@ bool Decoder::tryPopAudioData(AudioFramePtr& out) {
return res == queue_op_status::success;
}
bool Decoder::tryPopSubtitleData(SubtitleFramePtr& out) {
auto res = m_subtitleQueue->try_pull_front(out);
return res == queue_op_status::success;
}
bool Decoder::tryPopVideoFrame(VideoFramePtr& out) {
auto res = m_videoQueue->try_pull_front(out);
return res == queue_op_status::success;
@@ -24,6 +29,7 @@ void Decoder::initializeQueues(size_t queueSize) {
m_videoQueue.reset(new sync_bounded_queue<VideoFramePtr>(m_queueSize));
m_audioQueue.reset(new sync_bounded_queue<AudioFramePtr>(m_queueSize));
m_subtitleQueue.reset(new sync_bounded_queue<SubtitleFramePtr>(m_queueSize));
}
void Decoder::stopDecoder() {
@@ -31,6 +37,7 @@ void Decoder::stopDecoder() {
m_videoQueue->close();
m_audioQueue->close();
m_subtitleQueue->close();
}
bool Decoder::canPushAudioData() {
@@ -48,6 +55,20 @@ void Decoder::pushAudioData(AudioFramePtr&& data) {
}
}
bool Decoder::canPushSubtitleData() {
return !isSubtitleQueueFull();
}
void Decoder::pushSubtitleData(SubtitleFramePtr&& data) {
Assertion(data, "Invalid audio data passed!");
try {
m_subtitleQueue->push_back(std::move(data));
}
catch (sync_queue_is_closed&) {
// Ignore
}
}
bool Decoder::canPushVideoData() {
return !isVideoQueueFull();
}
+25 -2
View File
@@ -58,6 +58,14 @@ struct AudioFrame {
};
typedef std::unique_ptr<AudioFrame> AudioFramePtr;
struct SubtitleFrame {
double displayStartTime = -1.0;
double displayEndTime = -1.0;
SCP_string text;
};
typedef std::unique_ptr<SubtitleFrame> SubtitleFramePtr;
/**
* @brief Abstract class for decoding a video or audio stream
*
@@ -68,6 +76,7 @@ class Decoder {
private:
std::unique_ptr<sync_bounded_queue<VideoFramePtr>> m_videoQueue;
std::unique_ptr<sync_bounded_queue<AudioFramePtr>> m_audioQueue;
std::unique_ptr<sync_bounded_queue<SubtitleFramePtr>> m_subtitleQueue;
bool m_decoding;
size_t m_queueSize = 0;
@@ -96,7 +105,7 @@ class Decoder {
* @brief Returns the properties of the video
* @return The properties
*/
virtual MovieProperties getProperties() = 0;
virtual MovieProperties getProperties() const = 0;
/**
* @brief Starts decoding the video
@@ -107,7 +116,9 @@ class Decoder {
* @brief Determines if the video has audio
* @return @c true if audio is included in the video
*/
virtual bool hasAudio() = 0;
virtual bool hasAudio() const = 0;
virtual bool hasSubtitles() const = 0;
/**
* @brief Ends decoding of the video file
@@ -122,6 +133,14 @@ class Decoder {
bool tryPopAudioData(AudioFramePtr&);
bool isSubtitleQueueFull() { return m_subtitleQueue->size() == m_queueSize; }
bool isSubtitleFrameAvailable() { return !m_subtitleQueue->empty(); }
size_t getSubtitleQueueSize() { return m_subtitleQueue->size(); }
bool tryPopSubtitleData(SubtitleFramePtr&);
bool isVideoQueueFull() { return m_videoQueue->size() == m_queueSize; }
bool isVideoFrameAvailable() { return !m_videoQueue->empty(); }
@@ -141,6 +160,10 @@ class Decoder {
void pushAudioData(AudioFramePtr&& data);
bool canPushSubtitleData();
void pushSubtitleData(SubtitleFramePtr&& data);
bool canPushVideoData();
void pushFrameData(VideoFramePtr&& frame);
+95
View File
@@ -0,0 +1,95 @@
#include "VideoPresenter.h"
#include "graphics/matrix.h"
using namespace cutscene;
using namespace cutscene::player;
namespace {
struct movie_vertex {
vec2d pos;
vec2d uv;
};
}
namespace cutscene {
namespace player {
VideoPresenter::VideoPresenter(const MovieProperties& props) {
GR_DEBUG_SCOPE("Init video");
auto w = static_cast<int>(props.size.width);
auto h = static_cast<int>(props.size.height);
// Create buffer textures
_yTexBuffer.reset(new uint8_t[w * h]);
_ytex = bm_create(8, w, h, _yTexBuffer.get(), BMP_AABITMAP);
_uTexBuffer.reset(new uint8_t[w / 2 * h / 2]);
_utex = bm_create(8, w / 2, h / 2, _uTexBuffer.get(), BMP_AABITMAP);
_vTexBuffer.reset(new uint8_t[w / 2 * h / 2]);
_vtex = bm_create(8, w / 2, h / 2, _vTexBuffer.get(), BMP_AABITMAP);
material_set_movie(&_render_material, _ytex, _utex, _vtex);
}
VideoPresenter::~VideoPresenter() {
GR_DEBUG_SCOPE("Deinit video");
bm_release(_ytex);
bm_release(_utex);
bm_release(_vtex);
_ytex = _utex = _vtex = -1;
}
void VideoPresenter::uploadVideoFrame(const VideoFramePtr& frame) {
GR_DEBUG_SCOPE("Update video frame");
auto ptrs = frame->getDataPointers();
memcpy(_yTexBuffer.get(), ptrs.y, frame->ySize.stride * frame->ySize.height);
memcpy(_uTexBuffer.get(), ptrs.u, frame->uvSize.stride * frame->uvSize.height);
memcpy(_vTexBuffer.get(), ptrs.v, frame->uvSize.stride * frame->uvSize.height);
gr_update_texture(_ytex, 8, _yTexBuffer.get(), (int) frame->ySize.width, (int) frame->ySize.height);
gr_update_texture(_utex, 8, _uTexBuffer.get(), (int) frame->uvSize.width, (int) frame->uvSize.height);
gr_update_texture(_vtex, 8, _vTexBuffer.get(), (int) frame->uvSize.width, (int) frame->uvSize.height);
}
void VideoPresenter::displayFrame(float x1, float y1, float x2, float y2) {
GR_DEBUG_SCOPE("Draw video frame");
movie_vertex vertex_data[4];
vertex_data[0].pos.x = x1;
vertex_data[0].pos.y = y1;
vertex_data[0].uv.x = 0.0f;
vertex_data[0].uv.y = 0.0f;
vertex_data[1].pos.x = x1;
vertex_data[1].pos.y = y2;
vertex_data[1].uv.x = 0.0f;
vertex_data[1].uv.y = 1.0f;
vertex_data[2].pos.x = x2;
vertex_data[2].pos.y = y1;
vertex_data[2].uv.x = 1.0f;
vertex_data[2].uv.y = 0.0f;
vertex_data[3].pos.x = x2;
vertex_data[3].pos.y = y2;
vertex_data[3].uv.x = 1.0f;
vertex_data[3].uv.y = 1.0f;
// Use the immediate buffer for storing our data since that is exactly what we need
auto offset = gr_add_to_immediate_buffer(sizeof(vertex_data), vertex_data);
vertex_layout layout;
layout.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex_data[0]), offset + offsetof(movie_vertex, pos));
layout.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(vertex_data[0]), offset + offsetof(movie_vertex, uv));
gr_render_movie(&_render_material, PRIM_TYPE_TRISTRIP, &layout, 4, gr_immediate_buffer_handle);
}
}
}
+42
View File
@@ -0,0 +1,42 @@
#ifndef FS2_OPEN_OPENGLVIDEOPRESENTER_H
#define FS2_OPEN_OPENGLVIDEOPRESENTER_H
#include "globalincs/pstypes.h"
#include "graphics/2d.h"
#include "graphics/material.h"
#include "cutscene/Decoder.h"
#include <memory>
namespace cutscene {
namespace player {
class VideoPresenter {
int _ytex = -1;
std::unique_ptr<uint8_t[]> _yTexBuffer;
int _utex = -1;
std::unique_ptr<uint8_t[]> _uTexBuffer;
int _vtex = -1;
std::unique_ptr<uint8_t[]> _vTexBuffer;
movie_material _render_material;
public:
explicit VideoPresenter(const MovieProperties& props);
// Disallow copying
VideoPresenter(const VideoPresenter&) = delete;
VideoPresenter& operator=(const VideoPresenter&) = delete;
virtual ~VideoPresenter();
void uploadVideoFrame(const VideoFramePtr& frame);
void displayFrame(float x1, float y1, float x2, float y2);
};
}
}
#endif //FS2_OPEN_OPENGLVIDEOPRESENTER_H
+12 -12
View File
@@ -286,10 +286,10 @@ void cutscenes_screen_scroll_line_up()
if (Selected_line)
{
Selected_line--;
gamesnd_play_iface(SND_SCROLL);
gamesnd_play_iface(InterfaceSounds::SCROLL);
} else
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
if (Selected_line < Scroll_offset)
Scroll_offset = Selected_line;
@@ -302,10 +302,10 @@ void cutscenes_screen_scroll_line_down()
if (Selected_line < (int) Cutscene_list.size() - 1)
{
Selected_line++;
gamesnd_play_iface(SND_SCROLL);
gamesnd_play_iface(InterfaceSounds::SCROLL);
} else
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
if (Selected_line >= Scroll_offset + h)
@@ -328,11 +328,11 @@ void cutscenes_screen_scroll_screen_up()
Selected_line--;
}
gamesnd_play_iface(SND_SCROLL);
gamesnd_play_iface(InterfaceSounds::SCROLL);
} else
{
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
}
@@ -349,10 +349,10 @@ void cutscenes_screen_scroll_screen_down()
Selected_line = Scroll_offset;
}
gamesnd_play_iface(SND_SCROLL);
gamesnd_play_iface(InterfaceSounds::SCROLL);
} else
{
gamesnd_play_iface(SND_GENERAL_FAIL);
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
}
}
@@ -361,17 +361,17 @@ int cutscenes_screen_button_pressed(int n)
switch (n)
{
case TECH_DATABASE_BUTTON:
gamesnd_play_iface(SND_SWITCH_SCREENS);
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
gameseq_post_event(GS_EVENT_TECH_MENU);
return 1;
case SIMULATOR_BUTTON:
gamesnd_play_iface(SND_SWITCH_SCREENS);
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
return 1;
case CREDITS_BUTTON:
gamesnd_play_iface(SND_SWITCH_SCREENS);
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
gameseq_post_event(GS_EVENT_CREDITS);
return 1;
@@ -388,7 +388,7 @@ int cutscenes_screen_button_pressed(int n)
break;
case EXIT_BUTTON:
gamesnd_play_iface(SND_COMMIT_PRESSED);
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
gameseq_post_event(GS_EVENT_MAIN_MENU);
game_flush();
break;
+3
View File
@@ -55,6 +55,9 @@ int resample_convert(SwrContext* ctx, uint8_t** output,
#ifdef WITH_LIBAV
return avresample_convert(ctx, output, out_plane_size, out_samples, input, in_plane_size, in_samples);
#else
(void)out_plane_size;
(void)in_plane_size;
return swr_convert(ctx, output, out_samples, (const uint8_t**) input, in_samples);
#endif
}
+3 -3
View File
@@ -25,11 +25,11 @@ class AudioDecoder: public FFMPEGStreamDecoder<AudioFrame> {
public:
explicit AudioDecoder(DecoderStatus* status);
virtual ~AudioDecoder();
~AudioDecoder() override;
virtual void decodePacket(AVPacket* packet) SCP_OVERRIDE;
void decodePacket(AVPacket* packet) override;
virtual void finishDecoding() SCP_OVERRIDE;
void finishDecoding() override;
};
}
}
+228 -22
View File
@@ -9,6 +9,10 @@
#include "cutscene/ffmpeg/AudioDecoder.h"
#include "cutscene/ffmpeg/VideoDecoder.h"
#include "cutscene/ffmpeg/SubtitleDecoder.h"
#include "FFMPEGDecoder.h"
#include "localization/localize.h"
using namespace libs::ffmpeg;
@@ -36,6 +40,8 @@ const char* CHECKED_EXTENSIONS[] = {
"mve"
};
const char *CHECKED_SUBT_EXTENSIONS[] = {"srt"};
double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
auto fps = av_q2d(av_stream_get_r_frame_rate(stream));
@@ -52,26 +58,48 @@ double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
return fps;
}
CodecContextParameters getCodecParameters(AVStream* stream) {
CodecContextParameters getCodecParameters(AVStream *stream) {
CodecContextParameters paras;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
paras.width = stream->codecpar->width;
paras.height = stream->codecpar->height;
paras.width = stream->codecpar->width;
paras.height = stream->codecpar->height;
paras.pixel_format = (AVPixelFormat)stream->codecpar->format;
paras.channel_layout = stream->codecpar->channel_layout;
paras.sample_rate = stream->codecpar->sample_rate;
paras.audio_format = (AVSampleFormat)stream->codecpar->format;
paras.sample_rate = stream->codecpar->sample_rate;
paras.audio_format = (AVSampleFormat)stream->codecpar->format;
paras.codec_id = stream->codecpar->codec_id;
#else
paras.width = stream->codec->width;
paras.height = stream->codec->height;
paras.width = stream->codec->width;
paras.height = stream->codec->height;
paras.pixel_format = stream->codec->pix_fmt;
paras.channel_layout = stream->codec->channel_layout;
paras.sample_rate = stream->codec->sample_rate;
paras.audio_format = stream->codec->sample_fmt;
paras.sample_rate = stream->codec->sample_rate;
paras.audio_format = stream->codec->sample_fmt;
paras.codec_id = stream->codec->codec_id;
#endif
return paras;
return paras;
}
SCP_string normalizeLanguage(const char *langauge_name) {
if (!stricmp(langauge_name, "eng")) {
return "English";
}
if (!stricmp(langauge_name, "ger")) {
return "German";
}
if (!stricmp(langauge_name, "spa")) {
return "Spanish";
}
// Print to log so that we can find the actual value more easily later
mprintf(("FFmpeg log: Found unknown language value '%s'!\n", langauge_name));
// Default to english for everything else
return "English";
}
}
@@ -118,7 +146,8 @@ std::unique_ptr<InputStream> openStream(const SCP_string& name) {
return input;
}
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& stream) {
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream> &stream,
std::unique_ptr<InputStream> &subt) {
std::unique_ptr<DecoderStatus> status(new DecoderStatus());
auto ctx = stream->m_ctx->ctx();
@@ -140,7 +169,7 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
if (audioStream < 0) {
if (audioStream == AVERROR_STREAM_NOT_FOUND) {
mprintf(("FFmpeg: No audio stream found in file!\n"));
} else if (videoStream == AVERROR_DECODER_NOT_FOUND) {
} else if (audioStream == AVERROR_DECODER_NOT_FOUND) {
mprintf(("FFmpeg: Codec for audio stream could not be found!\n"));
} else {
mprintf(("FFmpeg: Unknown error while finding audio stream!\n"));
@@ -155,7 +184,54 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
status->audioStream = ctx->streams[audioStream];
}
status->videoCodecPars = getCodecParameters(status->videoStream);
if (subt) {
auto subtCtx = subt->m_ctx->ctx();
auto subtStream = av_find_best_stream(subtCtx, AVMEDIA_TYPE_SUBTITLE, -1, -1, nullptr, 0);
if (subtStream < 0) {
if (subtStream == AVERROR_STREAM_NOT_FOUND) {
mprintf(("FFmpeg: No subtitle stream found in subtitle file!\n"));
} else if (subtStream == AVERROR_DECODER_NOT_FOUND) {
mprintf(("FFmpeg: Codec for subtitle stream could not be found!\n"));
} else {
mprintf(("FFmpeg: Unknown error while finding subtitle stream!\n"));
}
} else {
status->subtitleStream = subtCtx->streams[subtStream];
status->externalSubtitles = true;
status->subtitleStreamIndex = subtStream;
}
}
if (status->subtitleStream == nullptr) {
// We don't have an external subtitle stream or loading from that file has failed
auto &current_language = Lcl_languages[Lcl_current_lang];
for (uint32_t i = 0; i < ctx->nb_streams; ++i) {
auto test_stream = ctx->streams[i];
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
auto &pars = test_stream->codecpar;
if (!(pars->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
continue;
}
#endif
AVDictionaryEntry *tag = nullptr;
if ((tag = av_dict_get(test_stream->metadata, "language", nullptr, 0)) == nullptr) {
continue;
}
auto normalized_language = normalizeLanguage(tag->value);
if (!stricmp(normalized_language.c_str(), current_language.lang_name)) {
status->subtitleStreamIndex = i;
status->subtitleStream = test_stream;
break;
}
}
}
status->videoCodecPars = getCodecParameters(status->videoStream);
int err;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
@@ -213,6 +289,38 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
status->audioCodec->name ? status->audioCodec->name : "<Unknown>"));
}
if (status->subtitleStream != nullptr) {
// Not really sure if this makes sense for subtitles but it shouldn't break anything...
status->subtitleCodecPars = getCodecParameters(status->subtitleStream);
status->subtitleCodec = avcodec_find_decoder(status->subtitleCodecPars.codec_id);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
status->subtitleCodecCtx = avcodec_alloc_context3(status->subtitleCodec);
err = avcodec_parameters_to_context(status->subtitleCodecCtx, status->subtitleStream->codecpar);
if (err < 0) {
char errorStr[512];
av_strerror(err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to copy context parameters! Error: %s\n", errorStr));
return nullptr;
}
#else
status->subtitleCodecCtx = status->subtitleStream->codec;
#endif
err = avcodec_open2(status->subtitleCodecCtx, status->subtitleCodec, nullptr);
if (err < 0) {
char errorStr[512];
av_strerror(err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to open subtitle codec! Error: %s\n", errorStr));
}
mprintf(("FFmpeg: Using subtitle codec %s (%s).\n",
status->subtitleCodec->long_name ? status->subtitleCodec->long_name : "<Unknown>",
status->subtitleCodec->name ? status->subtitleCodec->name : "<Unknown>"));
}
return status;
}
@@ -231,6 +339,27 @@ std::unique_ptr<InputStream> openInputStream(const SCP_string& name) {
return nullptr;
}
std::unique_ptr<InputStream> openSubtitleStream(const SCP_string &name) {
auto &current_language = Lcl_languages[Lcl_current_lang];
for (auto ext : CHECKED_SUBT_EXTENSIONS) {
SCP_string fileName;
if (strlen(current_language.lang_ext) == 0) {
fileName = name + "." + ext;
} else {
fileName = name + "-" + current_language.lang_ext + "." + ext;
}
auto input = openStream(fileName);
if (input) {
return input;
}
}
return nullptr;
}
}
bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
@@ -250,8 +379,10 @@ bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
return false;
}
auto subt = openSubtitleStream(movieName);
// We now have a valid input stream, try to find the correct streams
auto status = initializeStatus(input);
auto status = initializeStatus(input, subt);
if (!status) {
return false;
}
@@ -261,11 +392,12 @@ bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
// We're done, now just put the pointer into this
std::swap(m_input, input);
std::swap(m_subtitleInput, subt);
std::swap(m_status, status);
return true;
}
MovieProperties FFMPEGDecoder::getProperties() {
MovieProperties FFMPEGDecoder::getProperties() const {
MovieProperties props;
props.size.width = static_cast<size_t>(m_status->videoCodecPars.width);
props.size.height = static_cast<size_t>(m_status->videoCodecPars.height);
@@ -279,10 +411,22 @@ void FFMPEGDecoder::startDecoding() {
std::unique_ptr<VideoDecoder> videoDecoder(new VideoDecoder(m_status.get()));
std::unique_ptr<AudioDecoder> audioDecoder;
std::unique_ptr<SubtitleDecoder> subtitleDecoder;
if (hasAudio()) {
audioDecoder.reset(new AudioDecoder(m_status.get()));
}
if (hasSubtitles()) {
subtitleDecoder.reset(new SubtitleDecoder(m_status.get()));
}
std::unique_ptr<std::thread> subtitle_thread;
if (hasExternalSubtitle()) {
// Start a new thread for the subtitles since otherwise we would need to make sure that neither of the input
// streames starves while the other waits for more space in the queues
subtitle_thread.reset(
new std::thread([this, &subtitleDecoder]() { runSubtitleDecoder(subtitleDecoder.get()); }));
}
auto ctx = m_input->m_ctx->ctx();
AVPacket packet;
@@ -290,13 +434,13 @@ void FFMPEGDecoder::startDecoding() {
auto read_err = av_read_frame(ctx, &packet);
AVPacketScope scope(&packet);
if (avio_feof(ctx->pb) != 0) {
// EOF!!
break;
} else if (read_err < 0) {
if (read_err < 0) {
if (read_err == AVERROR_EOF) {
// Finished reading -> break out of loop
break;
} else if (avio_feof(ctx->pb) != 0) {
// Also EOF!
break;
} else {
// Some kind of other error, try to continue reading
char errorStr[512];
@@ -322,6 +466,13 @@ void FFMPEGDecoder::startDecoding() {
while ((ptr = audioDecoder->getFrame()) != nullptr) {
pushAudioData(std::move(ptr));
}
} else if (subtitleDecoder && packet.stream_index == m_status->subtitleStreamIndex) {
subtitleDecoder->decodePacket(&packet);
SubtitleFramePtr ptr;
while ((ptr = subtitleDecoder->getFrame()) != nullptr) {
pushSubtitleData(std::move(ptr));
}
}
}
@@ -342,12 +493,18 @@ void FFMPEGDecoder::startDecoding() {
}
}
if (subtitle_thread) {
subtitle_thread->join();
}
stopDecoder();
}
bool FFMPEGDecoder::hasAudio() {
return m_status->audioStreamIndex >= 0;
}
bool FFMPEGDecoder::hasAudio() const { return m_status->audioStreamIndex >= 0; }
bool FFMPEGDecoder::hasSubtitles() const { return m_status->subtitleStream != nullptr; }
bool FFMPEGDecoder::hasExternalSubtitle() const { return m_status->externalSubtitles; }
void FFMPEGDecoder::close() {
if (m_status) {
@@ -358,6 +515,55 @@ void FFMPEGDecoder::close() {
// This will delete the InputStream pointer and free all data
m_input = nullptr;
}
if (m_subtitleInput) {
m_subtitleInput = nullptr;
}
}
void FFMPEGDecoder::runSubtitleDecoder(SubtitleDecoder *decoder) {
auto ctx = m_subtitleInput->m_ctx->ctx();
AVPacket packet;
while (isDecoding()) {
auto read_err = av_read_frame(ctx, &packet);
AVPacketScope scope(&packet);
if (read_err < 0) {
if (read_err == AVERROR_EOF) {
// Finished reading -> break out of loop
break;
} else if (avio_feof(ctx->pb) != 0) {
// Also EOF!
break;
} else {
// Some kind of other error, try to continue reading
char errorStr[512];
av_strerror(read_err, errorStr, sizeof(errorStr));
mprintf(("FFMPEG: Failed to read frame! Error: %s\n", errorStr));
// Skip packet
continue;
}
}
if (packet.stream_index == m_status->subtitleStreamIndex) {
decoder->decodePacket(&packet);
SubtitleFramePtr ptr;
while ((ptr = decoder->getFrame()) != nullptr) {
pushSubtitleData(std::move(ptr));
}
}
}
if (isDecoding()) {
// If we are still alive then read the last frames from the decoders
decoder->finishDecoding();
SubtitleFramePtr ptr;
while ((ptr = decoder->getFrame()) != nullptr) {
pushSubtitleData(std::move(ptr));
}
}
}
}
}
+17 -7
View File
@@ -8,26 +8,36 @@ struct InputStream;
struct DecoderStatus;
class SubtitleDecoder;
class FFMPEGDecoder: public Decoder {
private:
std::unique_ptr<InputStream> m_input;
std::unique_ptr<InputStream> m_subtitleInput;
std::unique_ptr<DecoderStatus> m_status;
public:
bool hasExternalSubtitle() const;
void runSubtitleDecoder(SubtitleDecoder *decoder);
public:
FFMPEGDecoder();
virtual ~FFMPEGDecoder();
~FFMPEGDecoder() override;
bool initialize(const SCP_string& fileName) SCP_OVERRIDE;
bool initialize(const SCP_string& fileName) override;
MovieProperties getProperties() SCP_OVERRIDE;
MovieProperties getProperties() const override;
void startDecoding() SCP_OVERRIDE;
void startDecoding() override;
bool hasAudio() SCP_OVERRIDE;
bool hasAudio() const override;
void close() SCP_OVERRIDE;
bool hasSubtitles() const override;
void close() override;
};
}
}
+135
View File
@@ -0,0 +1,135 @@
//
//
#include "SubtitleDecoder.h"
namespace {
double getFrameTime(int64_t pts, AVRational time_base) {
return pts * av_q2d(time_base);
}
}
namespace cutscene {
namespace ffmpeg {
SubtitleDecoder::SubtitleDecoder(cutscene::ffmpeg::DecoderStatus* status) : FFMPEGStreamDecoder(status) {
}
SubtitleDecoder::~SubtitleDecoder() {
}
void SubtitleDecoder::decodePacket(AVPacket* packet) {
int finishedFrame = 0;
AVSubtitle subtitle;
auto result = avcodec_decode_subtitle2(m_status->subtitleCodecCtx, &subtitle, &finishedFrame, packet);
if (result >= 0 && finishedFrame) {
pushSubtitleFrame(packet, &subtitle);
avsubtitle_free(&subtitle);
}
}
void SubtitleDecoder::finishDecoding() {
// Handle those decoders that have a delay
AVPacket nullPacket;
memset(&nullPacket, 0, sizeof(nullPacket));
nullPacket.data = nullptr;
nullPacket.size = 0;
AVSubtitle subtitle;
while (true) {
int finishedFrame = 1;
auto err = avcodec_decode_subtitle2(m_status->subtitleCodecCtx, &subtitle, &finishedFrame, &nullPacket);
if (err < 0 || !finishedFrame) {
break;
}
pushSubtitleFrame(&nullPacket, &subtitle);
avsubtitle_free(&subtitle);
}
}
void SubtitleDecoder::pushSubtitleFrame(AVPacket* packet, AVSubtitle* subtitle) {
if (subtitle->format != 1) {
// Non-text subtitles are not supported yet.
mprintf(("FFmpeg: Detected a non-text subtitle! This is not supported yet!\n"));
return;
}
if (subtitle->num_rects < 1) {
return;
}
int64_t pts = subtitle->pts;
if (pts == AV_NOPTS_VALUE) {
pts = packet->pts;
}
if (pts == AV_NOPTS_VALUE) {
// Still no valid timestamp...
return;
}
auto packet_time = getFrameTime(pts, m_status->subtitleStream->time_base);
auto start_time = packet_time + (subtitle->start_display_time / 1000.0);
auto end_time = packet_time + (subtitle->end_display_time / 1000.0);
if (subtitle->end_display_time == 0 && m_status->subtitleStream->time_base.num != 0) {
end_time = packet_time + getFrameTime(packet->duration, m_status->subtitleStream->time_base);
}
SCP_string processed_text;
// For now we only use the first subtitle rectangle
auto subtitle_rect = subtitle->rects[0];
if (subtitle_rect->type == SUBTITLE_BITMAP) {
// Same as above, non-text subtitles are not supported yet.
mprintf(("FFmpeg: Detected a non-text subtitle! This is not supported yet!\n"));
return;
} else if (subtitle_rect->type == SUBTITLE_TEXT) {
// Subtitle does not need to be processed any further
processed_text = subtitle_rect->text;
} else if (subtitle_rect->type == SUBTITLE_ASS) {
SCP_string ass_text = subtitle_rect->ass;
// We are not interested in any of the other information contained in the ASS line but we still need to figure
// out where our text starts
auto comma_pos = ass_text.find(',');
for (auto i = 0; i < 8 && comma_pos != SCP_string::npos; ++i) {
comma_pos = ass_text.find(',', comma_pos + 1);
}
Assertion(comma_pos != SCP_string::npos, "Received an ill-formed ASS line from FFmpeg! Text was '%s'.", subtitle_rect->ass);
// This + 1 is safe since comma_pos points to a valid character so the next character is at worst the end of the string
processed_text = ass_text.substr(comma_pos + 1);
// ASS has a special sequence for new lines that needs to be converted to an actual new line
auto newline_pos = processed_text.find("\\N");
while(newline_pos != SCP_string::npos) {
processed_text.replace(newline_pos, 2, "\n");
newline_pos = processed_text.find("\\N");
}
} else {
mprintf(("FFmpeg: Detected unknown subtitle name in movie!\n"));
return;
}
// Remove \r from string. Some subtitles use \r\n for line breaks and we only support \n
auto ret_pos = processed_text.find('\r');
while(ret_pos != SCP_string::npos) {
processed_text.erase(ret_pos, 1);
ret_pos = processed_text.find('\r');
}
SubtitleFramePtr frame(new SubtitleFrame());
frame->text = processed_text;
frame->displayStartTime = start_time;
frame->displayEndTime = end_time;
pushFrame(std::move(frame));
}
}
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "cutscene/ffmpeg/internal.h"
#include "cutscene/ffmpeg/FFMPEGDecoder.h"
namespace cutscene {
namespace ffmpeg {
class SubtitleDecoder: public FFMPEGStreamDecoder<SubtitleFrame> {
public:
explicit SubtitleDecoder(DecoderStatus* status);
~SubtitleDecoder() override;
void decodePacket(AVPacket* packet) override;
void finishDecoding() override;
void pushSubtitleFrame(AVPacket* subtitle, AVSubtitle* pSubtitle);
};
}
}
+2 -2
View File
@@ -22,14 +22,14 @@ class FFMPEGVideoFrame: public VideoFrame {
FFMPEGVideoFrame() : frame(nullptr) {
}
virtual ~FFMPEGVideoFrame() {
~FFMPEGVideoFrame() override {
if (frame != nullptr) {
av_freep(&frame->data[0]);
av_frame_free(&frame);
}
}
virtual DataPointers getDataPointers() {
DataPointers getDataPointers() override {
DataPointers ptrs;
ptrs.y = frame->data[0];
ptrs.u = frame->data[1];
+3 -3
View File
@@ -15,11 +15,11 @@ class VideoDecoder: public FFMPEGStreamDecoder<VideoFrame> {
public:
explicit VideoDecoder(DecoderStatus* status);
virtual ~VideoDecoder();
~VideoDecoder() override;
virtual void decodePacket(AVPacket* packet) SCP_OVERRIDE;
void decodePacket(AVPacket* packet) override;
virtual void finishDecoding() SCP_OVERRIDE;
void finishDecoding() override;
};
}
}
+12
View File
@@ -30,6 +30,18 @@ DecoderStatus::~DecoderStatus() {
#endif
audioCodecCtx = nullptr;
}
subtitleStreamIndex = -1;
subtitleStream = nullptr;
subtitleCodec = nullptr;
if (subtitleCodecCtx != nullptr) {
avcodec_close(subtitleCodecCtx);
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
avcodec_free_context(&subtitleCodecCtx);
#endif
subtitleCodecCtx = nullptr;
}
}
} // namespace ffmpeg
+10
View File
@@ -16,6 +16,8 @@ struct CodecContextParameters {
uint64_t channel_layout = 0;
int sample_rate = -1;
AVSampleFormat audio_format = AV_SAMPLE_FMT_NONE;
AVCodecID codec_id = AV_CODEC_ID_NONE;
};
struct DecoderStatus {
@@ -31,6 +33,14 @@ struct DecoderStatus {
AVCodec* audioCodec = nullptr;
AVCodecContext* audioCodecCtx = nullptr;
// Subtitles are a bit different since they max come from a different file
bool externalSubtitles = false;
int subtitleStreamIndex = -1;
AVStream* subtitleStream = nullptr;
CodecContextParameters subtitleCodecPars;
AVCodec* subtitleCodec = nullptr;
AVCodecContext* subtitleCodecCtx = nullptr;
DecoderStatus();
~DecoderStatus();
+200 -1
View File
@@ -14,6 +14,7 @@
#endif
#include "globalincs/pstypes.h"
#include "globalincs/alphacolors.h"
#include "globalincs/systemvars.h"
#include "io/cursor.h"
#include "graphics/2d.h"
@@ -21,10 +22,203 @@
#include "cmdline/cmdline.h"
#include "cutscene/cutscenes.h" // cutscene_mark_viewable()
#include "cutscene/player.h" // cutscene_mark_viewable()
#include "tracing/categories.h"
#include "tracing/tracing.h"
#include "io/timer.h"
#include "io/key.h"
#include "mod_table/mod_table.h"
extern int Game_mode;
extern int Is_standalone;
namespace {
using namespace cutscene;
struct PlaybackState {
bool playing = true;
vec2d posTopLeft;
vec2d posBottomRight;
int subtitle_font = -1;
};
void processEvents(PlaybackState* state) {
io::mouse::CursorManager::get()->showCursor(false);
os_poll();
int k = key_inkey();
switch (k) {
case KEY_ESC:
case KEY_ENTER:
case KEY_SPACEBAR:
state->playing = false;
break;
default:
break;
}
}
template<typename... Args>
float print_string(float x, float y, const char* fmt, Args... params) {
SCP_string text;
sprintf(text, fmt, params...);
gr_string(x, y, text.c_str(), GR_RESIZE_NONE);
return y + font::get_current_font()->getHeight();
}
void showVideoInfo(const PlayerState& state) {
gr_set_color_fast(&Color_white);
font::set_font(font::FONT1);
float y = 200.f;
float x = 100.f;
y = print_string(x, y, "Movie FPS: %f", state.props.fps);
y = print_string(x, y, "Size: %dx%d", state.props.size.width, state.props.size.height);
y = gr_screen.max_h - 200.f;
size_t audio_queue_size = state.decoder->getAudioQueueSize();
if (state.hasAudio) {
ALint queued;
OpenAL_ErrorPrint(alGetSourcei(state.audioSid, AL_BUFFERS_QUEUED, &queued));
audio_queue_size += queued;
}
y = print_string(x, y, "Audio Queue size: " SIZE_T_ARG, audio_queue_size);
y = print_string(x, y, "Video Queue size: " SIZE_T_ARG, state.decoder->getVideoQueueSize());
y += font::get_current_font()->getHeight();
// Estimate the size of the video buffer
// We use YUV420p frames so one pixel uses 1.5 bytes of storage
size_t single_frame_size = (size_t) (state.props.size.width * state.props.size.height * 1.5);
size_t total_size = single_frame_size * state.decoder->getVideoQueueSize();
print_string(x, y, "Video buffer size: " SIZE_T_ARG "B", total_size);
}
void displayVideo(Player* player, PlaybackState* state) {
TRACE_SCOPE(tracing::CutsceneDrawVideoFrame);
GR_DEBUG_SCOPE("Display Video");
gr_clear();
player->draw(state->posTopLeft.x, state->posTopLeft.y, state->posBottomRight.x, state->posBottomRight.y);
auto subtitle = player->getCurrentSubtitle();
if (!subtitle.empty() && state->subtitle_font >= 0) {
gr_set_color_fast(&Color_bright_white);
font::set_font(state->subtitle_font);
int width;
int height;
gr_get_string_size(&width, &height, subtitle.c_str());
// Offset the subtitle by 20% of the viewport size from the bottom
auto y_offset = static_cast<int>((state->posBottomRight.y - state->posTopLeft.y) * 0.1);
auto center_x = (state->posBottomRight.x - state->posTopLeft.x) / 2;
auto text_x = center_x - width / 2;
auto text_y = state->posBottomRight.y - y_offset - height;
gr_string(text_x, text_y, subtitle.c_str(), GR_RESIZE_NONE);
}
if (Cmdline_show_video_info) {
showVideoInfo(player->getInternalState());
}
gr_flip();
}
void determine_display_positions(Player* player, PlaybackState* state) {
auto& props = player->getMovieProperties();
float screen_ratio = (float) gr_screen.center_w / (float) gr_screen.center_h;
float movie_ratio = (float) props.size.width / (float) props.size.height;
float scale_by;
if (screen_ratio > movie_ratio) {
scale_by = (float) gr_screen.center_h / (float) props.size.height;
} else {
scale_by = (float) gr_screen.center_w / (float) props.size.width;
}
float screenX;
float screenY;
if (!Cmdline_noscalevid && (scale_by != 1.0f)) {
screenX = ((gr_screen.center_w / 2.0f + gr_screen.center_offset_x) / scale_by) - (static_cast<int>(props.size.width) / 2.0f) + 0.5f;
screenY = ((gr_screen.center_h / 2.0f + gr_screen.center_offset_y) / scale_by) - (static_cast<int>(props.size.height) / 2.0f) + 0.5f;
} else {
// centers on 1024x768, fills on 640x480
screenX = i2fl(((gr_screen.center_w - static_cast<int>(props.size.width)) / 2) + gr_screen.center_offset_x);
screenY = i2fl(((gr_screen.center_h - static_cast<int>(props.size.height)) / 2) + gr_screen.center_offset_y);
}
// set additional values for screen width/height and UV coords
float screenXW = screenX + static_cast<int>(props.size.width);
float screenYH = screenY + static_cast<int>(props.size.height);
if (!Cmdline_noscalevid && (scale_by != 1.0f)) {
// Apply scaling
screenX *= scale_by;
screenY *= scale_by;
screenXW *= scale_by;
screenYH *= scale_by;
}
state->posTopLeft.x = screenX;
state->posTopLeft.y = screenY;
state->posBottomRight.x = screenXW;
state->posBottomRight.y = screenYH;
}
void initialize_player_state(Player* player, PlaybackState* state) {
determine_display_positions(player, state);
state->subtitle_font = font::FontManager::getFontIndex(Movie_subtitle_font);
if (state->subtitle_font < 0) {
Warning(LOCATION, "Failed to load subtitle font '%s'! Subtitles will be disabled.", Movie_subtitle_font.c_str());
}
}
void movie_display_loop(Player* player, PlaybackState* state) {
// Compute the maximum time we will sleep to make sure we can still maintain the movie FPS
// and not waste too much CPU time
// We will sleep at most half the time a frame would be displayed
auto sleepTime = static_cast<std::uint64_t>((1. / (4. * player->getMovieProperties().fps)) * 1000.);
auto lastDisplayTimestamp = timer_get_microseconds();
while (state->playing) {
TRACE_SCOPE(tracing::CutsceneStep);
auto timestamp = timer_get_microseconds();
auto passed = timestamp - lastDisplayTimestamp;
lastDisplayTimestamp = timestamp;
// Play as long as the player reports that there is more to display
state->playing = player->update(passed);
displayVideo(player, state);
processEvents(state);
if (passed < sleepTime) {
auto sleep = sleepTime - passed;
os_sleep(static_cast<uint>(sleep));
}
}
}
}
namespace movie {
// Play one movie
bool play(const char* name) {
@@ -57,7 +251,12 @@ bool play(const char* name) {
auto player = cutscene::Player::newPlayer(name);
if (player) {
player->startPlayback();
PlaybackState state;
initialize_player_state(player.get(), &state);
movie_display_loop(player.get(), &state);
player->stopPlayback();
} else {
// uh-oh, movie is invalid... Abory, Retry, Fail?
mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
+96 -176
View File
@@ -1,7 +1,7 @@
#include "cutscene/player.h"
#include "cutscene/Decoder.h"
#include "cutscene/player/VideoPresenter.h"
#include "cutscene/VideoPresenter.h"
#include "cutscene/ffmpeg/FFMPEGDecoder.h"
#include "graphics/2d.h"
@@ -19,62 +19,19 @@
#include "parse/parselo.h"
#include "cutscene/player/OpenGLVideoPresenter.h"
using namespace cutscene::player;
namespace cutscene {
struct PlayerState {
MovieProperties props;
Decoder* decoder = nullptr;
bool playing = true;
bool playbackHasBegun = false;
// Timing state
std::uint64_t playback_time = 0;
// Audio state
bool audioInited = false;
bool hasAudio = false;
ALuint audioSid = 0;
SCP_vector<ALuint> audioBuffers;
SCP_queue<ALuint> unqueuedAudioBuffers;
// Graphics state following
bool videoInited = false;
VideoFramePtr currentFrame;
VideoFramePtr nextFrame;
bool newFrameAdded = false;
std::unique_ptr<VideoPresenter> videoPresenter;
PlayerState() : decoder(nullptr), playing(true), playbackHasBegun(false),
playback_time(0),
audioInited(0), hasAudio(false), audioSid(0),
videoInited(false), newFrameAdded(false) {}
private:
PlayerState(const PlayerState&) SCP_DELETED_FUNCTION;
PlayerState& operator=(const PlayerState&) SCP_DELETED_FUNCTION;
};
}
namespace {
using namespace cutscene;
const int MAX_AUDIO_BUFFERS = 15;
Decoder* findDecoder(const SCP_string& name) {
std::unique_ptr<Decoder> findDecoder(const SCP_string& name) {
{
auto ffmpeg = new ffmpeg::FFMPEGDecoder();
std::unique_ptr<Decoder> ffmpeg(new ffmpeg::FFMPEGDecoder());
if (ffmpeg->initialize(name)) {
return ffmpeg;
}
delete ffmpeg;
}
return nullptr;
@@ -93,7 +50,7 @@ void videoPlaybackInit(PlayerState* state) {
Assert(state != NULL);
if (gr_screen.mode == GR_OPENGL) {
state->videoPresenter.reset(new OpenGLVideoPresenter(state->props));
state->videoPresenter.reset(new VideoPresenter(state->props));
}
state->videoInited = true;
@@ -163,7 +120,7 @@ void processVideoData(PlayerState* state) {
return;
}
while(currentTime >= state->nextFrame->frameTime) {
while (currentTime >= state->nextFrame->frameTime) {
// Move the next frame to the current frame slot
state->currentFrame = std::move(state->nextFrame);
@@ -184,6 +141,34 @@ void processVideoData(PlayerState* state) {
}
}
void processSubtitleData(PlayerState* state) {
SubtitleFramePtr ptr;
while (state->decoder->tryPopSubtitleData(ptr)) {
// Take all subtitle frames from our queue
state->queued_subtitles.push(std::move(ptr));
}
if (state->currentSubtitle && playbackGetTime(state) <= state->currentSubtitle->displayEndTime) {
// We currently have a frame and it it still being displayed so there is nothing for us to do here
return;
}
// Subtitle has expired so we don't need it anymore
state->currentSubtitle = nullptr;
while(!state->queued_subtitles.empty()) {
// Take a look at the first entry and check if it's time to display it yet
auto& nextSubtitle = state->queued_subtitles.front();
if (playbackGetTime(state) >= nextSubtitle->displayStartTime) {
state->currentSubtitle = std::move(nextSubtitle);
state->queued_subtitles.pop();
} else {
// The next subtitle should not be displayed yet so we are done here
break;
}
}
}
bool processAudioData(PlayerState* state) {
TRACE_SCOPE(tracing::CutsceneProcessAudioData);
@@ -191,7 +176,7 @@ bool processAudioData(PlayerState* state) {
if (state->decoder->hasAudio()) {
// Even if we don't play the sound we still need to remove it from the queue
AudioFramePtr audioData;
while(state->decoder->tryPopAudioData(audioData)) {
while (state->decoder->tryPopAudioData(audioData)) {
// Intentionally left empty
}
}
@@ -216,7 +201,9 @@ bool processAudioData(PlayerState* state) {
ALenum format = (audioData->channels == 2) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
OpenAL_ErrorCheck(alBufferData(buffer, format, audioData->audioData.data(),
OpenAL_ErrorCheck(alBufferData(buffer,
format,
audioData->audioData.data(),
static_cast<ALsizei>(audioData->audioData.size() * sizeof(short)),
static_cast<ALsizei>(audioData->rate)), return false);
@@ -269,82 +256,10 @@ void videoPlaybackClose(PlayerState* state) {
state->videoInited = false;
}
template<typename... Args>
float print_string(float x, float y, const char* fmt, Args... params) {
SCP_string text;
sprintf(text, fmt, params...);
gr_string(x, y, text.c_str(), GR_RESIZE_NONE);
return y + font::get_current_font()->getHeight();
}
void showVideoInfo(PlayerState* state) {
gr_set_color_fast(&Color_white);
float y = 200.f;
float x = 100.f;
y = print_string(x, y, "Movie FPS: %f", state->props.fps);
y = print_string(x, y, "Size: %dx%d", state->props.size.width, state->props.size.height);
y = gr_screen.max_h - 200.f;
size_t audio_queue_size = state->decoder->getAudioQueueSize();
if (state->hasAudio) {
ALint queued;
OpenAL_ErrorPrint(alGetSourcei(state->audioSid, AL_BUFFERS_QUEUED, &queued));
audio_queue_size += queued;
}
y = print_string(x, y, "Audio Queue size: " SIZE_T_ARG, audio_queue_size);
y = print_string(x, y, "Video Queue size: " SIZE_T_ARG, state->decoder->getVideoQueueSize());
y += font::get_current_font()->getHeight();
// Estimate the size of the video buffer
// We use YUV420p frames so one pixel uses 1.5 bytes of storage
size_t single_frame_size = (size_t) (state->props.size.width * state->props.size.height * 1.5);
size_t total_size = single_frame_size * state->decoder->getVideoQueueSize();
print_string(x, y, "Video buffer size: " SIZE_T_ARG "B", total_size);
}
void displayVideo(PlayerState* state) {
if (!state->currentFrame) {
return;
}
TRACE_SCOPE(tracing::CutsceneDrawVideoFrame);
gr_clear();
if (state->videoPresenter) {
state->videoPresenter->displayFrame();
}
if (Cmdline_show_video_info) {
showVideoInfo(state);
}
gr_flip();
}
void processEvents(PlayerState* state) {
io::mouse::CursorManager::get()->showCursor(false);
os_poll();
int k = key_inkey();
switch (k) {
case KEY_ESC:
case KEY_ENTER:
case KEY_SPACEBAR:
state->playing = false;
break;
default:
break;
}
}
bool shouldBeginPlayback(Decoder* decoder) {
auto video = decoder->isVideoQueueFull();
auto audio = decoder->isAudioQueueFull();
auto subtitles = decoder->isSubtitleQueueFull();
// Wait until one of the queues is full, that should make sure
// that we have enough frames at the beginning of playback and that
@@ -352,92 +267,79 @@ bool shouldBeginPlayback(Decoder* decoder) {
// or video at the beginning
// Also only wait while the decoder is still working. Otherwise we will wait indefinitely if the video
// is very short.
return (audio || video) || !decoder->isDecoding();
return (audio || video || subtitles) || !decoder->isDecoding();
}
}
namespace cutscene {
Player::Player() {
Player::Player(std::unique_ptr<Decoder>&& decoder) : m_decoder(std::move(decoder)) {
initPlayback();
}
Player::~Player() {
// If video is initialized it means that stopPlayback has not been called yet
if (m_state.videoInited) {
stopPlayback();
}
if (m_decoder) {
m_decoder->close();
}
}
void Player::processDecoderData(PlayerState* state) {
if (!state->playbackHasBegun) {
bool Player::processDecoderData() {
if (!m_state.playbackHasBegun) {
// Wait until video and audio are available
// If we don't have audio, don't wait for it (obviously...)
if (!shouldBeginPlayback(state->decoder)) {
return;
if (!shouldBeginPlayback(m_state.decoder)) {
return true;
}
state->playbackHasBegun = true;
m_state.playbackHasBegun = true;
}
TRACE_SCOPE(tracing::CutsceneProcessDecoder);
processVideoData(state);
processVideoData(&m_state);
auto audioPlaying = processAudioData(state);
processSubtitleData(&m_state);
auto audioPlaying = processAudioData(&m_state);
// Set the playing flag if the decoder is still active or there is still data available
auto decoding = m_decoder->isDecoding();
// Audio is pending if there is data left in the queue or of OpenAL is still playing audio
// Audio is pending if there is data left in the queue or if OpenAL is still playing audio
auto pendingAudio = (m_decoder->isAudioFrameAvailable() && m_decoder->hasAudio()) || audioPlaying;
auto pendingVideo = m_decoder->isVideoFrameAvailable();
state->playing = decoding || pendingAudio || pendingVideo;
return decoding || pendingAudio || pendingVideo;
}
void Player::startPlayback() {
void Player::initPlayback() {
Assertion(!m_state.videoInited, "Internal State has been initialized before! Create a new player for replaying a movie.");
m_decoderThread.reset(new std::thread(std::bind(&Player::decoderThread, this)));
PlayerState state;
state.props = m_decoder->getProperties();
state.decoder = m_decoder.get();
m_state.props = m_decoder->getProperties();
m_state.decoder = m_decoder.get();
// Compute the maximum time we will sleep to make sure we can still maintain the movie FPS
// and not waste too much CPU time
// We will sleep at most half the time a frame would be displayed
auto sleepTime = static_cast<std::uint64_t>((1. / (4. * state.props.fps)) * 1000.);
videoPlaybackInit(&m_state);
videoPlaybackInit(&state);
audioPlaybackInit(&state);
auto lastDisplayTimestamp = timer_get_microseconds();
while (state.playing) {
TRACE_SCOPE(tracing::CutsceneStep);
processDecoderData(&state);
displayVideo(&state);
processEvents(&state);
auto timestamp = timer_get_microseconds();
auto passed = timestamp - lastDisplayTimestamp;
lastDisplayTimestamp = timestamp;
if (state.playbackHasBegun) {
state.playback_time += passed;
}
if (passed < sleepTime) {
auto sleep = sleepTime - passed;
os_sleep(static_cast<uint>(sleep));
}
audioPlaybackInit(&m_state);
}
bool Player::update(uint64_t diff_time_micro) {
if (m_state.playbackHasBegun) {
m_state.playback_time += diff_time_micro;
}
return processDecoderData();
}
void Player::stopPlayback() {
m_decoder->stopDecoder();
audioPlaybackClose(&state);
videoPlaybackClose(&state);
audioPlaybackClose(&m_state);
videoPlaybackClose(&m_state);
m_decoderThread->join();
}
@@ -460,10 +362,28 @@ std::unique_ptr<Player> Player::newPlayer(const SCP_string& name) {
if (decoder == nullptr) {
return nullptr;
}
return std::unique_ptr<Player>(new Player(std::move(decoder)));
}
const PlayerState& Player::getInternalState() const {
return m_state;
}
const MovieProperties& Player::getMovieProperties() const {
return m_state.props;
}
void Player::draw(float x1, float y1, float x2, float y2) {
if (!m_state.currentFrame) {
return;
}
std::unique_ptr<Player> player(new Player());
player->m_decoder.reset(decoder);
return player;
if (m_state.videoPresenter) {
m_state.videoPresenter->displayFrame(x1, y1, x2, y2);
}
}
SCP_string Player::getCurrentSubtitle() {
if (!m_state.currentSubtitle) {
return "";
} else {
return m_state.currentSubtitle->text;
}
}
}
+89 -8
View File
@@ -5,11 +5,48 @@
#include <thread>
#include "globalincs/pstypes.h"
#include "sound/openal.h"
#include "Decoder.h"
#include "VideoPresenter.h"
namespace cutscene {
class Decoder;
struct PlayerState;
struct PlayerState {
MovieProperties props;
Decoder* decoder = nullptr;
bool playbackHasBegun = false;
// Timing state
std::uint64_t playback_time = 0;
// Audio state
bool audioInited = false;
bool hasAudio = false;
ALuint audioSid = 0;
SCP_vector<ALuint> audioBuffers;
SCP_queue<ALuint> unqueuedAudioBuffers;
// Graphics state following
bool videoInited = false;
VideoFramePtr currentFrame;
VideoFramePtr nextFrame;
bool newFrameAdded = false;
std::unique_ptr<player::VideoPresenter> videoPresenter;
SCP_queue<SubtitleFramePtr> queued_subtitles;
SubtitleFramePtr currentSubtitle;
PlayerState() {
}
PlayerState(const PlayerState&) = delete;
PlayerState& operator=(const PlayerState&) = delete;
};
/**
* @brief A movie player
@@ -20,22 +57,66 @@ class Player {
std::unique_ptr<std::thread> m_decoderThread;
void processDecoderData(PlayerState* state);
PlayerState m_state;
bool processDecoderData();
private:
Player(const Player&) = delete;
void decoderThread();
void initPlayback();
public:
Player();
explicit Player(std::unique_ptr<Decoder>&& decoder);
~Player();
Player(const Player&) = delete;
Player& operator=(const Player&) = delete;
/**
* @brief Begin playing the previously selected movie
*/
void startPlayback();
* @brief Update the player and increase display timestamp by specified delta time
* @param diff_time_micro The time to increase the display timestamp in microseconds (not milliseconds!)
* @return @c true if there is more content to display. @c false if the player reached the end of the movie and has
* displayed the last frame.
*/
bool update(uint64_t diff_time_micro);
/**
* @brief Gives access to the internal state of the player
*
* @warning This should only be used for debugging purposed!
*
* @return A reference to the internal state
*/
const PlayerState& getInternalState() const;
/**
* @brief Gets the properties of the movie that this player is displaying
* @return A reference to the movie properties
*/
const MovieProperties& getMovieProperties() const;
/**
* @brief Draws the current movie frame at the specified coordinates.
*
* This may not draw anything if there is currently not a frame to display.
*
* @param x1 The X coordinate of the top left corner
* @param y1 The Y coordinate of the top left corner
* @param x2 The X coordinate of the bottom right corner
* @param y2 The Y coordinate of the bottom right corner
*/
void draw(float x1, float y1, float x2, float y2);
SCP_string getCurrentSubtitle();
/**
* @brief Stops playback
*
* This is also automatically called when this instance is destroyed.
*/
void stopPlayback();
/**
* @brief Creates a player
@@ -1,223 +0,0 @@
#include "OpenGLVideoPresenter.h"
#include "graphics/opengl/gropenglstate.h"
#include "graphics/opengl/gropengltnl.h"
#include "graphics/opengl/gropengldraw.h"
using namespace cutscene;
using namespace cutscene::player;
namespace cutscene {
namespace player {
OpenGLVideoPresenter::OpenGLVideoPresenter(const MovieProperties& props) : _scaleVideo(false),
_ytex(0), _utex(0), _vtex(0) {
GR_DEBUG_SCOPE("Init video");
opengl_set_texture_target(GL_TEXTURE_2D);
_vertexBuffer = gr_create_vertex_buffer(true);
auto w = static_cast<int>(props.size.width);
auto h = static_cast<int>(props.size.height);
_sdr_handle = gr_maybe_create_shader(SDR_TYPE_VIDEO_PROCESS, 0);
glGenTextures(1, &_ytex);
glGenTextures(1, &_utex);
glGenTextures(1, &_vtex);
if (_ytex + _utex + _vtex == 0) {
throw std::runtime_error("Can't create a GL texture");
}
opengl_shader_set_current(_sdr_handle);
gr_set_lighting(false, false);
GL_state.SetAlphaBlendMode(ALPHA_BLEND_NONE);
GL_state.SetZbufferType(ZBUFFER_TYPE_NONE);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.SetTarget(GL_texture_target);
GL_state.Texture.Enable(_ytex);
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RED, w, h, 0, GL_RED,
GL_UNSIGNED_BYTE, NULL);
GL_state.Texture.SetActiveUnit(1);
GL_state.Texture.SetTarget(GL_texture_target);
GL_state.Texture.Enable(_utex);
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RED, w / 2, h / 2, 0, GL_RED,
GL_UNSIGNED_BYTE, NULL);
GL_state.Texture.SetActiveUnit(2);
GL_state.Texture.SetTarget(GL_texture_target);
GL_state.Texture.Enable(_vtex);
glTexParameteri(GL_texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// NOTE: using NULL instead of pixelbuf crashes some drivers, but then so does pixelbuf
glTexImage2D(GL_state.Texture.GetTarget(), 0, GL_RED, w / 2, h / 2, 0, GL_RED,
GL_UNSIGNED_BYTE, NULL);
float screen_ratio = (float) gr_screen.center_w / (float) gr_screen.center_h;
float movie_ratio = (float) props.size.width / (float) props.size.height;
float scale_by;
if (screen_ratio > movie_ratio) {
scale_by = (float) gr_screen.center_h / (float) props.size.height;
} else {
scale_by = (float) gr_screen.center_w / (float) props.size.width;
}
// don't bother setting anything if we aren't going to need it
if (!Cmdline_noscalevid && (scale_by != 1.0f)) {
vec3d scale;
scale.xyz.x = scale_by;
scale.xyz.y = scale_by;
scale.xyz.z = -1.0f;
gr_push_scale_matrix(&scale);
_scaleVideo = true;
}
int screenX;
int screenY;
if (_scaleVideo) {
screenX = fl2i(((gr_screen.center_w / 2.0f + gr_screen.center_offset_x) / scale_by) - (static_cast<int>(props.size.width) / 2.0f) + 0.5f);
screenY = fl2i(((gr_screen.center_h / 2.0f + gr_screen.center_offset_y) / scale_by) - (static_cast<int>(props.size.height) / 2.0f) + 0.5f);
} else {
// centers on 1024x768, fills on 640x480
screenX = ((gr_screen.center_w - static_cast<int>(props.size.width)) / 2) + gr_screen.center_offset_x;
screenY = ((gr_screen.center_h - static_cast<int>(props.size.height)) / 2) + gr_screen.center_offset_y;
}
// set additional values for screen width/height and UV coords
int screenXW = screenX + static_cast<int>(props.size.width);
int screenYH = screenY + static_cast<int>(props.size.height);
Current_shader->program->Uniforms.setUniformi("ytex", 0);
Current_shader->program->Uniforms.setUniformi("utex", 1);
Current_shader->program->Uniforms.setUniformi("vtex", 2);
Current_shader->program->Uniforms.setUniformMatrix4f("projMatrix", GL_projection_matrix);
Current_shader->program->Uniforms.setUniformMatrix4f("modelViewMatrix", GL_model_view_matrix);
GLfloat glVertices[4][4] = {{0}};
glVertices[0][0] = (GLfloat)screenX;
glVertices[0][1] = (GLfloat)screenY;
glVertices[0][2] = 0.0f;
glVertices[0][3] = 0.0f;
glVertices[1][0] = (GLfloat)screenX;
glVertices[1][1] = (GLfloat)screenYH;
glVertices[1][2] = 0.0f;
glVertices[1][3] = 1.0f;
glVertices[2][0] = (GLfloat)screenXW;
glVertices[2][1] = (GLfloat)screenY;
glVertices[2][2] = 1.0f;
glVertices[2][3] = 0.0f;
glVertices[3][0] = (GLfloat)screenXW;
glVertices[3][1] = (GLfloat)screenYH;
glVertices[3][2] = 1.0f;
glVertices[3][3] = 1.0f;
_vertexLayout.add_vertex_component(vertex_format_data::POSITION2, sizeof(glVertices[0]), 0);
_vertexLayout.add_vertex_component(vertex_format_data::TEX_COORD, sizeof(glVertices[0]), sizeof(GLfloat) * 2);
gr_update_buffer_data(_vertexBuffer, sizeof(glVertices[0]) * 4, glVertices);
}
OpenGLVideoPresenter::~OpenGLVideoPresenter() {
GR_DEBUG_SCOPE("Deinit video");
if (_scaleVideo) {
gr_pop_scale_matrix();
}
gr_delete_buffer(_vertexBuffer);
_vertexBuffer = -1;
GL_state.Texture.Delete(_ytex);
GL_state.Texture.Delete(_utex);
GL_state.Texture.Delete(_vtex);
glDeleteTextures(1, &_ytex);
glDeleteTextures(1, &_utex);
glDeleteTextures(1, &_vtex);
opengl_set_texture_target();
_ytex = _utex = _vtex = 0;
opengl_shader_set_current();
}
void OpenGLVideoPresenter::uploadVideoFrame(const VideoFramePtr& frame) {
GR_DEBUG_SCOPE("Update video frame");
auto ptrs = frame->getDataPointers();
auto stride = static_cast<GLint>(frame->ySize.stride);
auto width = static_cast<GLint>(frame->ySize.width);
auto height = static_cast<GLint>(frame->ySize.height);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.Enable(_ytex);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE,
ptrs.y);
stride = static_cast<int>(frame->uvSize.stride);
width = static_cast<int>(frame->uvSize.width);
height = static_cast<int>(frame->uvSize.height);
GL_state.Texture.SetActiveUnit(1);
GL_state.Texture.Enable(_utex);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE,
ptrs.u);
GL_state.Texture.SetActiveUnit(2);
GL_state.Texture.Enable(_vtex);
glTexSubImage2D(GL_state.Texture.GetTarget(), 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE,
ptrs.v);
// Reset this back to default
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
void OpenGLVideoPresenter::displayFrame() {
opengl_shader_set_current(_sdr_handle);
opengl_bind_buffer_object(_vertexBuffer);
opengl_bind_vertex_layout(_vertexLayout);
// Bind textures
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.Enable(_ytex);
GL_state.Texture.SetActiveUnit(1);
GL_state.Texture.Enable(_utex);
GL_state.Texture.SetActiveUnit(2);
GL_state.Texture.Enable(_vtex);
GR_DEBUG_SCOPE("Draw video frame");
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
}
@@ -1,38 +0,0 @@
#ifndef FS2_OPEN_OPENGLVIDEOPRESENTER_H
#define FS2_OPEN_OPENGLVIDEOPRESENTER_H
#include "globalincs/pstypes.h"
#include "cutscene/player/VideoPresenter.h"
#include <glad/glad.h>
#include <memory>
#include <graphics/2d.h>
namespace cutscene {
namespace player {
class OpenGLVideoPresenter: public VideoPresenter {
int _vertexBuffer = -1;
vertex_layout _vertexLayout;
int _sdr_handle = -1;
bool _scaleVideo = false;
GLuint _ytex = 0;
GLuint _utex = 0;
GLuint _vtex = 0;
public:
OpenGLVideoPresenter(const MovieProperties& props);
virtual ~OpenGLVideoPresenter();
virtual void uploadVideoFrame(const VideoFramePtr& frame) SCP_OVERRIDE;
virtual void displayFrame() SCP_OVERRIDE;
};
}
}
#endif //FS2_OPEN_OPENGLVIDEOPRESENTER_H
-21
View File
@@ -1,21 +0,0 @@
#ifndef FS2_OPEN_VIDEOPRESENTER_H
#define FS2_OPEN_VIDEOPRESENTER_H
#include "globalincs/pstypes.h"
#include "cutscene/Decoder.h"
namespace cutscene {
namespace player {
class VideoPresenter {
public:
virtual ~VideoPresenter() {}
virtual void uploadVideoFrame(const VideoFramePtr& frame) = 0;
virtual void displayFrame() = 0;
};
}
}
#endif //FS2_OPEN_VIDEOPRESENTER_H
+8 -8
View File
@@ -74,7 +74,7 @@ static void debris_start_death_roll(object *debris_obj, debris *debris_p)
// only play debris destroy sound if hull piece and it has been around for at least 2 seconds
if ( Missiontime > debris_p->time_started + 2*F1_0 ) {
snd_play_3d( &Snds[SND_MISSILE_IMPACT1], &debris_obj->pos, &View_position, debris_obj->radius );
snd_play_3d( gamesnd_get_game_sound(gamesnd_id(GameSounds::MISSILE_IMPACT1)), &debris_obj->pos, &View_position, debris_obj->radius );
}
}
@@ -238,7 +238,7 @@ void debris_process_post(object * obj, float frame_time)
radar_plot_object( obj );
if ( timestamp_elapsed(db->sound_delay) ) {
obj_snd_assign(objnum, SND_DEBRIS, &vmd_zero_vector, 0);
obj_snd_assign(objnum, GameSounds::DEBRIS, &vmd_zero_vector, 0);
db->sound_delay = 0;
}
} else {
@@ -324,19 +324,19 @@ void debris_process_post(object * obj, float frame_time)
//Play a sound effect
if ( lifetime > 750 ) {
// 1.00 second effect
snd_play_3d( &Snds[SND_DEBRIS_ARC_05], &snd_pos, &View_position, obj->radius );
snd_play_3d( gamesnd_get_game_sound(GameSounds::DEBRIS_ARC_05), &snd_pos, &View_position, obj->radius );
} else if ( lifetime > 500 ) {
// 0.75 second effect
snd_play_3d( &Snds[SND_DEBRIS_ARC_04], &snd_pos, &View_position, obj->radius );
snd_play_3d( gamesnd_get_game_sound(GameSounds::DEBRIS_ARC_04), &snd_pos, &View_position, obj->radius );
} else if ( lifetime > 250 ) {
// 0.50 second effect
snd_play_3d( &Snds[SND_DEBRIS_ARC_03], &snd_pos, &View_position, obj->radius );
snd_play_3d( gamesnd_get_game_sound(GameSounds::DEBRIS_ARC_03), &snd_pos, &View_position, obj->radius );
} else if ( lifetime > 100 ) {
// 0.25 second effect
snd_play_3d( &Snds[SND_DEBRIS_ARC_02], &snd_pos, &View_position, obj->radius );
snd_play_3d( gamesnd_get_game_sound(GameSounds::DEBRIS_ARC_02), &snd_pos, &View_position, obj->radius );
} else {
// 0.10 second effect
snd_play_3d( &Snds[SND_DEBRIS_ARC_01], &snd_pos, &View_position, obj->radius );
snd_play_3d( gamesnd_get_game_sound(GameSounds::DEBRIS_ARC_01), &snd_pos, &View_position, obj->radius );
}
}
}
@@ -693,7 +693,7 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
* Alas, poor debris_obj got whacked. Fortunately, we know who did it, where and how hard, so we
* can do something about it.
*/
void debris_hit(object *debris_obj, object *other_obj, vec3d *hitpos, float damage)
void debris_hit(object *debris_obj, object * /*other_obj*/, vec3d *hitpos, float damage)
{
debris *debris_p = &Debris[debris_obj->instance];
+2 -2
View File
@@ -162,7 +162,7 @@ void dc_do_command(SCP_string *cmd_str)
try {
dc_commands[i]->func(); // Run the command!
} catch (errParseString err) {
} catch (const errParseString& err) {
dc_printf("Require string(s) not found: \n");
for (uint j = 0; j < err.expected_tokens.size(); ++j) {
dc_printf("%i: %s\n", j, err.expected_tokens[j].c_str());
@@ -170,7 +170,7 @@ void dc_do_command(SCP_string *cmd_str)
dc_printf("Found '%s' instead\n", err.found_token.c_str());
} catch (errParse err) {
} catch (const errParse& err) {
dc_printf("Invalid argument. Expected %s, found '%s'\n", token_str[err.expected_type], err.found_token.c_str());
}
+1 -1
View File
@@ -20,7 +20,7 @@
#include <cmath>
#include <cstdarg>
#include <cstring>
#include <limits.h>
#include <climits>
// ========================= LOCALS =========================
+541
View File
@@ -0,0 +1,541 @@
#include <nebula/neb.h>
#include <utility>
#include "decals/decals.h"
#include "graphics/2d.h"
#include "graphics/decal_draw_list.h"
#include "graphics/util/uniform_structs.h"
#include "parse/parselo.h"
#include "tracing/tracing.h"
#include "ship/ship.h"
namespace {
class DecalDefinition {
SCP_string _name;
SCP_string _diffuseFilename;
bool _loopDiffuse = true;
SCP_string _glowFilename;
bool _loopGlow = true;
SCP_string _normalMapFilename;
bool _loopNormal = true;
int _diffuseBitmap = -1;
int _glowBitmap = -1;
int _normalBitmap = -1;
public:
explicit DecalDefinition(SCP_string name) : _name(std::move(name)) {
}
~DecalDefinition() {
if (_diffuseBitmap >= 0) {
bm_release(_diffuseBitmap);
}
if (_glowBitmap >= 0) {
bm_release(_glowBitmap);
}
if (_normalBitmap >= 0) {
bm_release(_normalBitmap);
}
}
// Disallow copying
DecalDefinition(const DecalDefinition&) = delete;
DecalDefinition& operator=(const DecalDefinition&) = delete;
// Move constructor and operator
DecalDefinition(DecalDefinition&& other) SCP_NOEXCEPT {
*this = std::move(other); // Use operator implementation
}
DecalDefinition& operator=(DecalDefinition&& other) SCP_NOEXCEPT {
std::swap(_name, other._name);
std::swap(_diffuseFilename, other._diffuseFilename);
std::swap(_glowFilename, other._glowFilename);
std::swap(_normalMapFilename, other._normalMapFilename);
std::swap(_diffuseBitmap, other._diffuseBitmap);
std::swap(_glowBitmap, other._glowBitmap);
std::swap(_normalBitmap, other._normalBitmap);
std::swap(_loopDiffuse, other._loopDiffuse);
std::swap(_loopGlow, other._loopGlow);
std::swap(_loopNormal, other._loopNormal);
return *this;
}
void parse() {
if (optional_string("+Diffuse:")) {
stuff_string(_diffuseFilename, F_FILESPEC);
if (!bm_validate_filename(_diffuseFilename, true, true)) {
error_display(0, "Animation '%s' is not valid!", _diffuseFilename.c_str());
_diffuseFilename = "";
}
if (optional_string("+Loop:")) {
stuff_boolean(&_loopDiffuse);
}
}
if (optional_string("+Glow:")) {
stuff_string(_glowFilename, F_FILESPEC);
if (!bm_validate_filename(_glowFilename, true, true)) {
error_display(0, "Animation '%s' is not valid!", _glowFilename.c_str());
_glowFilename = "";
}
if (optional_string("+Loop:")) {
stuff_boolean(&_loopGlow);
}
}
if (optional_string("+Normal:")) {
stuff_string(_normalMapFilename, F_FILESPEC);
if (!bm_validate_filename(_normalMapFilename, true, true)) {
error_display(0, "Animation '%s' is not valid!", _normalMapFilename.c_str());
_normalMapFilename = "";
}
if (optional_string("+Loop:")) {
stuff_boolean(&_loopNormal);
}
}
}
void loadBitmaps() {
if (_diffuseBitmap == -1 && VALID_FNAME(_diffuseFilename)) {
_diffuseBitmap = bm_load_either(_diffuseFilename.c_str());
if (_diffuseBitmap == -1) {
Warning(LOCATION,
"Bitmap '%s' failed to load for decal definition %s!",
_diffuseFilename.c_str(),
_name.c_str());
}
}
if (_glowBitmap == -1 && VALID_FNAME(_glowFilename)) {
_glowBitmap = bm_load_either(_glowFilename.c_str());
if (_glowBitmap == -1) {
Warning(LOCATION,
"Bitmap '%s' failed to load for decal definition %s!",
_glowFilename.c_str(),
_name.c_str());
}
}
if (_normalBitmap == -1 && VALID_FNAME(_normalMapFilename)) {
_normalBitmap = bm_load_either(_normalMapFilename.c_str());
if (_normalBitmap == -1) {
Warning(LOCATION,
"Bitmap '%s' failed to load for decal definition %s!",
_normalMapFilename.c_str(),
_name.c_str());
}
}
}
void pageIn() {
if (_diffuseBitmap >= 0) {
bm_page_in_texture(_diffuseBitmap);
}
if (_glowBitmap >= 0) {
bm_page_in_texture(_glowBitmap);
}
if (_normalBitmap >= 0) {
bm_page_in_texture(_normalBitmap);
}
}
bool bitmapsLoaded() {
// Since both bitmap types are optional we need to check if either is loaded to determine if any bitmap is loaded
return _diffuseBitmap >= 0 || _glowBitmap >= 0 || _normalBitmap >= 0;
}
const SCP_string& getName() const {
return _name;
}
int getDiffuseBitmap() const {
return _diffuseBitmap;
}
int getGlowBitmap() const {
return _glowBitmap;
}
int getNormalBitmap() const {
return _normalBitmap;
}
bool isDiffuseLooping() const {
return _loopDiffuse;
}
bool isGlowLooping() const {
return _loopGlow;
}
bool isNormalLooping() const {
return _loopNormal;
}
};
SCP_vector<DecalDefinition> decalDefinitions;
// Variable to indicate if the system is able to work correctly on the current system
bool decal_system_active = true;
void parse_decals_table(const char* filename) {
try {
read_file_text(filename, CF_TYPE_TABLES);
reset_parse();
required_string("#Decals");
while (optional_string("$Decal:")) {
SCP_string name;
stuff_string(name, F_NAME);
DecalDefinition def(name);
def.parse();
decalDefinitions.push_back(std::move(def));
}
required_string("#End");
} catch (const parse::ParseException& e) {
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
return;
}
if (!gr_is_capable(CAPABILITY_DEFERRED_LIGHTING)) {
// we need deferred lighting
decal_system_active = false;
mprintf(("Note: Decal system has been disabled due to lack of deferred lighting.\n"));
}
if (!gr_is_capable(CAPABILITY_NORMAL_MAP)) {
// We need normal mapping for the full feature range
decal_system_active = false;
mprintf(("Note: Decal system has been disabled due to lack of normal mapping.\n"));
}
if (!gr_is_capable(CAPABILITY_SEPARATE_BLEND_FUNCTIONS)) {
// WWe need separate blending functions for different color buffers
decal_system_active = false;
mprintf(("Note: Decal system has been disabled due to lack of separate color buffer blend functions.\n"));
}
}
struct Decal {
int definition_handle = -1;
object_h object;
int submodel = -1;
float creation_time = -1.0f; //!< The mission time at which this decal was created
float lifetime = -1.0f; //!< The time this decal is active. When negative it never expires
vec3d position = vmd_zero_vector;
vec3d scale;
matrix orientation = vmd_identity_matrix;
Decal() {
vm_vec_make(&scale, 1.f, 1.f, 1.f);
}
bool isValid() {
if (!object.IsValid()) {
return false;
}
if (lifetime > 0.0f) {
if (f2fl(Missiontime) >= creation_time + lifetime) {
// Decal has expired
return false;
}
}
auto objp = object.objp;
if (objp->type == OBJ_SHIP) {
auto shipp = &Ships[objp->instance];
auto model_instance = model_get_instance(shipp->model_instance_num);
Assertion(submodel >= 0 && submodel < model_get(object_get_model(objp))->n_models,
"Invalid submodel number detected!");
auto smi = &model_instance->submodel[submodel];
if (smi->blown_off) {
return false;
}
}
return true;
}
};
SCP_vector<Decal> active_decals;
bool required_string_if_new(const char* token, bool new_entry) {
if (!new_entry) {
return optional_string(token) == 1;
}
required_string(token);
return true;
}
float clamp(float x, float min, float max) {
return std::min(std::max(x, min), max);
}
/**
* @brief Produces a smoothstep value as specified by the GLSL specification
* @param edge0
* @param edge1
* @param x
* @return
*/
float smoothstep(float edge0, float edge1, float x) {
auto t = clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
return t * t * (3.0f - 2.0f * t);
}
}
namespace decals {
void initialize() {
decalDefinitions.clear();
graphics::decal_draw_list::globalInit();
parse_modular_table(NOX("*-dcl.tbm"), parse_decals_table);
}
void shutdown() {
graphics::decal_draw_list::globalShutdown();
// Free allocated resources
decalDefinitions.clear();
}
int getDecalConfig(const SCP_string& name) {
int index = 0;
for (auto& def : decalDefinitions) {
if (!stricmp(def.getName().c_str(), name.c_str())) {
return index;
}
++index;
}
return -1;
}
void parseDecalReference(creation_info& dest_info, bool is_new_entry) {
SCP_string name;
stuff_string(name, F_NAME);
auto decalRef = getDecalConfig(name);
if (decalRef < 0) {
error_display(0, "Decal definition '%s' is unknown!", name.c_str());
}
dest_info.definition_handle = decalRef;
if (required_string_if_new("+Radius:", is_new_entry)) {
stuff_float(&dest_info.radius);
if (dest_info.radius <= 0.0f) {
error_display(0, "Invalid radius of %f! Must be a positive number.", dest_info.radius);
dest_info.radius = 1.0f;
}
}
if (required_string_if_new("+Lifetime:", is_new_entry)) {
if (optional_string("Eternal")) {
dest_info.lifetime = util::UniformFloatRange(-1.0f);
} else {
// Require at least a small lifetime so that the calculations don't have to deal with div-by-zero
dest_info.lifetime = util::parseUniformRange(0.0001f);
}
}
}
void loadBitmaps(const creation_info& info) {
if (!decal_system_active) {
return;
}
// Silently ignore invalid definition handle since weapons use the default values if the decal option is not present
if (info.definition_handle < 0) {
return;
}
Assertion(info.definition_handle >= 0 && info.definition_handle < (int) decalDefinitions.size(),
"Invalid decal handle detected!");
auto& def = decalDefinitions[info.definition_handle];
def.loadBitmaps();
}
void pageInDecal(const creation_info& info) {
if (!decal_system_active) {
return;
}
// Silently ignore invalid definition handle since weapons use the default values if the decal option is not present
if (info.definition_handle < 0) {
return;
}
Assertion(info.definition_handle >= 0 && info.definition_handle < (int) decalDefinitions.size(),
"Invalid decal handle detected!");
decalDefinitions[info.definition_handle].pageIn();
}
void initializeMission() {
active_decals.clear();
}
matrix4 getDecalTransform(Decal& decal) {
Assertion(decal.object.objp->type == OBJ_SHIP, "Only ships are currently supported for decals!");
auto objp = decal.object.objp;
auto ship = &Ships[objp->instance];
vec3d worldPos;
model_instance_find_world_point(&worldPos,
&decal.position,
ship->model_instance_num,
decal.submodel,
&objp->orient,
&objp->pos);
vec3d worldDir;
model_instance_find_world_dir(&worldDir,
&decal.orientation.vec.fvec,
ship->model_instance_num,
decal.submodel,
&objp->orient);
vec3d worldUp;
model_instance_find_world_dir(&worldUp,
&decal.orientation.vec.fvec,
ship->model_instance_num,
decal.submodel,
&objp->orient);
matrix worldOrient;
vm_vector_2_matrix(&worldOrient, &worldDir, &worldUp);
// Apply scaling
worldOrient.a2d[0][0] *= decal.scale.xyz.x;
worldOrient.a2d[0][1] *= decal.scale.xyz.x;
worldOrient.a2d[0][2] *= decal.scale.xyz.x;
worldOrient.a2d[1][0] *= decal.scale.xyz.y;
worldOrient.a2d[1][1] *= decal.scale.xyz.y;
worldOrient.a2d[1][2] *= decal.scale.xyz.y;
worldOrient.a2d[2][0] *= decal.scale.xyz.z;
worldOrient.a2d[2][1] *= decal.scale.xyz.z;
worldOrient.a2d[2][2] *= decal.scale.xyz.z;
matrix4 mat4;
vm_matrix4_set_transform(&mat4, &worldOrient, &worldPos);
return mat4;
}
void renderAll() {
if (!decal_system_active) {
return;
}
// Clear out any invalid decals
for (auto iter = active_decals.begin(); iter != active_decals.end(); ++iter) {
if (!iter->isValid()) {
// if we're sitting on the very last element, popping-back will invalidate the iterator!
if (iter + 1 == active_decals.end()) {
active_decals.pop_back();
break;
}
*iter = active_decals.back();
active_decals.pop_back();
continue;
}
}
if (active_decals.empty()) {
return;
}
graphics::decal_draw_list draw_list;
auto mission_time = f2fl(Missiontime);
for (auto& decal : active_decals) {
int diffuse_bm = -1;
int glow_bm = -1;
int normal_bm = -1;
Assertion(decal.definition_handle >= 0 && decal.definition_handle < (int) decalDefinitions.size(),
"Invalid decal handle detected!");
auto& decalDef = decalDefinitions[decal.definition_handle];
auto decal_time = mission_time - decal.creation_time;
auto progress = decal_time / decal.lifetime;
float alpha = 1.0f;
if (progress > 0.8) {
// Fade the decal out for the last 20% of its lifetime
alpha = 1.0f - smoothstep(0.8f, 1.0f, progress);
}
if (decalDef.getDiffuseBitmap() >= 0) {
diffuse_bm = decalDef.getDiffuseBitmap()
+ bm_get_anim_frame(decalDef.getDiffuseBitmap(), decal_time, 0.0f, decalDef.isDiffuseLooping());
}
if (decalDef.getGlowBitmap() >= 0) {
glow_bm = decalDef.getGlowBitmap()
+ bm_get_anim_frame(decalDef.getGlowBitmap(), decal_time, 0.0f, decalDef.isGlowLooping());
}
if (decalDef.getNormalBitmap() >= 0) {
normal_bm = decalDef.getNormalBitmap()
+ bm_get_anim_frame(decalDef.getNormalBitmap(), decal_time, 0.0f, decalDef.isNormalLooping());
}
draw_list.add_decal(diffuse_bm, glow_bm, normal_bm, decal_time, getDecalTransform(decal), alpha);
}
draw_list.render();
}
void
addDecal(creation_info& info, object* host, int submodel, const vec3d& local_pos, const matrix& local_orient) {
if (!decal_system_active) {
return;
}
// Silently ignore invalid definition handle since weapons use the default values if the decal option is not present
if (info.definition_handle < 0) {
return;
}
Assertion(info.definition_handle >= 0 && info.definition_handle < (int) decalDefinitions.size(),
"Invalid decal handle detected!");
auto& def = decalDefinitions[info.definition_handle];
if (!def.bitmapsLoaded()) {
// If this decal was never used before then the bitmaps are not loaded so we need to do that here.
def.loadBitmaps();
}
Decal newDecal;
newDecal.definition_handle = info.definition_handle;
newDecal.object = object_h(host);
newDecal.submodel = submodel;
newDecal.creation_time = f2fl(Missiontime);
newDecal.lifetime = info.lifetime.next();
newDecal.position = local_pos;
newDecal.orientation = local_orient;
newDecal.scale.xyz.x = info.radius;
newDecal.scale.xyz.y = info.radius;
newDecal.scale.xyz.z = info.radius;
active_decals.push_back(newDecal);
}
}
+87
View File
@@ -0,0 +1,87 @@
#pragma once
#include "globalincs/pstypes.h"
#include "object/object.h"
#include "utils/RandomRange.h"
namespace decals {
/**
* @brief A reference to a decal definition
*/
typedef int DecalReference;
/**
* @brief A structure containing all information for creating a decal
*/
struct creation_info {
DecalReference definition_handle = -1;
float radius = -1.0f;
util::UniformFloatRange lifetime = ::util::UniformFloatRange(-1.0f);
};
/**
* @brief Initializes the global state of the decal system. Call once at game init.
*/
void initialize();
/**
* @brief Parses the information for a decal reference
*
* @details This function expects that the initial token has already been consumed by the parse system.
*
* @param dest_info The creation information struct to parse the information into
* @param is_new_entry Set to @c false if the currently parsed object used +nocreate
*/
void parseDecalReference(creation_info& dest_info, bool is_new_entry = true);
/**
* @brief Loads the bitmaps specified by the creation info into texture memory
*
* This should be called when the bitmaps of the object using this decal are loaded.
*
* @param info The creation information containing the decal definition handle
*/
void loadBitmaps(const creation_info& info);
/**
* @brief Page in the bitmap data of the specified creation information. Needs to be called after loadBitmaps
* @param info The information to page in
*/
void pageInDecal(const creation_info& info);
/**
* @brief Shut down the decal system. Must be called from game_shutdown
*/
void shutdown();
/**
* @brief Initialize the decal system for the mission. Must be called before every mission is started
*/
void initializeMission();
/**
* @brief Renders all currently active decals and removes invalid decals from the active list.
*/
void renderAll();
/**
* @brief Creates a new decal on the specified object at the specified location
*
* @param info The decal to create
* @param host The object host on which to create this decal. Must be a ship.
* @param submodel The submodel of the object model on which to create the decal.
* @param local_pos The position in the frame of reference of the submodel at which the decal should be created.
* @param local_orient The orientation of the decal in the frame of reference of the submodel. The forward vector of the
* orientation should look along the direction
*/
void addDecal(creation_info& info,
object* host,
int submodel,
const vec3d& local_pos,
const matrix& local_orient);
}
-3
View File
@@ -1,3 +0,0 @@
#ControlConfigOverride
#End
+18
View File
@@ -0,0 +1,18 @@
#include "gamma.sdr"
in vec4 fragTexCoord;
in vec4 fragColor;
out vec4 fragOut0;
uniform sampler2DArray baseMap;
uniform float intensity;
void main()
{
vec4 baseColor = texture(baseMap, fragTexCoord.xyz);
baseColor.rgb = srgb_to_linear(baseColor.rgb);
vec4 blendColor = vec4(srgb_to_linear(fragColor.rgb), fragColor.a);
fragOut0 = baseColor * blendColor * intensity;
}
+14
View File
@@ -0,0 +1,14 @@
in vec4 vertPosition;
in vec4 vertTexCoord;
in vec4 vertColor;
out vec4 fragTexCoord;
out vec4 fragColor;
uniform mat4 modelViewMatrix;
uniform mat4 projMatrix;
uniform vec4 color;
void main()
{
fragTexCoord = vec4(vertTexCoord.xyz, 0.0);
fragColor = vertColor * color;
gl_Position = projMatrix * modelViewMatrix * vertPosition;
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
+180
View File
@@ -0,0 +1,180 @@
// NOTE: The technique and some of this code is based on this tutorial:
// http://martindevans.me/game-development/2015/02/27/Drawing-Stuff-On-Other-Stuff-With-Deferred-Screenspace-Decals/
#include "lighting.sdr"
#include "normals.sdr"
#include "gamma.sdr"
out vec4 fragOut0; // Diffuse buffer
out vec4 fragOut1; // Normal buffer
out vec4 fragOut2; // Emissive buffer
uniform sampler2D gDepthBuffer;
uniform sampler2D gNormalBuffer;
uniform sampler2DArray diffuseMap;
uniform sampler2DArray glowMap;
uniform sampler2DArray normalMap;
layout (std140) uniform decalGlobalData {
mat4 viewMatrix;
mat4 projMatrix;
mat4 invViewMatrix;
mat4 invProjMatrix;
vec3 ambientLight;
vec2 viewportSize;
};
layout (std140) uniform decalInfoData {
mat4 model_matrix;
mat4 inv_model_matrix;
vec3 decal_direction;
float normal_angle_cutoff;
int diffuse_index;
int glow_index;
int normal_index;
float angle_fade_start;
float alpha_scale;
int diffuse_blend_mode;
int glow_blend_mode;
};
vec3 computeViewPosition(vec2 textureCoord) {
vec4 clipSpaceLocation;
vec2 normalizedCoord = textureCoord / viewportSize;
clipSpaceLocation.xy = normalizedCoord * 2.0f - 1.0f;
clipSpaceLocation.z = texelFetch(gDepthBuffer, ivec2(textureCoord), 0).r * 2.0f - 1.0f;
clipSpaceLocation.w = 1.0f;
vec4 homogenousLocation = invProjMatrix * clipSpaceLocation;
return homogenousLocation.xyz / homogenousLocation.w;
}
vec3 getPixelNormal(vec3 frag_position, vec2 tex_coord, inout float alpha, out vec3 binormal, out vec3 tangent) {
#ifdef USE_NORMAL_MAP
// If we can then we just use the existing normal buffer
vec3 normal = texelFetch(gNormalBuffer, ivec2(tex_coord), 0).xyz;
// If we use the normal map then we don't really need these values so we don't need to compute them here
binormal = vec3(0.0);
tangent = vec3(0.0);
#else
// Use some fancy screen-space derivates to determine the normal of the current pixel by looking at the surrounding pixels
vec3 pos_dx = dFdx(frag_position);
vec3 pos_dy = dFdy(frag_position);
vec3 normal = normalize(cross(pos_dx, pos_dy));
binormal = normalize(pos_dx);
tangent = normalize(pos_dy);
#endif
//Calculate angle between surface normal and decal direction
float angle = acos(dot(normal, decal_direction));
if (angle > normal_angle_cutoff) {
// The angle between surface normal and decal direction is too big
discard;
}
// Make a smooth alpha transition leading up to an edge
alpha = alpha * (1 - smoothstep(angle_fade_start, normal_angle_cutoff, angle));
return normal;
}
vec2 getDecalTexCoord(vec3 view_pos, inout float alpha) {
vec4 object_pos = inv_model_matrix * invViewMatrix * vec4(view_pos, 1.0);
bvec3 invalidComponents = greaterThan(abs(object_pos.xyz), vec3(0.5));
bvec4 nanComponents = isnan(object_pos); // nan can happen some times if we have an infinite depth value
if (any(invalidComponents) || any(nanComponents)) {
// Fragment is out of the box
discard;
}
// Fade out the texture when it gets close to the top or bottom of the decal box
alpha = alpha * (1.0 - smoothstep(0.4, 0.5, abs(object_pos.z)));
return object_pos.xy + 0.5;
}
void main() {
vec3 frag_position = computeViewPosition(gl_FragCoord.xy);
float alpha = alpha_scale;
vec2 tex_coord = getDecalTexCoord(frag_position, alpha);
vec3 binormal;
vec3 tangent;
vec3 normal = getPixelNormal(frag_position, gl_FragCoord.xy, alpha, binormal, tangent);
vec4 diffuse_out = vec4(0.0);
vec4 emissive_out = vec4(0.0, 0.0, 0.0, 0.0);
vec3 normal_out = vec3(0.0);
if (diffuse_index >= 0) {
// We have a valid diffuse map
vec4 color = texture(diffuseMap, vec3(tex_coord, float(diffuse_index)));
color.rgb = srgb_to_linear(color.rgb);
if (diffuse_blend_mode == 0) {
// Normal alpha blending
diffuse_out = vec4(color.rgb, color.a * alpha);
} else {
// Additive blending
diffuse_out = vec4(color.rgb * alpha, 1.0);
}
// The main model shader applies ambient lighting by drawing the ambient part of the texture into the emissive
// texture. We do the same here to make sure the decal material is applied correctly
if (glow_blend_mode == 0) {
// Normal alpha blending
emissive_out = vec4(color.rgb * ambientLight, color.a * alpha);
} else {
// Additive blending
emissive_out = vec4(alpha * color.rgb * ambientLight, 1.0);
}
}
if (glow_index >= 0) {
// We have a valid diffuse map
vec4 color = texture(glowMap, vec3(tex_coord, float(glow_index)));
color.rgb = srgb_to_linear(color.rgb) * GLOW_MAP_SRGB_MULTIPLIER;
color.rgb *= GLOW_MAP_INTENSITY;
if (glow_blend_mode == 0) {
// Normal alpha blending
emissive_out = vec4(color.rgb + emissive_out.rgb * emissive_out.a, color.a * alpha);
} else {
// Additive blending
emissive_out.rgb += color.rgb * alpha;
}
}
if (normal_index >= 0) {
vec3 decalNormal = unpackNormal(texture(normalMap, vec3(tex_coord, float(normal_index))).ag);
mat3 tangentToView;
tangentToView[0] = tangent;
tangentToView[1] = binormal;
tangentToView[2] = normal;
normal_out = tangentToView * decalNormal * alpha;
}
fragOut0 = diffuse_out;
fragOut1 = vec4(normal_out, 0.0);
fragOut2 = emissive_out;
}
+33
View File
@@ -0,0 +1,33 @@
in vec4 vertPosition;
layout (std140) uniform decalGlobalData {
mat4 viewMatrix;
mat4 projMatrix;
mat4 invViewMatrix;
mat4 invProjMatrix;
vec3 ambientLight;
vec2 viewportSize;
};
layout (std140) uniform decalInfoData {
mat4 model_matrix;
mat4 inv_model_matrix;
vec3 decal_direction;
float normal_angle_cutoff;
int diffuse_index;
int glow_index;
int normal_index;
float angle_fade_start;
float alpha_scale;
int diffuse_blend_mode;
int glow_blend_mode;
};
void main() {
gl_Position = projMatrix * viewMatrix * model_matrix * vertPosition;
}
@@ -1,18 +1,23 @@
#include "gamma.sdr"
in vec4 fragTexCoord;
in vec4 fragColor;
out vec4 fragOut0;
uniform sampler2D baseMap;
uniform sampler2DArray baseMap;
uniform int baseMapIndex;
uniform int alphaTexture;
uniform int noTexturing;
uniform int srgb;
uniform float intensity;
uniform float alphaThreshold;
#define SRGB_GAMMA 2.2
void main()
{
vec4 baseColor = texture(baseMap, fragTexCoord.xy);
vec4 baseColor = texture(baseMap, vec3(fragTexCoord.xy, float(baseMapIndex)));
if(alphaThreshold > baseColor.a) discard;
baseColor.rgb = (srgb == 1) ? pow(baseColor.rgb, vec3(SRGB_GAMMA)) : baseColor.rgb;
vec4 blendColor = (srgb == 1) ? vec4(pow(fragColor.rgb, vec3(SRGB_GAMMA)), fragColor.a) : fragColor;
baseColor.rgb = (srgb == 1) ? srgb_to_linear(baseColor.rgb) : baseColor.rgb;
vec4 blendColor = (srgb == 1) ? vec4(srgb_to_linear(fragColor.rgb), fragColor.a) : fragColor;
fragOut0 = mix(mix(baseColor * blendColor, vec4(blendColor.rgb, baseColor.r * blendColor.a), float(alphaTexture)), blendColor, float(noTexturing)) * intensity;
}
}
@@ -2,10 +2,12 @@ out vec4 fragOut0;
out vec4 fragOut1;
out vec4 fragOut2;
out vec4 fragOut3;
out vec4 fragOut4;
void main()
{
fragOut0 = vec4(0.0, 0.0, 0.0, 1.0); // color
fragOut1 = vec4(0.0, 0.0, -1000000.0, 1.0); // position
fragOut2 = vec4(0.0, 0.0, 0.0, 1.0); // normal
fragOut3 = vec4(0.0, 0.0, 0.0, 0.0); // specular
}
fragOut4 = vec4(0.0, 0.0, 0.0, 1.0); // emissive
}
+138
View File
@@ -0,0 +1,138 @@
#include "lighting.sdr"
#include "shadows.sdr"
in vec3 beamVec;
in vec3 lightPosition;
out vec4 fragOut0;
uniform sampler2D ColorBuffer;
uniform sampler2D NormalBuffer;
uniform sampler2D PositionBuffer;
uniform sampler2D SpecBuffer;
uniform sampler2DArray shadow_map;
layout (std140) uniform globalDeferredData {
mat4 shadow_mv_matrix;
mat4 shadow_proj_matrix[4];
mat4 inv_view_matrix;
float veryneardist;
float neardist;
float middist;
float fardist;
float specFactor;
float invScreenWidth;
float invScreenHeight;
};
layout (std140) uniform lightData {
vec3 diffuseLightColor;
float coneAngle;
vec3 specLightColor;
float coneInnerAngle;
vec3 coneDir;
bool dualCone;
vec3 scale;
float lightRadius;
vec3 lightDir;
int lightType;
bool enable_shadows;
};
void GetLightInfo(vec3 position, out vec3 lightDir, out float attenuation)
{
if (lightType == LT_DIRECTIONAL) {
lightDir = normalize(lightPosition);
attenuation = 1.0;
} else {
// Positional light source
lightDir = lightPosition - position.xyz;
float dist = length(lightDir);
attenuation = 1.0 - clamp(dist / lightRadius, 0.0, 1.0);
if(dist > lightRadius && lightType != LT_TUBE) {
discard;
}
if (lightType == LT_TUBE) { // Tube light
float beamLength = length(beamVec);
vec3 beamDir = beamVec / beamLength;
// Get nearest point on line
float neardist = clamp(dot(lightDir, beamDir), 0.0, beamLength);
// Move back from the endpoint of the beam along the beam by the distance we calculated
vec3 nearest = lightPosition - beamDir * neardist;
lightDir = nearest - position.xyz;
dist = length(lightDir);
if(dist > lightRadius) {
discard;
}
} else if (lightType == LT_CONE) {
float coneDot = dot(normalize(-lightDir), coneDir);
if(dualCone) {
if(abs(coneDot) < coneAngle) {
discard;
} else {
attenuation *= smoothstep(coneAngle, coneInnerAngle, abs(coneDot));
}
} else {
if (coneDot < coneAngle) {
discard;
} else {
attenuation *= smoothstep(coneAngle, coneInnerAngle, coneDot);
}
}
}
lightDir = normalize(lightDir);
}
}
void main()
{
vec2 screenPos = gl_FragCoord.xy * vec2(invScreenWidth, invScreenHeight);
vec3 position = texture(PositionBuffer, screenPos).xyz;
if(abs(dot(position, position)) < 0.1)
discard;
vec3 color = texture(ColorBuffer, screenPos).rgb;
vec4 normalData = texture(NormalBuffer, screenPos);
vec4 specColor = texture(SpecBuffer, screenPos);
// The vector in the normal buffer could be longer than the unit vector since decal rendering only adds to the normal buffer
vec3 normal = normalize(normalData.xyz);
float gloss = normalData.a;
float fresnel = specColor.a;
vec3 eyeDir = normalize(-position);
vec3 lightDir;
float attenuation;
GetLightInfo(position, lightDir, attenuation);
if (enable_shadows) {
vec4 fragShadowPos = shadow_mv_matrix * inv_view_matrix * vec4(position, 1.0);
vec4 fragShadowUV[4];
fragShadowUV[0] = transformToShadowMap(shadow_proj_matrix[0], 0, fragShadowPos);
fragShadowUV[1] = transformToShadowMap(shadow_proj_matrix[1], 1, fragShadowPos);
fragShadowUV[2] = transformToShadowMap(shadow_proj_matrix[2], 2, fragShadowPos);
fragShadowUV[3] = transformToShadowMap(shadow_proj_matrix[3], 3, fragShadowPos);
attenuation *= getShadowValue(shadow_map, -position.z, fragShadowPos.z, fragShadowUV, fardist, middist,
neardist, veryneardist);
}
vec3 halfVec = normalize(lightDir + eyeDir);
float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0);
vec4 fragmentColor = vec4(color * (diffuseLightColor * NdotL * attenuation), 1.0);
fragmentColor.rgb += computeLighting(specColor.rgb, lightDir, normal.xyz, halfVec, eyeDir, gloss, fresnel, NdotL).rgb * specLightColor * attenuation;
fragOut0 = max(fragmentColor, vec4(0.0));
}
@@ -0,0 +1,40 @@
#include "lighting.sdr"
in vec4 vertPosition;
uniform mat4 modelViewMatrix;
uniform mat4 projMatrix;
layout (std140) uniform lightData {
vec3 diffuseLightColor;
float coneAngle;
vec3 specLightColor;
float coneInnerAngle;
vec3 coneDir;
bool dualCone;
vec3 scale;
float lightRadius;
vec3 lightDir;
int lightType;
bool enable_shadows;
};
out vec3 lightPosition;
out vec3 beamVec;
void main()
{
if (lightType == LT_DIRECTIONAL) {
gl_Position = vec4(vertPosition.xyz, 1.0);
lightPosition = lightDir;
} else {
gl_Position = projMatrix * modelViewMatrix * vec4(vertPosition.xyz * scale, 1.0);
lightPosition = modelViewMatrix[3].xyz;
if(lightType == LT_TUBE)
beamVec = vec3(modelViewMatrix * vec4(0.0, 0.0, -scale.z, 0.0));
}
}
@@ -2,7 +2,7 @@ in vec4 fragTexCoord;
in vec4 fragColor;
in float fragOffset;
out vec4 fragOut0;
uniform sampler2D baseMap;
uniform sampler2DArray baseMap;
uniform sampler2D depthMap;
uniform float window_width;
uniform float window_height;
@@ -11,10 +11,10 @@ uniform sampler2D frameBuffer;
void main()
{
vec2 depthCoord = vec2(gl_FragCoord.x / window_width, gl_FragCoord.y / window_height);
vec4 fragmentColor = texture(baseMap, fragTexCoord.xy) * fragColor.a;
vec4 fragmentColor = texture(baseMap, fragTexCoord.xyz) * fragColor.a;
vec2 distortion = texture(distMap, fragTexCoord.xy+vec2(0.0, fragOffset)).rg;
float alpha = clamp(dot(fragmentColor.rgb,vec3(0.3333))*10.0,0.0,1.0);
distortion = ((distortion - 0.5) * 0.01) * alpha;
fragOut0 = texture(frameBuffer,depthCoord+distortion);
fragOut0.a = alpha;
}
}
@@ -12,6 +12,6 @@ void main()
{
gl_Position = projMatrix * modelViewMatrix * vertPosition;
fragOffset = vertRadius * use_offset;
fragTexCoord = vertTexCoord;
fragTexCoord = vec4(vertTexCoord.xyz, 0.0);
fragColor = vertColor;
}
}
Loaded 100 of 898 files, more files were not shown because too many files have changed in this diff. Show more