Compare commits

...
Author SHA1 Message Date
asarium 1111dcf0a8 Add system for reading flags from stdin
This adds support for reading flags from the standard input stream
instead of from the command line. This allows more complex formats to be
used such as JSON which is implemented in this first version. This can
be used for implementing much more sophisticated ways of expressing
complex data structures such as the mod command line.
2019-06-07 18:31:33 +02:00
Goober5000 a94550ee1a Merge pull request #2049 from plieblang/MapIteratorCleanup
Clean up map::iterator usage
2019-05-25 00:45:46 -04:00
plieblang 3dbe27e772 Clean up map::iterator usage 2019-05-24 13:43:04 -07:00
m!m 8f11d2e11c Merge pull request #2037 from Goober5000/on_subsystem_destroyed
add $On Subsystem Destroyed scripting hook
2019-05-17 19:47:11 +02:00
Goober5000 e4036b9e5a Merge pull request #2045 from MageKing17/bugfix/multi-sexp-flag-validity
Check flags are valid in multi_sexp_deal_with_ship_flag().
2019-05-17 13:42:09 -04:00
MageKing17 c86e94a4e7 Correct NULL to nullptr so clang-tidy is happy. 2019-05-17 09:13:02 -07:00
MageKing17 a6475f59f0 Check flags are valid in multi_sexp_deal_with_ship_flag().
In single-player, or while running as a server, sexp_deal_with_ship_flag() makes sure that object_flag, ship_flag, and p_object_flag aren't NUM_VALUES (i.e. not set) before trying to call flags.set() with them. However, the client code in multi_sexp_deal_with_ship_flag() had no such security checks, and as such would try to set NUM_VALUES, which is outside the range of valid flags; this led to a crash in Release builds and an Assertion otherwise.
2019-05-13 12:29:54 -07:00
Goober5000 69ebdd0417 Merge pull request #2043 from wookieejedi/add_gethotkey_sexp
Adds `get-hotkey` sexp
2019-05-13 13:32:21 -04:00
niffiwan 9444b9ff9f Merge pull request #2024 from CasparKielwein/collision_cleanup_ck
Refactoring of objcollision
2019-05-13 19:41:38 +10:00
wookieejedi 8d3eeec238 Updated description 2019-05-11 14:03:15 -04:00
Goober5000 da0ff33fcb address feedback and implement asarium's suggestion 2019-05-11 13:06:21 -04:00
wookieejedi 764b4b8422 Improve comments and description 2019-05-11 10:38:40 -04:00
m!m a5d22589ec Merge pull request #2036 from wookieejedi/class_flyby_sounds
Adds per-class flyby sounds
2019-05-11 12:28:09 +02:00
wookieejedi 6a6940e0f0 Adds get-hotkey sexp
This PR adds a sexp that returns the integer value of a ship or wing hotkey. No hotkey returns -1, F5 returns 0, F6 returns 1, ... and the sexp takes one arguemnt, the ship or wing name.
2019-05-10 23:09:00 -04:00
niffiwan 2dfd9936d8 Merge pull request #2041 from niffiwan/fix/issue2040
Don't link if ship has 'no primary linking' flag
2019-05-11 10:19:29 +10:00
Goober5000 fb0847f4b5 Merge pull request #2038 from wookieejedi/add_sethotkey_sexp
Add new sexp: `add-remove-hotkey`
2019-05-10 17:50:48 -04:00
wookieejedi 7b959b09d2 Incorporate Goober's feedback 2019-05-10 15:34:05 -04:00
wookieejedi f4b713c56c Add bool arg 2019-05-10 15:12:49 -04:00
wookieejedi d32d3f55d1 Updated name and function
Incorporated all revisions and suggestions
2019-05-10 09:32:15 -04:00
niffiwan 1ebb72ee88 Don't link if ship has 'no primary linking' flag
Also adds/enhances some handy nprintf debug statements.
Fixes #2040
2019-05-10 23:06:16 +10:00
wookieejedi a988d0e972 Adds a new sexp, set-hotkey
This new sexp allows a FREDer to set a hotkey for a ship or wing. The sexp takes 2 or more arguemnts, the integer of the hotkey to set (F5=0, F6=1, ... F12=7) and the names of the ship(s) and/or wing(s).
2019-05-09 13:46:21 -04:00
Goober5000 8aa2f3b099 tweak spacing 2019-05-08 20:04:19 -04:00
Goober5000 8365f0abb7 add $On Subsystem Destroyed scripting hook
Implements the feature request from issue #610.

As an aside, this PR also patches the `ship_set_subsystem_strength` function (which is only used by the debug console and in the event you fire at your training instructor) to use the same code as the `set-subystem-strength` sexp.  This properly handles submodels blown off, sounds, etc.
2019-05-08 19:55:03 -04:00
wookieejedi 4afe739cbb Clean and shorten per request
Fixes spelling error in comment, uses proper flyby_snd and makes code more concise.
2019-05-08 14:14:01 -04:00
wookieejedi 2c469e0c88 Adds per-class flyby sounds
Previosuly, flyby sounds were only specified on a per-species basis. This PR allows each ship class to use a specific flyby sound. This will allow modders to set the custom sound in ships.tbl, just like any other per-class sound.
2019-05-08 14:00:28 -04:00
MageKing17 822e61665d Merge pull request #2026 from Goober5000/some_sexp_fixes
various sexp formatting and cleanup changes
2019-05-07 07:18:28 -07:00
niffiwan 5f5616c0fa Merge pull request #2030 from niffiwan/feature/deathroll_customisation
Allow death max rotation to be set per ship
2019-05-07 19:28:54 +10:00
Goober5000 b38f6aa014 HA! 2019-05-06 14:07:11 -04:00
Goober5000 d88e6f5a88 Merge pull request #2034 from niffiwan/fix/issue2033
Null wp_list on setting order, same as for sexps
2019-05-06 14:01:58 -04:00
niffiwan 760b601a95 Null wp_list on setting order, same as for sexps
Making wp_list null lets ai_mission_goal_achievable reset the waypoints
list correctly, otherwise it thinks the waypoints are ok when in fact
something has invalidated them
2019-05-06 18:30:38 +10:00
Fabian Woltermann 0bf116b0cc Merge pull request #2032 from The-E/fix/2031_copy_paste_error_in_lua_vecmath
Fix for error in validation of matrices accessed by lua
2019-05-06 07:51:40 +02:00
The_E 2180296f9c When setting individual elements of a matrix through lua, we need to mark the matrix as either having out of date angles or out of date vectors. 2019-05-05 20:06:28 +02:00
niffiwan b84fe72778 address feedback
This moves DEATHROLL_ROTVEL_CAP to shiphit.h & converts it to a
constexpr float
2019-05-05 22:13:32 +10:00
niffiwan c5e460a90d Allow death max rotation to be set per ship
This allows modders to restrict the amount of rotation in a death roll.
It's fairly simple to fit in with the existing code which has a lot of
hard coded constants. The intended use case is to restrict pitch &
heading changes so there's less chance of rapid forward rolls or flat
spins, especially with faster-than-FS2 ships.

I'd almost rather rewrite the entire code to dynamically use ships mass
& velocity except for retail compatibility issues.
2019-05-05 10:07:21 +10:00
CasparKielwein 271d3f97bd remove unused functions obj_add_pair and obj_add_pairs in object code.
These functions where not used anymore and probably made redundant
by swifties changes to the collision system in 2012.
2019-05-04 11:30:54 +02:00
CasparKielwein e70d6a89ee objcollide cleanup: declare local variables at point of first use
made some loops range based.
removed some typedef struct, as it is c++.
2019-05-04 11:30:16 +02:00
Goober5000 d1a8e66fce Merge pull request #2029 from niffiwan/fix/qtfred_mission_load_failure
Allow qtFred to open missions again
2019-05-04 01:58:58 -04:00
niffiwan 964f8f5ef1 Allow qtFred to open missions again
Minor miss from 9332311b57
Also has trivial comment fix
2019-05-04 14:02:50 +10:00
Goober5000 8ebe012e12 more complaints 2019-05-03 15:24:16 -04:00
Goober5000 92f142452a even more complaints 2019-05-03 14:07:13 -04:00
Goober5000 cfb80cfd16 fix modulo 2019-05-03 13:59:48 -04:00
Goober5000 39313ed8d7 Address feedback. Also fix a few things github complained about. Also fix depart-node-delay by correctly handling the 'delay' parameter as a value of type 'fix', just like the other *-delay sexps. 2019-05-03 13:06:51 -04:00
MageKing17 1da2c03cef Merge pull request #2016 from Goober5000/a_few_good_sexps
Three sexps and some sexp improvements
2019-05-01 20:13:11 -07:00
Goober5000 f9dbe4941b various sexp formatting and cleanup changes 2019-05-01 22:45:59 -04:00
Goober5000 46319f1b4e Merge pull request #2025 from Mithi83/bug/1827-targeting-brackets
fix bug #1827: targeting brackets stuck in top left corner
2019-05-01 14:31:47 -04:00
Thomas Jansen 8653d824cd fix bug #1827: targeting brackets stuck in top left corner
Every g3_start_frame must have a matching g3_end_frame. Thus, a return
in the middle of a function after an opening g3_start_frame must make
sure to call g3_end_frame before it leaves to avoid a dangling frame
context.

As described in the bug report at
https://github.com/scp-fs2open/fs2open.github.com/issues/1827
a floating point rounding issue could be the trigger for the problem.
2019-05-01 18:32:26 +02:00
CasparKielwein 3e7e7cde00 made functions from objcollide, which are only used in .cpp local to compilation unit 2019-05-01 10:41:27 +02:00
CasparKielwein f63667b29e Cleanup in objcollide: Remove code that was commented out 2019-05-01 10:07:35 +02:00
CasparKielwein b42fc2122a Cleanup in object collide code.
A bit of small cleanups in preparation of larger scale refactoring.

remove unused member heavy_collision_cm_pos of collision info struct,
which was set in several places but never used.
2019-05-01 09:44:19 +02:00
Goober5000 3ca4ba16fe Merge pull request #1892 from asarium/feature/optionsUI
Add new options system
2019-04-29 17:16:21 -04:00
Goober5000 36c14e21e8 Merge pull request #2021 from asarium/feature/axemWantsLuaAudioAPIs
Add unload function for freeing audio memory of a soundfile handle
2019-04-29 17:07:48 -04:00
asarium ce1ea75714 Add unload function for freeing audio memory of a soundfile handle
This can be used by scripts for explicitly freeing up some memory when
necessary.
2019-04-27 08:53:07 +02:00
Goober5000 30373e9138 Merge pull request #2019 from wookieejedi/clean_fix_showship_detailbox_bug
Cleaner fix for show-ship bug with detail_box calculations
2019-04-22 19:15:56 -04:00
wookieejedi 9e460332a6 add ship check
per Goober's request added a ship check
2019-04-22 17:53:07 -04:00
wookieejedi 473e2588bf Cleaner fix for show-ship bug with detail_box calculations
This provides a cleaner fix for the bug where using show ship caused detail_box calculations to incorrectly work on the player's ship.

It also reverts the changes made by PR #2018.
2019-04-22 10:28:41 -04:00
niffiwan 6350110b21 Merge pull request #2018 from wookieejedi/fix_detailbox_with_showship
Fix `detail_box` calculations when using `show ship`
2019-04-21 18:49:16 +10:00
wookieejedi 0c92134de5 fix detailbox using show ship
This PR fixes issue #2015, which is a bug where using `show ship` caused detail_box calculations to incorrectly use world coordinates for submodels on the player's ship, rather then the correct local coordinates.
2019-04-20 20:45:14 -04:00
Goober5000 681dd9b871 Merge pull request #1993 from niffiwan/fix/blackdetailboxes
detail boxes can ignore default distance scaling
2019-04-19 13:43:51 -04:00
Goober5000 213422076e KNOWN_ values aren't returned after all, derp 2019-04-19 00:34:39 -04:00
Goober5000 41aff9d094 ooooooops 2019-04-19 00:14:53 -04:00
Goober5000 337ca94b53 write out the full word 'number' 2019-04-18 01:18:05 -04:00
Goober5000 13f5037b0c add is-nan, nan-t-num, and functional-if-then-else 2019-04-18 01:12:00 -04:00
Goober5000 221d96f5d6 defensively check both regular and known sexp boolean values 2019-04-18 01:11:19 -04:00
Goober5000 bd6441004b optimize eval_sexp by not reconciling positive/negative if we have a magic number 2019-04-18 01:09:36 -04:00
Goober5000 14b6e86e5d made the SEXP_ numbers even more unlikely, in case someone wants to use large negative numbers 2019-04-17 12:32:51 -04:00
m!m 4824428971 Merge pull request #2014 from MageKing17/feature/ssm-strike-warp-effect-field
Add "+WarpEffect:" field to ssm.tbl.
2019-04-14 13:01:52 +02:00
MageKing17 6af8d4ccbd Add "+WarpEffect:" field to ssm.tbl.
Allows subspace strikes to choose which fireball to use for the warp effect. If absent, FIREBALL_WARP is used as the default (which was the previous hardcoded behavior).

"+WarpEffect:" can be specified as either an index or using the fireball's unique ID.
2019-04-13 20:35:52 -07:00
niffiwan d2d730138f Merge pull request #2013 from chief1983/fix/revert_nightly_test
Revert "Test the upload"
2019-04-08 02:38:22 +10:00
Cliff 7d67d16094 Revert "Test the upload"
This reverts commit 5fa5a199bf.
2019-04-07 09:15:41 -05:00
niffiwan 3f4eb05f3e Merge pull request #2012 from chief1983/fix/travis_uploads
Make sure to use a path that contains the new curl binary
2019-04-07 08:54:36 +10:00
Cliff Gordon 49f8660f7a fix/travis_uploads: Make sure to use a path that contains the new curl binary. 2019-04-06 13:20:35 -05:00
niffiwan 2833ae150f detail boxes can ignore default distance scaling
Add a submodel property that overrides the hard-coded distance
multipliers applied to the distances at which details boxes & spheres
are rendered. The distance multipliers are set by the "model detail"
setting in the options screen. Note that this is different to the LOD
distance multipliers which are not hard-coded.

This allows some more creative uses of detail boxes & spheres, e.g. to
stop models subobjects from being rendered when they're out of player
view. Past testing showed a reasonable performance improvement with
complicated models.

This is a submodel property rather than global, or a ship flag, to allow
flexibility, i.e. a single model could choose this option only for the
submodels that want to use detail boxes/spheres in this fashion, which
other detail boxes/spheres use the conventional approach.

Code & ideas originally from zookeeper, I've just packaged it up for
the PR.

This has been rebased & squashed based on feedback in the PR
2019-04-06 15:24:27 +10:00
niffiwan 8470548376 Merge pull request #2011 from wookieejedi/fix_drawRect_for_scripted_gauge
Fixes minor bug with `drawRectangle` for scripted HUD gauges
2019-04-05 20:20:12 +10:00
wookieejedi ea6bd1d9a4 Update hudgauge.cpp
Fixes a minor bug that incorrectly draws Rectangles to a scripted HUD gauge. The third and fourht arguments needed to be width and heigth, not x2 and y2.
2019-04-04 16:03:45 -04:00
m!m 18c0314652 Merge pull request #2010 from wookieejedi/Add_more_draw_functions_toScriptedGauge
Add more draw functions to scripted gauge
2019-03-30 21:22:28 +01:00
wookieejedi 98165dbce5 Fix typo, drawCirle -> drawCircle 2019-03-30 13:55:12 -04:00
wookieejedi 60bf6dec2c Merge branch 'Add_more_draw_functions_toScriptedGauge' of https://github.com/wookieejedi/fs2open.github.com into Add_more_draw_functions_toScriptedGauge 2019-03-30 09:54:35 -04:00
wookieejedi 252ab4e282 Follw m!m request for optional arg 2019-03-30 09:54:01 -04:00
wookieejedi bd93c8e661 Merge pull request #2 from wookieejedi/master
Rebase
2019-03-30 09:50:35 -04:00
wookieejedi 0e4056f795 Merge pull request #1 from scp-fs2open/master
Rebase
2019-03-30 09:49:10 -04:00
wookieejedi 8f877d3826 Fixed typo 2019-03-29 09:36:10 -04:00
wookieejedi 6025ab8318 Update drawCircle too to match gr.drawCircle 2019-03-29 08:57:54 -04:00
wookieejedi 679cbe2526 Made the draw functions more consistent with gr draw functions 2019-03-29 08:53:37 -04:00
m!m fa0140fea7 Merge pull request #2009 from wookieejedi/Add_drawImage_toScriptGauge
Add `drawImage` to Scripted Gauge
2019-03-29 10:57:31 +01:00
wookieejedi 5343503385 Add more draw functions to scripted gauge
This adds the following functions to the scripted gauge API: drawCircle, drawRect, and drawLine. Also note that I created an additional function, for HUDGauge:renderCircle_unfilled, becuase the precedent shown by having two functions for `gr_unfilled_circle` and `gr_circle` and adding a fourth argument to `renderCircle` seemed to affect a lot of other functions.
2019-03-28 16:58:25 -04:00
wookieejedi edd2cb89c7 Removed unneeded include 2019-03-28 13:44:54 -04:00
wookieejedi 6a2327088f Add drawImage to Scripted Gauge
Adds an additional draw function, `drawImage` to the new Scripted Gauge API.
2019-03-28 09:53:19 -04:00
niffiwan f798c5b916 Merge pull request #2007 from asarium/feature/scriptedHudGauges
Add new HUD gauge type for scripted gauges
2019-03-28 21:31:47 +10:00
m!m 76115122a0 Merge pull request #2003 from Goober5000/abort_processing_missions_which_failed_to_parse
cancel mission load when a syntax error is found
2019-03-27 17:58:00 +01:00
MageKing17 b4cb602e31 Merge pull request #2008 from NovachenFS2/new-strings
New translateable strings for the strings.tbl
2019-03-23 09:13:07 -07:00
m!mandNovachenFS2 d26b5310e7 Update code/controlconfig/controlsconfigcommon.cpp
Suggestion

Co-Authored-By: NovachenFS2 <[email protected]>
2019-03-23 14:14:36 +01:00
niffiwan cdb65c154c Merge pull request #2004 from wookieejedi/chase_displays
Add `Chase View Only` Option for HUD Gauges
2019-03-23 10:58:25 +10:00
Jenna Trassa fd0b612c64 New translateable strings for the strings.tbl
This commit adds new id for existing strings, so that they are translateable through the strings.tbl.
The following is translateable now:
- The 'or' seperator in the Keypress Directive gauge, if one function is bound to two keys.
- The Supernova warning.
- The error message that is displayed prior the pilot selection screen, if something is wrong with the loaded modification.
2019-03-22 22:44:35 +01:00
MageKing17 07d83d473c Merge pull request #1999 from asarium/cleanup/cleanupCfileType
Unify Cfile blocks and CFILE handles
2019-03-21 09:02:57 -07:00
asarium 1662a3c317 Add new HUD gauge type for scripted gauges
The new gauge can be accessed by the scripting API with which a function
can be set which will be called when this gauge is rendered. This can be
used for exposing the HUD gauge positioning and RTT options to the
scripting API without a lot of work needed for the script writer.

There is currently only one rendering function implemented since this is
only a proof of concept.
2019-03-17 09:27:58 +01:00
Goober5000 c70e4a0e7e Merge pull request #1991 from niffiwan/fix/issue1867
Fix issues with docked ships warping
2019-03-12 12:53:47 -04:00
niffiwan d82479fb14 tweak variable name for clarity 2019-03-12 21:13:02 +10:00
niffiwan be90059b65 fix documentation & var-name issue
Thanks to Goober5000 for noticing a very confusing var-name & errors in
the comments. Also switch to using bool check without '=='
2019-03-11 19:05:00 +10:00
niffiwan 04abbf55ed address feedback
Switch from 3x specific is_arriving functions to a single with params
Change flag names; replace "ndl" with "dock_follower"
Change dock-arrival helpers to not set follower flag on leaders
2019-03-10 09:26:12 +10:00
niffiwan 1bc925ee9b Merge pull request #2005 from wookieejedi/fix_font_lua_bug
Fixes bug with lua font handle
2019-03-09 10:12:04 +10:00
wookieejedi d558c2d632 Fixes bug with lua font handle
This PR fixes a bug where an invalid lua font handle would not be properly returned as invalid. An invalid handle is returned properly if the font name is invalid, but not if the index is invalid, thus this PR fixes that.
2019-03-08 17:07:21 -05:00
asarium 1c799653ce Unify Cfile blocks and CFILE handles
The only thing a CFILE contained was a version field which isn't used
anymore so that could be removed which basically meant that CFILE was
just an indirection to a Cfile_block which I then just renamed to CFILE.
The CFILE type is an opaque handle now since the contents are not
relevant to a user of Cfile.
2019-03-08 18:34:00 +01:00
wookieejedi 35af3a8b73 Place in correct order 2019-03-07 18:27:00 -05:00
wookieejedi 8586a319b0 Attempt Travis to rebuild 2019-03-07 18:10:30 -05:00
wookieejedi 15748adfda Adding Chase View Only Option for HUD Gauges
Currently, the player is unable to see a RTT hud gauge if in chase view. This adds an option in the hud_gauges.tbl that tells the game whether to draw a gauge based on if chase view is the active view. So for example, a modder using RTT mapped gauges can now make a HUD that displays on the interior of the ship (ie RTT with the cockpit model) and a HUD that displays when the player switches to chase view.
2019-03-07 16:06:51 -05:00
Cliff Gordon 6b0f73e427 Merge pull request #1990 from ngld/fix/curl-mac-upload
Compile curl ourselves on macOS and cache the result
2019-03-06 11:55:46 -06:00
Goober5000 1d744d347c add changes for qtfred 2019-03-06 00:18:40 -05:00
Goober5000 9332311b57 change C-style 0 on success, nonzero on failure to true on success, false on failure 2019-03-05 16:27:06 -05:00
Goober5000 47e9c01ce6 cancel mission load when a syntax error is found 2019-03-05 11:00:57 -05:00
MageKing17 5f176173bd Merge pull request #2000 from asarium/build/luaNatvis
Add natvis file for Lua
2019-03-04 19:48:20 -08:00
MageKing17 8d6538d7a9 Merge pull request #2002 from Goober5000/detroy
spelling fix
2019-03-04 19:39:13 -08:00
Goober5000 cc9e0a1096 spelling fix
now that all troys have been removed from all subsystems, this word can be changed
2019-03-04 17:32:29 -05:00
Goober5000 223e78926f Merge pull request #1998 from Goober5000/fix_missing_weapon_hook_variable
make sure to set all hook variables when the script hook is called
2019-03-04 17:09:31 -05:00
Goober5000 6679b623e4 same script stuff in beam.cpp 2019-03-03 15:20:45 -05:00
Goober5000 8aa2d0e212 a bit of minor housekeeping 2019-03-03 15:02:47 -05:00
Goober5000 1dc449ffa6 standardize order of parameters 2019-03-03 14:39:53 -05:00
Goober5000 6369cdec7c standardize comment 2019-03-03 14:39:25 -05:00
Goober5000 31fe15c4f4 remove hook variables immediately 2019-03-03 14:34:36 -05:00
Goober5000 dd384e7f1d standardize order of parameters 2019-03-03 14:32:54 -05:00
Goober5000 c8fa5803b9 set all hook variables (and unset them immediately after) for debris and asteroids 2019-03-03 14:24:50 -05:00
Goober5000 b57a608177 set all hook variables (and unset them immediately after) for debris and asteroids 2019-03-03 14:20:25 -05:00
Goober5000 f9f7a23b4d clearer invocation of the script hook 2019-03-03 14:11:29 -05:00
asarium 7e88feff16 Add natvis file for Lua
This should make debugging issues with Lua easier by providing a better
view on how the Lua state looks like.
2019-03-03 12:57:40 +01:00
Goober5000 c6bf5e927b make sure to set all hook variables when the script hook is called
In this block of code, the conditions were checked with a set of four hook variables but then subsequently run with only two.  This adds all four previously used variables.  More importantly, it adds the hook variables with expected and user-friendly names, since 'self' and 'object' are not necessarily intuitive.
2019-03-02 21:16:00 -05:00
asarium ad1ede7b74 Add new options system
This is a system for storing arbitrary data in the config file and then
easily retrieving it later on. This has full Lua support for exposing
the available options in a custom UI and changing the values of the
options. This ported some of the existing command line options over to
the new system which is opt-in for the moment by using a mod_table flag.
2019-03-02 14:02:21 +01:00
niffiwan 3c812915e4 add dock-related is_arriving helper functions
Address feedback from PR; reduce the number of hardcoded flags
2019-03-01 19:26:02 +10:00
Goober5000 62963d23ec Merge pull request #1908 from asarium/feature/scriptingFileAutoClose
Add scripting file handle auto-closing and error message
2019-02-27 22:47:18 -05:00
asarium dc71bb47d7 Add scripting file handle auto-closing and error message
This adds some auto-closing code to the scripting API of the CFile
system. If a file has to be auto-closed then an error will be displayed
to let the the script writer know that something is wrong.

This should not break existing scripts since causing file handle leaks
should never happen and if it does, this will make it easier to find
these issues.
2019-02-27 21:16:30 +01:00
m!m b79a3385a1 Merge pull request #1994 from asarium/build/circleci
Add CircleCI config file
2019-02-27 18:05:10 +01:00
asarium dfac2e98e9 Add CircleCI config file 2019-02-26 19:53:11 +01:00
niffiwan 37f2c8249d Fix issues with docked ships warping
There's a number of issues fixed here:
* Radar blips of docked ships were the wrong colour in stage 1
* You could target docked ships in stage 1
* Docked ships thrusters were visible in stage 1
* Hyperspace warptype ship could initially appear at their
warp-destination, then spring back to the correct location to complete
the rest of their warpin (because a docked ship had higher speed than
the dock leader)

There may also be a number of other subtle bugs with docked warpin;
e.g. I suspect (but haven't tested) that AI turrets could fire on
docked ships during warpin
These should also be fixed

Lastly, fixes issue #1867
2019-02-24 09:20:57 +10:00
ngld 5fa5a199bf Test the upload 2019-02-21 19:18:29 +01:00
ngld c00a2897f4 Compile curl ourselves on macOS and cache the result (for Linux as well).
We need to build our own curl binary since Homebrew doesn't support
 --with-libssh2 anymore.
I've also added caching to both the Linux and macOS code to avoid
rebuilding curl for each nightly.
2019-02-21 19:14:41 +01:00
Goober5000 ad4b1ca965 Merge pull request #1988 from niffiwan/fix/isdockedsingle
make is-docked work with a single argument
2019-02-17 11:13:40 -05:00
niffiwan f1f784f237 make is-docked work with a single argument
Currently is-docked always returns true if only a single argument is
supplied. This is probably as designed (except for not erroring on a
single arg) however it's quite easy to update to work for a single
argument and this case is useful for FotG, and might be useful for
others.
2019-02-17 19:19:03 +10:00
Goober5000 2c307ef5d3 Merge pull request #1983 from Goober5000/ship_initialization_tweaks
some tweaks and minor improvements to ship initialization
2019-02-07 14:40:58 -05:00
Goober5000 6f24d8d079 never mind, this is handled in the preloader 2019-02-05 02:23:58 -05:00
Goober5000 9fc94ab873 reconcile script and sexp 2019-02-05 02:21:20 -05:00
Goober5000 728ee2921f move ship_assign_sound into ship_create. also only assign sounds on change_ship_type if Fred is not running 2019-02-05 02:14:05 -05:00
MageKing17 caea0f56ed Merge pull request #1984 from Goober5000/ship_info_flag_fix
fix some flag information
2019-02-04 08:16:10 -08:00
niffiwan 94c9e1b494 Merge pull request #1985 from wookieejedi/AddWaypointHook
Add 'On Waypoints Done' Hook
2019-02-04 19:01:48 +10:00
wookieejedi 7dd1788aee Add 'On Waypoint Done' Hook
Adds 'On Waypoint Done' hook variable for scripting system.
2019-02-03 13:26:35 -05:00
Goober5000 77934c7215 actually it's better to document this 2019-02-02 23:32:57 -05:00
Goober5000 4a7c69082e ¯\_(ツ)_/¯ 2019-02-02 23:27:08 -05:00
Goober5000 74c4075aa6 address clang complaint 2019-01-29 23:43:28 -05:00
Goober5000 008d66c706 fix some flag information
Somewhere along the line, "sentry gun" was replaced with "escape pod" in the inverted is_flyable check.  This made the game think an escape pod wasn't flyable and therefore things like waypoint orders were not displayed.  This PR fixes that.

Additionally, I fixed a potential bug in weapons.cpp where the HUGE flag should really check against HUGE ships.  And there's a no-op formatting change in hudtargetbox.cpp.
2019-01-29 23:35:37 -05:00
Goober5000 1c385901cb prune a bit 2019-01-27 22:27:31 -05:00
Goober5000 5b9b06ab84 some tweaks and minor improvements to ship initialization
The core bug fixed here is #1982.  After ship_create sets up the ship, parse_object_create_sub does further initialization by copying some values from the parse object.  In most cases there are sensible defaults, but a few special cases require some post-processing...

- ship sounds
- the new way of initializing warp effects to allow per-ship customization
- intrinsic-no-shields
- an arrival entry in the mission log
- script hooks

I also took a further look at normal ship creation and tweaked some things...

- initialize ai mode in ai_object_init
- remove redundant assigment of ship name from parse_object_create_sub (it's also done in ship_create)
- remove redundant goal clearing from parse_object_create_sub (it's also done in ai_clear_ship_goals via ship_create)
- avoid overwriting the initial ai mode if the fix-ai-class-bug flag is set
- make the code slightly more efficient by not redundantly setting flags while searching for subsystems
2019-01-27 22:13:14 -05:00
MageKing17 f8da2cdc83 Merge pull request #1979 from MageKing17/bugfix/lua-control-info-player-nullptr-checks
Add checks for Player being nullptr to l_Control_Info.
2019-01-23 06:36:50 -08:00
niffiwan b790d6a388 Merge pull request #1978 from MageKing17/bugfix/lua-useButtonControl-command-definition
Use modulo instead of division in Lua useButtonControl() function.
2019-01-23 19:16:50 +10:00
niffiwan a7ba3fa373 Merge pull request #1977 from MageKing17/bugfix/lua-setButtonControlMode-additive-override-swap
Swap back return values for lua setButtonControlMode() function.
2019-01-23 17:55:25 +10:00
niffiwan 6d7c786a38 Merge pull request #1976 from MageKing17/bugfix/special-messages-skip-lookup
Avoid ship name lookup when sending "special" messages.
2019-01-23 17:54:54 +10:00
MageKing17 49d5356043 Add checks for Player being nullptr to l_Control_Info.
If various functions on l_Control_Info were called while Player was nullptr, FSO would CTD due to a null pointer dereference. This commit adds nullptr checks to avoid the problem.
2019-01-22 20:21:28 -08:00
MageKing17 572565c7bc Swap back return values for lua setButtonControlMode() function.
When setting LUA_ADDITIVE_BUTTON_CONTROL, the setButtonControlMode() function (in l_Base) would return "LUA OVERRIDE BUTTON CONTROL", and when setting LUA_OVERRIDE_BUTTON_CONTROL, "LUA ADDITIVE BUTTON CONTROL" would be returned. This commit simply swaps these back so that the appropriate return value is with the corresponding enum value.
2019-01-22 20:19:14 -08:00
MageKing17 c090ee5405 Use modulo instead of division in Lua useButtonControl() function.
When using a string to define the appropriate control in the useButtonControl() function (in l_Control_Info), the command definition was being divided by 32 when the appropriate mathematical operator was modulo; as a result, the only controls that could actually wind up being referenced are these four: TARGET_NEXT, MAX_THROTTLE, END_MISSION, and MULTI_MESSAGE_HOSTILE. By using the modulo operator, the string lookup now appropriately references the relevant button.
2019-01-22 20:15:46 -08:00
MageKing17 5597b56139 Avoid ship name lookup when sending "special" messages.
MESSAGE_SOURCE_SPECIAL indicates messages whose sender starts with "#", indicating that it's not a ship; however, the code was looking up the source as a ship name regardless, and if the message had a persona set, failing to find that ship name would result in the message failing to send. Commit f67596bc5e (a.k.a. SVN revision 5383) was supposed to fix this, however it was checking if q->source was MESSAGE_SOURCE_SPECIAL when q->source was one of the HUD_SOURCE_* #defines (specifically, MESSAGE_SOURCE_SPECIAL resulted in HUD_SOURCE_TERRAN_CMD). It turned out there was an unused HUD_SOURCE_* #define which behaves identically to HUD_SOURCE_TERRAN_CMD, namely HUD_SOURCE_IMPORTANT. By making MESSAGE_SOURCE_SPECIAL use HUD_SOURCE_IMPORTANT and changing the conditional to compare q->source to HUD_SOURCE_IMPORTANT, the intent behind the original fix can be carried out with minimal effort.

This also fixes issue #1706, which is basically the same as the original mantis issue.
2019-01-22 20:06:22 -08:00
MageKing17 c72a062a84 Merge pull request #1975 from asarium/feature/effectsPerSecond
Add support for "Effects per second" feature
2019-01-21 10:53:23 -08:00
asarium 422753976f Add support for "Effects per second" feature
This allows specifying how many times per second an effect should be
triggered for a particle source instead of triggering the effect every
frame. This will allow modders to achieve more consistent particle
effects regardless of FPS.
2019-01-19 13:56:45 +01:00
Goober5000 374383bacb Merge pull request #1973 from Goober5000/more_lenient_subsys_set_random
replace most Errors in sexp.cpp with Warnings
2019-01-17 23:16:37 -05:00
Goober5000 adfce4ec60 replace most Errors in sexp.cpp with Warnings
This is a follow-up to commit 1614384a6a.  `Error` is to be avoided if possible because almost all sexp problems are recoverable, and we don't want to bring the entire game to a halt.

Also add some more information to warnings about sexp operators on strings.
2019-01-17 12:52:17 -05:00
MageKing17 08faf52871 Merge pull request #1962 from asarium/fix/1961
Update internal NanoVG bitmap data buffer when updating texture
2019-01-14 02:43:08 -08:00
MageKing17 d99121cd52 Merge pull request #1970 from Goober5000/per_ship_warp_type_fixes
fix some bugs with the per_ship_warp_type feature
2019-01-14 01:56:47 -08:00
MageKing17 6ff292a43c Merge pull request #1971 from MageKing17/bugfix/dont-repeatedly-set-selection-effect
Don't repeatedly set selection_effect in parse_ship_values().
2019-01-13 23:26:26 -08:00
Goober5000 09f4f63be4 preserve warp params if we are parsing a TBM 2019-01-14 00:53:51 -05:00
MageKing17 2d67fd3ef8 Don't repeatedly set selection_effect in parse_ship_values().
Every time an entry for a ship was parsed (e.g. every time it showed up in a .tbm), the selection effect would be reset to the default. Since it's already set to the default in the ship_info constructor, this was both redundant and would make it extremely difficult to actually use a selection effect other than the default without constantly setting it in every .tbm.
2019-01-13 21:52:24 -08:00
Goober5000 5666eb5014 tweak comment 2019-01-13 23:51:30 -05:00
Goober5000 8542e9e113 fix some bugs with the per_ship_warp_type feature
Since FRED and FS2 load mission data slightly differently, the warp effect loading code had to be slightly reorganized in order for the warp effects to not be based on invalid data.  Additionally, the warp effects had to be initialized a little bit later so that it could accommodate a new set of warp parameters from the parse object.  As a bonnus, this PR also handles warp effects being reassigned in change_ship_class.
2019-01-13 23:40:59 -05:00
Goober5000 699c9e8d52 Merge pull request #1966 from Goober5000/per_ship_warp_type
per-ship warp type
2019-01-12 13:27:43 -05:00
Goober5000 5b45a89287 restore missing caption 2019-01-12 02:36:32 -05:00
Goober5000 741fc311cd fix comment rot 2019-01-12 02:31:09 -05:00
Goober5000 aaa9c779c0 remove spurious newline; word choice 2019-01-12 01:18:14 -05:00
Goober5000 bfae614189 fix bug: only reverse the warp effect when the ship is warping out; and while we're at it, change that parameter to bool 2019-01-12 01:05:19 -05:00
Fabian Woltermann cb956961f6 Merge pull request #1968 from MageKing17/bugfix/replacement-textures-initialization
Remember to initialize Replacement_textures array after allocation.
2019-01-11 19:24:59 +01:00
MageKing17 6d2ebd1ed7 Remember to initialize Replacement_textures array after allocation.
In commit 9e4c6df219 (PR #1265), the model_render_params::set_replacement_textures() override that accepts a vector of texture replacements was added, which includes allocating its own Replacement_textures array. However, unlike its counterpart from missionparse.cpp, this array doesn't then have all of its elements set to -1. Since it works just fine there, I copied that code here so both versions should behave the same.
2019-01-11 05:21:22 -08:00
Goober5000 d7e6187ba8 Merge pull request #1967 from MageKing17/bugfix/glow-texture-assert-data-check
Avoid using Asserts for data security in modelread properties-reading code.
2019-01-11 00:32:12 -05:00
MageKing17 62f6ee86ef Remove redundant length check, remove asserts from ID_FUEL case.
The (length > base_length) conditional was redundant with the other conditions. Additionally, the code from the ID_FUEL case (thruster points) checking for "$engine_subsystem=" was making the exact same mistake, so I made the same changes there.
2019-01-10 17:58:46 -08:00
Goober5000 56ae91c973 maybe it will work now 2019-01-09 16:08:05 -05:00
Goober5000 dfc8cbd1c9 okay this is pretty stupid 2019-01-09 11:01:32 -05:00
Goober5000 77e61af23c add new files to the project 2019-01-09 09:30:47 -05:00
Goober5000 7b80b0c564 minor header reorganization 2019-01-09 01:44:19 -05:00
Goober5000 a98d3bb064 more clang complaints 2019-01-09 00:59:12 -05:00
Goober5000 741ee07249 address warnings 2019-01-09 00:17:20 -05:00
Goober5000 04cefad927 inherit from ship_info warp params instead of resetting to default 2019-01-09 00:00:53 -05:00
Goober5000 3d68476505 remove WD_ prefix 2019-01-08 23:44:09 -05:00
Goober5000 81c63929b5 stage 3: add FRED2 support 2019-01-08 23:03:37 -05:00
Goober5000 d6d03fbb14 format saves using two-decimal floats, and insert missing newlines 2019-01-08 23:03:37 -05:00
Goober5000 9acd25bc28 create a new convenience function 2019-01-08 23:03:37 -05:00
Goober5000 7e00a8b10f stage 2: allow individual ships to also use Warp_params; implement loading and saving 2019-01-08 23:03:36 -05:00
Goober5000 bb0df2dc43 stage 1: replace individual parameters with an index into Warp_params 2019-01-08 23:03:36 -05:00
Goober5000 38f858198b Merge pull request #1964 from Goober5000/warp_direction_enum
create WarpDirection enum
2019-01-08 22:35:38 -05:00
MageKing17 a83307402a Avoid using Asserts for data security in glow texture reading code.
In a Release build, there was absolutely no code making sure that the text "$glow_texture=" was actually present in the properties field of a glow point bank, beyond a simple strlen() check. Even in Debug builds, there was no guarantee that the text was at the start of the properties field; it was just assumed (without even an assertion verifying it). Now, the assertions have been removed and the appropriate conditions are checked in both Release and Debug.
2019-01-08 15:04:42 -08:00
Goober5000 097148c2c2 remove WD_ prefix 2019-01-07 12:01:17 -05:00
Goober5000 fbf8a931c4 fix warning 2019-01-06 22:38:31 -05:00
Goober5000 32d951b27a create WarpDirection enum 2019-01-06 17:33:47 -05:00
Goober5000 630e6c3e96 Merge pull request #1963 from CasparKielwein/enable_wunusedfunction
enable Warnings for unused functions
2019-01-02 00:12:52 -05:00
CasparKielwein 72ed33502b remove unused and undeclared function hatEnumToIdx in joy-sdl 2018-12-31 16:06:37 +01:00
CasparKielwein d3806b2107 remove unused graphics function is_power_of_two. There is a generic one in ddutils. 2018-12-31 16:05:34 +01:00
CasparKielwein c9a481f4f3 wrapped function only used in debug mode in ifndef NDEBUG in ffmeg 2018-12-31 16:03:15 +01:00
CasparKielwein 0a02f677fe remove unused (and undeclared) function get_subsys_bounding_rect in qtfred 2018-12-31 16:03:15 +01:00
CasparKielwein d55e4343f9 enable Warnings for unused functions in gcc and clang toolchain files. 2018-12-31 14:28:25 +01:00
m!m e902934e89 Merge pull request #1958 from CasparKielwein/dead_code_remove_ck5
remove unused functions O to R
2018-12-31 11:54:18 +01:00
m!m 26395f7c12 Merge pull request #1959 from CasparKielwein/dead_code_remove_ck3
Remove unused Code S to Z
2018-12-30 15:08:15 +01:00
asarium de92fe25e3 Update internal NanoVG bitmap data buffer when updating texture
This was causing issues since the new bitmap data was never stored in
the internal buffer FSO uses for getting the image data. Instead, it was
only uploaded to the GPU texture which could be deleted at any time.
This was the case when changing the "3D Hardware Texture" setting which
causes a texture flush.

This fixes #1961.
2018-12-30 14:00:09 +01:00
CasparKielwein c72fa0917b remove unused functions in render code.
Left those functions in 3dmath alone, as it is more of a library.
2018-12-29 16:45:47 +01:00
CasparKielwein bc0f47269d remove unused functions in radar 2018-12-29 16:45:47 +01:00
CasparKielwein 94469dc43f remove unused functions in playerman 2018-12-29 16:45:47 +01:00
CasparKielwein ce335dbcc2 remove unused functions in physics 2018-12-29 16:45:47 +01:00
CasparKielwein 6660d21f7e remove unused and commented out functions in pcxutils. 2018-12-29 16:45:47 +01:00
CasparKielwein e622d81e89 remove unused functions and defines in object/code 2018-12-29 16:45:47 +01:00
CasparKielwein 10c8e16cda remove unused function in nebula code 2018-12-29 16:45:47 +01:00
CasparKielwein 25029bfdf1 remove unused functions and defines in weapon code 2018-12-29 16:41:23 +01:00
CasparKielwein 2255616ed5 remove unused functions in stats 2018-12-29 16:41:23 +01:00
CasparKielwein 62ab705d75 remove unused and not implemented functions in starfield. 2018-12-29 16:41:23 +01:00
CasparKielwein 77fc335580 remove unused functions in ship/shield and afterburner 2018-12-29 16:41:23 +01:00
CasparKielwein 981b01eea2 remove unused functions in ship/shipfx 2018-12-29 16:41:23 +01:00
CasparKielwein 366dc3749c remove unused functions and variables in ship/ship.cpp and .h 2018-12-29 16:41:23 +01:00
CasparKielwein e693367dd0 remove unused functions in sound 2018-12-29 16:41:23 +01:00
m!m da53960003 Merge pull request #1960 from asarium/fix/cppLuaHandlesPointer
Add Lua state destruction event
2018-12-28 18:46:18 +01:00
Goober5000 687c1ba4f7 Merge pull request #1957 from CasparKielwein/dead_code_remove_ck4
remove unused functions I to O
2018-12-28 11:52:24 -05:00
CasparKielwein d901470880 remove unused functions in model/ code. 2018-12-28 10:29:22 +01:00
CasparKielwein 7e74153a3d remove unused functions in mission code.
There where serval relics of prior refactorings like unimplemented functions.
2018-12-28 10:29:22 +01:00
CasparKielwein 6cf75b77dc remove unused functions in localization code. 2018-12-28 10:29:21 +01:00
CasparKielwein 3ec0a9c35e remove unused functions in lighting code. 2018-12-28 10:29:21 +01:00
CasparKielwein 519f60a63b remove unused globals and functions in mouse support io code 2018-12-28 10:29:21 +01:00
CasparKielwein 252da89782 remove unused function in keyboard support io code 2018-12-28 10:29:21 +01:00
CasparKielwein 0f1b3fd6c2 remove unused function in joystick support code. 2018-12-28 10:29:21 +01:00
CasparKielwein 58722425a3 remove unused function in osapi/dialog.cpp 2018-12-28 10:29:21 +01:00
asarium 211110d415 Add Lua state destruction event
This can be used by the various subsystems for cleaning up Lua
references before the Lua state is destroyed. This avoids having
dangling references to the Lua state which would cause segfaults later
on.

The first subsystem to use this is the dynamic SEXP system which had
dangling references due to keeping Lua references to the SEXP functions.

This fixes #1954.
2018-12-27 14:14:34 +01:00
m!m 61a8aa5592 Merge pull request #1956 from CasparKielwein/unused_function_ck2
remove unused Functions D to H
2018-12-27 13:50:52 +01:00
CasparKielwein 0692286bba Remove dead code in hud directory.
Removed a lot of unused functions.
This is mostly a cleanup of a prior refactoring.
There where a lot of unimplemented functions remaining from renaming.
Removed several outcommented parts of code.
2018-12-26 20:40:20 +01:00
CasparKielwein 72dae916a9 remove dead code in gamessnd/eventmusik
remove unused functions.
remove some uncommented code.
remove unused global variables.
2018-12-26 20:40:20 +01:00
CasparKielwein 189ad9f694 remove two unused functions in gamesequence 2018-12-26 20:40:20 +01:00
CasparKielwein b9f9fa0f73 remove unused function in gameplayhelp: gameplay_help_close 2018-12-26 20:40:20 +01:00
CasparKielwein dc7e88c888 remove unused deinfe in fireball.cpp and unused function fireball_render_plane 2018-12-26 20:40:20 +01:00
CasparKielwein b5dae2a56e remove dead code in debugconsole
remove unused functions.
Remove some unused defines and an unused class in console.h
2018-12-26 20:40:20 +01:00
CasparKielwein 969bfd0bdd remove unused functions in debris 2018-12-26 20:40:20 +01:00
m!m 63e8ae53c5 Merge pull request #1953 from plieblang/SupportDontAddPrimaries
AI profile flag for support to not equip new primary
2018-12-26 14:09:54 +01:00
m!m d57aaac8e4 Merge pull request #1952 from CasparKielwein/dead_code_remove_ck
remove unused functions A to C
2018-12-26 14:02:36 +01:00
plieblang ab981bd415 Document why the flag exists 2018-12-22 14:22:58 -08:00
CasparKielwein df7c91f3e7 remove some unused functions in ai code.
There is a lot of dead code left, but my IDE failds on the 15k file.
2018-12-22 20:10:56 +01:00
CasparKielwein ee73694cc8 remove unused functions on anim
Functionality related to pausing animations was not being used anymore.
2018-12-22 20:10:56 +01:00
CasparKielwein 65dcfe0a7c remove unused functions in autopilot 2018-12-22 20:10:56 +01:00
CasparKielwein ae8f8baade remove unused functions in cutscene 2018-12-22 20:10:56 +01:00
CasparKielwein 86fcdb1502 remove unused functions and variables in controlconfig 2018-12-22 20:10:56 +01:00
CasparKielwein b71fc4595c remove unused functions in cmeasures 2018-12-22 20:10:56 +01:00
CasparKielwein 471402ec5d remove unused functions in cfile 2018-12-22 20:10:56 +01:00
CasparKielwein 97fdca6b52 remove unused functions in camera 2018-12-22 20:10:56 +01:00
CasparKielwein b50833e6fb remove unused or unread variables in bmpman.
Global variables, function pointers and fields,
that where either unused or only set and never read.
2018-12-22 20:10:56 +01:00
CasparKielwein 4429cbb21c remove unused functions in bmpman 2018-12-22 20:10:56 +01:00
plieblang 4a6d8573a0 AI profile flag for support to not equip new primary 2018-12-21 13:26:32 -08:00
m!m 2c6039759c Merge pull request #1951 from Goober5000/fix_comment_rot
fix comment rot in speech.h
2018-12-18 17:42:41 +01:00
Goober5000 f3a0d56a85 remove comment that is no longer applicable 2018-12-18 00:07:40 -05:00
Goober5000 243aac1667 Merge pull request #1934 from plieblang/LabLightingSlidersResetView
Set initial slider values to the command line parameters and add functionality to reset view
2018-12-17 23:58:29 -05:00
Goober5000 19fbe05cee Merge pull request #1949 from Goober5000/small_collision_optimization
simple optimization for obj_sort_and_collide
2018-12-17 16:00:50 -05:00
Goober5000 e581a3b8a3 make these variables global 2018-12-16 14:28:47 -05:00
m!m 67a2d99a9b Merge pull request #1950 from asarium/fix/particleEffectParsing
Improve particle parsing code
2018-12-16 19:12:23 +01:00
asarium 569f1ee237 Improve particle parsing code
This makes some general changes to the particle parsing code. It moves
the trail effect option to the end of the options list to remove an
ambiguity in the resulting parsing code. This is done in a backwards
compatible manner so existing tables will not be broken by this.

This also introduces support for specifying single number ranges
without the parentheses to make that easier to use.
2018-12-16 14:23:22 +01:00
Goober5000 e9a8b9d8a2 make vectors static, per discussion on Discord 2018-12-15 16:45:58 -05:00
m!m 0efb98d4a9 Merge pull request #1948 from MageKing17/bugfix/sexp-nonexistent-AI-class
Don't rely on Assert to check for a valid AI class in SEXP code.
2018-12-13 20:10:34 +01:00
MageKing17 ec99bf9c03 Don't rely on Assert to check for a valid AI class in SEXP code.
Bad data can cause the name search to fail, and if change-ai-class was called with an invalid AI class, it could cause later invalid array accesses (using an index of -1).
2018-12-13 07:00:17 -08:00
plieblang bd6ff021fd Hopefully fix compilation bug 2018-12-09 12:14:43 -06:00
MageKing17 69213c3338 Merge pull request #1947 from asarium/fix/audiofile_play_api_fix
Add missing parameters to soundfile:play
2018-12-08 10:09:03 -08:00
asarium 0bffac7615 Add missing parameters to soundfile:play
This was missing from the API code and was uncovered by the new
scripting API changes.
2018-12-08 17:32:49 +01:00
niffiwan ba089bd95e Merge pull request #1945 from asarium/fix/1944
Fix move constructor of streaminganim_h
2018-12-08 16:17:35 +10:00
m!m 0a1519284f Merge pull request #1943 from TheMatthew/fast-path-microoptimization
Add a cache map for shaders in order to accelerate shader lookup
2018-12-07 18:09:08 +01:00
Matthew Khouzam 877a138192 Update gropenglshader.cpp 2018-12-06 22:53:42 -05:00
m!mandTheMatthew 8a34ceef91 Update code/graphics/opengl/gropenglshader.cpp
Co-Authored-By: TheMatthew <[email protected]>
2018-12-06 22:51:35 -05:00
niffiwan d638cacc51 Merge pull request #1932 from Goober5000/fix_warp_clipping
Fix warp clipping
2018-12-07 07:56:33 +10:00
asarium 871317b5bd Fix move constructor of streaminganim_h
The move constructor was written wrongly which caused issues when moving
the value into the Lua memory. This fixes that issue.

This fixes #1944.
2018-12-06 19:53:50 +01:00
m!mandTheMatthew 9b7a87d4c5 Update code/graphics/opengl/gropenglshader.cpp
Co-Authored-By: TheMatthew <[email protected]>
2018-12-03 20:04:30 -05:00
Matthew Khouzam 3b07636a16 Add a cache map for shaders in order to accelerate shader lookup
Shaders lookup in opengl_get_shader_idx performance reduces from
O(n) shader to O(1).

Signed-off-by: Matthew Khouzam <[email protected]>
2018-12-03 20:03:25 -05:00
m!m 8840d238d7 Merge pull request #1942 from TRBlount/lua/WeaponCreatedHook
Add On Weapon Created Hook
2018-12-03 17:58:03 +01:00
TRBlount 95128dd734 Fix Travis Errors 2018-12-02 01:10:22 -07:00
TRBlount 30866afbd6 Add On Weapon Created Hook 2018-12-02 01:10:22 -07:00
plieblang 2b43677c82 Improve UpdateSlider and add help text 2018-12-01 19:18:36 -06:00
Goober5000 94a542a2a3 Merge pull request #1940 from TheMatthew/minor_cleanup
objectsort: remove useless check
2018-11-29 02:02:44 -05:00
Matthew Khouzam 5c064afd95 Update objectsort.cpp 2018-11-28 23:12:55 -05:00
Matthew Khouzam 6ee41c06d8 Update objectsort.cpp 2018-11-28 23:12:34 -05:00
Matthew Khouzam 58fa411ad3 Update objectsort.cpp 2018-11-28 23:11:57 -05:00
Matthew Khouzam 08c2449672 Update objectsort.cpp 2018-11-28 23:11:27 -05:00
Matthew Khouzam 726af82c56 objectsort: remove useless check
if an object is a ship, it is a model. No need
to check twice.
2018-11-28 20:41:45 -05:00
m!m c11dce4a92 Merge pull request #1939 from TheMatthew/clean-fast-path
objectsort: Move nebula detection to common area
2018-11-28 19:11:56 +01:00
Matthew Khouzam 0121eb6123 objectsort: Move nebula detection to common area
Run nebula test once per frame rather than once
per object.

Use a common function to avoid drifting errors.
2018-11-27 23:45:09 -05:00
niffiwan 8a325362f6 Merge pull request #1938 from asarium/fix/optionalScriptingParameters
Check optional scripting parameters before using them
2018-11-27 20:07:29 +10:00
asarium 4eb0e41142 Check optional scripting parameters before using them
These were all cases where the parameter was the new value when setting
a variable. The variables should always be initialized when that code is
reached but it is still better to check the pointers before using them.

These were found by @niffiwan.
2018-11-26 18:50:12 +01:00
Goober5000 5528e4e42d Merge pull request #1933 from Goober5000/multi_sexp_destroy_and_subsys
multi capability for destroy-instantly and destroy-subsys-instantly
2018-11-25 13:41:33 -05:00
Goober5000 968695f851 fix handling of multiplayer packets 2018-11-25 00:27:14 -05:00
Goober5000 8f00c6e842 since we switched from a while-loop to a for-loop, don't repeat the CDR 2018-11-25 00:27:14 -05:00
Goober5000 8a9edb1215 remove error_bypass from new function 2018-11-25 00:27:14 -05:00
Goober5000 1c9e47ad3d address clang-tidy complaints 2018-11-25 00:26:29 -05:00
Goober5000 74fd3c0637 multi capability for destroy-instantly and destroy-subsys-instantly
Previously, these two SEXPs could only be used in single-player; now they can be used in multiplayer.  (This now allows Admiral MS's ship save/load script to work in multiplayer too.)

Inspired by Parias's patch included in the FSPort Co-Op Mod Beta (https://www.hard-light.net/forums/index.php?topic=88385.0) though with some modifications.
2018-11-25 00:26:29 -05:00
Goober5000 fe0f0558c2 Merge pull request #1937 from Goober5000/remove_error_bypass
remove error bypass in subsys functions
2018-11-25 00:20:34 -05:00
Goober5000 11ded47bd5 qtfred too 2018-11-24 14:57:38 -05:00
Goober5000 f8801446db fix function references 2018-11-24 14:11:26 -05:00
Goober5000 7492615a31 remove error_bypass 2018-11-24 14:05:37 -05:00
m!m 53cfc1eae4 Merge pull request #1936 from niffiwan/fix/issue1935
Fixes issue #1935
2018-11-24 09:25:06 +01:00
niffiwan 252facb6c4 Merge pull request #1927 from asarium/fix/decalObjectTypeChanges
Add additional validity check for decals
2018-11-24 10:52:18 +10:00
niffiwan 65417be571 Fixes issue #1935
If the optional arg isn't present; just pass -1 to bm_set_render_target
2018-11-24 09:04:12 +10:00
Goober5000 0da41b3943 address clang-tidy complaint 2018-11-22 16:07:00 -05:00
plieblang 97f9a6c91b Set default lighting to cmdline params and add reset view 2018-11-22 13:40:05 -06:00
m!m 10cd82456d Merge pull request #1914 from Goober5000/small_collision_optimization
only recompute collision pairs if we moved a colliding object
2018-11-21 18:59:08 +01:00
Goober5000 7878ba0d19 only recompute collision pairs if we moved a colliding object
The code already only recomputed collisions if we moved a ship or a wing, but this further optimizes things so that only ships or wings that can collide will cause a recomputation.
2018-11-20 13:54:39 -05:00
Goober5000 a6879a1b40 remove warning 2018-11-20 13:49:50 -05:00
Goober5000 cf7706eb1c might as well add the extents functionality too 2018-11-20 13:49:50 -05:00
Goober5000 09ed127d06 fix typo 2018-11-20 13:49:50 -05:00
Goober5000 77c3c79143 update special-warp-dist 2018-11-20 13:49:50 -05:00
Goober5000 62b74b8743 upgrade position_ship_for_knossos_warpin 2018-11-20 13:49:50 -05:00
Goober5000 4d99a3b8b3 fix determination of dist_to_plane 2018-11-20 13:49:49 -05:00
Goober5000 3a9a840633 forgot one of these 2018-11-20 13:49:49 -05:00
Goober5000 86f67c3c84 warp should be pretty much working correctly now
precalculate warp values before beginning warp, and use them throughout the warp instead of recalculating in every function
standardize on always using the entire docked assembly for length and half-length calculation, instead of some places the assembly and some places just the dock leader
consolidate and simplify the compute_warpout* functions in light of the above
2018-11-20 13:49:49 -05:00
Goober5000 28bb3bf914 rewrite dock_calc_docked_center to find the true physical center of the docked assembly 2018-11-20 13:49:49 -05:00
Goober5000 bd4b116188 this should fix the warpin/warpout distances for regular warpin 2018-11-20 13:49:49 -05:00
Tyler Blount 0a429e8a32 Merge pull request #1931 from asarium/fix/qtAppveyorNightlies
Also fix Appveyor Qt path for nightly builds
2018-11-18 16:59:09 -07:00
asarium f70253e219 Also fix Appveyor Qt path for nightly builds 2018-11-18 19:45:32 +01:00
m!m e901e44418 Merge pull request #1881 from asarium/cleanup/adeSignature
Add proper class support to Lua API
2018-11-18 19:09:45 +01:00
asarium 651268eeea Fix rvalue reference issue in SetHookVar 2018-11-18 12:43:39 +01:00
asarium 9b7c32d0c1 Fix merge issue 2018-11-18 12:43:39 +01:00
asarium d014e53505 Fix clang-tidy issues 2018-11-18 12:43:39 +01:00
asarium 00b0a80ad9 Call scripting handle destructor when Lua collects garbage
This will automatically call the destructor of a type of Lua calls the
garbage collector for an object of that type. This is the last step
towards fully supporting non-trivial objects in the Lua API and all
previous workarounds have been removed.
2018-11-18 12:43:39 +01:00
asarium 4a7109e1d5 Convert scripting value getting to templates
This is pretty much similar to the value setting changes. This is a much
safer solution for getting values out of the scripting system which has
compile time validation for move-only types.
2018-11-18 12:43:39 +01:00
asarium 1484ddbe77 Convert scripting value setting to using placement-new
This commit changes the way the scripting API works by properly using
the newly available type information for moving the FSO resources into
the memory supplied by lua. This has full support for rvalue references
which will make it possible to use move-only types with the scripting
API.

This also makes the API much safer to use since it doesn't use pointers
to local values anymore which made it very hard to use the API in a
different context without causing issues.

This only covers writing the FSO values to Lua. Getting values back is
not covered yet.
2018-11-18 12:43:39 +01:00
asarium 48b03a1789 Remove ADE signature from scripting API
This was previously used for allowing scripts to set arbitrary values on
scripting objects. However, it was used by only a few scripting
functions and, as far as I know, no script uses this features.

This removes that feature which simplifies the code ade_index_handler
of.

This also simplifies the code that handles the userdata for libraries
provided by FSO.
2018-11-18 12:43:39 +01:00
asarium e790cf209a Add additional validity check for decals
This tracks the original object type of a decal and marks a decal as
invalid if the type changes. This should fix a bug reported by Spoon.
2018-11-18 12:41:55 +01:00
Tyler Blount 1eea298fe1 Merge pull request #1929 from TRBlount/fix/lab_insignia
Fix oversights when a mod has zero Insignias
2018-11-13 19:08:43 -07:00
TRBlount 1de63cc881 Make sure having no insignias doesn't trigger asserts and prevent insignias from being rendered 2018-11-13 14:57:22 -07:00
Tyler Blount c7be4734d3 Merge pull request #1930 from asarium/build/appveyorDebug
Fix Appveyor Qt directory
2018-11-13 14:55:19 -07:00
asarium fbc2a2dab2 Fix Appveyor Qt directory
They updated their Qt version and didn't update the documentation page.
This fixes the recent build errors by using the 5.9 symlink which is
linked to the most recent version.
2018-11-13 18:27:02 +01:00
Tyler Blount e5be2372e1 Merge pull request #1928 from TRBlount/fix/share_fire_dir_access
Fix access violation in ship_get_global_turret_gun_info
2018-11-12 21:06:21 -07:00
TRBlount 9c69e11fe5 Add requested changes 2018-11-12 17:56:50 -07:00
TRBlount 0173f44070 Fix access violation in share_fire_direction code path 2018-11-11 16:09:05 -07:00
Fabian Woltermann 45559c13a9 Merge pull request #1912 from asarium/cleanup/noOldCollision
Remove -old_collision command line option
2018-11-10 17:52:17 +01:00
Fabian Woltermann 34888cb1a6 Merge pull request #1923 from asarium/cleanup/speechAPI
Cleanup the speech API code a bit
2018-11-10 17:51:32 +01:00
Fabian Woltermann b77b425f2f Merge pull request #1920 from The-E/feature/lab_camera_controls
Make the lab camera better
2018-11-10 17:40:51 +01:00
Fabian Woltermann 49b5c10295 Addresses feedback, switches default rotation mode to "Both" 2018-11-07 17:13:11 +01:00
niffiwan 0396d5670b Merge pull request #1924 from tomimaki/fix-incomplete-fb-attachment
Fix for incomplete attachment in shadow framebuffer
2018-11-07 07:54:12 +10:00
tomimaki bb6c00a516 Update gropengltnl.cpp 2018-11-06 15:13:59 +01:00
Fabian Woltermann 4d0703ad98 Remove the "disabled" rotation mode 2018-11-04 12:06:00 +01:00
asarium 27e91d8f6c Cleanup the speech API code a bit
This replaces the previously used defines with inline functions which
fixes a few warnings if the macros were ever used. This also changes
fsspeech.cpp so it is compiled always since it has no dependency on the
underlying speech system.
2018-11-03 14:54:29 +01:00
Fabian Woltermann 3c4ab2eef1 Add roll controls 2018-11-03 10:34:17 +01:00
Fabian Woltermann 4e7f29ea88 MORE CI fixes 2018-11-03 10:34:17 +01:00
Fabian Woltermann 793a3d8dd3 Even more CI fixes 2018-11-03 10:34:16 +01:00
Fabian Woltermann 49abb88385 Avoid CI errors 2018-11-03 10:33:06 +01:00
Fabian Woltermann 4c2ed1501e Switch the model rotation controls to a "turntable" model, add constraints, make speed configurable 2018-11-03 10:33:06 +01:00
Fabian Woltermann 6b425c1e6b Merge pull request #1922 from asarium/fix/1921
Fix cubemap offset computation for texture uploads
2018-11-03 10:27:58 +01:00
m!m 978a58dba2 Merge pull request #1917 from plieblang/LabArrowScrolling
Add arrow key scrolling to the lab
2018-11-03 09:07:20 +01:00
plieblang 3de05aefef Fire the item's existing function when selected 2018-11-03 01:21:47 -05:00
asarium da951e8be4 Fix cubemap offset computation for texture uploads
The changes from #1752 changed how the offset was computed but the
cubemap code did not update the initial offset computation to account
for this.

This fixes #1921.
2018-11-02 17:33:16 +01:00
m!m 483a6096bb Merge pull request #1885 from ngld/fix/rocketUI/tooMuchSound
Only play UI sounds if the event is triggered on the element where the property is set.
2018-10-31 19:14:19 +01:00
ngld 0ac810e7f0 Only play UI sounds if the event is triggered on the element where the property is set. 2018-10-31 06:46:27 +01:00
plieblang 0de1e55fb7 CI feedback 2018-10-28 17:25:43 -05:00
plieblang 3827bb9783 Fix nullptr crash and use vectors for *_list_endpoints 2018-10-28 12:59:36 -05:00
plieblang 69013f1d41 Add arrow key scrolling to the lab 2018-10-28 12:31:12 -05:00
m!m 3ac7864ac6 Merge pull request #1752 from asarium/opengl/baseLevelImprovement
Only upload mipmap levels that are actually needed
2018-10-28 18:22:01 +01:00
asarium 35a654660f Only upload mipmap levels that are actually needed
Previously, the game uploaded all mipmap levels found in the image files
and then selected which ones it will use by using GL_TEXTURE_BASE_LEVEL.
This unnecessarily used additional GPU memory which is especially bad if
the player already needs to use a lower detail level. This fixes that by
only uploading the necessary mipmap levels.
2018-10-28 14:57:00 +01:00
Goober5000 f975edd343 Merge pull request #1911 from asarium/feature/noSubsystemSparks
Add option for disabling spark spawning for subsystem
2018-10-27 12:50:50 -04:00
asarium 9219712ff0 Add option for disabling impact debris spawning 2018-10-27 16:37:42 +02:00
plieblang ead6cd9825 Separate ships by species properly 2018-10-26 00:21:08 -05:00
Goober5000 a32c5dad27 Merge pull request #1913 from Goober5000/whack_from_center_of_mass
calculate physics whack from docked center-of-mass, not docked center
2018-10-25 15:42:25 -04:00
plieblang 34d4ed5dba Scroll through ships/weapons with up/down keys 2018-10-25 11:50:16 -05:00
Goober5000 eb012584d6 Merge pull request #1880 from Goober5000/play_dead_persistent
add ai-play-dead-persistent
2018-10-24 14:50:40 -04:00
Goober5000 7cadce113d calculate physics whack from docked center-of-mass, not docked center 2018-10-24 00:17:10 -04:00
asarium 15dc45cc0a Remove -old_collision command line option
The new system has been tested pretty thoroughly so I think it is time
to remove this option.
2018-10-21 18:36:59 +02:00
asarium 3c41b56449 Add option for disabling spark spawning for subsystem
This adds the "no sparks" flag for subsystems which disables the
generation of spark sources for that subsystem when it is hit.

This was requested by Axem.
2018-10-21 18:03:48 +02:00
Goober5000 c667668c17 don't override play-dead goals 2018-09-27 01:33:44 -04:00
Goober5000 8d4643bc7a add ai-play-dead-persistent
This adds a new AI goal which is equivalent to play-dead except that it "sticks".  It doesn't clear the goal list
so it will continue playing dead until the goal is removed or another goal with a higher priority is added.
2018-09-27 00:48:57 -04:00
352 changed files with 10604 additions and 12023 deletions

No files matched your search

+182
View File
@@ -0,0 +1,182 @@
version: 2
references:
container_config: &container_config
docker:
- image: "debian:stretch"
working_directory: /root/build
restore_repo: &restore_repo
restore_cache:
keys:
- source-repo-{{ .Branch }}-{{ .Revision }}
- source-repo-{{ .Branch }}
- source-repo
cmake_configure: &cmake_configure
run:
name: Creating Build Files
command: |
mkdir build
cd build
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
if [[ "$CC" =~ ^clang.*$ ]]; then
CXXFLAGS="$CXXFLAGS -stdlib=libc++"
fi
eval $CC --version
export CXXFLAGS
export CFLAGS
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON $CMAKE_OPTIONS"
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON ..
compile: &compile
run:
name: Compiling Source code
command: |
cd build
ninja -k 20 all
run_tests: &run_tests
run:
name: Run unit tests
command: |
./build/bin/unittests --gtest_shuffle
compile_steps: &compile_steps
steps:
- *restore_repo
- *cmake_configure
- *compile
- *run_tests
jobs:
checkout_code:
<<: *container_config
steps:
- run:
name: Installing Git
command: 'apt-get update && apt-get -yq install git'
- *restore_repo
- checkout
- run:
name: Updating submodules
command: 'git submodule update --init --recursive'
- save_cache:
key: source-repo-{{ .Branch }}-{{ .Revision }}
paths:
- .
build_gcc_lowest_debug:
docker:
- image: asarium/fso_compile:gcc-lowest
working_directory: /root/build
environment:
CC: gcc
CXX: g++
CONFIGURATION: Debug
<<: *compile_steps
build_gcc_lowest_release:
docker:
- image: asarium/fso_compile:gcc-lowest
working_directory: /root/build
environment:
CC: gcc
CXX: g++
CONFIGURATION: Release
<<: *compile_steps
build_gcc_latest_debug:
docker:
- image: asarium/fso_compile:gcc-latest
working_directory: /root/build
environment:
CC: gcc
CXX: g++
CONFIGURATION: Debug
<<: *compile_steps
build_gcc_latest_release:
docker:
- image: asarium/fso_compile:gcc-latest
working_directory: /root/build
environment:
CC: gcc
CXX: g++
CONFIGURATION: Release
<<: *compile_steps
build_clang_latest_debug:
docker:
- image: asarium/fso_compile:clang-latest
working_directory: /root/build
environment:
CC: clang-8
CXX: clang++-8
CONFIGURATION: Debug
<<: *compile_steps
build_clang_latest_release:
docker:
- image: asarium/fso_compile:clang-latest
working_directory: /root/build
environment:
CC: clang-8
CXX: clang++-8
CONFIGURATION: Release
<<: *compile_steps
build_clang_lowest_debug:
docker:
- image: asarium/fso_compile:clang-lowest
working_directory: /root/build
environment:
CC: clang
CXX: clang++
CONFIGURATION: Debug
<<: *compile_steps
build_clang_lowest_release:
docker:
- image: asarium/fso_compile:clang-lowest
working_directory: /root/build
environment:
CC: clang
CXX: clang++
CONFIGURATION: Release
<<: *compile_steps
workflows:
version: 2
build_test:
jobs:
- checkout_code
- build_gcc_lowest_debug:
requires:
- checkout_code
- build_gcc_lowest_release:
requires:
- checkout_code
- build_gcc_latest_debug:
requires:
- checkout_code
- build_gcc_latest_release:
requires:
- checkout_code
- build_clang_latest_debug:
requires:
- checkout_code
- build_clang_latest_release:
requires:
- checkout_code
- build_clang_lowest_debug:
requires:
- checkout_code
- build_clang_lowest_release:
requires:
- checkout_code
+1
View File
@@ -47,6 +47,7 @@ Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^(<.*\.(h|hh|hpp)>)$' # Includes of external libraries
Priority: 4
+1
View File
@@ -5,6 +5,7 @@ cache:
directories:
- $HOME/cmake-3.8
- $HOME/.ccache
- $HOME/curl_cache
addons:
apt:
packages: &global_deps
+2 -2
View File
@@ -9,11 +9,11 @@ environment:
- BuildID: 0
CMAKE_GENERATOR: Visual Studio 14 2015
PlatformToolset: v140_xp
QT_DIR: C:\Qt\5.9.5\msvc2015
QT_DIR: C:\Qt\5.9\msvc2015
- BuildID: 1
CMAKE_GENERATOR: Visual Studio 14 2015 Win64
PlatformToolset: v140_xp
QT_DIR: C:\Qt\5.9.5\msvc2015_64
QT_DIR: C:\Qt\5.9\msvc2015_64
before_build:
- git submodule update --init --recursive
build_script:
+6 -6
View File
@@ -14,7 +14,7 @@ $NightlyConfigurations = @(
PackageType="Win64";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9.5\msvc2015_64";
QtDir="C:\Qt\5.9\msvc2015_64";
SourcePackage=$false;
},
[BuildConfig]@{
@@ -22,7 +22,7 @@ $NightlyConfigurations = @(
PackageType="Win32";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9.5\msvc2015";
QtDir="C:\Qt\5.9\msvc2015";
SourcePackage=$false;
}
)
@@ -32,7 +32,7 @@ $ReleaseConfigurations = @(
PackageType="Win32";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9.5\msvc2015";
QtDir="C:\Qt\5.9\msvc2015";
SourcePackage=$true;
}
[BuildConfig]@{
@@ -40,7 +40,7 @@ $ReleaseConfigurations = @(
PackageType="Win32-AVX";
Toolset="v140_xp";
SimdType="AVX";
QtDir="C:\Qt\5.9.5\msvc2015";
QtDir="C:\Qt\5.9\msvc2015";
SourcePackage=$false;
}
[BuildConfig]@{
@@ -48,7 +48,7 @@ $ReleaseConfigurations = @(
PackageType="Win64";
Toolset="v140_xp";
SimdType="SSE2";
QtDir="C:\Qt\5.9.5\msvc2015_64";
QtDir="C:\Qt\5.9\msvc2015_64";
SourcePackage=$false;
}
[BuildConfig]@{
@@ -56,7 +56,7 @@ $ReleaseConfigurations = @(
PackageType="Win64-AVX";
Toolset="v140_xp";
SimdType="AVX";
QtDir="C:\Qt\5.9.5\msvc2015_64";
QtDir="C:\Qt\5.9\msvc2015_64";
SourcePackage=$false;
}
)
+53 -18
View File
@@ -10,27 +10,62 @@ if [[ ! "$(curl -V)" == *"sftp"* ]]; then
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
# Since the Travis CI people are not capable of enabling SSH/SCP support for their libcurl we need to build that manually...
# These commands are based on the tutorial from here: http://zeroset.mnim.org/2013/03/14/sftp-support-for-curl-in-ubuntu-12-10-quantal-quetzal-and-later/
mkdir /tmp/curl
cd /tmp/curl
sudo apt-get update
sudo apt-get install build-essential debhelper libssh2-1-dev libgnutls-dev libidn11-dev libkrb5-dev libldap2-dev libnss3-dev librtmp-dev libtool openssh-server quilt
apt-get source curl
sudo apt-get build-dep curl
if [ -f ~/curl_cache/curl*.deb ]; then
cd ~/curl_cache
sudo dpkg -i libcurl3*.deb
sudo dpkg -i curl*.deb
else
# Since the Travis CI people are not capable of enabling SSH/SCP support for their libcurl we need to build that manually...
# These commands are based on the tutorial from here: http://zeroset.mnim.org/2013/03/14/sftp-support-for-curl-in-ubuntu-12-10-quantal-quetzal-and-later/
mkdir /tmp/curl
cd /tmp/curl
sudo apt-get update
sudo apt-get install build-essential debhelper libssh2-1-dev libgnutls-dev libidn11-dev libkrb5-dev libldap2-dev libnss3-dev librtmp-dev libtool openssh-server quilt
apt-get source curl
sudo apt-get build-dep curl
cd curl-*
export DEB_BUILD_OPTIONS="nocheck"
sudo dpkg-buildpackage -uc -us -j"$(grep -c ^processor /proc/cpuinfo)"
cd curl-*
export DEB_BUILD_OPTIONS="nocheck"
sudo dpkg-buildpackage -uc -us -j"$(grep -c ^processor /proc/cpuinfo)"
cd ..
dpkg -l | grep curl
ls -al
sudo dpkg -i libcurl3*.deb
sudo dpkg -i curl*.deb
cd ..
dpkg -l | grep curl
ls -al
if [ ! -d ~/curl_cache ]; then
mkdir ~/curl_cache
fi
cp libcurl3*.deb curl*.deb ~/curl_cache
sudo dpkg -i libcurl3*.deb
sudo dpkg -i curl*.deb
fi
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew install curl --with-libssh2
export PATH="/usr/local/opt/curl/bin:$PATH"
brew install libssh2
if [ -d ~/curl_cache/curl ]; then
cd ~/curl_cache/curl
sudo make install
else
mkdir /tmp/curl
cd /tmp/curl
curl -LO "https://curl.haxx.se/download/curl-7.64.0.tar.bz2"
tar -xjf curl-7.64.0.tar.bz2
cd curl-7.64.0
./configure --disable-debug --disable-dependency-tracking --disable-silent-rules --with-libssh2 --with-darwinssl --without-ca-bundle --without-ca-path
make -j"$(sysctl hw.logicalcpu | cut -d " " -f 2)"
if [ ! -d ~/curl_cache ]; then
mkdir ~/curl_cache
fi
cp -a . ~/curl_cache/curl
sudo make install
fi
export PATH=/usr/local/bin:$PATH
fi
# After
-2
View File
@@ -9,8 +9,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -funroll-loops -fsigned-char -Wno-
# Omit "conversion from string literal to 'char *' is deprecated" warnings.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-write-strings")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-char-subscripts")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
-2
View File
@@ -66,8 +66,6 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} ${SANITIZE_FLAGS}")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wformat-security")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-function")
# Dear Clang, please tell us if a function does not return a value since that part of the standard is stupid!
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
-2
View File
@@ -78,8 +78,6 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} ${SANITIZE_FLAGS}")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wformat-security")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-function")
# Dear GCC, please tell us if a function does not return a value since that part of the standard is stupid!
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
-5
View File
@@ -587,13 +587,10 @@ extern void get_absolute_wing_pos_autopilot( vec3d *result_pos, object *leader_o
// Interface from goals code to AI. Set ship to guard. *objp guards *other_objp
extern void ai_set_guard_object(object *objp, object *other_objp);
extern void ai_set_evade_object(object *objp, object *other_objp);
extern void ai_set_guard_wing(object *objp, int wingnum);
extern void ai_warp_out(object *objp, vec3d *vp);
extern void ai_attack_wing(object *attacker, int wingnum);
extern void ai_deathroll_start(object *ship_obj);
extern void ai_fly_in_formation(int wing_num); // Force wing to fly in formation.
extern void ai_disband_formation(int wing_num); // Force wing to disband formation flying.
extern int set_target_objnum(ai_info *aip, int objnum);
extern void ai_form_on_wing(object *objp, object *goal_objp);
extern void ai_do_stay_near(object *objp, object *other_obj, float dist);
@@ -646,8 +643,6 @@ extern void ai_do_objects_repairing_stuff( object *repaired_obj, object *repair_
// Move to a position relative to a dock bay using thrusters.
extern float dock_orient_and_approach(object *docker_objp, int docker_index, object *dockee_objp, int dockee_index, int dock_mode, rotating_dockpoint_info *rdinfo = NULL);
extern int find_danger_weapon(object *sobjp, float dtime, float *atime, float dot_threshhold);
void ai_set_mode_warp_out(object *objp, ai_info *aip);
// prototyped by Goober5000
+1
View File
@@ -110,6 +110,7 @@ namespace AI {
Smart_shield_management,
Smart_subsystem_targeting_for_turrets,
Strict_turred_tagged_only_targeting,
Support_dont_add_primaries, //Prevents support ship from equipping new primary as requested in http://scp.indiegames.us/mantis/view.php?id=3198
Turrets_ignore_target_radius,
Use_actual_primary_range,
Use_additive_weapon_velocity,
+2
View File
@@ -435,6 +435,8 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$ai guards specific ship in wing:", AI::Profile_Flags::Ai_guards_specific_ship_in_wing);
set_flag(profile, "$support don't add primaries:", AI::Profile_Flags::Support_dont_add_primaries);
profile->ai_path_mode = AI_PATH_MODE_NORMAL;
if (optional_string("$ai path mode:"))
{
+19 -77
View File
@@ -58,6 +58,8 @@
#include "physics/physics.h"
#include "playerman/player.h"
#include "render/3d.h"
#include "scripting/api/objs/wing.h"
#include "scripting/scripting.h"
#include "ship/afterburner.h"
#include "ship/awacs.h"
#include "ship/ship.h"
@@ -1345,6 +1347,7 @@ void ai_object_init(object * obj, int ai_index)
aip->wing = -1; // Member of what wing? -1 means none.
aip->ai_class = Ship_info[Ships[obj->instance].ship_info_index].ai_class;
aip->behavior = AIM_NONE;
aip->mode = aip->behavior;
}
/**
@@ -4586,6 +4589,11 @@ void ai_waypoints()
ai_mission_wing_goal_complete( Ships[Pl_objp->instance].wingnum, &(aip->goals[aip->active_goal]) );
mission_log_add_entry( LOG_WAYPOINTS_DONE, Wings[Ships[Pl_objp->instance].wingnum].name, aip->wp_list->get_name(), -1 );
}
// adds scripting hook for 'On Waypoints Done' --wookieejedi
Script_system.SetHookObject("Ship", &Objects[Ships[Pl_objp->instance].objnum]);
Script_system.SetHookVar("Wing", 'o', scripting::api::l_Wing.Set(Ships[Pl_objp->instance].wingnum));
Script_system.RunCondition(CHA_ONWAYPOINTSDONE);
Script_system.RemHookVars(2, "Ship", "Wing");
}
}
}
@@ -5346,7 +5354,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Capital_plus])
{
swp->current_primary_bank = i;
nprintf(("AI", "%i: Ship %s selecting weapon %s\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i]].name));
nprintf(("AI", "%i: Ship %s selecting weapon %s (capital+) vs target %s\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i]].name, Ships[other_objp->instance].ship_name));
return i;
}
}
@@ -5384,6 +5392,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
i_hullfactor_prev_bank = 0; // Just switch to the first one
}
swp->current_primary_bank = i_hullfactor_prev_bank; // Select the best weapon
nprintf(("AI", "%i: Ship %s selecting weapon %s (no shields) vs target %s\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i_hullfactor_prev_bank]].name, (other_objp->type == OBJ_SHIP ? Ships[other_objp->instance].ship_name : "non-ship") ));
return i_hullfactor_prev_bank; // Return
}
@@ -5398,6 +5407,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
if ((Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags[Weapon::Info_Flags::Pierce_shields]) && !(Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags[Weapon::Info_Flags::Capital_plus]))
{
nprintf(("AI", "%i: Ship %s selecting weapon %s (>10%% shields)\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[bank_index]].name));
return swp->current_primary_bank;
}
}
@@ -5412,6 +5422,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
if ((Weapon_info[weapon_info_index].wi_flags[Weapon::Info_Flags::Pierce_shields]) && !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Capital_plus]))
{
swp->current_primary_bank = i;
nprintf(("AI", "%i: Ship %s selecting weapon %s (>10%% shields)\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i]].name));
return i;
}
}
@@ -5446,6 +5457,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
i_hullfactor_prev_bank = 0; // Just switch to the first one
}
swp->current_primary_bank = i_hullfactor_prev_bank; // Select the best weapon
nprintf(("AI", "%i: Ship %s selecting weapon %s (<50%% shields)\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i_hullfactor_prev_bank]].name));
return i_hullfactor_prev_bank; // Return
}
else
@@ -5475,6 +5487,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
i_hullfactor_prev_bank = 0; // Just switch to the first one
}
swp->current_primary_bank = i_hullfactor_prev_bank; // Select the best weapon
nprintf(("AI", "%i: Ship %s selecting weapon %s (>50%% shields)\n", Framecount, Ships[objp->instance].ship_name, Weapon_info[swp->primary_bank_weapons[i_hullfactor_prev_bank]].name));
return i_hullfactor_prev_bank; // Return
}
}
@@ -5502,7 +5515,9 @@ void set_primary_weapon_linkage(object *objp)
// If trying to destroy a big ship (i.e., not disable/disarm), always unleash all weapons
if ( Ship_info[Ships[Objects[aip->target_objnum].instance].ship_info_index].is_big_ship() ) {
if ( aip->targeted_subsys == NULL ) {
shipp->flags.set(Ship::Ship_Flags::Primary_linked);
if (!sip->flags[Ship::Info_Flags::No_primary_linking] ) {
shipp->flags.set(Ship::Ship_Flags::Primary_linked);
}
shipp->flags.set(Ship::Ship_Flags::Secondary_dual_fire);
return;
}
@@ -7478,32 +7493,6 @@ void ai_set_guard_wing(object *objp, int wingnum)
}
}
// Make object *objp guard object *other_objp.
// To be called from the goals code.
void ai_set_evade_object(object *objp, object *other_objp)
{
ship *shipp;
ai_info *aip;
int other_objnum;
Assert(objp->type == OBJ_SHIP);
Assert(objp->instance >= 0);
shipp = &Ships[objp->instance];
Assert(shipp->ai_index >= 0);
aip = &Ai_info[shipp->ai_index];
other_objnum = OBJ_INDEX(other_objp);
Assert(other_objnum >= 0);
Assert(other_objnum != Ships[aip->shipnum].objnum); // make sure not targeting self
aip->target_objnum = other_objnum;
aip->mode = AIM_EVADE;
}
// Make objp guard other_objp
// If other_objp is a member of a wing, objp will guard that whole wing
// UNLESS objp is also a member of the wing!
@@ -11538,53 +11527,6 @@ void render_wing_phantoms_all()
#endif
// Hook from goals code to AI.
// Force a wing to fly in formation.
// Sets AIF_FORMATION bit in ai_flags.
// wingnum Wing to force to fly in formation
void ai_fly_in_formation(int wingnum)
{
object *objp;
ship *shipp;
ship_obj *so;
for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
objp = &Objects[so->objnum];
Assert((objp->instance >= 0) && (objp->instance < MAX_SHIPS));
shipp = &Ships[objp->instance];
Assert((shipp->ai_index >= 0) && (shipp->ai_index < MAX_AI_INFO));
if (Ai_info[shipp->ai_index].wing == wingnum) {
Ai_info[shipp->ai_index].ai_flags.set(AI::AI_Flags::Formation_wing);
Ai_info[shipp->ai_index].ai_flags.remove(AI::AI_Flags::Formation_object);
}
}
}
// Hook from goals code to AI.
// Force a wing to abandon formation flying.
// Clears AIF_FORMATION bit in ai_flags.
// wingnum Wing to force to fly in formation
void ai_disband_formation(int wingnum)
{
object *objp;
ship *shipp;
ship_obj *so;
for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
objp = &Objects[so->objnum];
Assert((objp->instance >= 0) && (objp->instance < MAX_SHIPS));
shipp = &Ships[objp->instance];
Assert((shipp->ai_index >= 0) && (shipp->ai_index < MAX_AI_INFO));
if (Ai_info[shipp->ai_index].wing == wingnum) {
Ai_info[shipp->ai_index].ai_flags.remove(AI::AI_Flags::Formation_wing);
}
}
}
float Leader_chaos = 0.0f;
int Chaos_frame = -1;
@@ -13359,7 +13301,7 @@ void ai_warp_out(object *objp)
case AIS_WARP_2: // Make sure won't collide with any object.
if (timestamp_elapsed(aip->force_warp_time)
|| (!collide_predict_large_ship(objp, objp->radius*2.0f + 100.0f)
|| (Ship_info[shipp->ship_info_index].warpout_type == WT_HYPERSPACE
|| (Warp_params[shipp->warpout_params_index].warp_type == WT_HYPERSPACE
&& !collide_predict_large_ship(objp, 100000.0f)))) {
aip->submode = AIS_WARP_3;
aip->submode_start_time = Missiontime;
@@ -13402,7 +13344,7 @@ void ai_warp_out(object *objp)
break;
case AIS_WARP_4: {
// Only lets the ship warp after waiting for the warpout engage time
if ( (Missiontime / 100) >= (aip->submode_start_time / 100 + Ship_info[shipp->ship_info_index].warpout_engage_time) ) {
if ( (Missiontime / 100) >= (aip->submode_start_time / 100 + Warp_params[shipp->warpout_params_index].warpout_engage_time) ) {
shipfx_warpout_start(objp);
aip->submode = AIS_WARP_5;
aip->submode_start_time = Missiontime;
+54 -47
View File
@@ -62,31 +62,32 @@ char Ai_dock_names[MAX_AI_DOCK_NAMES][NAME_LENGTH];
// Used in objecttypes.tbl to define custom ship types
ai_goal_list Ai_goal_names[] =
{
{ "Attack ship", AI_GOAL_CHASE, 0 },
{ "Dock", AI_GOAL_DOCK, 0 },
{ "Waypoints", AI_GOAL_WAYPOINTS, 0 },
{ "Waypoints once", AI_GOAL_WAYPOINTS_ONCE, 0 },
{ "Depart", AI_GOAL_WARP, 0 },
{ "Attack subsys", AI_GOAL_DESTROY_SUBSYSTEM, 0 },
{ "Form on wing", AI_GOAL_FORM_ON_WING, 0 },
{ "Undock", AI_GOAL_UNDOCK, 0 },
{ "Attack wing", AI_GOAL_CHASE_WING, 0 },
{ "Guard ship", AI_GOAL_GUARD, 0 },
{ "Disable ship", AI_GOAL_DISABLE_SHIP, 0 },
{ "Disarm ship", AI_GOAL_DISARM_SHIP, 0 },
{ "Attack any", AI_GOAL_CHASE_ANY, 0 },
{ "Ignore ship", AI_GOAL_IGNORE, 0 },
{ "Ignore ship (new)", AI_GOAL_IGNORE_NEW, 0 },
{ "Guard wing", AI_GOAL_GUARD_WING, 0 },
{ "Evade ship", AI_GOAL_EVADE_SHIP, 0 },
{ "Stay near ship", AI_GOAL_STAY_NEAR_SHIP, 0 },
{ "keep safe dist", AI_GOAL_KEEP_SAFE_DISTANCE, 0 },
{ "Rearm ship", AI_GOAL_REARM_REPAIR, 0 },
{ "Stay still", AI_GOAL_STAY_STILL, 0 },
{ "Play dead", AI_GOAL_PLAY_DEAD, 0 },
{ "Attack weapon", AI_GOAL_CHASE_WEAPON, 0 },
{ "Fly to ship", AI_GOAL_FLY_TO_SHIP, 0 },
{ "Attack ship class", AI_GOAL_CHASE_SHIP_CLASS, 0 },
{ "Attack ship", AI_GOAL_CHASE, 0 },
{ "Dock", AI_GOAL_DOCK, 0 },
{ "Waypoints", AI_GOAL_WAYPOINTS, 0 },
{ "Waypoints once", AI_GOAL_WAYPOINTS_ONCE, 0 },
{ "Depart", AI_GOAL_WARP, 0 },
{ "Attack subsys", AI_GOAL_DESTROY_SUBSYSTEM, 0 },
{ "Form on wing", AI_GOAL_FORM_ON_WING, 0 },
{ "Undock", AI_GOAL_UNDOCK, 0 },
{ "Attack wing", AI_GOAL_CHASE_WING, 0 },
{ "Guard ship", AI_GOAL_GUARD, 0 },
{ "Disable ship", AI_GOAL_DISABLE_SHIP, 0 },
{ "Disarm ship", AI_GOAL_DISARM_SHIP, 0 },
{ "Attack any", AI_GOAL_CHASE_ANY, 0 },
{ "Ignore ship", AI_GOAL_IGNORE, 0 },
{ "Ignore ship (new)", AI_GOAL_IGNORE_NEW, 0 },
{ "Guard wing", AI_GOAL_GUARD_WING, 0 },
{ "Evade ship", AI_GOAL_EVADE_SHIP, 0 },
{ "Stay near ship", AI_GOAL_STAY_NEAR_SHIP, 0 },
{ "keep safe dist", AI_GOAL_KEEP_SAFE_DISTANCE, 0 },
{ "Rearm ship", AI_GOAL_REARM_REPAIR, 0 },
{ "Stay still", AI_GOAL_STAY_STILL, 0 },
{ "Play dead", AI_GOAL_PLAY_DEAD, 0 },
{ "Play dead (persistent)", AI_GOAL_PLAY_DEAD_PERSISTENT, 0 },
{ "Attack weapon", AI_GOAL_CHASE_WEAPON, 0 },
{ "Fly to ship", AI_GOAL_FLY_TO_SHIP, 0 },
{ "Attack ship class", AI_GOAL_CHASE_SHIP_CLASS, 0 },
};
int Num_ai_goals = sizeof(Ai_goal_names) / sizeof(ai_goal_list);
@@ -732,6 +733,12 @@ void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, ch
aigp->target_signature = Objects[Weapons[submode].objnum].signature;
}
if ( mode == AI_GOAL_WAYPOINTS_ONCE || mode == AI_GOAL_WAYPOINTS ) {
// should be the same as setting via sexp, see ai_add_goal_sub_sexp
// set to null so the AI code can setup the new waypoint list, see ai_mission_goal_achievable
aigp->wp_list = nullptr;
}
if ( target_name != NULL )
aigp->target_name = ai_get_goal_target_name( target_name, &aigp->target_name_index );
else
@@ -937,6 +944,11 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
aigp->ai_mode = AI_GOAL_PLAY_DEAD;
break;
case OP_AI_PLAY_DEAD_PERSISTENT:
aigp->priority = atoi( CTEXT(CDR(node)) );
aigp->ai_mode = AI_GOAL_PLAY_DEAD_PERSISTENT;
break;
case OP_AI_KEEP_SAFE_DISTANCE:
aigp->priority = atoi( CTEXT(CDR(node)) );
aigp->ai_mode = AI_GOAL_KEEP_SAFE_DISTANCE;
@@ -1126,6 +1138,10 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
goalmode = AI_GOAL_PLAY_DEAD;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_PLAY_DEAD_PERSISTENT:
goalmode = AI_GOAL_PLAY_DEAD_PERSISTENT;
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
break;
case OP_AI_KEEP_SAFE_DISTANCE:
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
goalmode = AI_GOAL_KEEP_SAFE_DISTANCE;
@@ -1340,25 +1356,6 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*
ai_process_mission_orders( Ships[aip->shipnum].objnum, aip );
}
// function to add an internal goal to a wing. Mike K says that the goal doesn't need to persist
// across waves of the wing so we merely need to add the goal to each ship in the wing. Certain
// goal are simply not valid for wings (like dock, undock). Immediate parameter gets passed to add_ship_goal
// to say whether or not we should process this goal right away
void ai_add_goal_wing_internal( wing *wingp, int goal_type, char *name, int immediate )
{
int i;
// be sure we are not trying to issue dock or undock goals to wings
Assert ( (goal_type != AI_GOAL_DOCK) && (goal_type != AI_GOAL_UNDOCK) );
for (i = 0; i < wingp->current_count; i++) {
int num = wingp->ship_index[i];
if ( num == -1 ) // ship must have been destroyed or departed
continue;
ai_add_goal_ship_internal( &Ai_info[Ships[num].ai_index], goal_type, name, -1, -1, immediate);
}
}
// this function copies goals from a wing to an ai_info * from a ship.
void ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip )
{
@@ -1401,7 +1398,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
// these orders are always achievable.
if ( (aigp->ai_mode == AI_GOAL_KEEP_SAFE_DISTANCE)
|| (aigp->ai_mode == AI_GOAL_CHASE_ANY) || (aigp->ai_mode == AI_GOAL_STAY_STILL)
|| (aigp->ai_mode == AI_GOAL_PLAY_DEAD) )
|| (aigp->ai_mode == AI_GOAL_PLAY_DEAD) || (aigp->ai_mode == AI_GOAL_PLAY_DEAD_PERSISTENT) )
return AI_GOAL_ACHIEVABLE;
// warp (depart) only achievable if there's somewhere to depart to
@@ -1895,9 +1892,12 @@ int ai_goal_priority_compare(const void *a, const void *b)
// check whether or not the goal override flag is set. If it is set, then push this goal higher
// in the list
else if ( (ga->flags[AI::Goal_Flags::Goal_override]) && !(gb->flags[AI::Goal_Flags::Goal_override]) )
// Goober5000: the ONLY goals we do not override are play-dead and play-dead-persistent,
// because the override flag needs to work in any other situation
else if ( (ga->flags[AI::Goal_Flags::Goal_override]) && !(gb->flags[AI::Goal_Flags::Goal_override]) && !(gb->ai_mode == AI_GOAL_PLAY_DEAD) && !(gb->ai_mode == AI_GOAL_PLAY_DEAD_PERSISTENT) )
return -1;
else if ( !(ga->flags[AI::Goal_Flags::Goal_override]) && (gb->flags[AI::Goal_Flags::Goal_override]) )
else if ( !(ga->flags[AI::Goal_Flags::Goal_override]) && (gb->flags[AI::Goal_Flags::Goal_override]) && !(ga->ai_mode == AI_GOAL_PLAY_DEAD) && !(ga->ai_mode == AI_GOAL_PLAY_DEAD_PERSISTENT))
return 1;
// now normal priority processing
@@ -2290,6 +2290,13 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
aip->submode_start_time = Missiontime;
break;
case AI_GOAL_PLAY_DEAD_PERSISTENT:
// same as above, but we don't clear out ship goals
aip->mode = AIM_PLAY_DEAD;
aip->submode = -1;
aip->submode_start_time = Missiontime;
break;
case AI_GOAL_FORM_ON_WING:
// for form on wing, we need to clear out all goals for this ship, and then call the form
// on wing AI code
+5 -5
View File
@@ -58,16 +58,17 @@ struct ai_goal;
#define AI_GOAL_FLY_TO_SHIP (1<<23) // 0x00800000
#define AI_GOAL_IGNORE_NEW (1<<24) // 0x01000000
#define AI_GOAL_CHASE_SHIP_CLASS (1<<25) // 0x02000000
#define AI_GOAL_PLAY_DEAD_PERSISTENT (1<<26) // 0x03000000
// now the masks for ship types
// Goober5000: added AI_GOAL_STAY_NEAR_SHIP and AI_GOAL_KEEP_SAFE_DISTANCE as valid for fighters
//WMC - Don't need these anymore. Whee!
/*
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
#define AI_GOAL_ACCEPT_BOMBER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_STEALTH ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_TRANSPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_DOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_UNDOCK | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD| AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_TRANSPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_DOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_UNDOCK | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_FREIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_TRANSPORT | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_CRUISER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FREIGHTER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_CORVETTE ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER | AI_GOAL_STAY_NEAR_SHIP )
@@ -75,7 +76,7 @@ struct ai_goal;
#define AI_GOAL_ACCEPT_AWACS ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_CAPITAL ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER & ~(AI_GOAL_DOCK | AI_GOAL_UNDOCK) | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_SUPERCAP ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CAPITAL | AI_GOAL_STAY_NEAR_SHIP )
#define AI_GOAL_ACCEPT_SUPPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_DOCK | AI_GOAL_UNDOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD)
#define AI_GOAL_ACCEPT_SUPPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_DOCK | AI_GOAL_UNDOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT )
#define AI_GOAL_ACCEPT_ESCAPEPOD ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_TRANSPORT| AI_GOAL_STAY_NEAR_SHIP )
*/
@@ -102,7 +103,7 @@ extern int ai_goal_num(ai_goal *goals);
extern void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipname, ai_info *aip);
extern void ai_add_ship_goal_sexp( int sexp, int type, ai_info *aip );
extern void ai_add_wing_goal_sexp( int sexp, int type, int wingnum );
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp );
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name );
extern int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp );
extern void ai_remove_wing_goal_sexp(int sexp, int wingnum);
@@ -127,6 +128,5 @@ extern char *ai_add_dock_name(const char *str);
extern int ai_query_goal_valid( int ship, int ai_goal_type );
extern void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate = 1 );
extern void ai_add_goal_wing_internal( wing *wingp, int goal_type, char *name, int immediate = 1 );
#endif
+5 -3
View File
@@ -1290,7 +1290,9 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos
model_instance_find_world_point(&tmp_pos, &avg, Ships[objp->instance].model_instance_num, tp->turret_gun_sobj, &objp->orient, &objp->pos);
if (targetp == nullptr) {
Assertion(ssp->turret_enemy_objnum >= 0, "The turret enemy object number %d for %s on ship number %d is invalid.", ssp->turret_enemy_objnum, ssp->sub_name, ssp->parent_objnum);
ship* shipp = &Ships[Objects[ssp->parent_objnum].instance];
Assertion(ssp->turret_enemy_objnum >= 0, "The turret enemy object number %d for %s on ship name %s is invalid.", ssp->turret_enemy_objnum, ssp->sub_name,
(shipp->has_display_name()) ? shipp->display_name.c_str() : shipp->ship_name);
object *lep = &Objects[ssp->turret_enemy_objnum];
int best_weapon_tidx = turret_select_best_weapon(ssp, lep);
@@ -1301,9 +1303,9 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos
weapon_info *wip = get_turret_weapon_wip(&ssp->weapons, best_weapon_tidx);
float weapon_system_strength = ship_get_subsystem_strength(&Ships[ssp->parent_objnum], SUBSYSTEM_WEAPONS);
float weapon_system_strength = ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS);
turret_ai_update_aim(&Ai_info[Ships[ssp->parent_objnum].ai_index], &Objects[ssp->turret_enemy_objnum], ssp);
turret_ai_update_aim(&Ai_info[shipp->ai_index], &Objects[ssp->turret_enemy_objnum], ssp);
if ((ssp->targeted_subsys != nullptr) && !(ssp->flags[Ship::Subsystem_Flags::No_SS_targeting])) {
vm_vec_unrotate(&enemy_point, &ssp->targeted_subsys->system_info->pnt, &Objects[ssp->turret_enemy_objnum].orient);
-169
View File
@@ -519,19 +519,6 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
return 0;
}
/**
* @brief Stop an anim instance that is on the anim_render_list from playing
*/
int anim_stop_playing(anim_instance* instance)
{
Assert(instance != NULL);
if ( anim_playing(instance) ) {
anim_release_render_instance(instance);
}
return 0;
}
/**
* @brief Free a particular animation instance that is on the anim_render_list.
* Do not call this function to free an animation instance in general (use
@@ -866,20 +853,6 @@ int anim_free(anim *ptr)
return 0;
}
/**
* @brief Return if an anim is playing or not.
*/
int anim_playing(anim_instance *ai)
{
Assert(ai != NULL);
if ( ai->frame == NULL )
return 0;
else
return 1;
}
/**
* @brief Called at the beginning of a mission to initialize any mission dependent anim data.
* @todo Redundant?
@@ -896,138 +869,6 @@ void anim_level_close()
anim_release_all_instances();
}
/**
* @brief Write the frames of a .ani file out to disk as .pcx files.
* @details Use naming convention: filename0000.pcx, filename0001.pcx etc.
*
* @return If success 0, or if failed -1
*/
int anim_write_frames_out(char *filename)
{
anim *source_anim;
anim_instance *ai;
char root_name[256], pcxname[256];
char buf[64];
int i,j;
ubyte **row_data;
strcpy_s(root_name, filename);
root_name[strlen(filename)-4] = 0;
source_anim = anim_load(filename);
if ( source_anim == NULL )
return -1;
ai = init_anim_instance(source_anim, 16);
row_data = (ubyte**)vm_malloc((source_anim->height+1) * 4);
for ( i = 0; i < source_anim->total_frames; i++ ) {
anim_get_next_raw_buffer(ai, 0, 0, 16);
strcpy_s(pcxname, root_name);
sprintf(buf,"%04d",i);
strcat_s(pcxname, buf);
for ( j = 0; j < source_anim->height; j++ ) {
row_data[j] = &ai->frame[j*source_anim->width];
}
pcx_write_bitmap( pcxname,
source_anim->width,
source_anim->height,
row_data,
source_anim->palette);
printf(".");
}
printf("\n");
vm_free(row_data);
return 0;
}
/**
* @brief Display information and statistics about a .ani file.
* @details This is called when -i switch is on when running ac.exe
*/
void anim_display_info(char *real_filename)
{
CFILE *fp;
anim A;
float percent;
int i, uncompressed, compressed, *key_frame_nums=NULL, tmp;
char filename[MAX_FILENAME_LEN];
strcpy_s( filename, real_filename );
char *p = strchr( filename, '.' );
if ( p ) {
*p = 0;
}
strcat_s( filename, ".ani" );
fp = cfopen(filename, "rb");
if ( !fp ) {
printf("Fatal error opening %s", filename);
return;
}
anim_read_header(&A, fp);
if (A.width < 0 || A.height < 0) {
Error(LOCATION, "Ani file %s has a faulty header and cannot be loaded.", filename);
}
// read the keyframe frame nums and offsets
key_frame_nums = (int*)vm_malloc(sizeof(int)*A.num_keys);
Assert(key_frame_nums != NULL);
if (key_frame_nums == NULL)
return;
for ( i = 0; i < A.num_keys; i++ ) {
key_frame_nums[i] = 0;
cfread(&key_frame_nums[i], 2, 1, fp);
cfread(&tmp, 4, 1, fp);
}
cfread(&compressed, 4, 1, fp);
uncompressed = A.width * A.height * A.total_frames; // 8 bits per pixel
percent = i2fl(compressed) / uncompressed * 100.0f;
printf("%% of uncompressed size: %.0f%%\n", percent);
printf("Width: %d\n", A.width);
printf("Height: %d\n", A.height);
printf("Total Frames: %d\n", A.total_frames);
#ifndef NDEBUG
printf("Key Frames: %d\n", A.num_keys);
if ( A.num_keys > 1 && (A.total_frames != A.num_keys) ) {
printf("key list: (");
for ( i = 0; i < A.num_keys; i++ ) {
if ( i < A.num_keys-1 )
printf("%d, ", key_frame_nums[i]);
else
printf("%d)\n", key_frame_nums[i]);
}
}
#endif
printf("FPS: %d\n", A.fps);
#ifndef NDEBUG
printf("Transparent RGB: (%u,%u,%u)\n", A.xparent_r, A.xparent_g, A.xparent_b);
#endif
printf("ac version: %d\n", A.version);
if ( key_frame_nums != NULL ) {
vm_free(key_frame_nums);
}
cfclose(fp);
}
void anim_reverse_direction(anim_instance *ai)
{
int temp;
@@ -1061,16 +902,6 @@ void anim_reverse_direction(anim_instance *ai)
}
}
void anim_pause(anim_instance *ai)
{
ai->paused = 1;
}
void anim_unpause(anim_instance *ai)
{
ai->paused = 0;
}
void anim_ignore_next_frametime()
{
Anim_ignore_frametime=1;
-6
View File
@@ -54,19 +54,13 @@ void anim_render_one(int screen_id, anim_instance *ani, float frametime);
void anim_play_init(anim_play_struct *aps, anim *a_info, int x, int y, int max_x = -1, int max_y = -1);
anim_instance *anim_play(anim_play_struct *aps);
void anim_ignore_next_frametime();
int anim_stop_playing(anim_instance* anim_instance);
int anim_show_next_frame(anim_instance *instance, float frametime);
void anim_release_all_instances(int screen_id = 0);
void anim_release_render_instance(anim_instance* instance);
anim *anim_load(const char *name, int cf_dir_type = CF_TYPE_ANY, int file_mapped = PAGE_FROM_DISK);
int anim_free(anim *ptr);
int anim_playing(anim_instance *ai);
int anim_write_frames_out(char *filename);
void anim_display_info(char *filename);
void anim_read_header(anim *ptr, CFILE *fp);
void anim_reverse_direction(anim_instance *ai); // called automatically for ping-ponging, and can also be called externally
void anim_pause(anim_instance *ai);
void anim_unpause(anim_instance *ai);
int anim_instance_is_streamed(anim_instance *ai);
unsigned char anim_instance_get_byte(anim_instance *ai, int offset);
-361
View File
@@ -78,52 +78,6 @@ void free_anim_instance(anim_instance *inst)
vm_free(inst);
}
int anim_get_next_frame(anim_instance *inst)
{
int bm, bitmap_flags;
int aabitmap = 0;
int bpp = 16;
if ( anim_instance_is_streamed(inst) ) {
if ( inst->file_offset <= 0 ) {
return -1;
}
} else {
if (!inst->data)
return -1;
}
inst->frame_num++;
if (inst->frame_num >= inst->parent->total_frames) {
inst->data = NULL;
inst->file_offset = inst->parent->file_offset;
return -1;
}
bitmap_flags = 0;
bpp = 16;
if(inst->aa_color != NULL){
bitmap_flags |= BMP_AABITMAP;
aabitmap = 1;
bpp = 8;
}
anim_check_for_palette_change(inst);
BM_SELECT_TEX_FORMAT();
if ( anim_instance_is_streamed(inst) ) {
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
} else {
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
}
bm = bm_create(bpp, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
bm_unload(bm);
return bm;
}
ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp)
{
if ( anim_instance_is_streamed(inst) ) {
@@ -162,321 +116,6 @@ ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap
return inst->frame;
}
/**
* @brief Pack key frame
*
* @param frame Frame pixel data to pack
* @param save Memory to store packed data to
* @param size Number of bytes to pack
* @param max Maximum number of packed bytes (size of buffer)
* @param compress_type Compress type
* @return Actual number of bytes data packed to or -1 if error
*/
int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_type)
{
int last = -32768, count = 0;
long packed_size = 1;
switch ( compress_type ) {
case PACKING_METHOD_RLE_KEY:
*save++ = PACKING_METHOD_RLE_KEY;
while (size--) {
if (*frame != last || count > 255) {
if (packed_size + 3 >= max)
return -1;
if (count < 3) {
if (last == packer_code) {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
packed_size += 2;
} else
while (count--) {
*save++ = (ubyte)last;
packed_size++;
}
} else {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
*save++ = (ubyte)last;
packed_size += 3;
}
count = 0;
last = *frame;
}
count++;
frame++;
}
if (packed_size + 3 >= max)
return -1;
if (count < 3) {
if (last == packer_code) {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
packed_size += 2;
} else
while (count--) {
*save++ = (ubyte)last;
packed_size++;
}
} else {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
*save++ = (ubyte)last;
packed_size += 3;
}
break;
case PACKING_METHOD_STD_RLE_KEY: {
ubyte *dest_start;
int i;
dest_start = save;
count = 1;
last = *frame++;
*save++ = PACKING_METHOD_STD_RLE_KEY;
for (i=1; i < size; i++ ) {
if ( *frame != last ) {
if ( count ) {
if (packed_size + 2 >= max)
return -1;
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
*save++ = (ubyte)last;
packed_size++;
Assert( last != STD_RLE_CODE );
}
else {
count |= STD_RLE_CODE;
*save++ = (ubyte)count;
*save++ = (ubyte)last;
packed_size += 2;
}
}
last = *frame;
count = 0;
}
count++;
frame++;
if ( count == 127 ) {
count |= STD_RLE_CODE;
*save++ = (ubyte)count;
*save++ = (ubyte)last;
packed_size += 2;
count = 0;
}
} // end for
if (count) {
if (packed_size + 2 >= max)
return -1;
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
*save++ = (ubyte)last;
packed_size++;
Assert( last != STD_RLE_CODE );
}
else {
count |= STD_RLE_CODE;
*save++ = (ubyte)count;
*save++ = (ubyte)last;
packed_size += 2;
}
}
Assert(packed_size == (save-dest_start) );
return packed_size;
}
default:
Assert(0);
return -1;
break;
} // end switch
return packed_size;
}
/**
* @brief Pack frame
*
* @param frame Frame pixel data to pack
* @param frame2 Previous frame's pixel data
* @param save Memory to store packed data to
* @param size Number of bytes to pack
* @param max Maximum number of packed bytes (size of buffer)
* @param compress_type Compress type
* @return Actual number of bytes data packed to or -1 if error
*/
int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, int compress_type)
{
int pixel, last = -32768, count = 0, i;
long packed_size = 1;
switch ( compress_type ) {
case PACKING_METHOD_RLE: // Hoffoss RLE regular frame
*save++ = PACKING_METHOD_RLE;
while (size--) {
if (*frame != *frame2++)
pixel = *frame;
else
pixel = transparent_code;
if (pixel != last || count > 255) {
if (packed_size + 3 >= max)
return -1;
if (count < 3) {
if (last == packer_code) {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
packed_size += 2;
} else
while (count--) {
*save++ = (ubyte)last;
packed_size++;
}
} else {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
*save++ = (ubyte)last;
packed_size += 3;
}
count = 0;
last = pixel;
}
frame++;
count++;
}
if (packed_size + 3 >= max)
return -1;
if (count < 3) {
if (last == packer_code) {
*save++ = (ubyte)packer_code;
*save++ = (ubyte)(count - 1);
packed_size += 2;
} else
while (count--) {
*save++ = (ubyte)last;
packed_size++;
}
} else {
*save++ = (ubyte)(packer_code);
*save++ = (ubyte)(count - 1);
*save++ = (ubyte)(last);
packed_size += 3;
}
break;
case PACKING_METHOD_STD_RLE: { // high bit count regular RLE frame
ubyte *dest_start;
dest_start = save;
count = 1;
if (*frame++ != *frame2++)
last = *frame;
else
last = transparent_code;
*save++ = PACKING_METHOD_STD_RLE;
for (i=1; i < size; i++ ) {
if (*frame != *frame2++)
pixel = *frame;
else
pixel = transparent_code;
if ( pixel != last ) {
if ( count ) {
if (packed_size + 2 >= max)
return -1;
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
*save++ = (ubyte)last;
packed_size++;
Assert( last != STD_RLE_CODE );
}
else {
count |= STD_RLE_CODE;
*save++ = (ubyte)count;
*save++ = (ubyte)last;
packed_size += 2;
}
}
last = pixel;
count = 0;
}
count++;
frame++;
if ( count == 127 ) {
count |= STD_RLE_CODE;
*save++ = (ubyte)count;
*save++ = (ubyte)last;
packed_size += 2;
count = 0;
}
} // end for
if (count) {
if (packed_size + 2 >= max)
return -1;
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
*save++ = (ubyte)last;
packed_size++;
Assert( last != STD_RLE_CODE );
}
else {
count |= STD_RLE_CODE;
*save++ = (ubyte)count;
*save++ = (ubyte)last;
packed_size += 2;
}
}
Assert(packed_size == (save-dest_start) );
return packed_size;
}
default:
Assert(0);
return -1;
break;
} // end switch
return packed_size;
}
/**
* @brief Convert a 24 bit value to a 16 bit value
* @param bit_24 24 bit value
-4
View File
@@ -97,16 +97,12 @@ typedef struct anim_instance {
int loop_count; // starts at 0, and is incremented each time it loops
} anim_instance;
int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_type);
int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, int compress_type);
ubyte *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp);
int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp);
void anim_init();
anim_instance *init_anim_instance(anim *ptr, int bpp);
void free_anim_instance(anim_instance *inst);
int anim_get_next_frame(anim_instance *inst);
ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp);
void anim_set_palette(anim *a);
void anim_check_for_palette_change(anim_instance *inst);
+1 -3
View File
@@ -1143,8 +1143,6 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
// SET PHYSICS PARAMETERS
// already have (hitpos - heavy) and light_cm_pos
// get heavy cm pos - already have light_cm_pos
asteroid_hit_info->heavy_collision_cm_pos = zero;
// get r_heavy and r_light
asteroid_hit_info->r_heavy = asteroid_hit_info->hit_pos;
@@ -1263,7 +1261,7 @@ static float asteroid_create_explosion(object *objp)
fireball_scale_multiplier = asteroid_get_fireball_scale_multiplier(objp->instance);
fireball_objnum = fireball_create( &objp->pos, fireball_type, FIREBALL_LARGE_EXPLOSION, OBJ_INDEX(objp), objp->radius*fireball_scale_multiplier, 0, &objp->phys_info.vel );
fireball_objnum = fireball_create( &objp->pos, fireball_type, FIREBALL_LARGE_EXPLOSION, OBJ_INDEX(objp), objp->radius*fireball_scale_multiplier, false, &objp->phys_info.vel );
if ( fireball_objnum > -1 ) {
explosion_life = fireball_lifeleft(&Objects[fireball_objnum]);
} else {
+1 -47
View File
@@ -122,31 +122,6 @@ vec3d *NavPoint::GetPosition()
}
}
char* NavPoint::GetInternalName()
{
char *NavName;
char strtmp[33];
if (flags & NP_WAYPOINT)
{
NavName = new char[strlen(((waypoint_list*)target_obj)->get_name())+5];
memset(NavName, 0, strlen(((waypoint_list*)target_obj)->get_name())+5);
strcpy(NavName, ((waypoint_list*)target_obj)->get_name());
strcat(NavName, ":");
sprintf(strtmp, "%d", waypoint_num);
strcat(NavName, strtmp);
}
else
{
NavName = new char[strlen(((ship*)target_obj)->ship_name)+1];
memset(NavName, 0, strlen(((ship*)target_obj)->ship_name)+1);
strcpy(NavName, ((ship*)target_obj)->ship_name);
}
return NavName;
}
// ********************************************************************************************
bool CanAutopilot(vec3d targetPos, bool send_msg)
{
@@ -998,7 +973,6 @@ camera* nav_get_set_camera()
return nav_camera.getCamera();
}
extern int Cmdline_old_collision_sys;
void nav_warp(bool prewarp=false)
{
/* ok... find our end distance - norm1 is still a unit vector in the
@@ -1053,11 +1027,7 @@ void nav_warp(bool prewarp=false)
}
// retime all collision pairs
if ( Cmdline_old_collision_sys ) {
obj_all_collisions_retime();
} else {
obj_collide_retime_cached_pairs();
}
obj_collide_retime_cached_pairs();
}
// ********************************************************************************************
@@ -1464,22 +1434,6 @@ bool AddNav_Waypoint(char *Nav, char *WP_Path, int node, int flags)
}
// ********************************************************************************************
//Change Flags
bool Nav_Alt_Flags(char *Nav, int flags)
{
flags &= ~NP_VALIDTYPE; //clear the NP_SHIP and NP_WAYPOINT bits, make sure they haven't been set
int nav = FindNav(Nav);
if (nav != -1)
{
Navs[nav].flags &= NP_VALIDTYPE; // Clear all bits BUT NP_SHIP or NO_WAYPOINT
Navs[nav].flags |= flags; // merge
}
return (nav != -1);
}
//Get Flags
int Nav_Get_Flags(char *Nav)
{
-7
View File
@@ -36,7 +36,6 @@ public:
int waypoint_num; //only used when flags & NP_WAYPOINT
vec3d *GetPosition();
char* GetInternalName();
void clear()
{
@@ -129,9 +128,6 @@ void SelectNav(char *Nav);
// Deselects any navpoint selected.
void DeselectNav();
// Set A Nav point to "ZERO"
void ZeroNav(int i);
// Removes a Nav
bool DelNavPoint(char *Nav);
bool DelNavPoint(int nav);
@@ -140,9 +136,6 @@ bool DelNavPoint(int nav);
bool AddNav_Ship(char *Nav, char *TargetName, int flags);
bool AddNav_Waypoint(char *Nav, char *WP_Path, int node, int flags);
//Change Flags
bool Nav_Alt_Flags(char *Nav, int flags);
// Sexp Accessors
bool Nav_Set_Flag(char *Nav, int flag);
bool Nav_UnSet_Flag(char *Nav, int flag);
-2
View File
@@ -67,9 +67,7 @@ struct bitmap_entry {
char filename[MAX_FILENAME_LEN]; //!< filename for this bitmap
uint signature; //!< a unique signature identifying the data
uint palette_checksum; //!< checksum used to be sure bitmap is in current palette
int handle; //!< Handle = id*MAX_BITMAPS + bitmapnum
int last_used; //!< When this bitmap was last used
BM_TYPE type; //!< PCX, USER, ANI, etc
BM_TYPE comp_type; //!< What sort of compressed type, BM_TYPE_NONE if not compressed
-123
View File
@@ -55,14 +55,7 @@ MONITOR(SizeBitmapPage)
// --------------------------------------------------------------------------------------------------------------------
// Definition of public variables (declared as extern in bmpman.h).
int GLOWMAP = -1;
int SPECMAP = -1;
int SPECGLOSSMAP = -1;
int ENVMAP = -1;
int NORMMAP = -1;
int HEIGHTMAP = -1;
int MISCMAP = -1;
int AMBIENTMAP = -1;
size_t bm_texture_ram = 0;
int Bm_paging = 0;
@@ -80,11 +73,6 @@ const char *bm_ani_ext_list[] = { ".eff", ".ani", ".png" };
const int BM_ANI_NUM_TYPES = sizeof(bm_ani_type_list) / sizeof(bm_ani_type_list[0]);
void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
// --------------------------------------------------------------------------------------------------------------------
// Declaration of protected variables (defined in cmdline.cpp).
extern int Cmdline_cache_bitmaps;
// --------------------------------------------------------------------------------------------------------------------
// Definition of public variables (declared as extern in bm_internal.h).
@@ -193,42 +181,6 @@ float bitmap_lookup::map_texture_address(float address)
return address - floorf(address);
}
float bitmap_lookup::get_channel_red(float u, float v)
{
Assert( Bitmap_data != NULL );
CLAMP(u, 0.0f, 1.0f);
CLAMP(v, 0.0f, 1.0f);
int x = fl2i(map_texture_address(u) * (Width-1));
int y = fl2i(map_texture_address(v) * (Height-1));
return i2fl(Bitmap_data[(y*Width + x)*Num_channels]) / 255.0f;
}
float bitmap_lookup::get_channel_green(float u, float v)
{
Assert( Bitmap_data != NULL );
CLAMP(u, 0.0, 1.0f);
CLAMP(v, 0.0, 1.0f);
int x = fl2i(map_texture_address(u) * (Width-1));
int y = fl2i(map_texture_address(v) * (Height-1));
return i2fl(Bitmap_data[(y*Width + x)*Num_channels + 1]) / 255.0f;
}
float bitmap_lookup::get_channel_blue(float u, float v)
{
Assert( Bitmap_data != NULL );
int x = fl2i(map_texture_address(u) * (Width-1));
int y = fl2i(map_texture_address(v) * (Height-1));
return i2fl(Bitmap_data[(y*Width + x)*Num_channels + 2]) / 255.0f;
}
float bitmap_lookup::get_channel_alpha(float u, float v)
{
Assert( Bitmap_data != NULL );
@@ -594,7 +546,6 @@ int bm_create(int bpp, int w, int h, void *data, int flags) {
sprintf_safe(entry->filename, "TMP%dx%d+%d", w, h, bpp);
entry->type = BM_TYPE_USER;
entry->comp_type = BM_TYPE_NONE;
entry->palette_checksum = 0;
entry->bm.w = (short)w;
entry->bm.h = (short)h;
@@ -612,7 +563,6 @@ int bm_create(int bpp, int w, int h, void *data, int flags) {
entry->signature = Bm_next_signature++;
entry->handle = n;
entry->last_used = -1;
entry->mem_taken = (w * h * (bpp >> 3));
entry->load_count++;
@@ -958,16 +908,6 @@ void bm_get_palette(int handle, ubyte *pal, char *name) {
}
}
uint bm_get_signature(int handle) {
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
return bm_get_entry(handle)->signature;
}
size_t bm_get_size(int handle) {
return bm_get_entry(handle)->mem_taken;
}
int bm_get_tcache_type(int num) {
if (bm_is_compressed(num))
return TCACHE_TYPE_COMPRESSED;
@@ -1268,9 +1208,7 @@ int bm_load(const char *real_filename) {
entry->num_mipmaps = mm_lvl;
entry->mem_taken = (size_t)bm_size;
entry->dir_type = CF_TYPE_ANY;
entry->palette_checksum = 0;
entry->handle = handle;
entry->last_used = -1;
entry->load_count++;
@@ -1733,10 +1671,8 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
entry->bm.palette = nullptr;
entry->type = type;
entry->comp_type = c_type;
entry->palette_checksum = 0;
entry->signature = Bm_next_signature++;
entry->handle = n + i;
entry->last_used = -1;
entry->num_mipmaps = mm_lvl;
entry->mem_taken = (size_t)img_size;
entry->dir_type = dir_type;
@@ -1979,8 +1915,6 @@ bitmap * bm_lock(int handle, int bpp, ubyte flags, bool nodebug) {
// Mark all the bitmaps in this bitmap or animation as recently used
auto frame_entry = bm_get_entry(first + i);
frame_entry->last_used = timer_get_milliseconds();
#ifdef BMPMAN_NDEBUG
// Mark all the bitmaps in this bitmap or animation as used for the usage tracker.
frame_entry->used_count++;
@@ -1989,9 +1923,6 @@ bitmap * bm_lock(int handle, int bpp, ubyte flags, bool nodebug) {
frame_entry->used_flags = flags;
}
} else {
// Mark all the bitmaps in this bitmap or animation as recently used
be->last_used = timer_get_milliseconds();
#ifdef BMPMAN_NDEBUG
// Mark all the bitmaps in this bitmap or animation as used for the usage tracker.
be->used_count++;
@@ -2536,9 +2467,7 @@ int bm_make_render_target(int width, int height, int flags) {
entry->mem_taken = (size_t)size;
entry->dir_type = CF_TYPE_ANY;
entry->palette_checksum = 0;
entry->handle = n;
entry->last_used = -1;
if (entry->mem_taken) {
entry->bm.data = (ptr_u)bm_malloc(n, entry->mem_taken);
@@ -2775,30 +2704,6 @@ void bm_page_in_xparent_texture(int bitmapnum, int nframes) {
}
}
bool bm_page_out(int handle) {
auto entry = bm_get_entry(handle);
// in case it's already been released
if (entry->type == BM_TYPE_NONE)
return 0;
// it's possible to hit < 0 here when model_page_out_textures() is
// called from anywhere other than in a mission
if (entry->preload_count > 0) {
nprintf(("BmpMan",
"PAGE-OUT: %s - preload_count remaining: %d\n",
entry->filename,
entry->preload_count));
// lets decrease it for next time around
entry->preload_count--;
return 0;
}
return (bm_unload(handle) == 1);
}
void bm_print_bitmaps() {
#ifdef BMPMAN_NDEBUG
for (auto& block : bm_blocks) {
@@ -2884,7 +2789,6 @@ int bm_release(int handle, int clear_render_targets) {
// For debugging:
strcpy_s(entry->filename, "IVE_BEEN_RELEASED!");
entry->signature = 0xDEADBEEF; // a unique signature identifying the data
entry->palette_checksum = 0xDEADBEEF; // checksum used to be sure bitmap is in current palette
// bookeeping
entry->ref_count = -1; // Number of locks on bitmap. Can't unload unless ref_count is 0.
@@ -2911,7 +2815,6 @@ int bm_release(int handle, int clear_render_targets) {
// For debugging:
strcpy_s(entry->filename, "IVE_BEEN_RELEASED!");
entry->signature = 0xDEADBEEF; // a unique signature identifying the data
entry->palette_checksum = 0xDEADBEEF; // checksum used to be sure bitmap is in current palette
// bookeeping
entry->ref_count = -1; // Number of locks on bitmap. Can't unload unless ref_count is 0.
@@ -2953,7 +2856,6 @@ void BM_SELECT_ALPHA_TEX_FORMAT() {
Gr_current_alpha = &Gr_ta_alpha;
// setup pointers
bm_set_components_32 = bm_set_components_argb_32_tex;
// should always assume that 16-bit is the default request
bm_set_components = bm_set_components_argb_16_tex;
}
@@ -2965,7 +2867,6 @@ void BM_SELECT_SCREEN_FORMAT() {
Gr_current_alpha = &Gr_alpha;
// setup pointers
bm_set_components_32 = bm_set_components_argb_32_screen;
// should always assume that 16-bit is the default request
bm_set_components = bm_set_components_argb_16_screen;
}
@@ -2977,7 +2878,6 @@ void BM_SELECT_TEX_FORMAT() {
Gr_current_alpha = &Gr_t_alpha;
// setup pointers
bm_set_components_32 = bm_set_components_argb_32_tex;
// should always assume that 16-bit is the default request
bm_set_components = bm_set_components_argb_16_tex;
}
@@ -3005,29 +2905,6 @@ void bm_set_components_argb_16_tex(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv
*((unsigned short*)pixel) |= (unsigned short)(Gr_current_alpha->mask);
}
void bm_set_components_argb_32_screen(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av) {
if (*av == 0) {
*((unsigned int*)pixel) = (unsigned int)Gr_current_green->mask;
return;
}
*((unsigned int*)pixel) = (unsigned int)(((int)*rv / Gr_current_red->scale) << Gr_current_red->shift);
*((unsigned int*)pixel) |= (unsigned int)(((int)*gv / Gr_current_green->scale) << Gr_current_green->shift);
*((unsigned int*)pixel) |= (unsigned int)(((int)*bv / Gr_current_blue->scale) << Gr_current_blue->shift);
}
void bm_set_components_argb_32_tex(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av) {
if (*av == 0) {
*((unsigned int*)pixel) = 0;
return;
}
*((unsigned int*)pixel) = (unsigned int)(((int)*rv / Gr_current_red->scale) << Gr_current_red->shift);
*((unsigned int*)pixel) |= (unsigned int)(((int)*gv / Gr_current_green->scale) << Gr_current_green->shift);
*((unsigned int*)pixel) |= (unsigned int)(((int)*bv / Gr_current_blue->scale) << Gr_current_blue->shift);
*((unsigned int*)pixel) |= (unsigned int)(Gr_current_alpha->mask);
}
void bm_set_low_mem(int mode) {
Assert((mode >= 0) && (mode <= 2));
-53
View File
@@ -113,12 +113,7 @@ extern const BM_TYPE bm_ani_type_list[]; //!< List of valid bitmap animation t
extern const char *bm_ani_ext_list[]; //!< List of extensions for those types
extern const int BM_ANI_NUM_TYPES; //!< Calculated number of bitmap animation types
extern int GLOWMAP; //!< References a map that is a fully lit version of its index -Bobboau
extern int SPECMAP; //!< References a map that is for specular mapping -Bobboau
extern int ENVMAP; //!< References a map that is for environment mapping -Bobboau
extern int NORMMAP; //!< Normal mapping
extern int HEIGHTMAP; //!< Height map for normal mapping
extern int MISCMAP; //!< Utility map, to be utilized for various things shader authors can come up with
/**
* @brief Initilizes the bitmap manager
@@ -167,9 +162,6 @@ public:
bool valid();
float get_channel_red(float u, float v);
float get_channel_green(float u, float v);
float get_channel_blue(float u, float v);
float get_channel_alpha(float u, float v);
};
@@ -311,13 +303,6 @@ int bm_load_either(const char *filename, int *nframes = NULL, int *fps = NULL, i
*/
bitmap* bm_lock(int handle, int bpp, ubyte flags, bool nodebug = false);
/**
* @brief Returns a unique signiature for the bitmap indexed by handle
*
* @details A signature will change when the bitmap's data changes
*/
uint bm_get_signature(int handle);
/**
* @brief Returns the image type of the given bitmap handle
*/
@@ -459,15 +444,6 @@ void bm_page_in_xparent_texture(int bitmapnum, int num_frames = 1);
*/
void bm_page_in_aabitmap(int bitmapnum, int num_frames = 1);
/**
* @brief Unloads the bitmap indexed by handle that was previously paged-in
*
* @returns 0 If the bitmap had already been released, or
* @returns 0 If the handle is invalid, or
* @returns 1 If successful
*/
bool bm_page_out(int handle);
/**
* @brief Sets BMPMAN's memory mode
*
@@ -516,16 +492,6 @@ void BM_SELECT_ALPHA_TEX_FORMAT();
*/
extern void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
/**
* @brief Functional pointer that references any of the bm_set_components_32 functions.
*
* @details The bm_set_components functions packs the RGBA values into the ubyte array referenced by pixel, whose
* format differs according to its bpp value and presence of an alpha channel. The RGBA values are scaled accordingly.
*
* @see bm_set_components
*/
extern void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
/**
* @brief Sets the 16bpp screen pixel to the specified RGBA value
*
@@ -533,13 +499,6 @@ extern void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, u
*/
void bm_set_components_argb_16_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
/**
* @brief Sets the 32bpp screen pixel to the specified RGBA value
*
* @see bm_set_components
*/
void bm_set_components_argb_32_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
/**
* @brief Sets the 16bpp texture pixel to the specified RGBA value
*
@@ -561,15 +520,7 @@ void bm_set_components_argb_32_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, u
*/
void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
extern int UNLITMAP; //this holds a reference to a map that is optional used instead of the base map for unlit rendering
extern int GLOWMAP; //this holds a reference to a map that is a fully lit version of its index -Bobboau
extern int SPECMAP; //this holds a reference to a map that is for specular mapping -Bobboau
extern int SPECGLOSSMAP; //this holds a reference to a map that is for specular mapping -Bobboau
extern int ENVMAP; //this holds a reference to a map that is for environment mapping -Bobboau
extern int NORMMAP; // normal mapping
extern int HEIGHTMAP; // height map for normal mapping
extern int AMBIENTMAP; // ambient occluion map. red channel affects ambient lighting, green channel affects diffuse and specular
extern int MISCMAP; // Utility map, to be utilized for various things shader authors can come up with
/**
* @brief Returns the compression type of the bitmap indexed by handle
@@ -581,10 +532,6 @@ int bm_is_compressed(int handle);
*/
int bm_get_tcache_type(int handle);
/**
* @brief Gets the size, in bytes, taken up by the bitmap indexed by handle
*/
size_t bm_get_size(int handle);
/**
* @brief Gets the number of mipmaps of the indexed texture
+21 -15
View File
@@ -7,9 +7,10 @@
#include "math/vecmat.h"
#include "mod_table/mod_table.h"
#include "model/model.h" //polymodel, model_get
#include "options/Option.h"
#include "parse/parselo.h"
#include "playerman/player.h" //player_get_padlock_orient
#include "ship/ship.h" //compute_slew_matrix
#include "ship/ship.h" //compute_slew_matrix
//*************************IMPORTANT GLOBALS*************************
float VIEWER_ZOOM_DEFAULT = 0.75f; // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
@@ -24,6 +25,23 @@ SCP_vector<camera*> Cameras;
camid Current_camera;
camid Main_camera;
static SCP_string fov_display(float val)
{
auto degrees = fl_degrees(val);
SCP_string out;
sprintf(out, u8"%.1f\u00B0", degrees);
return out;
}
auto FovOption = options::OptionBuilder<float>("Graphics.FOV", "Field Of View", "The vertical field of view.")
.category("Graphics")
.range(0.436332f, 1.5708f)
.bind_to(&VIEWER_ZOOM_DEFAULT)
.display(fov_display)
.default_val(0.75f)
.level(options::ExpertLevel::Advanced)
.importance(60)
.finish();
//*************************CLASS: camera*************************
//This is where the camera class beings! :D
camera::camera(const char *in_name, int in_signature)
@@ -145,7 +163,7 @@ void camera::set_object_target(object *objp, int n_object_target_submodel)
* Custom function receives the already-modified current position value.
* It should be replaced or added to as the custom function modifier sees fit.
*/
void camera::set_custom_position_function(void (*n_func_custom_position)(camera *cam, vec3d *camera_pos))
void camera::set_custom_position_function(void (*n_func_custom_position)(camera* /*cam*/, vec3d* /*camera_pos*/))
{
func_custom_position = n_func_custom_position;
}
@@ -154,7 +172,7 @@ void camera::set_custom_position_function(void (*n_func_custom_position)(camera
* Custom function receives the already-modified current orientation value.
* It should be replaced or added to as the custom function modifier sees fit.
*/
void camera::set_custom_orientation_function(void (*n_func_custom_orientation)(camera *cam, matrix *camera_ori))
void camera::set_custom_orientation_function(void (*n_func_custom_orientation)(camera* /*cam*/, matrix* /*camera_ori*/))
{
func_custom_orientation = n_func_custom_orientation;
}
@@ -185,13 +203,6 @@ void camera::set_position(vec3d *in_position, float in_translation_time, float i
pos_z.setAVD(in_position->xyz.z, in_translation_time, in_translation_acceleration_time, in_translation_deceleration_time, in_end_velocity);
}
void camera::set_translation_velocity(vec3d *in_velocity, float in_acceleration_time)
{
pos_x.setVD(in_acceleration_time, in_acceleration_time, in_velocity->xyz.x);
pos_y.setVD(in_acceleration_time, in_acceleration_time, in_velocity->xyz.y);
pos_z.setVD(in_acceleration_time, in_acceleration_time, in_velocity->xyz.z);
}
void camera::set_rotation(matrix *in_orientation, float in_rotation_time, float in_rotation_acceleration_time, float in_rotation_deceleration_time)
{
if(in_orientation != NULL && in_rotation_time == 0.0f && in_rotation_acceleration_time == 0.0f && in_rotation_deceleration_time == 0.0f)
@@ -245,11 +256,6 @@ 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*/)
{
Error(LOCATION, "This function is disabled until further notice.");
}
void camera::do_frame(float /*in_frametime*/)
{
-3
View File
@@ -17,7 +17,6 @@
class camera
{
friend class avd_camera;
protected:
char name[NAME_LENGTH];
int sig;
@@ -60,12 +59,10 @@ public:
void set_fov(float in_fov, float in_fov_time = 0.0f, float in_fov_acceleration_time = 0.0f, float in_deceleration_time = 0.0f);
void set_position(vec3d *in_position = NULL, float in_translation_time = 0.0f, float in_translation_acceleration_time = 0.0f, float in_translation_deceleration_time = 0.0f, float in_end_velocity = 0.0f);
void set_translation_velocity(vec3d *in_velocity, float in_acceleration_time = 0.0f);
void set_rotation(matrix *in_orientation = NULL, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
void set_rotation(angles *in_angles, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
void set_rotation_facing(vec3d *in_target, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
void set_rotation_velocity(angles *in_rotation_rate, float in_acceleration_time = 0.0f);
//Get
const char* get_name() { return name; }
+116 -325
View File
@@ -38,9 +38,6 @@
#include <limits>
char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
// During cfile_init, verify that Pathtypes[n].index == n for each item
// Each path must have a valid parent that can be tracable all the way back to the root
// so that we can create directories when we need to.
@@ -101,10 +98,7 @@ static int Cfile_stack_pos = 0;
static char Cfile_stack[CFILE_STACK_MAX][CFILE_ROOT_DIRECTORY_LEN];
Cfile_block Cfile_block_list[MAX_CFILE_BLOCKS];
static CFILE Cfile_list[MAX_CFILE_BLOCKS];
static const char *Cfile_cdrom_dir = NULL;
std::array<CFILE, MAX_CFILE_BLOCKS> Cfile_block_list;
//
// Function prototypes for internally-called functions
@@ -148,47 +142,15 @@ void cfile_close()
#define MIN_NUM_PATH_COMPONENTS 3 /* Drive + directory + file */
#endif
/**
* @brief Determine if the given path is in the root directory
*
* @param exe_path Path to executable
*
* @return true if root directory, false if not
*/
static bool cfile_in_root_dir(const char *exe_path)
{
int new_token;
int token_count = 0;
const char *p = exe_path;
Assert(exe_path != NULL);
do {
new_token = 0;
while (*p == DIR_SEPARATOR_CHAR) {
p++;
}
while ((*p != '\0') && (*p != DIR_SEPARATOR_CHAR)) {
new_token = 1;
p++;
}
token_count += new_token;
} while (*p != '\0');
return (token_count < MIN_NUM_PATH_COMPONENTS);
}
/**
* @brief Initialize the cfile system. Called once at application start.
*
* @param exe_dir Path to a file (not a directory)
* @param cdrom_dir Path to a CD drive mount point (may be NULL)
*
* @return 0 On success
* @return 1 On error
*/
int cfile_init(const char *exe_dir, const char *cdrom_dir)
int cfile_init(const SCP_vector<cfile::ModRoot>& modRoots)
{
// initialize encryption
encrypt_init();
@@ -197,61 +159,20 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir)
return 0;
}
char buf[CFILE_ROOT_DIRECTORY_LEN];
strncpy(buf, exe_dir, CFILE_ROOT_DIRECTORY_LEN - 1);
buf[CFILE_ROOT_DIRECTORY_LEN - 1] = '\0';
size_t i = strlen(buf);
// are we in a root directory?
if(cfile_in_root_dir(buf)){
os::dialogs::Message(os::dialogs::MESSAGEBOX_ERROR, "FreeSpace2/Fred2 cannot be run from a drive root directory!");
return 1;
}
// This needs to be set here because cf_build_secondary_filelist assumes it to be true
cfile_inited = 1;
/*
* Determine the executable's directory. Note that DIR_SEPARATOR_CHAR
* is guaranteed to be found in the string else cfile_in_root_dir()
* would have failed.
*/
char *p;
p = strrchr(buf, DIR_SEPARATOR_CHAR);
*p = '\0';
cfile_chdir(buf);
// set root directory
strcpy_s(Cfile_root_dir, buf);
strcpy_s(Cfile_user_dir, os_get_config_path().c_str());
for (i = 0; i < MAX_CFILE_BLOCKS; i++) {
Cfile_block_list[i].type = CFILE_BLOCK_UNUSED;
}
// Initialize the block list with proper data
Cfile_block_list.fill({});
// 32 bit CRC table init
cf_chksum_long_init();
Cfile_cdrom_dir = cdrom_dir;
cf_build_secondary_filelist(Cfile_cdrom_dir);
cf_build_secondary_filelist(modRoots);
return 0;
}
// Call this if pack files got added or removed or the
// cdrom changed. This will refresh the list of filenames
// stored in packfiles and on the cdrom.
void cfile_refresh()
{
cf_build_secondary_filelist(Cfile_cdrom_dir);
}
#ifdef _WIN32
// Changes to a drive if valid.. 1=A, 2=B, etc
// If flag, then changes to it.
@@ -643,9 +564,6 @@ void cf_create_directory(int dir_type, uint32_t location_flags)
}
}
extern int game_cd_changed();
// cfopen()
//
// parameters: *filepath ==> name of file to open (may be path+name)
@@ -878,14 +796,14 @@ CFILE *ctmpfile()
static int cfget_cfile_block()
{
int i;
Cfile_block *cb;
CFILE* cfile;
for ( i = 0; i < MAX_CFILE_BLOCKS; i++ ) {
cb = &Cfile_block_list[i];
if ( cb->type == CFILE_BLOCK_UNUSED ) {
cb->data = NULL;
cb->fp = NULL;
cb->type = CFILE_BLOCK_USED;
cfile = &Cfile_block_list[i];
if (cfile->type == CFILE_BLOCK_UNUSED) {
cfile->data = nullptr;
cfile->fp = nullptr;
cfile->type = CFILE_BLOCK_USED;
return i;
}
}
@@ -913,39 +831,36 @@ int cfclose( CFILE * cfile )
int result;
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
result = 0;
if ( cb->data && cb->mem_mapped ) {
if ( cfile->data && cfile->mem_mapped ) {
// close memory mapped file
#if defined _WIN32
result = UnmapViewOfFile((void*)cb->data);
result = UnmapViewOfFile((void*)cfile->data);
Assert(result);
result = CloseHandle(cb->hInFile);
result = CloseHandle(cfile->hInFile);
Assert(result); // Ensure file handle is closed properly
result = CloseHandle(cb->hMapFile);
result = CloseHandle(cfile->hMapFile);
Assert(result); // Ensure file handle is closed properly
result = 0;
#elif defined SCP_UNIX
// FIXME: result is wrong after munmap() but it is successful
//result = munmap(cb->data, cb->data_length);
//result = munmap(cfile->data, cfile->data_length);
//Assert(result);
// 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);
munmap(const_cast<void*>(cfile->data), cfile->data_length);
if ( cfile->fp != nullptr)
result = fclose(cfile->fp);
#endif
} else if ( cb->fp != NULL ) {
Assert(cb->fp != NULL);
result = fclose(cb->fp);
} else if ( cfile->fp != nullptr ) {
Assert(cfile->fp != nullptr);
result = fclose(cfile->fp);
} else {
// VP do nothing
}
cb->type = CFILE_BLOCK_UNUSED;
cfile->type = CFILE_BLOCK_UNUSED;
return result;
}
@@ -955,13 +870,8 @@ int cf_is_valid(CFILE *cfile)
if(cfile == NULL)
return 0;
//Does it have a valid ID?
if(cfile->id < 0 || cfile->id >= MAX_CFILE_BLOCKS)
return 0;
//Is it used?
Cfile_block *cb = &Cfile_block_list[cfile->id];
if(cb->type != CFILE_BLOCK_USED && (cb->fp != NULL || cb->data != NULL))
if (cfile->type != CFILE_BLOCK_USED && (cfile->fp != nullptr || cfile->data != nullptr))
return 0;
//It's good, as near as we can tell.
@@ -986,20 +896,15 @@ static CFILE *cf_open_fill_cfblock(const char* source, int line, FILE *fp, int t
fclose(fp);
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->data = NULL;
cfbp->mem_mapped = false;
cfbp->fp = fp;
cfbp->dir_type = type;
cfbp->max_read_len = 0;
CFILE *cfp = &Cfile_block_list[cfile_block_index];
cfp->data = nullptr;
cfp->mem_mapped = false;
cfp->fp = fp;
cfp->dir_type = type;
cfp->max_read_len = 0;
cfbp->source_file = source;
cfbp->line_num = line;
cfp->source_file = source;
cfp->line_num = line;
int pos = ftell(fp);
if(pos == -1L)
@@ -1027,21 +932,16 @@ static CFILE *cf_open_packed_cfblock(const char* source, int line, FILE *fp, int
fclose(fp);
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->data = NULL;
cfbp->fp = fp;
cfbp->mem_mapped = false;
cfbp->dir_type = type;
cfbp->max_read_len = 0;
CFILE *cfp = &Cfile_block_list[cfile_block_index];
cfbp->source_file = source;
cfbp->line_num = line;
cfp->data = nullptr;
cfp->fp = fp;
cfp->mem_mapped = false;
cfp->dir_type = type;
cfp->max_read_len = 0;
cfp->source_file = source;
cfp->line_num = line;
cf_init_lowlevel_read_code(cfp,offset, size, 0 );
@@ -1073,44 +973,39 @@ static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, FILE *fp
return NULL;
}
else {
CFILE *cfp;
Cfile_block *cfbp;
cfbp = &Cfile_block_list[cfile_block_index];
CFILE *cfp = &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 = true;
cfp->max_read_len = 0;
cfp->fp = nullptr;
cfp->mem_mapped = true;
#if defined _WIN32
cfbp->hInFile = hFile;
cfp->hInFile = hFile;
#endif
cfbp->dir_type = type;
cfp->dir_type = type;
cfbp->source_file = source;
cfbp->line_num = line;
cfp->source_file = source;
cfp->line_num = line;
cf_init_lowlevel_read_code(cfp, 0, 0, 0 );
#if defined _WIN32
cfbp->hMapFile = CreateFileMapping(cfbp->hInFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (cfbp->hMapFile == NULL) {
cfp->hMapFile = CreateFileMapping(cfp->hInFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (cfp->hMapFile == NULL) {
nprintf(("Error", "Could not create file-mapping object.\n"));
return NULL;
}
cfbp->data = (ubyte*)MapViewOfFile(cfbp->hMapFile, FILE_MAP_READ, 0, 0, 0);
Assert( cfbp->data != NULL );
cfp->data = (ubyte*)MapViewOfFile(cfp->hMapFile, FILE_MAP_READ, 0, 0, 0);
Assert( cfp->data != NULL );
#elif defined SCP_UNIX
cfbp->fp = fp;
cfbp->data_length = filelength( fileno(fp) );
cfbp->data = mmap(NULL, // start
cfbp->data_length, // length
PROT_READ, // prot
MAP_SHARED, // flags
fileno(fp), // fd
0); // offset
Assert( cfbp->data != NULL );
cfp->fp = fp;
cfp->data_length = filelength(fileno(fp));
cfp->data = mmap(nullptr, // start
cfp->data_length, // length
PROT_READ, // prot
MAP_SHARED, // flags
fileno(fp), // fd
0); // offset
Assert(cfp->data != nullptr);
#endif
return cfp;
@@ -1126,23 +1021,18 @@ static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const vo
return NULL;
}
else {
CFILE *cfp;
Cfile_block *cfbp;
cfbp = &Cfile_block_list[cfile_block_index];
CFILE *cfp = &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;
cfp->max_read_len = 0;
cfp->fp = nullptr;
cfp->mem_mapped = false;
cfp->dir_type = dir_type;
cfbp->source_file = source;
cfbp->line_num = line;
cfp->source_file = source;
cfp->line_num = line;
cf_init_lowlevel_read_code(cfp, 0, size, 0 );
cfbp->data = data;
cfp->data = data;
return cfp;
}
@@ -1150,7 +1040,7 @@ static CFILE *cf_open_memory_fill_cfblock(const char* source, int line, const vo
int cf_get_dir_type(CFILE *cfile)
{
return Cfile_block_list[cfile->id].dir_type;
return cfile->dir_type;
}
// cf_returndata() returns the data pointer for a memory-mapped file that is associated
@@ -1161,22 +1051,8 @@ int cf_get_dir_type(CFILE *cfile)
const void *cf_returndata(CFILE *cfile)
{
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
Assert(cb->data != NULL);
return cb->data;
}
// version number of opened file. Will be 0 unless you put something else here after you
// open a file. Once set, you can use minimum version numbers with the read functions.
void cf_set_version( CFILE * cfile, int version )
{
Assert(cfile != NULL);
cfile->version = version;
Assert(cfile->data != nullptr);
return cfile->data;
}
// cutoff point where cfread() will throw an error when it hits this limit
@@ -1184,27 +1060,21 @@ void cf_set_version( CFILE * cfile, int version )
void cf_set_max_read_len( CFILE * cfile, size_t len )
{
Assert( cfile != NULL );
Assert( (cfile->id >= 0) && (cfile->id < MAX_CFILE_BLOCKS) );
Cfile_block *cb = &Cfile_block_list[cfile->id];
if (len) {
cb->max_read_len = cb->raw_position + len;
cfile->max_read_len = cfile->raw_position + len;
} else {
cb->max_read_len = 0;
cfile->max_read_len = 0;
}
}
// routines to read basic data types from CFILE's. Put here to
// simplify mac/pc reading from cfiles.
float cfread_float(CFILE *file, int ver, float deflt)
float cfread_float(CFILE* file, float deflt)
{
float f;
if (file->version < ver)
return deflt;
if (cfread( &f, sizeof(f), 1, file) != 1)
return deflt;
@@ -1212,13 +1082,10 @@ float cfread_float(CFILE *file, int ver, float deflt)
return f;
}
int cfread_int(CFILE *file, int ver, int deflt)
int cfread_int(CFILE* file, int deflt)
{
int i;
if (file->version < ver)
return deflt;
if (cfread( &i, sizeof(i), 1, file) != 1)
return deflt;
@@ -1226,13 +1093,10 @@ int cfread_int(CFILE *file, int ver, int deflt)
return i;
}
uint cfread_uint(CFILE *file, int ver, uint deflt)
uint cfread_uint(CFILE* file, uint deflt)
{
uint i;
if (file->version < ver)
return deflt;
if (cfread( &i, sizeof(i), 1, file) != 1)
return deflt;
@@ -1240,13 +1104,10 @@ uint cfread_uint(CFILE *file, int ver, uint deflt)
return i;
}
short cfread_short(CFILE *file, int ver, short deflt)
short cfread_short(CFILE* file, short deflt)
{
short s;
if (file->version < ver)
return deflt;
if (cfread( &s, sizeof(s), 1, file) != 1)
return deflt;
@@ -1254,13 +1115,10 @@ short cfread_short(CFILE *file, int ver, short deflt)
return s;
}
ushort cfread_ushort(CFILE *file, int ver, ushort deflt)
ushort cfread_ushort(CFILE* file, ushort deflt)
{
ushort s;
if (file->version < ver)
return deflt;
if (cfread( &s, sizeof(s), 1, file) != 1)
return deflt;
@@ -1268,58 +1126,26 @@ ushort cfread_ushort(CFILE *file, int ver, ushort deflt)
return s;
}
ubyte cfread_ubyte(CFILE *file, int ver, ubyte deflt)
ubyte cfread_ubyte(CFILE* file, ubyte deflt)
{
ubyte b;
if (file->version < ver)
return deflt;
if (cfread( &b, sizeof(b), 1, file) != 1)
return deflt;
return b;
}
void cfread_vector(vec3d *vec, CFILE *file, int ver, vec3d *deflt)
{
if (file->version < ver) {
if (deflt)
*vec = *deflt;
else
vec->xyz.x = vec->xyz.y = vec->xyz.z = 0.0f;
return;
}
vec->xyz.x = cfread_float(file, ver, deflt ? deflt->xyz.x : 0.0f);
vec->xyz.y = cfread_float(file, ver, deflt ? deflt->xyz.y : 0.0f);
vec->xyz.z = cfread_float(file, ver, deflt ? deflt->xyz.z : 0.0f);
}
void cfread_angles(angles *ang, CFILE *file, int ver, angles *deflt)
{
if (file->version < ver) {
if (deflt)
*ang = *deflt;
else
ang->p = ang->b = ang->h = 0.0f;
return;
}
ang->p = cfread_float(file, ver, deflt ? deflt->p : 0.0f);
ang->b = cfread_float(file, ver, deflt ? deflt->b : 0.0f);
ang->h = cfread_float(file, ver, deflt ? deflt->h : 0.0f);
void cfread_vector(vec3d* vec, CFILE* file, vec3d* deflt) {
vec->xyz.x = cfread_float(file, deflt ? deflt->xyz.x : 0.0f);
vec->xyz.y = cfread_float(file, deflt ? deflt->xyz.y : 0.0f);
vec->xyz.z = cfread_float(file, deflt ? deflt->xyz.z : 0.0f);
}
char cfread_char(CFILE *file, int ver, char deflt)
char cfread_char(CFILE* file, char deflt)
{
char b;
if (file->version < ver)
return deflt;
if (cfread( &b, sizeof(b), 1, file) != 1)
return deflt;
@@ -1400,28 +1226,6 @@ int cfwrite_ubyte(ubyte b, CFILE *file)
return cfwrite(&b, sizeof(b), 1, file);
}
int cfwrite_vector(vec3d *vec, CFILE *file)
{
if(!cfwrite_float(vec->xyz.x, file)){
return 0;
}
if(!cfwrite_float(vec->xyz.y, file)){
return 0;
}
return cfwrite_float(vec->xyz.z, file);
}
int cfwrite_angles(angles *ang, CFILE *file)
{
if(!cfwrite_float(ang->p, file)){
return 0;
}
if(!cfwrite_float(ang->b, file)){
return 0;
}
return cfwrite_float(ang->h, file);
}
int cfwrite_char(char b, CFILE *file)
{
return cfwrite( &b, sizeof(b), 1, file);
@@ -1454,22 +1258,18 @@ int cfwrite_string_len(const char *buf, CFILE *file)
}
// Get the filelength
int cfilelength( CFILE * cfile )
{
int cfilelength(CFILE* cfile) {
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
// TODO: return length of memory mapped file
Assert( !cb->mem_mapped );
Assert(!cfile->mem_mapped);
// cfile->size gets set at cfopen
// cb->size gets set at cfopen
// The rest of the code still uses ints, do an overflow check to detect cases where this fails
Assertion(cb->size <= static_cast<size_t>(std::numeric_limits<int>::max()),
"Integer overflow in cfilelength! A file is too large (but I don't know which...).");
return (int) cb->size;
Assertion(cfile->size <= static_cast<size_t>(std::numeric_limits<int>::max()),
"Integer overflow in cfilelength! A file is too large (but I don't know which...).");
return (int) cfile->size;
}
// cfwrite() writes to the file
@@ -1485,15 +1285,13 @@ int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile)
if(buf == NULL || elsize == 0 || nelem == 0)
return 0;
Cfile_block *cb = &Cfile_block_list[cfile->id];
if(cb->lib_offset != 0)
if(cfile->lib_offset != 0)
{
Error(LOCATION, "Attempt to write to a VP file (unsupported)");
return 0;
}
if(cb->data != NULL)
if(cfile->data != nullptr)
{
Warning(LOCATION, "Writing is not supported for mem-mapped files");
return EOF;
@@ -1502,16 +1300,16 @@ int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile)
size_t bytes_written = 0;
size_t size = elsize * nelem;
bytes_written = fwrite(buf, 1, size, cb->fp);
bytes_written = fwrite(buf, 1, size, cfile->fp);
//WMC - update filesize and position
if (bytes_written > 0) {
cb->size += bytes_written;
cb->raw_position += bytes_written;
cfile->size += bytes_written;
cfile->raw_position += bytes_written;
}
#if defined(CHECK_SIZE) && !defined(NDEBUG)
Assert( cb->size == filelength(fileno(cb->fp)) );
Assert( cfile->size == filelength(fileno(cfile->fp)) );
#endif
return (int)(bytes_written / elsize);
@@ -1528,34 +1326,32 @@ int cfputc(int c, CFILE *cfile)
if(!cf_is_valid(cfile))
return EOF;
Cfile_block *cb = &Cfile_block_list[cfile->id];
if(cb->lib_offset != 0)
if(cfile->lib_offset != 0)
{
Error(LOCATION, "Attempt to write character to a VP file (unsupported)");
return EOF;
}
if(cb->data != NULL)
if(cfile->data != nullptr)
{
Warning(LOCATION, "Writing is not supported for mem-mapped files");
return EOF;
}
// writing not supported for memory-mapped files
Assert( !cb->data );
Assert( !cfile->data );
int result = fputc(c, cb->fp);
int result = fputc(c, cfile->fp);
//WMC - update filesize and position
if(result != EOF)
{
cb->size += 1;
cb->raw_position += 1;
cfile->size += 1;
cfile->raw_position += 1;
}
#if defined(CHECK_SIZE) && !defined(NDEBUG)
Assert( cb->size == filelength(fileno(cb->fp)) );
Assert( cfile->size == filelength(fileno(cfile->fp)) );
#endif
return result;
@@ -1574,31 +1370,29 @@ int cfputs(const char *str, CFILE *cfile)
if(str == NULL)
return EOF;
Cfile_block *cb = &Cfile_block_list[cfile->id];
if(cb->lib_offset != 0)
if(cfile->lib_offset != 0)
{
Error(LOCATION, "Attempt to write character to a VP file (unsupported)");
return EOF;
}
if(cb->data != NULL)
if(cfile->data != nullptr)
{
Warning(LOCATION, "Writing is not supported for mem-mapped files");
return EOF;
}
int result = fputs(str, cb->fp);
int result = fputs(str, cfile->fp);
//WMC - update filesize and position
if(result != EOF)
{
cb->size += strlen(str);
cb->raw_position += strlen(str);
cfile->size += strlen(str);
cfile->raw_position += strlen(str);
}
#if defined(CHECK_SIZE) && !defined(NDEBUG)
Assert( cb->size == filelength(fileno(cb->fp)) );
Assert( cfile->size == filelength(fileno(cfile->fp)) );
#endif
return result;
@@ -1960,19 +1754,16 @@ int cf_chksum_long(CFILE *file, uint *chksum, int max_size)
int cflush(CFILE *cfile)
{
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
// not supported for memory mapped files
Assert( !cb->data );
Assert( !cfile->data );
Assert(cb->fp != NULL);
Assert(cfile->fp != nullptr);
int result = fflush(cb->fp);
int result = fflush(cfile->fp);
//WMC - update filesize
cb->size = filelength(fileno(cb->fp));
cfile->size = filelength(fileno(cfile->fp));
return result;
}
+39 -37
View File
@@ -13,10 +13,11 @@
#define __CFILE_H__
#include <ctime>
#include "globalincs/pstypes.h"
#include <ctime>
#include <stdexcept>
#include <memory>
#define CF_EOF (-1)
@@ -25,10 +26,8 @@
#define CF_SEEK_CUR (1)
#define CF_SEEK_END (2)
typedef struct CFILE {
int id; // Index into cfile.cpp specific structure
int version; // version of this file
} CFILE;
// Opaque file handle
struct CFILE;
// extra info that can be returned when getting a file listing
typedef struct {
@@ -155,9 +154,6 @@ enum CFileLocationFlags {
CF_LOCATION_ALL = CF_LOCATION_ROOT_MASK | CF_LOCATION_TYPE_MASK
};
#define cfread_fix(file) (fix)cfread_int(file)
#define cfwrite_fix(i,file) cfwrite_int(i,file)
// callback function used for get_file_list() to filter files to be added to list. Return 1
// to add file to list, or 0 to not add it.
extern int (*Get_file_list_filter)(const char *filename);
@@ -169,18 +165,24 @@ extern const char *Get_file_list_child;
// cfile directory. valid after cfile_init() returns successfully
#define CFILE_ROOT_DIRECTORY_LEN 256
extern char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN];
extern char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN];
namespace cfile {
enum class ModRootType { Unknown, Folder, Package };
enum class LocationType { Unknown, SecondaryMod, PrimaryMod, GameRoot };
struct ModRoot {
ModRootType type = ModRootType::Unknown;
SCP_string path;
LocationType location_type = LocationType::Unknown;
bool user_location = false;
};
} // namespace cfile
//================= LOW-LEVEL FUNCTIONS ==================
int cfile_init(const char *exe_dir, const char *cdrom_dir=NULL);
int cfile_init(const SCP_vector<cfile::ModRoot>& modRoots);
void cfile_close();
// Call this if pack files got added or removed or the
// cdrom changed. This will refresh the list of filenames
// stored in packfiles and on the cdrom.
void cfile_refresh();
// add an extension to a filename if it doesn't already have it
char *cf_add_ext(const char *filename, const char *ext);
@@ -202,10 +204,6 @@ CFILE *_cfopen_special(const char* source_file, int line, const char *file_path,
// Flush the open file buffer
int cflush(CFILE *cfile);
// version number of opened file. Will be 0 unless you put something else here after you
// open a file. Once set, you can use minimum version numbers with the read functions.
void cf_set_version( CFILE * cfile, int version );
// will throw an error if cfread*() functions read past this mark
// converted to raw offsets when used, but gets passed actual length from current position
// setting 'len' to zero will disable the check
@@ -246,10 +244,6 @@ int cfread(void *buf, int elsize, int nelem, CFILE *fp);
// cfwrite() writes to the file
int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile);
// Reads/writes RLE compressed data.
int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile);
int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile);
// Moves the file pointer
int cfseek(CFILE *fp, int offset, int where);
@@ -301,7 +295,6 @@ uint cf_add_chksum_long(uint seed, ubyte *buffer, size_t size);
// convenient for misc checksumming purposes ------------------------------------------
//================= HIGH LEVEL FUNCTIONS ==================
int cfexist(const char *filename); // Returns true if file exists on disk (1) or in hog (2).
// rename a file, utilizing the extension to determine where file is.
#define CF_RENAME_SUCCESS 0 // successfully renamed the file
@@ -319,17 +312,15 @@ int cfile_flush_dir(int type);
// functions for reading from cfile
// These are all high level, built up from
// cfread.
int cfgetc(CFILE *fp);
char *cfgets(char *buf, size_t n, CFILE *fp);
char cfread_char(CFILE *file, int ver = 0, char deflt = 0);
ubyte cfread_ubyte(CFILE *file, int ver = 0, ubyte deflt = 0);
short cfread_short(CFILE *file, int ver = 0, short deflt = 0);
ushort cfread_ushort(CFILE *file, int ver = 0, ushort deflt = 0);
int cfread_int(CFILE *file, int ver = 0, int deflt = 0);
uint cfread_uint(CFILE *file, int ver = 0, uint deflt = 0);
float cfread_float(CFILE *file, int ver = 0, float deflt = 0.0f);
void cfread_vector(vec3d *vec, CFILE *file, int ver = 0, vec3d *deflt = NULL);
void cfread_angles(angles *ang, CFILE *file, int ver = 0, angles *deflt = NULL);
char cfread_char(CFILE* file, char deflt = 0);
ubyte cfread_ubyte(CFILE* file, ubyte deflt = 0);
short cfread_short(CFILE* file, short deflt = 0);
ushort cfread_ushort(CFILE* file, ushort deflt = 0);
int cfread_int(CFILE* file, int deflt = 0);
uint cfread_uint(CFILE* file, uint deflt = 0);
float cfread_float(CFILE* file, float deflt = 0.0f);
void cfread_vector(vec3d* vec, CFILE* file, vec3d* deflt = nullptr);
// Reads variable length, null-termined string. Will only read up
// to n characters.
@@ -360,8 +351,6 @@ int cfwrite_uint(uint i, CFILE *file);
int cfwrite_short(short s, CFILE *file);
int cfwrite_ushort(ushort s, CFILE *file);
int cfwrite_ubyte(ubyte u, CFILE *file);
int cfwrite_vector(vec3d *vec, CFILE *file);
int cfwrite_angles(angles *ang, CFILE *file);
// writes variable length, null-termined string.
int cfwrite_string(const char *buf, CFILE *file);
@@ -483,4 +472,17 @@ namespace cfile
}
// This allows to use std::unique_ptr with CFILE
namespace std {
template <>
struct default_delete<CFILE> {
void operator()(CFILE* ptr)
{
if (cf_is_valid(ptr)) {
cfclose(ptr);
}
}
};
} // namespace std
#endif /* __CFILE_H__ */
+55 -74
View File
@@ -36,24 +36,20 @@
void cf_init_lowlevel_read_code( CFILE * cfile, size_t lib_offset, size_t size, size_t pos )
{
Assert(cfile != NULL);
Assert(cfile != nullptr);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
cfile->lib_offset = lib_offset;
cfile->raw_position = pos;
cfile->size = size;
cb->lib_offset = lib_offset;
cb->raw_position = pos;
cb->size = size;
if ( cb->fp ) {
if ( cb->lib_offset ) {
fseek( cb->fp, (long)cb->lib_offset, SEEK_SET );
if ( cfile->fp ) {
if ( cfile->lib_offset ) {
fseek( cfile->fp, (long)cfile->lib_offset, SEEK_SET );
}
#if defined(CHECK_POSITION) && !defined(NDEBUG)
auto raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
auto raw_position = ftell(cfile->fp) - cfile->lib_offset;
Assert(raw_position == cfile->raw_position);
#endif
}
}
@@ -70,20 +66,16 @@ int cfeof(CFILE *cfile)
{
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
int result = 0;
#if defined(CHECK_POSITION) && !defined(NDEBUG)
if (cb->fp) {
auto raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
if (cfile->fp) {
auto raw_position = ftell(cfile->fp) - cfile->lib_offset;
Assert(raw_position == cfile->raw_position);
}
#endif
if (cb->raw_position >= cb->size ) {
if (cfile->raw_position >= cfile->size ) {
result = 1;
} else {
result = 0;
@@ -100,21 +92,18 @@ int cfeof(CFILE *cfile)
int cftell( CFILE * cfile )
{
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
#if defined(CHECK_POSITION) && !defined(NDEBUG)
if (cb->fp) {
auto raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
if (cfile->fp) {
auto raw_position = ftell(cfile->fp) - cfile->lib_offset;
Assert(raw_position == cfile->raw_position);
}
#endif
// The rest of the code still uses ints, do an overflow check to detect cases where this fails
Assertion(cb->raw_position <= static_cast<size_t>(std::numeric_limits<int>::max()),
Assertion(cfile->raw_position <= static_cast<size_t>(std::numeric_limits<int>::max()),
"Integer overflow in cftell, a file is probably too large (but I don't know which one).");
return (int) cb->raw_position;
return (int) cfile->raw_position;
}
@@ -127,27 +116,23 @@ int cfseek( CFILE *cfile, int offset, int where )
{
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
// TODO: seek to offset in memory mapped file
Assert( !cb->mem_mapped );
Assert( !cfile->mem_mapped );
size_t goal_position;
switch( where ) {
case CF_SEEK_SET:
goal_position = offset+cb->lib_offset;
goal_position = offset+cfile->lib_offset;
break;
case CF_SEEK_CUR:
{
goal_position = cb->raw_position+offset+cb->lib_offset;
goal_position = cfile->raw_position+offset+cfile->lib_offset;
}
break;
case CF_SEEK_END:
goal_position = cb->size+offset+cb->lib_offset;
goal_position = cfile->size+offset+cfile->lib_offset;
break;
default:
Int3();
@@ -155,23 +140,23 @@ 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);
CAP(goal_position, cfile->lib_offset, cfile->lib_offset + cfile->size);
int result = 0;
if (cb->fp) {
if (cfile->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);
result = fseek(cfile->fp, (long)goal_position, SEEK_SET );
Assertion(goal_position >= cfile->lib_offset, "Invalid offset values detected while seeking! Goal was " SIZE_T_ARG ", lib_offset is " SIZE_T_ARG ".", goal_position, cfile->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!");
cfile->raw_position = goal_position - cfile->lib_offset;
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
#if defined(CHECK_POSITION) && !defined(NDEBUG)
if (cb->fp) {
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset == cb->raw_position);
if (cfile->fp) {
auto tmp_offset = ftell(cfile->fp) - cfile->lib_offset;
Assert(tmp_offset == cfile->raw_position);
}
#endif
@@ -194,19 +179,17 @@ int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
if(buf == NULL || size <= 0)
return 0;
Cfile_block *cb = &Cfile_block_list[cfile->id];
if ( (cb->raw_position+size) > cb->size ) {
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
size = cb->size - cb->raw_position;
if ( (cfile->raw_position+size) > cfile->size ) {
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
size = cfile->size - cfile->raw_position;
if ( size < 1 ) {
return 0;
}
//mprintf(( "CFILE: EOF encountered in file\n" ));
}
if (cb->max_read_len) {
if ( cb->raw_position+size > cb->max_read_len ) {
if (cfile->max_read_len) {
if ( cfile->raw_position+size > cfile->max_read_len ) {
std::ostringstream s_buf;
s_buf << "Attempted to read " << size << "-byte(s) beyond length limit";
@@ -215,22 +198,22 @@ int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
}
size_t bytes_read;
if (cb->data != nullptr) {
if (cfile->data != nullptr) {
// This is a file from memory
bytes_read = size;
memcpy(buf, reinterpret_cast<const char*>(cb->data) + cb->raw_position, size);
memcpy(buf, reinterpret_cast<const char*>(cfile->data) + cfile->raw_position, size);
} else {
bytes_read = fread( buf, 1, size, cb->fp );
bytes_read = fread( buf, 1, size, cfile->fp );
}
if ( bytes_read > 0 ) {
cb->raw_position += bytes_read;
Assertion(cb->raw_position <= cb->size, "Invalid raw_position value detected!");
cfile->raw_position += bytes_read;
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
}
#if defined(CHECK_POSITION) && !defined(NDEBUG)
if (cb->fp) {
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
if (cfile->fp) {
auto tmp_offset = ftell(cfile->fp) - cfile->lib_offset;
Assert(tmp_offset==cfile->raw_position);
}
#endif
@@ -246,10 +229,8 @@ int cfread_lua_number(double *buf, CFILE *cfile)
if(buf == NULL)
return 0;
Cfile_block *cb = &Cfile_block_list[cfile->id];
// cfread() not supported for memory-mapped files
if(cb->data != NULL)
if(cfile->data != nullptr)
{
Warning(LOCATION, "Writing is not supported for mem-mapped files");
return 0;
@@ -257,28 +238,28 @@ int cfread_lua_number(double *buf, CFILE *cfile)
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);
if (cfile->fp) {
long orig_pos = ftell(cfile->fp);
items_read = fscanf(cfile->fp, LUA_NUMBER_SCAN, buf);
advance = (size_t) (ftell(cfile->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);
items_read = sscanf(reinterpret_cast<const char*>(cfile->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!");
cfile->raw_position += advance;
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
#if defined(CHECK_POSITION) && !defined(NDEBUG)
if (cb->fp) {
auto tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
if (cfile->fp) {
auto tmp_offset = ftell(cfile->fp) - cfile->lib_offset;
Assert(tmp_offset==cfile->raw_position);
}
#endif
+14 -15
View File
@@ -22,31 +22,30 @@
#define CFILE_BLOCK_UNUSED 0
#define CFILE_BLOCK_USED 1
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
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)
struct CFILE {
int type = CFILE_BLOCK_UNUSED; // CFILE_BLOCK_UNUSED, CFILE_BLOCK_USED
int dir_type; // directory location
FILE* fp; // File pointer if opening an individual file
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()
#else
// int fd; // file descriptor
size_t data_length; // length of data for mmap
size_t data_length; // length of data for mmap
#endif
size_t lib_offset;
size_t raw_position;
size_t size; // for packed files
size_t lib_offset;
size_t raw_position;
size_t size; // for packed files
size_t max_read_len; // max read offset, for special error handling
size_t max_read_len; // max read offset, for special error handling
const char* source_file;
int line_num;
} Cfile_block;
};
#define MAX_CFILE_BLOCKS 64
extern Cfile_block Cfile_block_list[MAX_CFILE_BLOCKS];
extern std::array<CFILE, MAX_CFILE_BLOCKS> Cfile_block_list;
// Called once to setup the low-level reading code.
void cf_init_lowlevel_read_code( CFILE * cfile, size_t lib_offset, size_t size, size_t pos );
+1 -350
View File
@@ -200,353 +200,4 @@ void cf_sort_filenames( int n, char **list, int sort, file_list_info *info )
}
nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
}
#if (0) // these aren't used anywhere now
// cf_compress - Do Run Length Compression on a block of data. Targa format.
//
// Usage:
// out Buffer to write it out to
// in Buffer to compress
// bytecount Number of bytes input
int cf_compress(char *out, char *in, int bytecount )
{
int pixcount; // number of pixels in the current packet
char *inputpixel=NULL; // current input pixel position
char *matchpixel=NULL; // pixel value to match for a run
char *flagbyte=NULL; // location of last flag byte to set
int rlcount; // current count in r.l. string
int rlthresh; // minimum valid run length
char *copyloc; // location to begin copying at
// set the threshold -- the minimum valid run length
rlthresh = 2; // Require a 2 pixel span before rle'ing
// set the first pixel up
flagbyte = out; // place to put next flag if run
inputpixel = in;
pixcount = 1;
rlcount = 0;
copyloc = (char *)0;
// loop till data processing complete
do {
// if we have accumulated a 128-byte packet, process it
if ( pixcount == 129 ) {
*flagbyte = 127;
// set the run flag if this is a run
if ( rlcount >= rlthresh ) {
*flagbyte |= 0x80;
pixcount = 2;
}
// copy the data into place
++flagbyte;
memmove( flagbyte, copyloc, pixcount-1 );
flagbyte += pixcount-1;
pixcount = 1;
// set up for next packet
continue;
}
// if zeroth byte, handle as special case
if ( pixcount == 1 ) {
rlcount = 0;
copyloc = inputpixel; /* point to 1st guy in packet */
matchpixel = inputpixel; /* set pointer to pix to match */
pixcount = 2;
inputpixel += 1;
continue;
}
// assembling a packet -- look at next pixel
// current pixel == match pixel?
if ( *inputpixel == *matchpixel ) {
// establishing a run of enough length to
// save space by doing it
// -- write the non-run length packet
// -- start run-length packet
if ( ++rlcount == rlthresh ) {
// close a non-run packet
if ( pixcount > (rlcount+1) ) {
// write out length and do not set run flag
*flagbyte++ = (char)(pixcount - 2 - rlthresh);
memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
flagbyte += (pixcount-1-rlcount);
copyloc = inputpixel;
pixcount = rlcount + 1;
}
}
} else {
// no match -- either break a run or continue without one
// if a run exists break it:
// write the bytes in the string (1+1)
// start the next string
if ( rlcount >= rlthresh ) {
*flagbyte++ = (char)(0x80 | rlcount);
memmove(flagbyte, copyloc, 1 );
flagbyte += 1;
pixcount = 1;
continue;
} else {
// not a match and currently not a run
// - save the current pixel
// - reset the run-length flag
rlcount = 0;
matchpixel = inputpixel;
}
}
pixcount++;
inputpixel += 1;
} while ( inputpixel < (in + bytecount));
// quit this buffer without loosing any data
if ( --pixcount >= 1 ) {
*flagbyte = (char)(pixcount - 1);
if ( rlcount >= rlthresh ) {
*flagbyte |= 0x80;
pixcount = 1;
}
// copy the data into place
++flagbyte;
memmove(flagbyte, copyloc, pixcount );
flagbyte += pixcount;
}
return(flagbyte-out);
}
// cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
//
// Usage:
// out Buffer to write it out to
// in Buffer to compress
// bytecount Number of bytes input
int cf_decompress(char *out, char *in )
{
int count;
char *param_out = out;
while(1) {
count = int(*in++);
int run_span = count & 0x80;
count &= (~0x80);
if ( count > 0 ) {
if ( run_span ) {
// RLE'd data
ubyte c = *in++;
memset( out, c, count );
out += count;
} else {
memmove( out, in, count );
in += count;
out += count;
}
}
}
return out - param_out;
}
#endif // 0
// cfread() reads from a file and decompresses it
//
// returns: returns the number of full elements read
//
//
int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
{
char *out = (char *)buf;
while(1) {
ubyte count;
if ( cfread( &count, 1, 1, cfile ) != 1 ) {
break;
}
int run_span = count & 0x80;
count &= (~0x80);
count++;
if ( count > 0 ) {
if ( run_span ) {
// RLE'd data
ubyte c;
if ( cfread( &c, 1, 1, cfile ) != 1 ) {
break;
}
memset( out, c, count );
} else {
if ( cfread( out, 1, count, cfile ) != count ) {
break;
}
}
out += count;
if ( out >= (char *)buf + (elsize*nelem)) {
break;
}
} else {
break;
}
}
return (int)((out - (char *)buf)/elsize);
}
int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
{
char *in = (char *)param_buf;
int bytecount = (param_elsize * param_nelem );
int pixcount; // number of pixels in the current packet
char *inputpixel=NULL; // current input pixel position
char *matchpixel=NULL; // pixel value to match for a run
int rlcount; // current count in r.l. string
int rlthresh; // minimum valid run length
char *copyloc; // location to begin copying at
// set the threshold -- the minimum valid run length
rlthresh = 2; // Require a 2 pixel span before rle'ing
// set the first pixel up
inputpixel = in;
pixcount = 1;
rlcount = 0;
copyloc = (char *)0;
// loop till data processing complete
do {
// if we have accumulated a 128-byte packet, process it
if ( pixcount == 129 ) {
ubyte code = 127;
// set the run flag if this is a run
if ( rlcount >= rlthresh ) {
code |= 0x80;
pixcount = 2;
}
cfwrite( &code, 1, 1, cfile );
// copy the data into place
cfwrite( copyloc, 1, pixcount-1, cfile );
pixcount = 1;
// set up for next packet
continue;
}
// if zeroth byte, handle as special case
if ( pixcount == 1 ) {
rlcount = 0;
copyloc = inputpixel; /* point to 1st guy in packet */
matchpixel = inputpixel; /* set pointer to pix to match */
pixcount = 2;
inputpixel += 1;
continue;
}
// assembling a packet -- look at next pixel
// current pixel == match pixel?
if ( *inputpixel == *matchpixel ) {
// establishing a run of enough length to
// save space by doing it
// -- write the non-run length packet
// -- start run-length packet
if ( ++rlcount == rlthresh ) {
// close a non-run packet
if ( pixcount > (rlcount+1) ) {
// write out length and do not set run flag
ubyte code = (ubyte)(pixcount - 2 - rlthresh);
cfwrite( &code, 1, 1, cfile );
cfwrite( copyloc, 1, (pixcount-1-rlcount), cfile );
copyloc = inputpixel;
pixcount = rlcount + 1;
}
}
} else {
// no match -- either break a run or continue without one
// if a run exists break it:
// write the bytes in the string (1+1)
// start the next string
if ( rlcount >= rlthresh ) {
ubyte code = (ubyte)(0x80 | rlcount);
cfwrite( &code, 1, 1, cfile );
cfwrite( copyloc, 1, 1, cfile );
pixcount = 1;
continue;
} else {
// not a match and currently not a run
// - save the current pixel
// - reset the run-length flag
rlcount = 0;
matchpixel = inputpixel;
}
}
pixcount++;
inputpixel += 1;
} while ( inputpixel < (in + bytecount));
// quit this buffer without loosing any data
if ( --pixcount >= 1 ) {
ubyte code = ubyte(pixcount - 1);
// set the run flag if this is a run
if ( rlcount >= rlthresh ) {
code |= 0x80;
pixcount = 1;
}
cfwrite( &code, 1, 1, cfile );
// copy the data into place
cfwrite( copyloc, 1, pixcount, cfile );
}
return param_nelem;
}
}
+266
View File
@@ -0,0 +1,266 @@
#define _CFILE_INTERNAL
#include "cfilemod.h"
#include "cfile.h"
#include "cmdline/cmdline.h"
#include "osapi/osapi.h"
#include "cfilesystem.h"
#ifdef SCP_UNIX
#include <glob.h>
#include <sys/types.h>
#include <dirent.h>
#include <fnmatch.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>
#endif
namespace cfile {
namespace {
typedef struct cf_root_sort {
SCP_string path;
int cf_type;
} cf_root_sort;
// packfile sort function
bool cf_packfile_sort_func(const cf_root_sort& r1, const cf_root_sort& r2) {
// if the 2 directory types are the same, do a string compare
if (r1.cf_type == r2.cf_type) {
return (stricmp(r1.path.c_str(), r2.path.c_str()) < 0);
}
// otherwise return them in order of CF_TYPE_* precedence
return (r1.cf_type < r2.cf_type);
}
// Go through a root and look for pack files
void build_pack_list(SCP_vector<ModRoot>& mod_roots,
const SCP_string& search_path,
LocationType location_type,
bool user_location) {
char filespec[MAX_PATH_LEN];
// allocate a temporary array of temporary roots so we can easily sort them
SCP_vector<cf_root_sort> temp_roots_sort;
// now just setup all the root info
for (int i = CF_TYPE_ROOT; i < CF_MAX_PATH_TYPES; i++) {
strcpy_s(filespec, search_path.c_str());
if (strlen(Pathtypes[i].path)) {
strcat_s(filespec, Pathtypes[i].path);
if (filespec[strlen(filespec) - 1] != DIR_SEPARATOR_CHAR)
strcat_s(filespec, DIR_SEPARATOR_STR);
}
#if defined _WIN32
strcat_s( filespec, "*.vp" );
intptr_t find_handle;
_finddata_t find;
find_handle = _findfirst( filespec, &find );
if (find_handle != -1) {
do {
// add the new item
if (!(find.attrib & _A_SUBDIR)) {
// get a temp pointer
rptr_sort = &temp_roots_sort[root_index++];
// fill in all the proper info
strcpy_s(rptr_sort->path, root->path);
if(strlen(Pathtypes[i].path)) {
strcat_s(rptr_sort->path, Pathtypes[i].path );
strcat_s(rptr_sort->path, DIR_SEPARATOR_STR);
}
strcat_s(rptr_sort->path, find.name );
rptr_sort->roottype = CF_ROOTTYPE_PACK;
rptr_sort->cf_type = i;
}
} while (!_findnext(find_handle, &find));
_findclose( find_handle );
}
#elif defined SCP_UNIX
strcat_s(filespec, "*.[vV][pP]");
glob_t globinfo;
memset(&globinfo, 0, sizeof(globinfo));
int status = glob(filespec, 0, NULL, &globinfo);
if (status == 0) {
for (uint j = 0; j < globinfo.gl_pathc; j++) {
// Determine if this is a regular file
struct stat statbuf;
memset(&statbuf, 0, sizeof(statbuf));
stat(globinfo.gl_pathv[j], &statbuf);
if (S_ISREG(statbuf.st_mode)) {
cf_root_sort sort;
// fill in all the proper info
sort.path = globinfo.gl_pathv[j];
sort.cf_type = i;
temp_roots_sort.push_back(sort);
}
}
globfree(&globinfo);
}
#endif
}
// sort the roots
std::sort(temp_roots_sort.begin(), temp_roots_sort.end(), cf_packfile_sort_func);
// now insert them all into the real root list properly
for (const auto& pack_root : temp_roots_sort) {
ModRoot root;
root.type = ModRootType::Package;
root.path = pack_root.path;
root.user_location = user_location;
root.location_type = location_type;
mod_roots.push_back(root);
}
}
char normalize_directory_separator(char in) {
if (in == '/') {
return DIR_SEPARATOR_CHAR;
}
return in;
}
void
add_mod_roots(SCP_vector<ModRoot>& mod_roots, const char* mod_cmdline, const SCP_string& rootDirectory, bool user_location) {
if (mod_cmdline) {
bool primary = true;
for (const char* cur_pos = mod_cmdline; strlen(cur_pos) != 0; cur_pos += (strlen(cur_pos) + 1)) {
SCP_stringstream ss;
ss << rootDirectory;
if (rootDirectory.back() != DIR_SEPARATOR_CHAR) {
ss << DIR_SEPARATOR_CHAR;
}
ss << cur_pos << DIR_SEPARATOR_STR;
SCP_string rootPath = ss.str();
// normalize the path to the native path format
std::transform(rootPath.begin(), rootPath.end(), rootPath.begin(), normalize_directory_separator);
ModRoot root;
root.type = ModRootType::Folder;
root.path = rootPath;
root.user_location = user_location;
if (primary) {
root.location_type = LocationType::PrimaryMod;
} else {
root.location_type = LocationType::SecondaryMod;
}
mod_roots.push_back(root);
build_pack_list(mod_roots, rootPath, root.location_type, user_location);
primary = false;
}
}
}
}
SCP_vector<ModRoot> getModRootsFromModCmdline(const SCP_string& content_root, const char* mod_cmdline) {
SCP_vector<ModRoot> mod_roots;
if (os_is_legacy_mode()) {
// =========================================================================
#ifdef WIN32
// Nothing to do here, Windows uses the current directory as the base
#else
add_mod_roots(mod_roots, mod_cmdline, os_get_legacy_user_dir(), true);
ModRoot root;
root.type = ModRootType::Folder;
root.path = os_get_legacy_user_dir();
root.user_location = true;
root.location_type = LocationType::GameRoot;
// do we already have a slash? as in the case of a root directory install
if (root.path.back() != DIR_SEPARATOR_CHAR) {
root.path += DIR_SEPARATOR_STR; // put trailing backslash on for easier path construction
}
mod_roots.push_back(root);
// Next, check any VP files under the current directory.
build_pack_list(mod_roots, root.path, root.location_type, root.user_location);
#endif
// =========================================================================
} else if (!Cmdline_portable_mode) {
// =========================================================================
// now look for mods under the users HOME directory to use before system ones
add_mod_roots(mod_roots, mod_cmdline, os_get_config_path(), true);
// =========================================================================
// =========================================================================
// set users HOME directory as default for loading and saving files
ModRoot root;
root.type = ModRootType::Folder;
root.path = os_get_config_path();
root.user_location = true;
root.location_type = LocationType::GameRoot;
// do we already have a slash? as in the case of a root directory install
if (root.path.back() != DIR_SEPARATOR_CHAR) {
root.path += DIR_SEPARATOR_STR; // put trailing backslash on for easier path construction
}
mod_roots.push_back(root);
// Next, check any VP files under the current directory.
build_pack_list(mod_roots, root.path, root.location_type, root.user_location);
// =========================================================================
}
add_mod_roots(mod_roots, mod_cmdline, content_root, false);
ModRoot root;
root.type = ModRootType::Folder;
root.path = content_root;
root.user_location = false;
root.location_type = LocationType::GameRoot;
// do we already have a slash? as in the case of a root directory install
if (root.path.back() != DIR_SEPARATOR_CHAR) {
root.path += DIR_SEPARATOR_STR; // put trailing backslash on for easier path construction
}
mod_roots.push_back(root);
//======================================================
// Next, check any VP files under the current directory.
build_pack_list(mod_roots, root.path, root.location_type, root.user_location);
return mod_roots;
}
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include "globalincs/pstypes.h"
#include "cfile/cfile.h"
namespace cfile {
SCP_vector<ModRoot> getModRootsFromModCmdline(const SCP_string& content_root, const char* mod_cmdline);
}
+86 -352
View File
@@ -160,379 +160,113 @@ cf_root *cf_create_root()
return &Root_blocks[block]->roots[offset];
}
// return the # of packfiles which exist
int cf_get_packfile_count(cf_root *root)
static bool has_mod_location(const SCP_vector<cfile::ModRoot>& modRoots)
{
SCP_string filespec;
int i;
int packfile_count;
// count up how many packfiles we're gonna have
packfile_count = 0;
for (i=CF_TYPE_ROOT; i<CF_MAX_PATH_TYPES; i++ )
for (const auto& root : modRoots)
{
filespec = root->path;
if(strlen(Pathtypes[i].path))
if (root.location_type == cfile::LocationType::PrimaryMod)
{
filespec += Pathtypes[ i ].path;
if ( filespec[ filespec.length( ) - 1 ] != DIR_SEPARATOR_CHAR )
{
filespec += DIR_SEPARATOR_STR;
}
}
#if defined _WIN32
filespec += "*.vp";
intptr_t find_handle;
_finddata_t find;
find_handle = _findfirst( filespec.c_str( ), &find );
if (find_handle != -1) {
do {
if (!(find.attrib & _A_SUBDIR)) {
packfile_count++;
}
} while (!_findnext(find_handle, &find));
_findclose( find_handle );
}
#elif defined SCP_UNIX
filespec += "*.[vV][pP]";
glob_t globinfo;
memset(&globinfo, 0, sizeof(globinfo));
int status = glob(filespec.c_str( ), 0, NULL, &globinfo);
if (status == 0) {
for (unsigned int j = 0; j < globinfo.gl_pathc; j++) {
// Determine if this is a regular file
struct stat statbuf;
memset(&statbuf, 0, sizeof(statbuf));
stat(globinfo.gl_pathv[j], &statbuf);
if (S_ISREG(statbuf.st_mode)) {
packfile_count++;
}
}
globfree(&globinfo);
}
#endif
}
return packfile_count;
}
// packfile sort function
bool cf_packfile_sort_func(const cf_root_sort &r1, const cf_root_sort &r2)
{
// if the 2 directory types are the same, do a string compare
if (r1.cf_type == r2.cf_type) {
return (stricmp(r1.path, r2.path) < 0);
}
// otherwise return them in order of CF_TYPE_* precedence
return (r1.cf_type < r2.cf_type);
}
// Go through a root and look for pack files
void cf_build_pack_list( cf_root *root )
{
char filespec[MAX_PATH_LEN];
int i;
cf_root_sort *temp_roots_sort, *rptr_sort;
int temp_root_count, root_index;
// determine how many packfiles there are
temp_root_count = cf_get_packfile_count(root);
if (temp_root_count <= 0)
return;
// allocate a temporary array of temporary roots so we can easily sort them
temp_roots_sort = (cf_root_sort*)vm_malloc(sizeof(cf_root_sort) * temp_root_count);
if (temp_roots_sort == NULL) {
Int3();
return;
}
// now just setup all the root info
root_index = 0;
for (i = CF_TYPE_ROOT; i < CF_MAX_PATH_TYPES; i++) {
strcpy_s( filespec, root->path );
if ( strlen(Pathtypes[i].path) ) {
strcat_s( filespec, Pathtypes[i].path );
if ( filespec[strlen(filespec)-1] != DIR_SEPARATOR_CHAR )
strcat_s( filespec, DIR_SEPARATOR_STR );
}
#if defined _WIN32
strcat_s( filespec, "*.vp" );
intptr_t find_handle;
_finddata_t find;
find_handle = _findfirst( filespec, &find );
if (find_handle != -1) {
do {
// add the new item
if (!(find.attrib & _A_SUBDIR)) {
Assert(root_index < temp_root_count);
// get a temp pointer
rptr_sort = &temp_roots_sort[root_index++];
// fill in all the proper info
strcpy_s(rptr_sort->path, root->path);
if(strlen(Pathtypes[i].path)) {
strcat_s(rptr_sort->path, Pathtypes[i].path );
strcat_s(rptr_sort->path, DIR_SEPARATOR_STR);
}
strcat_s(rptr_sort->path, find.name );
rptr_sort->roottype = CF_ROOTTYPE_PACK;
rptr_sort->cf_type = i;
}
} while (!_findnext(find_handle, &find));
_findclose( find_handle );
}
#elif defined SCP_UNIX
strcat_s( filespec, "*.[vV][pP]" );
glob_t globinfo;
memset(&globinfo, 0, sizeof(globinfo));
int status = glob(filespec, 0, NULL, &globinfo);
if (status == 0) {
for (uint j = 0; j < globinfo.gl_pathc; j++) {
// Determine if this is a regular file
struct stat statbuf;
memset(&statbuf, 0, sizeof(statbuf));
stat(globinfo.gl_pathv[j], &statbuf);
if ( S_ISREG(statbuf.st_mode) ) {
Assert(root_index < temp_root_count);
// get a temp pointer
rptr_sort = &temp_roots_sort[root_index++];
// fill in all the proper info
strcpy_s(rptr_sort->path, globinfo.gl_pathv[j] );
rptr_sort->roottype = CF_ROOTTYPE_PACK;
rptr_sort->cf_type = i;
}
}
globfree(&globinfo);
}
#endif
}
// these should always be the same
Assert(root_index == temp_root_count);
// sort the roots
std::sort(temp_roots_sort, temp_roots_sort + temp_root_count, cf_packfile_sort_func);
// now insert them all into the real root list properly
for (i = 0; i < temp_root_count; i++) {
auto new_root = cf_create_root();
new_root->location_flags = root->location_flags;
strcpy_s( new_root->path, root->path );
#ifndef NDEBUG
uint chksum = 0;
cf_chksum_pack(temp_roots_sort[i].path, &chksum);
mprintf(("Found root pack '%s' with a checksum of 0x%08x\n", temp_roots_sort[i].path, chksum));
#endif
// mwa -- 4/2/98 put in the next 2 lines because the path name needs to be there
// to find the files.
strcpy_s(new_root->path, temp_roots_sort[i].path);
new_root->roottype = CF_ROOTTYPE_PACK;
}
// free up the temp list
vm_free(temp_roots_sort);
}
static char normalize_directory_separator(char in)
{
if (in == '/')
{
return DIR_SEPARATOR_CHAR;
}
return in;
}
static void cf_add_mod_roots(const char* rootDirectory, uint32_t basic_location)
{
if (Cmdline_mod)
{
bool primary = true;
for (const char* cur_pos=Cmdline_mod; strlen(cur_pos) != 0; cur_pos+= (strlen(cur_pos)+1))
{
SCP_stringstream ss;
ss << rootDirectory;
if (rootDirectory[strlen(rootDirectory) - 1] != DIR_SEPARATOR_CHAR)
{
ss << DIR_SEPARATOR_CHAR;
}
ss << cur_pos << DIR_SEPARATOR_STR;
SCP_string rootPath = ss.str();
if (rootPath.size() + 1 >= CF_MAX_PATHNAME_LENGTH) {
Error(LOCATION, "The length of mod directory path '%s' exceeds the maximum of %d!\n", rootPath.c_str(), CF_MAX_PATHNAME_LENGTH);
}
// normalize the path to the native path format
std::transform(rootPath.begin(), rootPath.end(), rootPath.begin(), normalize_directory_separator);
cf_root* root = cf_create_root();
strncpy(root->path, rootPath.c_str(), CF_MAX_PATHNAME_LENGTH-1);
if (primary) {
root->location_flags = basic_location | CF_LOCATION_TYPE_PRIMARY_MOD;
} else {
root->location_flags = basic_location | CF_LOCATION_TYPE_SECONDARY_MODS;
}
root->roottype = CF_ROOTTYPE_PATH;
cf_build_pack_list(root);
primary = false;
return true;
}
}
return false;
}
void cf_build_root_list(const char *cdrom_dir)
void cf_build_root_list(const SCP_vector<cfile::ModRoot>& modRoots)
{
Num_roots = 0;
Num_path_roots = 0;
cf_root *root = nullptr;
auto has_mod = has_mod_location(modRoots);
if (os_is_legacy_mode())
mprintf(("CFile root configuration:\n"));
// Go through the roots specified and convert them to the internal data structure
for (const auto& root : modRoots)
{
// =========================================================================
#ifdef WIN32
// Nothing to do here, Windows uses the current directory as the base
#else
cf_add_mod_roots(os_get_legacy_user_dir(), CF_LOCATION_ROOT_USER);
root = cf_create_root();
strncpy(root->path, os_get_legacy_user_dir(), CF_MAX_PATHNAME_LENGTH - 1);
root->location_flags |= CF_LOCATION_ROOT_USER | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
if (root.path.size() >= CF_MAX_PATHNAME_LENGTH - 1)
{
Error(LOCATION, "Mod root path '%s' is longer than the maximum %d!", root.path.c_str(), CF_MAX_PATHNAME_LENGTH - 1);
return;
}
// do we already have a slash? as in the case of a root directory install
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
}
root->roottype = CF_ROOTTYPE_PATH;
auto cfile_root = cf_create_root();
memset(cfile_root, 0, sizeof(*cfile_root));
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
strcpy_s(cfile_root->path, root.path.c_str());
if (root.user_location)
{
cfile_root->location_flags |= CF_LOCATION_ROOT_USER;
} else {
cfile_root->location_flags |= CF_LOCATION_ROOT_GAME;
}
if (root.location_type == cfile::LocationType::SecondaryMod)
{
cfile_root->location_flags |= CF_LOCATION_TYPE_SECONDARY_MODS;
} else if (root.location_type == cfile::LocationType::PrimaryMod)
{
cfile_root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
} else if (root.location_type == cfile::LocationType::GameRoot)
{
cfile_root->location_flags |= CF_LOCATION_TYPE_ROOT;
if (!has_mod)
{
// If we do not have a mod then game roots are also primary mods
cfile_root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
} else {
UNREACHABLE("Unknown root location type!");
}
switch (root.type)
{
case cfile::ModRootType::Folder:
cfile_root->roottype = CF_ROOTTYPE_PATH;
break;
case cfile::ModRootType::Package:
cfile_root->roottype = CF_ROOTTYPE_PACK;
break;
default:
UNREACHABLE("Unknown root type!");
break;
}
if (root.type == cfile::ModRootType::Folder)
{
size_t path_len = strlen(cfile_root->path);
// do we already have a slash? as in the case of a root directory install
if ( (path_len < (CF_MAX_PATHNAME_LENGTH-1)) && (cfile_root->path[path_len-1] != DIR_SEPARATOR_CHAR) ) {
strcat_s(cfile_root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
}
}
#ifndef NDEBUG
switch (root.type)
{
case cfile::ModRootType::Folder:
mprintf((" Found root folder '%s'\n", root.path.c_str()));
break;
case cfile::ModRootType::Package: {
uint chksum = 0;
cf_chksum_pack(root.path.c_str(), &chksum);
mprintf((" Found root pack '%s' with a checksum of 0x%08x\n", root.path.c_str(), chksum));
break;
}
default:
UNREACHABLE("Unknown root type!");
break;
}
#endif
// =========================================================================
}
else if (!Cmdline_portable_mode)
{
// =========================================================================
// now look for mods under the users HOME directory to use before system ones
cf_add_mod_roots(Cfile_user_dir, CF_LOCATION_ROOT_USER);
// =========================================================================
// =========================================================================
// set users HOME directory as default for loading and saving files
root = cf_create_root();
strcpy_s(root->path, Cfile_user_dir);
root->location_flags |= CF_LOCATION_ROOT_USER | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
// do we already have a slash? as in the case of a root directory install
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
}
root->roottype = CF_ROOTTYPE_PATH;
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
// =========================================================================
}
char working_directory[CF_MAX_PATHNAME_LENGTH];
if ( !_getcwd(working_directory, CF_MAX_PATHNAME_LENGTH ) ) {
Error(LOCATION, "Can't get current working directory -- %d", errno );
}
cf_add_mod_roots(working_directory, CF_LOCATION_ROOT_GAME);
root = cf_create_root();
root->location_flags |= CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
strcpy_s(root->path, working_directory);
size_t path_len = strlen(root->path);
// do we already have a slash? as in the case of a root directory install
if ( (path_len < (CF_MAX_PATHNAME_LENGTH-1)) && (root->path[path_len-1] != DIR_SEPARATOR_CHAR) ) {
strcat_s(root->path, DIR_SEPARATOR_STR); // put trailing backslash on for easier path construction
}
root->roottype = CF_ROOTTYPE_PATH;
//======================================================
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
//======================================================
// Check the real CD if one...
if ( cdrom_dir && (strlen(cdrom_dir) < CF_MAX_PATHNAME_LENGTH) ) {
root = cf_create_root();
strcpy_s( root->path, cdrom_dir );
root->roottype = CF_ROOTTYPE_PATH;
//======================================================
// Next, check any VP files in the CD-ROM directory.
cf_build_pack_list(root);
}
// The final root is the in-memory root
root = cf_create_root();
auto root = cf_create_root();
root->location_flags = CF_LOCATION_ROOT_MEMORY | CF_LOCATION_TYPE_ROOT;
memset(root->path, 0, sizeof(root->path));
root->roottype = CF_ROOTTYPE_MEMORY;
}
// Given a lower case list of file extensions
@@ -923,7 +657,7 @@ void cf_build_file_list()
}
void cf_build_secondary_filelist(const char *cdrom_dir)
void cf_build_secondary_filelist(const SCP_vector<cfile::ModRoot>& modRoots)
{
int i;
@@ -944,7 +678,7 @@ void cf_build_secondary_filelist(const char *cdrom_dir)
mprintf(( "Building file index...\n" ));
// build the list of searchable roots
cf_build_root_list(cdrom_dir);
cf_build_root_list(modRoots);
// build the list of files themselves
cf_build_file_list();
+1 -1
View File
@@ -15,7 +15,7 @@
#include "cfile/cfile.h"
// Builds a list of all the files
void cf_build_secondary_filelist( const char *cdrom_path );
void cf_build_secondary_filelist(const SCP_vector<cfile::ModRoot>& modRoots);
void cf_free_secondary_filelist();
// Internal stuff
+396 -224
View File
File diff suppressed because it is too large. Load diff
+18 -23
View File
@@ -12,6 +12,7 @@
#ifndef FS_CMDLINE_HEADER_FILE
#define FS_CMDLINE_HEADER_FILE
#include "globalincs/pstypes.h"
int parse_cmdline(int argc, char *argv[]);
@@ -24,11 +25,11 @@ int parse_cmdline(int argc, char *argv[]);
// RETAIL OPTIONS ----------------------------------------------
extern char *Cmdline_connect_addr;
extern char *Cmdline_game_name;
extern char *Cmdline_game_password;
extern char *Cmdline_rank_above;
extern char *Cmdline_rank_below;
extern SCP_string Cmdline_connect_addr;
extern SCP_string Cmdline_game_name;
extern SCP_string Cmdline_game_password;
extern SCP_string Cmdline_rank_above;
extern SCP_string Cmdline_rank_below;
extern int Cmdline_cd_check;
extern int Cmdline_client_dodamage;
extern int Cmdline_closed_game;
@@ -46,8 +47,8 @@ extern int Cmdline_timeout;
extern int Cmdline_use_last_pilot;
extern int Cmdline_window;
extern int Cmdline_fullscreen_window;
extern char *Cmdline_res;
extern char *Cmdline_center_res;
extern SCP_string Cmdline_res;
extern SCP_string Cmdline_center_res;
// FSO OPTIONS -------------------------------------------------
@@ -55,7 +56,6 @@ extern char *Cmdline_center_res;
// Graphics related
extern double specular_exponent_value;
extern float Cmdline_clip_dist;
extern float Cmdline_fov;
extern float Cmdline_ogl_spec;
extern float static_light_factor;
extern float static_point_factor;
@@ -63,20 +63,13 @@ extern float static_tube_factor;
extern int Cmdline_ambient_factor;
extern int Cmdline_env;
extern int Cmdline_glow;
extern int Cmdline_nomotiondebris;
extern int Cmdline_noscalevid; // disables fit-to-window for movies - taylor
extern int Cmdline_spec;
extern int Cmdline_normal;
extern int Cmdline_height;
extern int Cmdline_enable_3d_shockwave;
extern int Cmdline_softparticles;
extern int Cmdline_postprocess;
extern int Cmdline_bloom_intensity;
extern bool Cmdline_fxaa;
extern int Cmdline_fxaa_preset;
extern bool Cmdline_fb_explosions;
extern bool Cmdline_fb_thrusters;
extern int Cmdline_shadow_quality;
extern int Cmdline_no_deferred_lighting;
extern int Cmdline_no_emissive;
extern int Cmdline_aniso_level;
@@ -101,18 +94,21 @@ extern int Cmdline_autopilot_interruptable;
extern int Cmdline_stretch_menu;
// Audio related
extern int Cmdline_query_speech;
extern int Cmdline_voice_recognition;
extern int Cmdline_no_enhanced_sound;
namespace cfile {
struct ModRoot;
} // namespace cfile
// MOD related
extern char *Cmdline_mod; // DTP for mod support
extern SCP_vector<cfile::ModRoot> Cmdline_mod; // DTP for mod support
// Multiplayer/Network related
extern char *Cmdline_almission; // DTP for autoload mission (for multi only)
extern SCP_string Cmdline_almission; // DTP for autoload mission (for multi only)
extern int Cmdline_ingamejoin;
extern int Cmdline_mpnoreturn;
extern char *Cmdline_spew_mission_crcs;
extern char *Cmdline_spew_table_crcs;
extern SCP_string Cmdline_spew_mission_crcs;
extern SCP_string Cmdline_spew_table_crcs;
extern int Cmdline_objupd;
// Launcher related options
@@ -128,7 +124,7 @@ extern int Cmdline_mipmap;
extern int Cmdline_ati_color_swap;
extern int Cmdline_no_3d_sound;
extern int Cmdline_drawelements;
extern char* Cmdline_keyboard_layout;
extern SCP_string Cmdline_keyboard_layout;
extern bool Cmdline_gl_finish;
extern bool Cmdline_no_geo_sdr_effects;
extern bool Cmdline_set_cpu_affinity;
@@ -139,8 +135,7 @@ extern bool Cmdline_alternate_registry_path;
#endif
// Developer/Testing related
extern char *Cmdline_start_mission;
extern int Cmdline_old_collision_sys;
extern SCP_string Cmdline_start_mission;
extern int Cmdline_dis_collisions;
extern int Cmdline_dis_weapons;
extern bool Cmdline_output_sexp_info;
+48
View File
@@ -0,0 +1,48 @@
{
"version": 1,
"flags": {
"-bool_option": false,
"-number_option": 5.8,
"-string_option": "asdf",
"-mod": [
{
"type": "folder",
"path": "/home/fso/mediavps",
"user": true,
"location_type": "primary_mod"
},
{
"type": "folder",
"path": "/home/fso",
"user": true,
"location_type": "game_root"
},
{
"type": "folder",
"path": "/path/to/fso/mediavps",
"user": false,
"location_type": "primary_mod"
},
{
"type": "package",
"path": "/path/to/fso/mediavps/MVPS-Z.vp",
"location_type": "primary_mod"
},
{
"type": "package",
"path": "/path/to/fso/mediavps/MVPS-X.vp",
"location_type": "primary_mod"
},
{
"type": "folder",
"path": "/path/to/fso",
"location_type": "game_root"
},
{
"type": "package",
"path": "/path/to/fso/retail.vp",
"location_type": "game_root"
}
]
}
}
-20
View File
@@ -53,26 +53,6 @@ void cmeasure_set_ship_launch_vel(object *objp, object *parent_objp, int arand)
vm_vec_copy_scale(&objp->phys_info.desired_vel, &objp->orient.vec.fvec, objp->phys_info.max_vel.xyz.z );
}
void cmeasure_select_next(ship *shipp)
{
Assert(shipp != NULL);
int i, new_index;
for (i = 1; i < Num_weapon_types; i++)
{
new_index = (shipp->current_cmeasure + i) % Num_weapon_types;
if(Weapon_info[new_index].wi_flags[Weapon::Info_Flags::Cmeasure])
{
shipp->current_cmeasure = new_index;
return;
}
}
mprintf(("Countermeasure type set to %i in frame %i\n", shipp->current_cmeasure, Framecount));
}
/**
* @brief If this is a player countermeasure, let the player know they evaded a missile.
* @param objp [description]
-1
View File
@@ -28,7 +28,6 @@ extern int Cmeasures_homing_check;
extern int Countermeasures_enabled;
extern void cmeasure_set_ship_launch_vel(object *objp, object *parent_objp, int arand);
extern void cmeasure_select_next(object *objp);
extern void cmeasure_maybe_alert_success(object *objp);
#endif // _CMEASURE_H
+1 -23
View File
@@ -38,7 +38,6 @@
#define NUM_SYSTEM_KEYS 14
#define NUM_BUTTONS 19
#define NUM_TABS 4
@@ -157,11 +156,6 @@ char *Mouse_button_text[NUM_MOUSE_TEXT];
char *Mouse_axis_text[NUM_MOUSE_AXIS_TEXT];
char *Invert_text[NUM_INVERT_TEXT];
ubyte System_keys[NUM_SYSTEM_KEYS] = {
KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,
KEY_F11, KEY_F12, KEY_PRINT_SCRN
};
int Control_check_count = 0;
static int Tab; // which tab we are currently in
@@ -2193,17 +2187,6 @@ void control_config_do_frame(float frametime)
gr_flip();
}
void clear_key_binding(short key)
{
int i;
for (i=0; i<CCFG_MAX; i++) {
if (Control_config[i].key_id == key) {
Control_config[i].key_id = -1;
}
}
}
float check_control_timef(int id)
{
float t1, t2;
@@ -2447,9 +2430,4 @@ void control_config_clear()
for (i=0; i<CCFG_MAX; i++) {
Control_config[i].key_id = Control_config[i].joy_id = -1;
}
}
int control_config_handle_conflict()
{
return 0;
}
}
-7
View File
@@ -277,12 +277,6 @@ enum IoActionId {
};
extern int Failed_key_index;
extern int Invert_heading;
extern int Invert_pitch;
extern int Invert_roll;
extern int Invert_thrust;
extern int Disable_axis2;
extern int Disable_axis3;
extern int Axis_map_to[];
extern int Invert_axis[];
@@ -336,7 +330,6 @@ int check_control(int id, int key = -1);
void control_get_axes_readings(int *h, int *p, int *b, int *ta, int *tr);
void control_used(int id);
void control_config_clear();
void clear_key_binding(short key);
void control_check_indicate();
void control_config_clear_used_status();
+3 -33
View File
@@ -34,13 +34,6 @@ int Failed_key_index;
int Joy_dead_zone_size = 10;
int Joy_sensitivity = 9;
// assume control keys are used as modifiers until we find out
int Shift_is_modifier;
int Ctrl_is_modifier;
int Alt_is_modifier;
int Axis_enabled[JOY_NUM_AXES] = { 1, 1, 1, 0, 0, 0 };
int Axis_enabled_defaults[JOY_NUM_AXES] = { 1, 1, 1, 0, 0, 0 };
int Invert_axis[JOY_NUM_AXES] = { 0, 0, 0, 0, 0, 0 };
int Invert_axis_defaults[JOY_NUM_AXES] = { 0, 0, 0, 0, 0, 0 };
@@ -410,31 +403,6 @@ const char **Joy_button_text = Joy_button_text_english;
SCP_vector<config_item*> Control_config_presets;
SCP_vector<SCP_string> Control_config_preset_names;
void set_modifier_status()
{
int i;
Alt_is_modifier = 0;
Shift_is_modifier = 0;
Ctrl_is_modifier = 0;
for (i=0; i<CCFG_MAX; i++) {
if (Control_config[i].key_id < 0)
continue;
if (Control_config[i].key_id & KEY_ALTED)
Alt_is_modifier = 1;
if (Control_config[i].key_id & KEY_SHIFTED)
Shift_is_modifier = 1;
if (Control_config[i].key_id & KEY_CTRLED) {
Assert(0); // get Alan
Ctrl_is_modifier = 1;
}
}
}
// If find_override is set to true, then this returns the index of the action
// which has been bound to the given key. Otherwise, the index of the action
// which has the given key as its default key will be returned.
@@ -536,7 +504,9 @@ char *translate_key(char *key)
// both key and joystick button are mapped to this control
if ((key_code >= 0 ) && (joy_code >= 0) ) {
strcpy_s(text, key_text);
strcat_s(text, " or ");
strcat_s(text, " ");
strcat_s(text, XSTR("or", 1638));
strcat_s(text, " ");
strcat_s(text, joy_text);
}
// if we only have one
+1 -12
View File
@@ -4,7 +4,7 @@
namespace cutscene {
FrameSize::FrameSize(size_t in_width, size_t in_height, size_t in_stride)
: width(in_width), height(in_height), stride(in_stride)
: width(in_width), height(in_height), stride(in_stride)
{
}
FrameSize::FrameSize() = default;
@@ -46,10 +46,6 @@ void Decoder::stopDecoder() {
m_subtitleQueue->close();
}
bool Decoder::canPushAudioData() {
return !isAudioQueueFull();
}
void Decoder::pushAudioData(AudioFramePtr&& data) {
Assertion(data, "Invalid audio data passed!");
@@ -61,9 +57,6 @@ void Decoder::pushAudioData(AudioFramePtr&& data) {
}
}
bool Decoder::canPushSubtitleData() {
return !isSubtitleQueueFull();
}
void Decoder::pushSubtitleData(SubtitleFramePtr&& data) {
Assertion(data, "Invalid audio data passed!");
@@ -75,10 +68,6 @@ void Decoder::pushSubtitleData(SubtitleFramePtr&& data) {
}
}
bool Decoder::canPushVideoData() {
return !isVideoQueueFull();
}
void Decoder::pushFrameData(VideoFramePtr&& frame) {
Assertion(frame, "Invalid video data passed!");
+1 -11
View File
@@ -11,8 +11,8 @@ struct FrameSize {
size_t height = 0;
size_t stride = 0;
FrameSize(size_t width, size_t in_height, size_t in_stride);
FrameSize();
FrameSize(size_t width, size_t in_height, size_t in_stride);
};
class VideoFrame {
@@ -147,10 +147,6 @@ class Decoder {
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; }
@@ -168,16 +164,10 @@ class Decoder {
protected:
void initializeQueues(size_t queueSize);
bool canPushAudioData();
void pushAudioData(AudioFramePtr&& data);
bool canPushSubtitleData();
void pushSubtitleData(SubtitleFramePtr&& data);
bool canPushVideoData();
void pushFrameData(VideoFramePtr&& frame);
};
}
-8
View File
@@ -21,15 +21,7 @@ typedef struct cutscene_info
bool viewable;
} cutscene_info;
#if SCP_COMPILER_IS_GNU
#pragma GCC diagnostic push
// This suppresses a GCC bug where it thinks that the Cutscenes from the enum class below shadows a global variable
#pragma GCC diagnostic ignored "-Wshadow"
#endif
extern SCP_vector<cutscene_info> Cutscenes;
#if SCP_COMPILER_IS_GNU
#pragma GCC diagnostic pop
#endif
// initializa table data
void cutscene_init();
+4 -21
View File
@@ -31,7 +31,6 @@
#include "weapon/weapon.h"
#include "tracing/Monitor.h"
#define MAX_LIFE 10.0f
#define MIN_RADIUS_FOR_PERSISTANT_DEBRIS 50 // ship radius at which debris from it becomes persistant
#define DEBRIS_SOUND_DELAY 2000 // time to start debris sound after created
#define MAX_HULL_PIECES MAX_DEBRIS_PIECES // limit the number of hull debris chunks that can exist.
@@ -52,10 +51,6 @@ int Debris_num_submodels = 0;
#define DEBRIS_DISTANCE_CHECK_TIME (10*1000) // Check every 10 seconds.
#define DEBRIS_INDEX(dp) (int)(dp-Debris)
#define MAX_SPEED_SMALL_DEBRIS 200 // maximum velocity of small debris piece
#define MAX_SPEED_BIG_DEBRIS 150 // maximum velocity of big debris piece
#define MAX_SPEED_CAPITAL_DEBRIS 100 // maximum velocity of capital debris piece
/**
* Start the sequence of a piece of debris writhing in unholy agony!!!
*/
@@ -270,13 +265,8 @@ void debris_process_post(object * obj, float frame_time)
vec3d v1, v2, v3, v4;
if ( Cmdline_old_collision_sys ) {
submodel_get_two_random_points( db->model_num, db->submodel_num, &v1, &v2 );
submodel_get_two_random_points( db->model_num, db->submodel_num, &v3, &v4 );
} else {
submodel_get_two_random_points_better( db->model_num, db->submodel_num, &v1, &v2 );
submodel_get_two_random_points_better( db->model_num, db->submodel_num, &v3, &v4 );
}
submodel_get_two_random_points_better(db->model_num, db->submodel_num, &v1, &v2);
submodel_get_two_random_points_better(db->model_num, db->submodel_num, &v3, &v4);
n = 0;
@@ -352,12 +342,8 @@ void debris_process_post(object * obj, float frame_time)
if ( mr < RAND_MAX/5 ) {
vec3d v1, v2;
if ( Cmdline_old_collision_sys ) {
submodel_get_two_random_points( db->model_num, db->submodel_num, &v1, &v2 );
} else {
submodel_get_two_random_points_better( db->model_num, db->submodel_num, &v1, &v2 );
}
submodel_get_two_random_points_better(db->model_num, db->submodel_num, &v1, &v2);
db->arc_pts[i][mr % 2] = v1;
}
}
@@ -505,7 +491,6 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
db->flags |= DEBRIS_USED;
db->is_hull = hull_flag;
db->source_objnum = parent_objnum;
db->source_sig = source_obj->signature;
db->damage_type_idx = shipp->debris_damage_type_idx;
db->ship_info_index = shipp->ship_info_index;
db->team = shipp->team;
@@ -989,8 +974,6 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
// SET PHYSICS PARAMETERS
// already have (hitpos - heavy) and light_cm_pos
// get heavy cm pos - already have light_cm_pos
debris_hit_info->heavy_collision_cm_pos = zero;
// get r_heavy and r_light
debris_hit_info->r_heavy = debris_hit_info->hit_pos;
-1
View File
@@ -24,7 +24,6 @@ typedef struct debris {
debris *next, *prev; // used for a linked list of the hull debris chunks
int flags; // See DEBRIS_??? defines
int source_objnum; // What object this came from
int source_sig; // Signature of the source object
int damage_type_idx; // Damage type of this debris
int ship_info_index; // Ship info index of the ship type debris came from
int team; // Team of the ship where the debris came from
-11
View File
@@ -70,7 +70,6 @@ int dc_font = font::FONT1;
SCP_string dc_title;
#define SCROLL_X_MAX (DBCOLS - DCOLS)
#define SCROLL_Y_MAX (DBROWS - DROWS)
// Commands and History
@@ -117,11 +116,6 @@ void dc_draw_window(bool show_prompt);
*/
void dc_putc(char c);
/**
* @brief Predicate function used to sort debug_commands
*/
bool dcmd_less(debug_command *first, debug_command *second);
// ============================== IMPLEMENTATIONS =============================
void dc_do_command(SCP_string *cmd_str)
{
@@ -494,11 +488,6 @@ void dc_putc(char c)
line_str->push_back(c);
}
bool dcmd_less(debug_command *first, debug_command *second)
{
return (strcmp(first->name, second->name) < 0);
}
void debug_console(void (*_func)(void))
{
int done = 0;
+1 -7
View File
@@ -28,10 +28,6 @@ debug_command *dc_commands[DC_MAX_COMMANDS];
int dc_commands_size = 0;
// ========================= LOCALS ==========================
// dcf_shell commands
void dc_shell_font( void );
void dc_shell_resize( void );
void dc_shell_resize_buf( void );
// =================== class debug_command ===================
debug_command::debug_command()
@@ -155,6 +151,4 @@ DCF(help, "Displays the help list." )
dc_printf(" %s - %s\n", dc_commands[i]->name, dc_commands[i]->help);
}
}
debug_command dc_man("man", "Also displays the help list", dcf_help);
}
+8
View File
@@ -226,6 +226,7 @@ void parse_decals_table(const char* filename) {
struct Decal {
int definition_handle = -1;
object_h object;
int orig_obj_type = OBJ_NONE;
int submodel = -1;
float creation_time = -1.0f; //!< The mission time at which this decal was created
@@ -244,6 +245,12 @@ struct Decal {
return false;
}
if (orig_obj_type != object.objp->type) {
mprintf(("Decal object type for object %d has changed from %s to %s. Please let m!m know about this\n",
OBJ_INDEX(object.objp), Object_type_names[orig_obj_type], Object_type_names[object.objp->type]));
return false;
}
if (lifetime > 0.0f) {
if (f2fl(Missiontime) >= creation_time + lifetime) {
// Decal has expired
@@ -525,6 +532,7 @@ addDecal(creation_info& info, object* host, int submodel, const vec3d& local_pos
Decal newDecal;
newDecal.definition_handle = info.definition_handle;
newDecal.object = object_h(host);
newDecal.orig_obj_type = host->type;
newDecal.submodel = submodel;
newDecal.creation_time = f2fl(Missiontime);
newDecal.lifetime = info.lifetime.next();
+14 -14
View File
@@ -45,7 +45,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 600.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+Turrets attack this: YES
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
@@ -79,7 +79,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 500.0
$AI:
+Valid goals: ( "fly to ship" "dock" "undock" "waypoints" "waypoints once" "stay near ship" "keep safe dist" "stay still" "play dead" )
+Valid goals: ( "fly to ship" "dock" "undock" "waypoints" "waypoints once" "stay near ship" "keep safe dist" "stay still" "play dead" "play dead (persistent)" )
+Accept Player Orders: YES
+Player orders: ( "rearm me" "abort rearm" "depart" )
+Auto attacks: YES
@@ -104,7 +104,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 500.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "stay near ship" "keep safe dist" )
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" )
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "disable ship" "disarm ship" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "depart" "disable subsys" )
+Auto attacks: YES
@@ -130,7 +130,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 500.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "stay near ship" "keep safe dist" "form on wing")
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing")
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "disable ship" "disarm ship" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "depart" "disable subsys" )
+Auto attacks: YES
@@ -157,7 +157,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 500.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "stay near ship" "keep safe dist" "form on wing" )
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing" )
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "disable ship" "disarm ship" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "depart" "disable subsys" )
+Auto attacks: YES
@@ -184,7 +184,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 500.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "stay near ship" "keep safe dist" "form on wing" )
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing" )
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "disable ship" "disarm ship" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "depart" "disable subsys" )
+Auto attacks: YES
@@ -210,7 +210,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 500.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "dock" "depart" )
+Auto attacks: YES
@@ -238,7 +238,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 600.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "dock" "depart" )
+Auto attacks: YES
@@ -266,7 +266,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 600.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "depart" )
+Auto attacks: YES
@@ -293,7 +293,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 600.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "depart" )
+Auto attacks: YES
@@ -320,7 +320,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 600.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "depart" )
+Auto attacks: YES
@@ -347,7 +347,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 600.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
+Accept Player Orders: YES
+Player Orders: ( "attack ship" "depart" )
+Auto attacks: YES
@@ -375,7 +375,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 750.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "waypoints" "waypoints once" "depart" "stay still" "play dead" "stay near ship" )
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "waypoints" "waypoints once" "depart" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
+Accept Player Orders: YES
+Player Orders: ( "depart" )
+Auto attacks: YES
@@ -403,7 +403,7 @@ $Fog:
+Start dist: 10.0
+Compl dist: 1000.0
$AI:
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "waypoints" "waypoints once" "depart" "stay still" "play dead" "stay near ship" )
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "waypoints" "waypoints once" "depart" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
+Auto attacks: YES
+Attempt Broadside: YES
+Actively Pursues: ( "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
+14 -8
View File
@@ -1,22 +1,21 @@
/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
*/
#include "fireball/fireballs.h"
#include "asteroid/asteroid.h"
#include "cmdline/cmdline.h"
#include "fireball/fireballs.h"
#include "gamesnd/gamesnd.h"
#include "graphics/tmapper.h"
#include "localization/localize.h"
#include "model/model.h"
#include "object/object.h"
#include "options/Option.h"
#include "parse/parselo.h"
#include "render/3d.h"
#include "render/batching.h"
@@ -46,8 +45,15 @@ int Num_fireball_types = 0;
bool fireballs_inited = false;
bool fireballs_parsed = false;
#define FB_INDEX(fb) (fb-Fireballs)
bool Fireball_use_3d_warp = false;
static auto WarpOption = options::OptionBuilder<bool>("Graphics.3dWarp", "3D Warp", "Use a 3D model for warp effects")
.category("Graphics")
.default_val(true)
.level(options::ExpertLevel::Advanced)
.bind_to(&Fireball_use_3d_warp)
.importance(65)
.finish();
/**
* Play warp in sound for warp effect
*/
@@ -767,7 +773,7 @@ int fireball_get_lod(vec3d *pos, fireball_info *fd, float size)
/**
* Create a fireball, return object index.
*/
int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_obj, float size, int reverse, vec3d *velocity, float warp_lifetime, int ship_class, matrix *orient_override, int low_res, int extra_flags, gamesnd_id warp_open_sound, gamesnd_id warp_close_sound, float warp_open_duration, float warp_close_duration)
int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_obj, float size, bool reverse, vec3d *velocity, float warp_lifetime, int ship_class, matrix *orient_override, int low_res, int extra_flags, gamesnd_id warp_open_sound, gamesnd_id warp_close_sound, float warp_open_duration, float warp_close_duration)
{
int n, objnum, fb_lod;
object *obj;
+6 -4
View File
@@ -103,11 +103,11 @@ void fireball_parse_tbl();
int fireball_info_lookup(const char *unique_id);
// reversed is for warp_in/out effects
// Velocity: If not NULL, the fireball will move at a constant velocity.
// reverse is for warp_in/out effects
// velocity: If not NULL, the fireball will move at a constant velocity.
// warp_lifetime: If warp_lifetime > 0.0f then makes the explosion loop so it lasts this long. Only works for warp effect
int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_obj, float size, int reversed=0, vec3d *velocity=nullptr, float warp_lifetime=0.0f, int ship_class=-1, matrix *orient=nullptr, int low_res=0, int extra_flags=0, gamesnd_id warp_open_sound=gamesnd_id(), gamesnd_id warp_close_sound=gamesnd_id(), float warp_open_duration=-1.0f, float warp_close_duration=-1.0f);
void fireball_render_plane(int plane);
int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_obj, float size, bool reverse=false, vec3d *velocity=nullptr, float warp_lifetime=0.0f, int ship_class=-1, matrix *orient=nullptr, int low_res=0, int extra_flags=0, gamesnd_id warp_open_sound=gamesnd_id(), gamesnd_id warp_close_sound=gamesnd_id(), float warp_open_duration=-1.0f, float warp_close_duration=-1.0f);
void fireball_close();
// Returns 1 if you can remove this fireball
@@ -137,4 +137,6 @@ float fireball_wormhole_intensity( fireball *fb );
// Goober5000
extern int Knossos_warp_ani_used;
extern bool Fireball_use_3d_warp;
#endif /* _FIREBALLS_H */
+2 -2
View File
@@ -100,7 +100,7 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
}
}
if ( (warp_model_id >= 0) && (warp_3d || Cmdline_3dwarp) ) {
if ( (warp_model_id >= 0) && (warp_3d || Fireball_use_3d_warp) ) {
model_render_params render_info;
float scale = radius / 25.0f;
@@ -137,7 +137,7 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
vm_vec_scale_add2( &vecs[3], &orient->vec.rvec, -radius );
vm_vec_scale_add2( &vecs[3], &orient->vec.fvec, Grid_depth );
// vm_vec_scale_add( &vecs[4], ¢er, &orient->vec.fvec, -Grid_depth );
// vm_vec_scale_add( &vecs[4], center, &orient->vec.fvec, -Grid_depth );
vecs[4] = center;
verts[0].texture_position.u = 0.01f;
+2 -2
View File
@@ -1678,7 +1678,7 @@ void fs2netd_spew_table_checksums(const char *outfile)
char description[512] = { 0 };
char filename[65] = { 0 };
size_t offset = 0;
char *p = NULL;
const char *p = nullptr;
if ( Table_valid_status.empty() ) {
return;
@@ -1693,7 +1693,7 @@ void fs2netd_spew_table_checksums(const char *outfile)
return;
}
p = Cmdline_spew_table_crcs;
p = Cmdline_spew_table_crcs.c_str();
while (*p && (offset < sizeof(description))) {
if (*p == '"' && offset < sizeof(description)-1) {
-49
View File
@@ -109,38 +109,6 @@ static int Gameplay_help_inited = 0;
static int Current_help_page;
// generate a line for the on-line help for a control item with specified id
// input: id => index for control item within Control_config[]
// buf => buffer with enough space to hold ouput string
const char *gameplay_help_control_text(int id, char *buf)
{
int has_key=0, has_joy=0;
config_item *ci;
ci = &Control_config[id];
if ( ci->key_id >= 0 ) {
strcpy(buf, textify_scancode(ci->key_id));
has_key=1;
}
if ( ci->joy_id >= 0 ) {
if ( has_key ) {
strcat(buf, XSTR( ", ", 129));
}
strcat(buf, Joy_button_text[ci->joy_id]);
has_joy=1;
}
if ( !has_key && !has_joy ) {
strcpy(buf, XSTR( "no binding", 130));
}
strcat(buf, XSTR( " - ", 131));
strcat(buf, ci->text);
return buf;
}
void gameplay_help_blit_control_line(int x, int y, int id)
{
@@ -824,20 +792,3 @@ void gameplay_help_do_frame(float /*frametime*/)
gameplay_help_draw_text();
gr_flip();
}
// called once when leaving the gameplay help state
void gameplay_help_close()
{
if ( Gameplay_help_inited ) {
if (Background_bitmap >= 0) {
bm_release(Background_bitmap);
}
Ui_window.destroy();
common_free_interface_palette(); // restore game palette
game_flush();
}
Gameplay_help_inited = 0;
}
-1
View File
@@ -13,7 +13,6 @@
#define __GAMEPLAY_HELP_H__
void gameplay_help_init();
void gameplay_help_close();
void gameplay_help_do_frame(float frametime);
#endif
-23
View File
@@ -350,29 +350,6 @@ void gameseq_pop_state()
}
// gameseq_pop_and_discard_state() is used to remove a state that was pushed onto the stack, but
// will never need to be popped. An example of this is entering a state that may require returning
// to the previous state (then you would call gameseq_pop_state). Or you may simply continue to
// another part of the game, to avoid filling up the stack with states that may never be popped, you
// call this function to discard the top of the gs.
//
void gameseq_pop_and_discard_state()
{
if (gs_current_stack > 0 ) {
gs_current_stack--;
}
}
// Returns the last state pushed on stack
int gameseq_get_pushed_state()
{
if (gs_current_stack >= 1) {
return gs[gs_current_stack-1].current_state;
} else
return -1;
}
// gameseq_process_events gets called every time through high level loops
// (i.e. game loops, main menu loop). Function is responsible for pulling
// game sequence events off the queue and changing the state when necessary.
-3
View File
@@ -181,11 +181,8 @@ int gameseq_get_event( void );
void gameseq_set_state(int new_state, int override = 0);
void gameseq_push_state( int new_state );
void gameseq_pop_state( void );
int gameseq_get_pushed_state();
int gameseq_get_depth();
int gameseq_get_previous_state();
void gameseq_pop_and_discard_state(void);
// Called by the sequencing code when things happen.
void game_process_event(int current_state, int event);
+1 -97
View File
@@ -57,11 +57,8 @@ SOUNDTRACK_INFO Soundtracks[MAX_SOUNDTRACKS];
int Num_soundtracks;
int Current_soundtrack_num; // Active soundtrack for the current mission.. index into Soundtracks[]
#define PATTERN_DELAY 1000 // in ms
int Current_pattern = -1; // currently playing part of track
int Pending_pattern = -1;
int Pattern_timer_id = 0;
int Current_nrml = SONG_NRML_1;
// File Globals
static int Num_enemy_arrivals;
@@ -240,7 +237,6 @@ static int Event_music_begun = FALSE;
// forward function declarations
int hostile_ships_present();
int hostile_ships_to_arrive();
extern int hud_target_invalid_awacs(object *objp);
// Holds file names of spooled music that is played at menus, briefings, credits etc.
@@ -544,7 +540,6 @@ void event_music_level_init(int force_soundtrack)
return;
Current_pattern = -1;
Current_nrml = SONG_NRML_1;
if (Event_music_inited == FALSE)
return;
@@ -556,15 +551,6 @@ void event_music_level_init(int force_soundtrack)
if (Current_soundtrack_num < 0)
{
return;
/*
// okay, assign a random soundtrack if one exists
if ( Num_soundtracks > 0 ) {
Current_soundtrack_num = rand()%Num_soundtracks;
nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Picking random event music soundtrack: %s\n", Soundtracks[Current_soundtrack_num].name));
} else {
return;
}
*/
}
Assert(Current_soundtrack_num >= 0 && Current_soundtrack_num < Num_soundtracks);
@@ -631,9 +617,7 @@ void event_music_level_init(int force_soundtrack)
// -------------------------------------------------------------------------------------------------
// event_music_first_pattern()
//
// Picks the first pattern to play, based on whether the battle has started. Delay start
// by PATTERN_DELAY
//
// Picks the first pattern to play, based on whether the battle has started.
void event_music_first_pattern()
{
if ( Event_music_inited == FALSE ) {
@@ -1520,59 +1504,6 @@ void event_music_start_default()
}
// -------------------------------------------------------------------------------------------------
// event_music_pause()
//
// Stop any playing pattern, but don't rewind.
//
void event_music_pause()
{
if ( Event_music_enabled == FALSE ) {
nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Requested a song switch when event music is not enabled\n"));
return;
}
if ( Event_music_level_inited == FALSE ) {
nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Event music is not enabled\n"));
return;
}
if (Current_pattern == -1)
return;
Assert( Current_pattern >= 0 && Current_pattern < MAX_PATTERNS );
if ( audiostream_is_playing(Patterns[Current_pattern].handle) ) {
audiostream_stop(Patterns[Current_pattern].handle, 0); // stop current and don't rewind
}
}
// -------------------------------------------------------------------------------------------------
// event_music_unpause()
//
// Start the Current_pattern if it is paused.
//
void event_music_unpause()
{
if ( Event_music_enabled == FALSE ) {
nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Requested a song switch when event music is not enabled\n"));
return;
}
if ( Event_music_level_inited == FALSE ) {
nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Event music is not enabled\n"));
return;
}
if (Current_pattern == -1)
return;
Assert( Current_pattern >= 0 && Current_pattern < MAX_PATTERNS );
if ( audiostream_is_paused(Patterns[Current_pattern].handle) == TRUE ) {
audiostream_play(Patterns[Current_pattern].handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
audiostream_set_sample_cutoff(Patterns[Current_pattern].handle, fl2i(Patterns[Current_pattern].num_measures * Patterns[Current_pattern].samples_per_measure) );
}
}
// -------------------------------------------------------------------------------------------------
// event_music_set_volume_all()
//
@@ -1628,33 +1559,6 @@ int hostile_ships_present()
return 0;
}
// ----------------------------------------------------------------------
// hostile_ships_to_arrive()
//
// Determine if there are any non-friendly ships yet to arrive
//
// NOTE: neutral ships are considered hostile for the purpose of event music
//
int hostile_ships_to_arrive()
{
p_object *p_objp;
for (p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp))
{
// check if ship can arrive
if (p_objp->flags[Mission::Parse_Object_Flags::SF_Cannot_arrive])
continue;
// check if ship is enemy ship (we attack it)
if (!(iff_x_attacks_y(Player_ship->team, p_objp->team)))
continue;
return 1;
}
return 0;
}
// ----------------------------------------------------------------
// event_music_get_info()
//
-2
View File
@@ -102,8 +102,6 @@ void event_music_level_close();
void event_music_do_frame();
void event_music_disable();
void event_music_enable();
void event_music_pause();
void event_music_unpause();
void event_music_set_volume_all(float volume);
void event_music_parse_musictbl(const char *filename);
void event_music_change_pattern(int new_pattern);
+1 -1
View File
@@ -246,7 +246,7 @@ enum class GameSounds {
/**
* Interface sounds
*/
enum InterfaceSounds {
enum class InterfaceSounds {
IFACE_MOUSE_CLICK =0, //!< mouse click
ICON_PICKUP =1, //!< pick up a ship icon (Empty in Retail)
ICON_DROP_ON_WING =2, //!< drop a ship icon on a wing slot
+9
View File
@@ -125,8 +125,17 @@ class flagset {
void from_u64(std::uint64_t num) { values = (unsigned long) num; }
std::uint64_t to_u64() const { return (std::uint64_t) values.to_ulong(); }
size_t hash() const { return std::hash<std::bitset<SIZE>>()(values); }
};
namespace std {
template <typename T, size_t N>
struct hash<::flagset<T, N>> {
size_t operator()(const ::flagset<T, N>& val) { return val.hash(); }
};
} // namespace std
#define FLAG_LIST(Type) enum class Type : size_t
template<typename TEnum, size_t SIZE>
+41 -7
View File
@@ -3,15 +3,15 @@
/* SCP_vm_allocator - maintained by portej05 (i.e. please don't patch this one yourself!) */
#include <vector>
#include <deque>
#include <list>
#include <map>
#include <string>
#include <sstream>
#include <queue>
#include <deque>
#include <unordered_map>
#include <sstream>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <vector>
template< typename T >
using SCP_vector = std::vector< T, std::allocator< T > >;
@@ -35,7 +35,41 @@ using SCP_queue = std::queue< T, std::deque< T, std::allocator< T > > >;
template< typename T >
using SCP_deque = std::deque< T, std::allocator< T > >;
template< typename Key, typename T, typename Hash = std::hash<Key>, typename KeyEqual = std::equal_to<Key> >
using SCP_unordered_map = std::unordered_map< Key, T, Hash, KeyEqual, std::allocator< std::pair<const Key, T> > >;
#if __cplusplus < 201402L
template <class T, bool>
struct enum_hasher_util {
inline size_t operator()(const T& elem) { return std::hash<T>()(elem); }
};
template <class T>
struct enum_hasher_util<T, true> {
inline size_t operator()(const T& elem)
{
typedef typename std::underlying_type<T>::type enumType;
return std::hash<enumType>()(static_cast<enumType>(elem));
}
};
/**
* @brief An enum class compatible hashing class
*
* This is the same as std::hash except that is can handle enum classes properly using their underlying type. This is
* only required for C++ < 14 since after that the standard mandates that enum classes should be hashable.
*
* @tparam T The type that should be hashed
*/
template <class T>
struct SCP_hash {
inline size_t operator()(const T& elem) const { return enum_hasher_util<T, std::is_enum<T>::value>()(elem); }
};
#else
// No need for the special hash class so just use the standard hash
template <typename T>
using SCP_hash = std::hash<T>;
#endif
template <typename Key, typename T, typename Hash = SCP_hash<Key>, typename KeyEqual = std::equal_to<Key>>
using SCP_unordered_map = std::unordered_map<Key, T, Hash, KeyEqual, std::allocator<std::pair<const Key, T>>>;
#endif // _VMALLOCATOR_H_INCLUDED_
+294 -51
View File
@@ -36,6 +36,8 @@
#include "graphics/util/UniformBufferManager.h"
#include "io/keycontrol.h" // m!m
#include "io/timer.h"
#include "libs/jansson.h"
#include "options/Option.h"
#include "osapi/osapi.h"
#include "parse/parselo.h"
#include "popup/popup.h"
@@ -103,6 +105,239 @@ float Gr_save_menu_zoomed_offset_X = 0.0f, Gr_save_menu_zoomed_offset_Y = 0.0f;
bool Save_custom_screen_size;
static int videodisplay_deserializer(const json_t* value)
{
int id;
json_error_t err;
if (json_unpack_ex((json_t*)value, &err, 0, "i", &id) != 0) {
throw json_exception(err);
}
return id;
}
static json_t* videodisplay_serializer(int value) { return json_pack("i", value); }
static SCP_vector<int> videodisplay_enumerator()
{
SCP_vector<int> vals;
for (int i = 0; i < SDL_GetNumVideoDisplays(); ++i) {
vals.push_back(i);
}
return vals;
}
static SCP_string videodisplay_display(int id)
{
SCP_string out;
sprintf(out, "(%d) %s", id + 1, SDL_GetDisplayName(id));
return out;
}
static bool videodisplay_change(int display, bool initial)
{
if (initial) {
return false;
}
auto window = os::getSDLMainWindow();
if (window == nullptr) {
return false;
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display), SDL_WINDOWPOS_CENTERED_DISPLAY(display));
return true;
}
static auto VideoDisplayOption =
options::OptionBuilder<int>("Graphics.Display", "Primary display", "The display used for rendering.")
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.deserializer(videodisplay_deserializer)
.serializer(videodisplay_serializer)
.enumerator(videodisplay_enumerator)
.display(videodisplay_display)
.default_val(0)
.change_listener(videodisplay_change)
.importance(99)
.finish();
struct ResolutionInfo {
uint32_t width = 0;
uint32_t height = 0;
ResolutionInfo(uint32_t _width, uint32_t _height) : width(_width), height(_height) {}
ResolutionInfo() = default;
friend bool operator==(const ResolutionInfo& lhs, const ResolutionInfo& rhs)
{
return lhs.width == rhs.width && lhs.height == rhs.height;
}
friend bool operator!=(const ResolutionInfo& lhs, const ResolutionInfo& rhs) { return !(rhs == lhs); }
};
static ResolutionInfo resolution_deserializer(const json_t* el)
{
int width;
int height;
json_error_t err;
if (json_unpack_ex((json_t*)el, &err, 0, "{s:i, s:i}", "width", &width, "height", &height) != 0) {
throw json_exception(err);
}
return {(uint32_t)width, (uint32_t)height};
}
static json_t* resolution_serializer(const ResolutionInfo& value)
{
return json_pack("{s:i, s:i}", "width", value.width, "height", value.height);
}
static SCP_vector<ResolutionInfo> resolution_enumerator()
{
SCP_vector<ResolutionInfo> out;
auto display = VideoDisplayOption->getValue();
for (auto i = 0; i < SDL_GetNumDisplayModes(display); ++i) {
SDL_DisplayMode mode;
if (SDL_GetDisplayMode(display, i, &mode) != 0) {
continue;
}
auto res = ResolutionInfo(mode.w, mode.h);
if (std::find(out.begin(), out.end(), res) == out.end()) {
out.push_back(res);
}
}
return out;
}
static SCP_string resolution_display(const ResolutionInfo& info)
{
SCP_string str;
sprintf(str, "%dx%d", info.width, info.height);
return str;
}
static ResolutionInfo resolution_default()
{
SDL_DisplayMode mode;
if (SDL_GetDesktopDisplayMode(VideoDisplayOption->getValue(), &mode) != 0) {
return {};
}
return ResolutionInfo(mode.w, mode.h);
}
static bool resolution_change(const ResolutionInfo& /*info*/, bool initial)
{
if (initial) {
return false;
}
return false;
// The following code should change the size of the window properly but FSO currently can't handle that
/*
auto window = os::getSDLMainWindow();
if (window == nullptr) {
return;
}
auto display = VideoDisplayOption->getValue();
if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
SDL_DisplayMode target;
target.w = info.width;
target.h = info.height;
target.format = 0; // don't care
target.refresh_rate = 0; // don't care
target.driverdata = 0; // initialize to 0
SDL_DisplayMode closest;
if (SDL_GetClosestDisplayMode(display, &target, &closest) == nullptr) {
return;
}
SDL_SetWindowDisplayMode(window, &closest);
} else {
SDL_SetWindowSize(window, info.width, info.height);
// Recenter the window
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display), SDL_WINDOWPOS_CENTERED_DISPLAY(display));
}
*/
}
static auto ResolutionOption =
options::OptionBuilder<ResolutionInfo>("Graphics.Resolution", "Resolution", "The rendering resolution.")
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.deserializer(resolution_deserializer)
.serializer(resolution_serializer)
.enumerator(resolution_enumerator)
.display(resolution_display)
.default_func(resolution_default)
.change_listener(resolution_change)
.importance(100)
.finish();
bool Gr_enable_soft_particles = false;
static auto SoftParticlesOption = options::OptionBuilder<bool>("Graphics.SoftParticles", "Soft Particles",
"Enable or disable soft particle rendering.")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(true)
.bind_to_once(&Gr_enable_soft_particles)
.importance(68)
.finish();
flagset<FramebufferEffects> Gr_framebuffer_effects;
static auto FramebufferEffectsOption =
options::OptionBuilder<flagset<FramebufferEffects>>(
"Graphics.FramebufferEffects", "Framebuffer effects",
"Controls which framebuffer effects will be applied to the scene.")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{{}, "None"},
{{FramebufferEffects::Shockwaves}, "Shockwaves"},
{{FramebufferEffects::Thrusters}, "Thrusters"},
{{FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters}, "All"}})
.default_val({FramebufferEffects::Shockwaves, FramebufferEffects::Thrusters})
.bind_to_once(&Gr_framebuffer_effects)
.importance(77)
.finish();
AntiAliasMode Gr_aa_mode = AntiAliasMode::None;
AntiAliasMode Gr_aa_mode_last_frame = AntiAliasMode::None;
static auto AAOption = options::OptionBuilder<AntiAliasMode>("Graphics.AAMode", "Anti Aliasing",
"Controls the anti aliasing mode of the engine.")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.values({{AntiAliasMode::None, "None"},
{AntiAliasMode::FXAA_Low, "FXAA Low"},
{AntiAliasMode::FXAA_Medium, "FXAA Medium"},
{AntiAliasMode::FXAA_High, "FXAA High"}})
.default_val(AntiAliasMode::None)
.bind_to(&Gr_aa_mode)
.importance(79)
.finish();
bool gr_is_fxaa_mode(AntiAliasMode mode)
{
return mode == AntiAliasMode::FXAA_Low || mode == AntiAliasMode::FXAA_Medium || mode == AntiAliasMode::FXAA_High;
}
bool Gr_post_processing_enabled = false;
static auto PostProcessOption =
options::OptionBuilder<bool>("Graphis.PostProcessing", "Post processing",
"Controls whether post processing is enabled in the engine")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(false)
.bind_to_once(&Gr_post_processing_enabled)
.importance(69)
.finish();
bool Gr_enable_vsync = true;
static auto VSyncOption = options::OptionBuilder<bool>("Graphis.VSync", "Vertical Sync",
"Controls how the engine does vertical synchronization")
.category("Graphics")
.level(options::ExpertLevel::Advanced)
.default_val(true)
.bind_to_once(&Gr_enable_vsync)
.importance(70)
.finish();
// Forward definitions
static void uniform_buffer_managers_init();
static void uniform_buffer_managers_deinit();
@@ -953,75 +1188,83 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
}
}
// We cannot continue without this, quit, but try to help the user out first
ptr = os_config_read_string(NULL, NOX("VideocardFs2open"), NULL);
if (Using_in_game_options) {
auto res = ResolutionOption->getValue();
width = res.width;
height = res.height;
} else {
// We cannot continue without this, quit, but try to help the user out first
ptr = os_config_read_string(nullptr, NOX("VideocardFs2open"), nullptr);
// if we don't have a config string then construct one, using OpenGL 1024x768 32-bit as the default
if (ptr == NULL) {
// If we don't have a display mode, use SDL to get default settings
// We need to initialize SDL to do this
// if we don't have a config string then construct one, using OpenGL 1024x768 32-bit as the default
if (ptr == nullptr) {
// If we don't have a display mode, use SDL to get default settings
// We need to initialize SDL to do this
if (SDL_InitSubSystem(SDL_INIT_VIDEO) == 0)
{
int display = static_cast<int>(os_config_read_uint("Video", "Display", 0));
SDL_DisplayMode displayMode;
if (SDL_GetDesktopDisplayMode(display, &displayMode) == 0)
if (SDL_InitSubSystem(SDL_INIT_VIDEO) == 0)
{
width = displayMode.w;
height = displayMode.h;
int sdlBits = SDL_BITSPERPIXEL(displayMode.format);
auto display = static_cast<int>(os_config_read_uint("Video", "Display", 0));
SDL_DisplayMode displayMode;
if (SDL_GetDesktopDisplayMode(display, &displayMode) == 0)
{
width = displayMode.w;
height = displayMode.h;
int sdlBits = SDL_BITSPERPIXEL(displayMode.format);
if (SDL_ISPIXELFORMAT_ALPHA(displayMode.format))
{
depth = sdlBits;
}
else
{
// Fix a few values
if (sdlBits == 24)
{
depth = 32;
}
else if (sdlBits == 15)
{
depth = 16;
}
else
if (SDL_ISPIXELFORMAT_ALPHA(displayMode.format))
{
depth = sdlBits;
}
else
{
// Fix a few values
if (sdlBits == 24)
{
depth = 32;
}
else if (sdlBits == 15)
{
depth = 16;
}
else
{
depth = sdlBits;
}
}
SCP_string videomode;
sprintf(videomode, "OGL -(%dx%d)x%d bit", width, height, depth);
os_config_write_string(nullptr, NOX("VideocardFs2open"), videomode.c_str());
}
}
} else {
Assert(ptr != nullptr);
SCP_string videomode;
sprintf(videomode, "OGL -(%dx%d)x%d bit", width, height, depth);
os_config_write_string(NULL, NOX("VideocardFs2open"), videomode.c_str());
// NOTE: The "ptr+5" is to skip over the initial "????-" in the video string.
// If the format of that string changes you'll have to change this too!!!
if (sscanf(ptr + 5, "(%dx%d)x%d ", &width, &height, &depth) != 3) {
Error(LOCATION, "Can't understand 'VideocardFs2open' config entry!");
}
}
} else {
Assert(ptr != NULL);
// NOTE: The "ptr+5" is to skip over the initial "????-" in the video string.
// If the format of that string changes you'll have to change this too!!!
if (sscanf(ptr + 5, "(%dx%d)x%d ", &width, &height, &depth) != 3) {
Error(LOCATION, "Can't understand 'VideocardFs2open' config entry!");
if (!Cmdline_res.empty()) {
int tmp_width = 0;
int tmp_height = 0;
if ( sscanf(Cmdline_res.c_str(), "%dx%d", &tmp_width, &tmp_height) == 2 ) {
width = tmp_width;
height = tmp_height;
}
}
}
if (Cmdline_res != NULL) {
int tmp_width = 0;
int tmp_height = 0;
if ( sscanf(Cmdline_res, "%dx%d", &tmp_width, &tmp_height) == 2 ) {
width = tmp_width;
height = tmp_height;
}
Gr_enable_soft_particles = Cmdline_softparticles != 0;
}
if (Cmdline_center_res != NULL) {
if (!Cmdline_center_res.empty()) {
int tmp_center_width = 0;
int tmp_center_height = 0;
if ( (sscanf(Cmdline_center_res, "%dx%d", &tmp_center_width, &tmp_center_height) == 2) && (tmp_center_width > 0) && (tmp_center_height > 0) ) {
if ( (sscanf(Cmdline_center_res.c_str(), "%dx%d", &tmp_center_width, &tmp_center_height) == 2) && (tmp_center_width > 0) && (tmp_center_height > 0) ) {
center_aspect_ratio = (float)tmp_center_width / (float)tmp_center_height;
}
}
+25 -4
View File
@@ -12,15 +12,15 @@
#ifndef _GRAPHICS_H
#define _GRAPHICS_H
#include "graphics/grinternal.h"
#include "osapi/osapi.h"
#include "bmpman/bmpman.h"
#include "cfile/cfile.h"
#include "globalincs/flagset.h"
#include "globalincs/pstypes.h"
#include "graphics/grinternal.h"
#include "graphics/tmapper.h"
#include "cfile/cfile.h"
#include "math/vecmat.h"
#include "io/cursor.h"
#include "math/vecmat.h"
#include "osapi/osapi.h"
// Forward definition
namespace graphics {
@@ -40,6 +40,26 @@ extern int Gr_inited;
extern int gr_zbuffering, gr_zbuffering_mode;
extern int gr_global_zbuffering;
extern bool Gr_enable_soft_particles;
FLAG_LIST(FramebufferEffects){Thrusters = 0, Shockwaves, NUM_VALUES};
extern flagset<FramebufferEffects> Gr_framebuffer_effects;
enum class AntiAliasMode {
None,
FXAA_Low,
FXAA_Medium,
FXAA_High
};
extern AntiAliasMode Gr_aa_mode;
extern AntiAliasMode Gr_aa_mode_last_frame;
bool gr_is_fxaa_mode(AntiAliasMode mode);
extern bool Gr_post_processing_enabled;
extern bool Gr_enable_vsync;
class material;
class model_material;
class particle_material;
@@ -294,6 +314,7 @@ typedef enum gr_capability {
enum class gr_property {
UNIFORM_BUFFER_OFFSET_ALIGNMENT,
UNIFORM_BUFFER_MAX_SIZE,
MAX_ANISOTROPY
};
// stencil buffering stuff
+67 -69
View File
@@ -667,7 +667,7 @@ float batch_add_laser(int texture, vec3d *p0, float width1, vec3d *p1, float wid
batch_item *item = NULL;
SCP_map<int, batch_item>::iterator it = geometry_map.find(texture);
if ( !geometry_map.empty() && it != geometry_map.end() ) {
if (it != geometry_map.end()) {
item = &it->second;
} else {
item = &geometry_map[texture];
@@ -690,12 +690,12 @@ int batch_add_bitmap(int texture, int tmap_flags, vertex *pnt, int orient, float
return 1;
}
if ( tmap_flags & TMAP_FLAG_SOFT_QUAD && !Cmdline_softparticles ) {
if ( tmap_flags & TMAP_FLAG_SOFT_QUAD && !Gr_enable_soft_particles ) {
// don't render this as a soft particle if we don't support soft particles
tmap_flags &= ~(TMAP_FLAG_SOFT_QUAD);
}
if ( Cmdline_softparticles && !Cmdline_no_geo_sdr_effects && (tmap_flags & TMAP_FLAG_VERTEX_GEN) ) {
if ( Gr_enable_soft_particles && !Cmdline_no_geo_sdr_effects && (tmap_flags & TMAP_FLAG_VERTEX_GEN) ) {
geometry_batch_add_bitmap(texture, tmap_flags, pnt, orient, rad, alpha, depth);
return 0;
} else if ( tmap_flags & TMAP_FLAG_VERTEX_GEN ) {
@@ -706,7 +706,7 @@ int batch_add_bitmap(int texture, int tmap_flags, vertex *pnt, int orient, float
SCP_map<int, batch_item>::iterator it = geometry_map.find(texture);
if ( !geometry_map.empty() && it != geometry_map.end() ) {
if (it != geometry_map.end()) {
item = &it->second;
} else {
item = &geometry_map[texture];
@@ -735,7 +735,7 @@ int geometry_batch_add_bitmap(int texture, int tmap_flags, vertex *pnt, int orie
g_sdr_batch_item *item = NULL;
SCP_map<int, g_sdr_batch_item>::iterator it = geometry_shader_map.find(texture);
if ( !geometry_shader_map.empty() && it != geometry_shader_map.end() ) {
if (it != geometry_shader_map.end()) {
item = &it->second;
} else {
item = &geometry_shader_map[texture];
@@ -759,7 +759,7 @@ int batch_add_bitmap_rotated(int texture, int tmap_flags, vertex *pnt, float ang
return 1;
}
if ( tmap_flags & TMAP_FLAG_SOFT_QUAD && !Cmdline_softparticles ) {
if ( tmap_flags & TMAP_FLAG_SOFT_QUAD && !Gr_enable_soft_particles ) {
// don't render this as a soft particle if we don't support soft particles
tmap_flags &= ~(TMAP_FLAG_SOFT_QUAD);
}
@@ -768,7 +768,7 @@ int batch_add_bitmap_rotated(int texture, int tmap_flags, vertex *pnt, float ang
SCP_map<int, batch_item>::iterator it = geometry_map.find(texture);
if ( !geometry_map.empty() && it != geometry_map.end() ) {
if (it != geometry_map.end()) {
item = &it->second;
} else {
item = &geometry_map[texture];
@@ -798,7 +798,7 @@ int batch_add_tri(int texture, int tmap_flags, vertex *verts, float alpha)
SCP_map<int, batch_item>::iterator it = geometry_map.find(texture);
if ( !geometry_map.empty() && it != geometry_map.end() ) {
if (it != geometry_map.end()) {
item = &it->second;
} else {
item = &geometry_map[texture];
@@ -828,7 +828,7 @@ int batch_add_quad(int texture, int tmap_flags, vertex *verts, float alpha)
SCP_map<int, batch_item>::iterator it = geometry_map.find(texture);
if ( !geometry_map.empty() && it != geometry_map.end() ) {
if (it != geometry_map.end()) {
item = &it->second;
} else {
item = &geometry_map[texture];
@@ -908,7 +908,7 @@ int batch_add_polygon(int texture, int tmap_flags, vec3d *pos, matrix *orient, f
SCP_map<int, batch_item>::iterator it = geometry_map.find(texture);
if ( !geometry_map.empty() && it != geometry_map.end() ) {
if (it != geometry_map.end()) {
item = &it->second;
} else {
item = &geometry_map[texture];
@@ -938,7 +938,7 @@ int batch_add_beam(int texture, int tmap_flags, vec3d *start, vec3d *end, float
SCP_map<int, batch_item>::iterator it = geometry_map.find(texture);
if ( !geometry_map.empty() && it != geometry_map.end() ) {
if (it != geometry_map.end()) {
item = &it->second;
} else {
item = &geometry_map[texture];
@@ -959,102 +959,102 @@ int batch_add_beam(int texture, int tmap_flags, vec3d *start, vec3d *end, float
void batch_render_lasers(int buffer_handle)
{
for (SCP_map<int, batch_item>::iterator bi = geometry_map.begin(); bi != geometry_map.end(); ++bi) {
for (auto &bi : geometry_map) {
if ( !bi->second.laser )
if ( !bi.second.laser )
continue;
if ( !bi->second.batch.need_to_render() )
if ( !bi.second.batch.need_to_render() )
continue;
Assert( bi->second.texture >= 0 );
gr_set_bitmap(bi->second.texture, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 0.99999f);
Assert( bi.second.texture >= 0 );
gr_set_bitmap(bi.second.texture, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 0.99999f);
if ( buffer_handle >= 0 ) {
bi->second.batch.render_buffer(buffer_handle, TMAP_FLAG_TEXTURED | TMAP_FLAG_XPARENT | TMAP_HTL_3D_UNLIT | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_FLAG_CORRECT | TMAP_FLAG_EMISSIVE);
bi.second.batch.render_buffer(buffer_handle, TMAP_FLAG_TEXTURED | TMAP_FLAG_XPARENT | TMAP_HTL_3D_UNLIT | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_FLAG_CORRECT | TMAP_FLAG_EMISSIVE);
} else {
bi->second.batch.render(TMAP_FLAG_TEXTURED | TMAP_FLAG_XPARENT | TMAP_HTL_3D_UNLIT | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_FLAG_CORRECT | TMAP_FLAG_EMISSIVE);
bi.second.batch.render(TMAP_FLAG_TEXTURED | TMAP_FLAG_XPARENT | TMAP_HTL_3D_UNLIT | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_FLAG_CORRECT | TMAP_FLAG_EMISSIVE);
}
}
}
void batch_load_buffer_lasers(effect_vertex* buffer, int *n_verts)
{
for (SCP_map<int, batch_item>::iterator bi = geometry_map.begin(); bi != geometry_map.end(); ++bi) {
for (auto &bi : geometry_map) {
if ( !bi->second.laser )
if ( !bi.second.laser )
continue;
if ( !bi->second.batch.need_to_render() )
if ( !bi.second.batch.need_to_render() )
continue;
Assert( bi->second.texture >= 0 );
bi->second.batch.load_buffer(buffer, n_verts);
Assert( bi.second.texture >= 0 );
bi.second.batch.load_buffer(buffer, n_verts);
}
}
void batch_render_geometry_map_bitmaps(int buffer_handle)
{
for (SCP_map<int, batch_item>::iterator bi = geometry_map.begin(); bi != geometry_map.end(); ++bi) {
for (auto &bi : geometry_map) {
if ( bi->second.laser )
if ( bi.second.laser )
continue;
if ( !bi->second.batch.need_to_render() )
if ( !bi.second.batch.need_to_render() )
continue;
Assert( bi->second.texture >= 0 );
gr_set_bitmap(bi->second.texture, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, bi->second.alpha);
Assert( bi.second.texture >= 0 );
gr_set_bitmap(bi.second.texture, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, bi.second.alpha);
if ( buffer_handle >= 0 ) {
bi->second.batch.render_buffer(buffer_handle, bi->second.tmap_flags);
bi.second.batch.render_buffer(buffer_handle, bi.second.tmap_flags);
} else {
bi->second.batch.render( bi->second.tmap_flags);
bi.second.batch.render( bi.second.tmap_flags);
}
}
}
void batch_render_geometry_shader_map_bitmaps(int buffer_handle)
{
for (SCP_map<int, g_sdr_batch_item>::iterator bi = geometry_shader_map.begin(); bi != geometry_shader_map.end(); ++bi) {
for (auto &bi : geometry_shader_map) {
if ( bi->second.laser )
if ( bi.second.laser )
continue;
if ( !bi->second.batch.need_to_render() )
if ( !bi.second.batch.need_to_render() )
continue;
Assert( bi->second.texture >= 0 );
gr_set_bitmap(bi->second.texture, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, bi->second.alpha);
bi->second.batch.render_buffer(buffer_handle, bi->second.tmap_flags);
Assert( bi.second.texture >= 0 );
gr_set_bitmap(bi.second.texture, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, bi.second.alpha);
bi.second.batch.render_buffer(buffer_handle, bi.second.tmap_flags);
}
}
void batch_load_buffer_geometry_map_bitmaps(effect_vertex* buffer, int *n_verts)
{
for (SCP_map<int, batch_item>::iterator bi = geometry_map.begin(); bi != geometry_map.end(); ++bi) {
for (auto &bi : geometry_map) {
if ( bi->second.laser )
if ( bi.second.laser )
continue;
if ( !bi->second.batch.need_to_render() )
if ( !bi.second.batch.need_to_render() )
continue;
Assert( bi->second.texture >= 0 );
bi->second.batch.load_buffer(buffer, n_verts);
Assert( bi.second.texture >= 0 );
bi.second.batch.load_buffer(buffer, n_verts);
}
}
void batch_load_buffer_geometry_shader_map_bitmaps(particle_pnt* buffer, size_t *n_verts)
{
for (SCP_map<int, g_sdr_batch_item>::iterator bi = geometry_shader_map.begin(); bi != geometry_shader_map.end(); ++bi) {
for (auto &bi : geometry_shader_map) {
if ( bi->second.laser )
if ( bi.second.laser )
continue;
if ( !bi->second.batch.need_to_render() )
if ( !bi.second.batch.need_to_render() )
continue;
Assert( bi->second.texture >= 0 );
bi->second.batch.load_buffer(buffer, n_verts);
Assert( bi.second.texture >= 0 );
bi.second.batch.load_buffer(buffer, n_verts);
}
}
@@ -1145,7 +1145,7 @@ int distortion_add_bitmap_rotated(int texture, int tmap_flags, vertex *pnt, floa
SCP_map<int, batch_item>::iterator it = distortion_map.find(texture);
if ( !distortion_map.empty() && it != distortion_map.end() ) {
if (it != distortion_map.end()) {
item = &it->second;
} else {
item = &distortion_map[texture];
@@ -1175,7 +1175,7 @@ int distortion_add_beam(int texture, int tmap_flags, vec3d *start, vec3d *end, f
SCP_map<int, batch_item>::iterator it = distortion_map.find(texture);
if ( !distortion_map.empty() && it != distortion_map.end() ) {
if (it != distortion_map.end()) {
item = &it->second;
} else {
item = &distortion_map[texture];
@@ -1196,54 +1196,53 @@ int distortion_add_beam(int texture, int tmap_flags, vec3d *start, vec3d *end, f
void batch_render_distortion_map_bitmaps(int buffer_handle)
{
for (SCP_map<int,batch_item>::iterator bi = distortion_map.begin(); bi != distortion_map.end(); ++bi) {
for (auto &bi : distortion_map) {
if ( bi->second.laser )
if ( bi.second.laser )
continue;
if ( !bi->second.batch.need_to_render() )
if ( !bi.second.batch.need_to_render() )
continue;
Assert( bi->second.texture >= 0 );
gr_set_bitmap(bi->second.texture, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, bi->second.alpha);
Assert( bi.second.texture >= 0 );
gr_set_bitmap(bi.second.texture, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, bi.second.alpha);
if ( buffer_handle >= 0 ) {
bi->second.batch.render_buffer(buffer_handle, bi->second.tmap_flags);
bi.second.batch.render_buffer(buffer_handle, bi.second.tmap_flags);
} else {
bi->second.batch.render( bi->second.tmap_flags);
bi.second.batch.render( bi.second.tmap_flags);
}
}
}
void batch_load_buffer_distortion_map_bitmaps(effect_vertex* buffer, int *n_verts)
{
for (SCP_map<int, batch_item>::iterator bi = distortion_map.begin(); bi != distortion_map.end(); ++bi) {
for (auto &bi : distortion_map) {
if ( bi->second.laser )
if ( bi.second.laser )
continue;
if ( !bi->second.batch.need_to_render() )
if ( !bi.second.batch.need_to_render() )
continue;
Assert( bi->second.texture >= 0 );
bi->second.batch.load_buffer(buffer, n_verts);
Assert( bi.second.texture >= 0 );
bi.second.batch.load_buffer(buffer, n_verts);
}
}
int batch_get_size()
{
int n_to_render = 0;
SCP_map<int, batch_item>::iterator bi;
for (bi = geometry_map.begin(); bi != geometry_map.end(); ++bi) {
n_to_render += bi->second.batch.need_to_render();
for (auto &bi : geometry_map) {
n_to_render += bi.second.batch.need_to_render();
}
for (bi = distortion_map.begin(); bi != distortion_map.end(); ++bi) {
if ( bi->second.laser )
for (auto &bi : distortion_map) {
if ( bi.second.laser )
continue;
n_to_render += bi->second.batch.need_to_render();
n_to_render += bi.second.batch.need_to_render();
}
return n_to_render * 3;
@@ -1252,10 +1251,9 @@ int batch_get_size()
size_t geometry_batch_get_size()
{
size_t n_to_render = 0;
SCP_map<int, g_sdr_batch_item>::iterator bi;
for (bi = geometry_shader_map.begin(); bi != geometry_shader_map.end(); ++bi) {
n_to_render += bi->second.batch.need_to_render();
for (auto &bi : geometry_shader_map) {
n_to_render += bi.second.batch.need_to_render();
}
return n_to_render;
+90 -46
View File
@@ -1,8 +1,16 @@
#include "gropengl.h"
#include "gropenglbmpman.h"
#include "gropengldeferred.h"
#include "gropengldraw.h"
#include "gropenglpostprocessing.h"
#include "gropenglquery.h"
#include "gropenglshader.h"
#include "gropenglstate.h"
#include "gropenglsync.h"
#include "gropengltexture.h"
#include "gropengltnl.h"
#include "bmpman/bmpman.h"
#include "cfile/cfile.h"
#include "cmdline/cmdline.h"
@@ -10,32 +18,22 @@
#include "debugconsole/console.h"
#include "globalincs/systemvars.h"
#include "graphics/2d.h"
#include "graphics/line.h"
#include "graphics/matrix.h"
#include "graphics/paths/PathRenderer.h"
#include "gropengl.h"
#include "gropenglbmpman.h"
#include "gropengldraw.h"
#include "gropenglpostprocessing.h"
#include "gropenglquery.h"
#include "gropenglsync.h"
#include "gropenglshader.h"
#include "gropenglstate.h"
#include "gropengltexture.h"
#include "gropengltnl.h"
#include "gropengldeferred.h"
#include "graphics/line.h"
#include "io/mouse.h"
#include "io/timer.h"
#include "libs/renderdoc/renderdoc.h"
#include "math/floating.h"
#include "model/model.h"
#include "nebula/neb.h"
#include "libs/renderdoc/renderdoc.h"
#include "options/Option.h"
#include "osapi/osapi.h"
#include "osapi/osregistry.h"
#include "render/3d.h"
#include "popup/popup.h"
#include "tracing/tracing.h"
#include "pngutils/pngutils.h"
#include "popup/popup.h"
#include "render/3d.h"
#include "tracing/tracing.h"
#if defined(_WIN32)
#include <windows.h>
@@ -99,6 +97,33 @@ static std::unique_ptr<os::OpenGLContext> GL_context = nullptr;
static std::unique_ptr<os::GraphicsOperations> graphic_operations = nullptr;
static os::Viewport* current_viewport = nullptr;
static bool mode_change_func(os::ViewportState state, bool initial)
{
if (initial) {
return false;
}
auto window = os::getMainViewport();
if (window == nullptr) {
return false;
}
window->setState(state);
return true;
}
static auto WindowModeOption = options::OptionBuilder<os::ViewportState>("Graphics.WindowMode", "Window Mode",
"Controls how the game window is created.")
.category("Graphics")
.level(options::ExpertLevel::Beginner)
.values({{os::ViewportState::Fullscreen, "Fullscreen"},
{os::ViewportState::Borderless, "Borderless"},
{os::ViewportState::Windowed, "Windowed"}})
.importance(98)
.default_val(os::ViewportState::Fullscreen)
.change_listener(mode_change_func)
.finish();
void opengl_go_fullscreen()
{
if (Cmdline_fullscreen_window || Cmdline_window || GL_fullscreen || Fred_running)
@@ -854,16 +879,16 @@ int opengl_check_for_errors(const char *err_at)
return num_errors;
}
void opengl_set_vsync(int status)
void opengl_set_vsync(bool enable)
{
if ( (status < 0) || (status > 1) ) {
Int3();
return;
if (enable) {
// Try to use adaptive vsync when supported
if (!GL_context->setSwapInterval(-1)) {
GL_context->setSwapInterval(1);
}
} else {
GL_context->setSwapInterval(0);
}
GL_context->setSwapInterval(status);
GL_CHECK_FOR_ERRORS("end of set_vsync()");
}
std::unique_ptr<os::Viewport> gr_opengl_create_viewport(const os::ViewPortProperties& props) {
@@ -1021,10 +1046,24 @@ int opengl_init_display_device()
attrs.title = Window_title;
}
if (!Cmdline_window && ! Cmdline_fullscreen_window) {
attrs.flags.set(os::ViewPortFlags::Fullscreen);
} else if (Cmdline_fullscreen_window) {
attrs.flags.set(os::ViewPortFlags::Borderless);
if (Using_in_game_options) {
switch (WindowModeOption->getValue()) {
case os::ViewportState::Windowed:
// That's the default
break;
case os::ViewportState::Borderless:
attrs.flags.set(os::ViewPortFlags::Borderless);
break;
case os::ViewportState::Fullscreen:
attrs.flags.set(os::ViewPortFlags::Fullscreen);
break;
}
} else {
if (!Cmdline_window && !Cmdline_fullscreen_window) {
attrs.flags.set(os::ViewPortFlags::Fullscreen);
} else if (Cmdline_fullscreen_window) {
attrs.flags.set(os::ViewPortFlags::Borderless);
}
}
auto viewport = gr_opengl_create_viewport(attrs);
@@ -1497,7 +1536,7 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
opengl_post_process_init();
// must be called after extensions are setup
opengl_set_vsync( !Cmdline_no_vsync );
opengl_set_vsync(Gr_enable_vsync);
gr_reset_matrices();
gr_setup_viewport();
@@ -1541,7 +1580,7 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
mprintf(( " Can use compressed textures: %s\n", Use_compressed_textures ? NOX("YES") : NOX("NO") ));
mprintf(( " Texture compression available: %s\n", Texture_compression_available ? NOX("YES") : NOX("NO") ));
mprintf(( " Post-processing enabled: %s\n", (Cmdline_postprocess) ? "YES" : "NO"));
mprintf(( " Post-processing enabled: %s\n", (Gr_post_processing_enabled) ? "YES" : "NO"));
mprintf(( " Using %s texture filter.\n", (GL_mipmap_filter) ? NOX("trilinear") : NOX("bilinear") ));
mprintf(( " OpenGL Shader Version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION) ));
@@ -1572,9 +1611,9 @@ bool gr_opengl_is_capable(gr_capability capability)
return Cmdline_height ? true : false;
case CAPABILITY_SOFT_PARTICLES:
case CAPABILITY_DISTORTION:
return Cmdline_softparticles && !Cmdline_no_fbo;
return Gr_enable_soft_particles && !Cmdline_no_fbo;
case CAPABILITY_POST_PROCESSING:
return Cmdline_postprocess && !Cmdline_no_fbo;
return Gr_post_processing_enabled && !Cmdline_no_fbo;
case CAPABILITY_DEFERRED_LIGHTING:
return !Cmdline_no_fbo && !Cmdline_no_deferred_lighting;
case CAPABILITY_SHADOWS:
@@ -1592,16 +1631,20 @@ bool gr_opengl_is_capable(gr_capability capability)
return false;
}
bool gr_opengl_get_property(gr_property prop, void* dest) {
switch(prop) {
case gr_property::UNIFORM_BUFFER_OFFSET_ALIGNMENT:
*((int*)dest) = GL_state.Constants.GetUniformBufferOffsetAlignment();
return true;
case gr_property::UNIFORM_BUFFER_MAX_SIZE:
*((int*)dest) = GL_state.Constants.GetMaxUniformBlockSize();
return true;
default:
return false;
bool gr_opengl_get_property(gr_property prop, void* dest)
{
switch (prop) {
case gr_property::UNIFORM_BUFFER_OFFSET_ALIGNMENT:
*((int*)dest) = GL_state.Constants.GetUniformBufferOffsetAlignment();
return true;
case gr_property::UNIFORM_BUFFER_MAX_SIZE:
*((int*)dest) = GL_state.Constants.GetMaxUniformBlockSize();
return true;
case gr_property::MAX_ANISOTROPY:
*((float*)dest) = GL_state.Constants.GetMaxAnisotropy();
return true;
default:
return false;
}
}
@@ -1679,7 +1722,8 @@ DCF(ogl_anisotropy, "toggles anisotropic filtering")
if (dc_optional_string_either("help", "--help")) {
dc_printf("Sets OpenGL anisotropic filtering level.\n");
dc_printf("GL_anisotropy [int] Valid values are 0 to %i. 0 turns off anisotropic filtering.\n", (int)opengl_get_max_anisotropy());
dc_printf("GL_anisotropy [int] Valid values are 0 to %i. 0 turns off anisotropic filtering.\n",
(int)GL_state.Constants.GetMaxAnisotropy());
process = false;
}
-6
View File
@@ -27,12 +27,6 @@
static inline int is_power_of_two(int w, int h)
{
// NOTE: OpenGL texture code has a min tex size of 16 (currently), so we need to be at least
// the min size here to qualify as power-of-2 and not get resized later on
return ( ((w >= GL_min_texture_width) && !(w & (w-1))) && ((h >= GL_min_texture_height) && !(h & (h-1))) );
}
int get_num_mipmap_levels(int w, int h)
{
+3 -3
View File
@@ -115,7 +115,7 @@ void gr_opengl_deferred_lighting_finish()
GL_state.Texture.Enable(1, GL_TEXTURE_2D, Scene_normal_texture);
GL_state.Texture.Enable(2, GL_TEXTURE_2D, Scene_position_texture);
GL_state.Texture.Enable(3, GL_TEXTURE_2D, Scene_specular_texture);
if (Cmdline_shadow_quality) {
if (Shadow_quality != ShadowQuality::Disabled) {
GL_state.Texture.Enable(4, GL_TEXTURE_2D_ARRAY, Shadow_map_texture);
}
@@ -133,7 +133,7 @@ void gr_opengl_deferred_lighting_finish()
GR_DEBUG_SCOPE("Build buffer data");
auto header = uniformAligner.getHeader<deferred_global_data>();
if (Cmdline_shadow_quality) {
if (Shadow_quality != ShadowQuality::Disabled) {
// Avoid this overhead when we are not going to use these values
header->shadow_mv_matrix = Shadow_view_matrix;
for (size_t i = 0; i < MAX_SHADOW_CASCADES; ++i) {
@@ -173,7 +173,7 @@ void gr_opengl_deferred_lighting_finish()
switch (l.type) {
case Light_Type::Directional:
if (Cmdline_shadow_quality) {
if (Shadow_quality != ShadowQuality::Disabled) {
light_data->enable_shadows = first_directional ? 1 : 0;
}
vec4 light_dir;
+10 -10
View File
@@ -88,9 +88,9 @@ void opengl_setup_scene_textures()
Scene_texture_initialized = 0;
if ( Cmdline_no_fbo ) {
Cmdline_postprocess = 0;
Cmdline_softparticles = 0;
Cmdline_fb_explosions = 0;
Gr_post_processing_enabled = false;
Gr_enable_soft_particles = false;
Gr_framebuffer_effects = {};
Scene_ldr_texture = 0;
Scene_color_texture = 0;
@@ -338,13 +338,13 @@ void opengl_setup_scene_textures()
//glDeleteTextures(1, &Scene_fxaa_output_texture);
//Scene_fxaa_output_texture = 0;
Cmdline_postprocess = 0;
Cmdline_softparticles = 0;
Gr_post_processing_enabled = false;
Gr_enable_soft_particles = false;
return;
}
//Setup thruster distortion framebuffer
if (Cmdline_fb_thrusters || Cmdline_fb_explosions)
if (Gr_framebuffer_effects.any_set())
{
glGenFramebuffers(1, &Distortion_framebuffer);
GL_state.BindFrameBuffer(Distortion_framebuffer);
@@ -392,8 +392,8 @@ void opengl_setup_scene_textures()
Scene_color_texture = 0;
Scene_depth_texture = 0;
Cmdline_postprocess = 0;
Cmdline_softparticles = 0;
Gr_post_processing_enabled = false;
Gr_enable_soft_particles = false;
return;
}
@@ -510,7 +510,7 @@ void gr_opengl_scene_texture_begin()
Scene_framebuffer_in_frame = true;
if ( Cmdline_postprocess && !PostProcessing_override ) {
if ( Gr_post_processing_enabled && !PostProcessing_override ) {
High_dynamic_range = true;
}
}
@@ -533,7 +533,7 @@ void gr_opengl_scene_texture_end()
time_buffer = 0.0f;
}
if ( Cmdline_postprocess && !PostProcessing_override ) {
if ( Gr_post_processing_enabled && !PostProcessing_override ) {
gr_post_process_end();
} else {
GR_DEBUG_SCOPE("Draw scene texture");
+18 -54
View File
@@ -21,10 +21,8 @@ extern bool PostProcessing_override;
extern int opengl_check_framebuffer();
//Needed to track where the FXAA shaders are
size_t fxaa_shader_id;
//In case we don't find the shaders at all, this override is needed
bool fxaa_unavailable = false;
int Fxaa_preset_last_frame;
bool zbuffer_saved = false;
// lightshaft parameters
@@ -227,8 +225,11 @@ void gr_opengl_post_process_begin()
}
void recompile_fxaa_shader() {
if (!gr_is_fxaa_mode(Gr_aa_mode)) {
return;
}
mprintf(("Recompiling FXAA shader with preset %d\n", Cmdline_fxaa_preset));
mprintf(("Recompiling FXAA shader...\n"));
// start recompile by grabbing deleting the current shader we have, assuming it's already created
opengl_delete_shader( gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA, 0) );
@@ -236,7 +237,7 @@ void recompile_fxaa_shader() {
// then recreate it again. shader loading code will be updated with the new FXAA presets
gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA, 0);
Fxaa_preset_last_frame = Cmdline_fxaa_preset;
Gr_aa_mode_last_frame = Gr_aa_mode;
}
void opengl_post_pass_fxaa() {
@@ -244,7 +245,7 @@ void opengl_post_pass_fxaa() {
TRACE_SCOPE(tracing::FXAA);
//If the preset changed, recompile the shader
if (Fxaa_preset_last_frame != Cmdline_fxaa_preset) {
if (Gr_aa_mode_last_frame != Gr_aa_mode) {
recompile_fxaa_shader();
}
@@ -362,7 +363,7 @@ void gr_opengl_post_process_end()
opengl_post_pass_tonemap();
// Do FXAA
if (Cmdline_fxaa && !fxaa_unavailable && !GL_rendering_to_texture) {
if (gr_is_fxaa_mode(Gr_aa_mode) && !fxaa_unavailable && !GL_rendering_to_texture) {
opengl_post_pass_fxaa();
}
@@ -728,63 +729,26 @@ void opengl_post_shader_header(SCP_stringstream &sflags, shader_type shader_t, i
sflags << "#define FXAA_GATHER4_ALPHA 1\n";
}
switch (Cmdline_fxaa_preset) {
case 0:
switch (Gr_aa_mode) {
case AntiAliasMode::None:
sflags << "#define FXAA_QUALITY_PRESET 10\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/6.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/12.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case 1:
sflags << "#define FXAA_QUALITY_PRESET 11\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/7.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/14.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case 2:
case AntiAliasMode::FXAA_Low:
sflags << "#define FXAA_QUALITY_PRESET 12\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/8.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/16.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case 3:
sflags << "#define FXAA_QUALITY_PRESET 13\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/9.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/18.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case 4:
sflags << "#define FXAA_QUALITY_PRESET 14\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/10.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/20.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case 5:
sflags << "#define FXAA_QUALITY_PRESET 25\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/11.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/22.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case 6:
case AntiAliasMode::FXAA_Medium:
sflags << "#define FXAA_QUALITY_PRESET 26\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/12.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/24.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case 7:
sflags << "#define FXAA_PC 1\n";
sflags << "#define FXAA_QUALITY_PRESET 27\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/13.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/26.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case 8:
sflags << "#define FXAA_QUALITY_PRESET 28\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/14.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/28.0)\n";
sflags << "#define FXAA_QUALITY_SUBPIX 0.33\n";
break;
case 9:
case AntiAliasMode::FXAA_High:
sflags << "#define FXAA_QUALITY_PRESET 39\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD (1.0/15.0)\n";
sflags << "#define FXAA_QUALITY_EDGE_THRESHOLD_MIN (1.0/32.0)\n";
@@ -821,7 +785,7 @@ bool opengl_post_init_shaders()
if ( gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA, 0) < 0 ||
gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA_PREPASS, 0) < 0 ) {
Cmdline_fxaa = false;
Gr_aa_mode = AntiAliasMode::None;
fxaa_unavailable = true;
mprintf(("Error while compiling FXAA shaders. FXAA will be unavailable.\n"));
}
@@ -918,11 +882,11 @@ void opengl_post_process_init()
//We need to read the tbl first. This is mostly for FRED's benefit, as otherwise the list of post effects for the sexp doesn't get updated.
if ( !opengl_post_init_table() ) {
mprintf((" Unable to read post-processing table! Disabling post-processing...\n\n"));
Cmdline_postprocess = 0;
Gr_post_processing_enabled = false;
return;
}
if ( !Cmdline_postprocess ) {
if ( !Gr_post_processing_enabled ) {
return;
}
@@ -931,19 +895,19 @@ void opengl_post_process_init()
}
if ( Cmdline_no_fbo ) {
Cmdline_postprocess = 0;
Gr_post_processing_enabled = false;
return;
}
if ( !opengl_post_init_shaders() ) {
mprintf((" Unable to initialize post-processing shaders! Disabling post-processing...\n\n"));
Cmdline_postprocess = 0;
Gr_post_processing_enabled = false;
return;
}
if ( !opengl_post_init_framebuffer() ) {
mprintf((" Unable to initialize post-processing framebuffer! Disabling post-processing...\n\n"));
Cmdline_postprocess = 0;
Gr_post_processing_enabled = false;
return;
}
+22 -20
View File
@@ -31,6 +31,18 @@
SCP_vector<opengl_shader_t> GL_shader;
typedef std::pair<int, uint32_t> shader_descriptor_t;
struct key_hasher
{
size_t operator()(const shader_descriptor_t &obj) const
{
return obj.first ^ obj.second;
}
};
SCP_unordered_map<shader_descriptor_t, size_t, key_hasher> GL_shader_map;
GLuint Framebuffer_fallback_texture_id = 0;
SCP_vector<opengl_vert_attrib> GL_vertex_attrib_info =
@@ -296,12 +308,10 @@ void opengl_shader_set_current(int handle)
size_t opengl_get_shader_idx(shader_type shader_t, unsigned int flags)
{
for (size_t idx = 0; idx < GL_shader.size(); idx++) {
if (GL_shader[idx].shader == shader_t && GL_shader[idx].flags == flags) {
return idx;
}
auto found = GL_shader_map.find(shader_descriptor_t(shader_t, flags));
if (found != GL_shader_map.end()) {
return found->second;
}
return GL_shader.size();
}
@@ -327,6 +337,8 @@ void opengl_delete_shader(int sdr_handle)
{
Assert(sdr_handle >= 0);
Assert(sdr_handle < (int)GL_shader.size());
opengl_shader_t &victim = GL_shader[sdr_handle];
GL_shader_map.erase(shader_descriptor_t(victim.shader, victim.flags));
GL_shader[sdr_handle].program.reset();
@@ -341,6 +353,7 @@ void opengl_delete_shader(int sdr_handle)
void opengl_shader_shutdown()
{
GL_shader.clear();
GL_shader_map.clear();
}
static SCP_string opengl_shader_get_header(shader_type type_id, int flags, bool has_geo_shader) {
@@ -840,6 +853,8 @@ int opengl_compile_shader(shader_type sdr, uint flags)
}
}
int new_shader_shader = new_shader.shader;
uint32_t new_shader_flags = new_shader.flags;
// then insert it at an empty slot or at the end
if ( empty_idx >= 0 ) {
GL_shader[empty_idx] = std::move(new_shader);
@@ -848,7 +863,7 @@ int opengl_compile_shader(shader_type sdr, uint flags)
sdr_index = (int)GL_shader.size();
GL_shader.push_back(std::move(new_shader));
}
GL_shader_map[shader_descriptor_t(new_shader_shader, new_shader_flags)] = sdr_index;
return sdr_index;
}
@@ -868,20 +883,6 @@ static void opengl_purge_shader_cache_type(const char* ext) {
SCP_string filter("*.");
filter += ext;
// Previously the cache files were stored in the mod directory. Since we have a better system now, those files
// should be cleaned out. This is only needed if we have a mod directory since otherwise we would delete the actual
// cache files
if (Cmdline_mod != nullptr && strlen(Cmdline_mod) > 0) {
SCP_vector<SCP_string> cache_files;
cf_get_file_list(cache_files, CF_TYPE_CACHE, filter.c_str(), CF_SORT_NONE, nullptr,
CF_LOCATION_TYPE_PRIMARY_MOD | CF_LOCATION_TYPE_SECONDARY_MODS);
for (auto& file : cache_files) {
cf_delete((file + "." + ext).c_str(), CF_TYPE_CACHE,
CF_LOCATION_TYPE_PRIMARY_MOD | CF_LOCATION_TYPE_SECONDARY_MODS);
}
}
SCP_vector<SCP_string> cache_files;
SCP_vector<file_list_info> file_info;
cf_get_file_list(cache_files, CF_TYPE_CACHE, filter.c_str(), CF_SORT_NONE, &file_info,
@@ -939,6 +940,7 @@ void opengl_shader_init()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &pixels);
GL_shader.clear();
GL_shader_map.clear();
// Reserve 32 shader slots. This should cover most use cases in real life.
GL_shader.reserve(32);
+19 -16
View File
@@ -718,10 +718,8 @@ void opengl_array_state::VertexAttribPointer(GLuint index, GLint size, GLenum ty
void opengl_array_state::ResetVertexAttribs()
{
SCP_map<GLuint, opengl_vertex_attrib_unit>::iterator it;
for ( it = vertex_attrib_units.begin(); it != vertex_attrib_units.end(); ++it ) {
DisableVertexAttrib(it->first);
for (auto &it : vertex_attrib_units) {
DisableVertexAttrib(it.first);
}
vertex_attrib_units.clear();
@@ -733,19 +731,17 @@ void opengl_array_state::BindPointersBegin()
client_texture_units[i].used_for_draw = false;
}
SCP_map<GLuint, opengl_vertex_attrib_unit>::iterator it;
for (it = vertex_attrib_units.begin(); it != vertex_attrib_units.end(); ++it) {
it->second.used_for_draw = false;
for (auto &it : vertex_attrib_units) {
it.second.used_for_draw = false;
}
}
void opengl_array_state::BindPointersEnd()
{
SCP_map<GLuint, opengl_vertex_attrib_unit>::iterator it;
for (it = vertex_attrib_units.begin(); it != vertex_attrib_units.end(); ++it) {
if ( !it->second.used_for_draw ) DisableVertexAttrib(it->first);
for (auto &it : vertex_attrib_units) {
if (!it.second.used_for_draw) {
DisableVertexAttrib(it.first);
}
}
}
@@ -764,10 +760,8 @@ void opengl_array_state::BindArrayBuffer(GLuint id)
client_texture_units[i].reset_ptr = true;
}
SCP_map<GLuint,opengl_vertex_attrib_unit>::iterator it;
for ( it = vertex_attrib_units.begin(); it != vertex_attrib_units.end(); ++it ) {
it->second.reset_ptr = true;
for (auto &it : vertex_attrib_units) {
it.second.reset_ptr = true;
}
}
@@ -849,6 +843,12 @@ void opengl_constant_state::init() {
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &_uniform_buffer_offset_alignment);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &_max_uniform_block_size);
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &_max_uniform_block_bindings);
if (GLAD_GL_EXT_texture_filter_anisotropic) {
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &_max_anisotropy);
} else {
_max_anisotropy = -1.0f;
}
}
GLint opengl_constant_state::GetUniformBufferOffsetAlignment() {
return _uniform_buffer_offset_alignment;
@@ -859,6 +859,9 @@ GLint opengl_constant_state::GetMaxUniformBlockSize() {
GLint opengl_constant_state::GetMaxUniformBlockBindings() {
return _max_uniform_block_bindings;
}
GLfloat opengl_constant_state::GetMaxAnisotropy() {
return _max_anisotropy;
}
void gr_opengl_clear_states()
{
+3
View File
@@ -178,6 +178,7 @@ class opengl_constant_state {
GLint _uniform_buffer_offset_alignment;
GLint _max_uniform_block_size;
GLint _max_uniform_block_bindings;
GLfloat _max_anisotropy;
public:
opengl_constant_state();
@@ -189,6 +190,8 @@ class opengl_constant_state {
GLint GetMaxUniformBlockSize();
GLint GetMaxUniformBlockBindings();
GLfloat GetMaxAnisotropy();
};
class opengl_state
+341 -302
View File
@@ -12,15 +12,16 @@
#endif
#define BMPMAN_INTERNAL
#include "gropenglstate.h"
#include "gropengltexture.h"
#include "bmpman/bm_internal.h"
#include "bmpman/bmpman.h"
#include "cmdline/cmdline.h"
#include "ddsutils/ddsutils.h"
#include "globalincs/systemvars.h"
#include "graphics/grinternal.h"
#include "gropenglstate.h"
#include "gropengltexture.h"
#include "math/vecmat.h"
#include "options/Option.h"
#include "osapi/osregistry.h"
matrix4 GL_texture_matrix;
@@ -35,7 +36,6 @@ int GL_last_detail = -1;
GLint GL_supported_texture_units = 2;
int GL_should_preload = 0;
GLfloat GL_anisotropy = 1.0f;
GLfloat GL_max_anisotropy = -1.0f;
int GL_mipmap_filter = 0;
GLenum GL_texture_target = GL_TEXTURE_2D;
GLenum GL_texture_face = GL_TEXTURE_2D;
@@ -49,6 +49,57 @@ extern int CLOAKMAP;
extern int ENVMAP;
extern int Interp_multitex_cloakmap;
static SCP_vector<float> anisotropic_value_enumerator()
{
float max;
if (!gr_get_property(gr_property::MAX_ANISOTROPY, &max)) {
return SCP_vector<float>();
}
if (max <= 2.0f) {
return SCP_vector<float>();
}
SCP_vector<float> out;
// We assume here that the anisotropy levels are powers of two...
float current = 1.0f;
while (current <= max) {
out.push_back(current);
current *= 2.0f;
}
return out;
}
static SCP_string anisotropic_display(float val)
{
if (val < 2.0f) {
return "None";
}
SCP_string out;
sprintf(out, "%.0fx", val);
return out;
}
static float anisotropic_default()
{
float max;
if (!gr_get_property(gr_property::MAX_ANISOTROPY, &max)) {
return 1.0f;
}
return max;
}
static auto AnisotropyOption =
options::OptionBuilder<float>("Graphics.Anisotropy", "Anisotropic filtering",
"Controls the amount of anisotropic filtering of the textures.")
.enumerator(anisotropic_value_enumerator)
.category("Graphics")
.display(anisotropic_display)
.default_func(anisotropic_default)
.level(options::ExpertLevel::Advanced)
.importance(78)
.finish();
// forward declarations
int opengl_free_texture(tcache_slot_opengl *t);
@@ -72,22 +123,6 @@ void opengl_set_modulate_tex_env()
GL_CHECK_FOR_ERRORS("end of set_modulate_tex_env()");
}
GLfloat opengl_get_max_anisotropy()
{
if ( !GLAD_GL_EXT_texture_filter_anisotropic ) {
return 0.0f;
}
if ( GL_max_anisotropy < 0.0f ) {
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GL_max_anisotropy);
}
// the spec says that it should be a minimum of 2.0
Assert( GL_max_anisotropy >= 2.0f );
return GL_max_anisotropy;
}
void opengl_set_texture_target( GLenum target )
{
GL_texture_target = target;
@@ -131,13 +166,17 @@ void opengl_tcache_init()
// anisotropy
if ( GLAD_GL_EXT_texture_filter_anisotropic ) {
// set max value first thing
GL_anisotropy = opengl_get_max_anisotropy();
GL_anisotropy = GL_state.Constants.GetMaxAnisotropy();
// now for the user setting
if (Cmdline_aniso_level != 0)
GL_anisotropy = (GLfloat) Cmdline_aniso_level;
if (Using_in_game_options) {
GL_anisotropy = AnisotropyOption->getValue();
} else {
// now for the user setting
if (Cmdline_aniso_level != 0)
GL_anisotropy = (GLfloat)Cmdline_aniso_level;
}
CLAMP(GL_anisotropy, 1.0f, GL_max_anisotropy);
CLAMP(GL_anisotropy, 1.0f, GL_state.Constants.GetMaxAnisotropy());
}
Assert( GL_supported_texture_units >= 2 );
@@ -284,37 +323,24 @@ int opengl_free_texture(tcache_slot_opengl *t)
// bmap_h == height of source bitmap
// tex_w == width of final texture
// tex_h == height of final texture
int opengl_texture_set_level(int bitmap_handle,
int bitmap_type,
int bmap_w,
int bmap_h,
int tex_w,
int tex_h,
ubyte* data,
tcache_slot_opengl* tSlot,
int /*base_level*/,
bool resize,
GLenum intFormat)
{
static int opengl_texture_set_level(int bitmap_handle, int bitmap_type, int bmap_w, int bmap_h, int tex_w, int tex_h,
ubyte* data, tcache_slot_opengl* tSlot, int base_level, int mipmap_levels,
bool resize, GLenum intFormat) {
GR_DEBUG_SCOPE("Upload single frame");
int ret_val = 1;
ubyte *bmp_data = data;
int ret_val = 1;
ubyte* bmp_data = data;
ubyte *texmem = NULL, *texmemp = NULL;
int skip_size = 0, mipmap_levels = 0;
int skip_size = 0;
GL_CHECK_FOR_ERRORS("start of create_texture_sub()");
// bogus
if ( (tSlot == NULL) || (bmp_data == NULL) ) {
if ((tSlot == nullptr) || (bmp_data == nullptr)) {
return 0;
}
// for everything that might use mipmaps
auto mipmap_w = tex_w;
auto mipmap_h = tex_h;
if ( (bitmap_type == TCACHE_TYPE_AABITMAP) || (bitmap_type == TCACHE_TYPE_INTERFACE) ) {
if ((bitmap_type == TCACHE_TYPE_AABITMAP) || (bitmap_type == TCACHE_TYPE_INTERFACE)) {
tSlot->u_scale = (float)bmap_w / (float)tex_w;
tSlot->v_scale = (float)bmap_h / (float)tex_h;
} else {
@@ -326,73 +352,207 @@ int opengl_texture_set_level(int bitmap_handle,
auto byte_mult = (tSlot->bpp >> 3);
GLenum texFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV;
GLenum glFormat = GL_BGRA;
GLenum glFormat = GL_BGRA;
// GL_BGRA_EXT is *much* faster with some hardware/drivers
if (byte_mult == 4) {
texFormat = GL_UNSIGNED_INT_8_8_8_8_REV;
intFormat = (gr_screen.bits_per_pixel == 32) ? GL_RGBA8 : GL_RGB5_A1;
glFormat = GL_BGRA;
glFormat = GL_BGRA;
} else if (byte_mult == 3) {
texFormat = GL_UNSIGNED_BYTE;
intFormat = (gr_screen.bits_per_pixel == 32) ? GL_RGB8 : GL_RGB5;
glFormat = GL_BGR;
glFormat = GL_BGR;
} else if (byte_mult == 2) {
texFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV;
intFormat = GL_RGB5_A1;
glFormat = GL_BGRA;
glFormat = GL_BGRA;
} else if (byte_mult == 1) {
Assertion( bitmap_type == TCACHE_TYPE_AABITMAP, "Invalid type for bitmap: %s BMPMAN handle: %d. Type expected was 0, we got %d instead.\nThis can be caused by using texture compression on a non-power-of-2 texture.\n", bm_get_filename(bitmap_handle), bitmap_handle, bitmap_type );
Assertion(bitmap_type == TCACHE_TYPE_AABITMAP,
"Invalid type for bitmap: %s BMPMAN handle: %d. Type expected was 0, we got %d instead.\nThis can be "
"caused by using texture compression on a non-power-of-2 texture.\n",
bm_get_filename(bitmap_handle), bitmap_handle, bitmap_type);
texFormat = GL_UNSIGNED_BYTE;
intFormat = GL_RED;
glFormat = GL_RED;
glFormat = GL_RED;
} else {
texFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV;
intFormat = GL_RGBA;
glFormat = GL_BGRA;
glFormat = GL_BGRA;
}
// check for compressed image types
auto block_size = 0;
switch ( bm_is_compressed(bitmap_handle) ) {
case DDS_DXT1:
case DDS_CUBEMAP_DXT1:
intFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
block_size = 8;
break;
switch (bm_is_compressed(bitmap_handle)) {
case DDS_DXT1:
case DDS_CUBEMAP_DXT1:
intFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
block_size = 8;
break;
case DDS_DXT3:
case DDS_CUBEMAP_DXT3:
intFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
block_size = 16;
break;
case DDS_DXT3:
case DDS_CUBEMAP_DXT3:
intFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
block_size = 16;
break;
case DDS_DXT5:
case DDS_CUBEMAP_DXT5:
intFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
block_size = 16;
break;
case DDS_DXT5:
case DDS_CUBEMAP_DXT5:
intFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
block_size = 16;
break;
}
if ( bitmap_type == TCACHE_TYPE_CUBEMAP ) {
if (bitmap_type == TCACHE_TYPE_CUBEMAP) {
tSlot->texture_target = GL_TEXTURE_CUBE_MAP;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
mipmap_levels = bm_get_num_mipmaps(bitmap_handle);
auto dsize = 0;
auto dsize = 0;
auto doffset = 0;
switch (bitmap_type) {
case TCACHE_TYPE_COMPRESSED: {
if (block_size > 0) {
for (auto i = 0; i < mipmap_levels; i++) {
case TCACHE_TYPE_COMPRESSED: {
if (block_size > 0) {
auto mipmap_w = bmap_w;
auto mipmap_h = bmap_h;
for (auto i = 0; i < mipmap_levels + base_level; i++) {
// size of data block (4x4)
dsize = ((mipmap_h + 3) / 4) * ((mipmap_w + 3) / 4) * block_size;
if (i >= base_level) {
glCompressedTexSubImage3D(tSlot->texture_target, i - base_level, 0, 0, tSlot->array_index, mipmap_w,
mipmap_h, 1, intFormat, dsize, bmp_data + doffset);
}
// adjust the data offset for the next block
doffset += dsize;
// reduce size by half for the next pass
mipmap_w >>= 1;
mipmap_h >>= 1;
if (mipmap_w <= 0) {
mipmap_w = 1;
}
if (mipmap_h <= 0) {
mipmap_h = 1;
}
}
} else {
Int3();
return 0;
}
break;
}
case TCACHE_TYPE_AABITMAP: {
texmem = (ubyte*)vm_malloc(tex_w * tex_h * byte_mult);
texmemp = texmem;
Assert(texmem != nullptr);
int luminance = 0;
for (auto i = 0; i < tex_h; i++) {
for (auto j = 0; j < tex_w; j++) {
if ((i < bmap_h) && (j < bmap_w)) {
if (byte_mult > 1) {
luminance = 0;
if (byte_mult > 3) {
for (auto k = 0; k < 3; k++) {
luminance += bmp_data[(i * bmap_w + j) * byte_mult + k];
}
*texmemp++ =
(ubyte)((luminance / 3) * (bmp_data[(i * bmap_w + j) * byte_mult + 3] / 255.0f));
} else {
for (auto k = 0; k < byte_mult; k++) {
luminance += bmp_data[(i * bmap_w + j) * byte_mult + k];
}
*texmemp++ = (ubyte)(luminance / byte_mult);
}
} else {
*texmemp++ = bmp_data[i * bmap_w + j];
}
} else {
*texmemp++ = 0;
}
}
}
GLenum aa_format = GL_RED;
glTexSubImage3D(tSlot->texture_target, 0, 0, 0, tSlot->array_index, tex_w, tex_h, 1, aa_format,
GL_UNSIGNED_BYTE, texmem);
if (texmem != nullptr) {
vm_free(texmem);
}
break;
}
case TCACHE_TYPE_INTERFACE: {
// if we aren't resizing then we can just use bmp_data directly
if (resize) {
texmem = (ubyte*)vm_malloc(tex_w * tex_h * byte_mult);
texmemp = texmem;
Assert(texmem != nullptr);
for (auto i = 0; i < tex_h; i++) {
for (auto j = 0; j < tex_w; j++) {
if ((i < bmap_h) && (j < bmap_w)) {
for (auto k = 0; k < byte_mult; k++) {
*texmemp++ = bmp_data[(i * bmap_w + j) * byte_mult + k];
}
} else {
for (auto k = 0; k < byte_mult; k++) {
*texmemp++ = 0;
}
}
}
}
}
glTexSubImage3D(tSlot->texture_target, 0, 0, 0, tSlot->array_index, tex_w, tex_h, 1, glFormat, texFormat,
(resize) ? texmem : bmp_data);
if (texmem != nullptr) {
vm_free(texmem);
}
break;
}
case TCACHE_TYPE_CUBEMAP: {
Assert(!resize);
Assert(texmem == nullptr);
// we have to load in all 6 faces...
doffset = 0;
for (auto i = 0; i < 6; i++) {
// We need to use the actual size of the bitmap here since tex_h/w is already
// adjusted for the size of the target bitmap. Since we are not resizing here that is not a problem
auto mipmap_w = bmap_w;
auto mipmap_h = bmap_h;
// check if it's a compressed cubemap first
if (block_size > 0) {
for (auto level = 0; level < mipmap_levels + base_level; level++) {
// size of data block (4x4)
dsize = ((mipmap_h + 3) / 4) * ((mipmap_w + 3) / 4) * block_size;
glCompressedTexSubImage3D(tSlot->texture_target, i, 0, 0, tSlot->array_index, mipmap_w, mipmap_h, 1, intFormat, dsize, bmp_data + doffset);
if (level >= base_level) {
// We skipped ahead to the base level so we can start uploading frames now
glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, level - base_level, 0, 0,
mipmap_w, mipmap_h, intFormat, dsize, bmp_data + doffset);
}
// adjust the data offset for the next block
doffset += dsize;
@@ -410,233 +570,112 @@ int opengl_texture_set_level(int bitmap_handle,
}
}
} else {
Int3();
return 0;
}
break;
}
case TCACHE_TYPE_AABITMAP: {
texmem = (ubyte *) vm_malloc (tex_w*tex_h*byte_mult);
texmemp = texmem;
Assert( texmem != NULL );
int luminance = 0;
for (auto i = 0; i < tex_h; i++) {
for (auto j = 0; j < tex_w; j++) {
if ( (i < bmap_h) && (j < bmap_w) ) {
if ( byte_mult > 1 ) {
luminance = 0;
if ( byte_mult > 3 ) {
for (auto k = 0; k < 3; k++) {
luminance += bmp_data[(i*bmap_w+j)*byte_mult+k];
}
*texmemp++ = (ubyte)((luminance / 3) * (bmp_data[(i*bmap_w+j)*byte_mult+3]/255.0f));
} else {
for (auto k = 0; k < byte_mult; k++) {
luminance += bmp_data[(i*bmap_w+j)*byte_mult+k];
}
*texmemp++ = (ubyte)(luminance / byte_mult);
}
} else {
*texmemp++ = bmp_data[i*bmap_w+j];
}
} else {
*texmemp++ = 0;
}
}
}
GLenum aa_format = GL_RED;
glTexSubImage3D (tSlot->texture_target, 0, 0, 0, tSlot->array_index, tex_w, tex_h, 1, aa_format, GL_UNSIGNED_BYTE, texmem);
if (texmem != NULL) {
vm_free(texmem);
}
break;
}
case TCACHE_TYPE_INTERFACE: {
// if we aren't resizing then we can just use bmp_data directly
if (resize) {
texmem = (ubyte *) vm_malloc (tex_w*tex_h*byte_mult);
texmemp = texmem;
Assert( texmem != NULL );
for (auto i = 0; i < tex_h; i++) {
for (auto j = 0;j < tex_w; j++) {
if ( (i < bmap_h) && (j < bmap_w) ) {
for (auto k = 0; k < byte_mult; k++) {
*texmemp++ = bmp_data[(i*bmap_w+j)*byte_mult+k];
}
} else {
for (auto k = 0; k < byte_mult; k++) {
*texmemp++ = 0;
}
}
}
}
}
glTexSubImage3D (tSlot->texture_target, 0, 0, 0, tSlot->array_index, mipmap_w, mipmap_h, 1, glFormat, texFormat, (resize) ? texmem : bmp_data);
if (texmem != NULL) {
vm_free(texmem);
}
break;
}
case TCACHE_TYPE_CUBEMAP: {
Assert( !resize );
Assert( texmem == NULL );
// we have to load in all 6 faces...
doffset = 0;
for (auto i = 0; i < 6; i++) {
doffset += dsize;
// check if it's a compressed cubemap first
if (block_size > 0) {
// size of data block (4x4)
dsize = ((mipmap_h + 3) / 4) * ((mipmap_w + 3) / 4) * block_size;
glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, 0, 0, mipmap_w, mipmap_h, intFormat, dsize, bmp_data + doffset);
// now that the base image is done handle any mipmap levels
for (auto j = 1; j < mipmap_levels; j++) {
// adjust the data offset for the next block
doffset += dsize;
// reduce size by half for the next pass
mipmap_w >>= 1;
mipmap_h >>= 1;
if (mipmap_w <= 0) {
mipmap_w = 1;
}
if (mipmap_h <= 0) {
mipmap_h = 1;
}
// size of data block (4x4)
dsize = ((mipmap_h + 3) / 4) * ((mipmap_w + 3) / 4) * block_size;
glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, j, 0, 0, mipmap_w, mipmap_h, intFormat, dsize, bmp_data + doffset);
}
}
// nope, it's uncompressed...
else {
for (auto level = 0; level < mipmap_levels + base_level; level++) {
dsize = mipmap_h * mipmap_w * byte_mult;
glTexSubImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, 0, 0, mipmap_w, mipmap_h, glFormat, texFormat, bmp_data + doffset);
if (level >= base_level) {
glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, level - base_level, 0, 0, mipmap_w,
mipmap_h, glFormat, texFormat, bmp_data + doffset);
}
// base image is done so now take care of any mipmap levels
for (auto j = 1; j < mipmap_levels; j++) {
doffset += dsize;
mipmap_w >>= 1;
mipmap_h >>= 1;
doffset += dsize;
mipmap_w >>= 1;
mipmap_h >>= 1;
if (mipmap_w <= 0) {
mipmap_w = 1;
}
if (mipmap_w <= 0) {
mipmap_w = 1;
}
if (mipmap_h <= 0) {
mipmap_h = 1;
}
dsize = mipmap_h * mipmap_w * byte_mult;
glTexSubImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, j, 0, 0, mipmap_w, mipmap_h, glFormat, texFormat, bmp_data + doffset);
if (mipmap_h <= 0) {
mipmap_h = 1;
}
}
// reset width and height for next face
mipmap_w = tex_w;
mipmap_h = tex_h;
}
break;
}
default: {
// if we aren't resizing then we can just use bmp_data directly
if (resize) {
texmem = (ubyte *) vm_malloc (tex_w*tex_h*byte_mult);
texmemp = texmem;
break;
}
Assert( texmem != NULL );
default: {
// if we aren't resizing then we can just use bmp_data directly
if (resize) {
texmem = (ubyte*)vm_malloc(tex_w * tex_h * byte_mult);
texmemp = texmem;
fix u, utmp, v, du, dv;
Assert(texmem != nullptr);
u = v = 0;
fix u, utmp, v, du, dv;
du = ( (bmap_w-1)*F1_0 ) / tex_w;
dv = ( (bmap_h-1)*F1_0 ) / tex_h;
u = v = 0;
for (auto j=0;j<tex_h;j++)
{
utmp = u;
for (auto i=0;i<tex_w;i++)
{
for (auto k = 0; k < byte_mult; k++) {
*texmemp++ = bmp_data[(f2i(v)*bmap_w+f2i(utmp))*byte_mult+k];
}
utmp += du;
du = ((bmap_w - 1) * F1_0) / tex_w;
dv = ((bmap_h - 1) * F1_0) / tex_h;
for (auto j = 0; j < tex_h; j++) {
utmp = u;
for (auto i = 0; i < tex_w; i++) {
for (auto k = 0; k < byte_mult; k++) {
*texmemp++ = bmp_data[(f2i(v) * bmap_w + f2i(utmp)) * byte_mult + k];
}
v += dv;
utmp += du;
}
v += dv;
}
// should never have mipmap levels if we also have to manually resize
if ( (mipmap_levels > 1) && resize ) {
Assert( texmem == NULL );
}
for (auto i = 0; i < mipmap_levels; i++) {
// size of data block (4x4)
dsize = mipmap_h * mipmap_w * byte_mult;
glTexSubImage3D (tSlot->texture_target, i, 0, 0, tSlot->array_index, mipmap_w, mipmap_h, 1, glFormat, texFormat, (texmem != NULL) ? texmem : bmp_data + doffset);
// adjust the data offset for the next block
doffset += dsize;
// reduce size by half for the next pass
mipmap_w >>= 1;
mipmap_h >>= 1;
if (mipmap_w <= 0) {
mipmap_w = 1;
}
if (mipmap_h <= 0) {
mipmap_h = 1;
}
}
if (texmem != NULL) {
vm_free(texmem);
}
break;
}
}//end switch
auto mipmap_w = tex_w;
auto mipmap_h = tex_h;
// should never have mipmap levels if we also have to manually resize
if ((mipmap_levels > 1) && resize) {
Assert(texmem == nullptr);
// If we have mipmaps then tex_w/h are already adjusted for the base level but that will cause problems with
// the code below. Instead we set the values to the actual size of the bitmap here to make sure we can
// iterate properly through the mipmap levels.
mipmap_w = bmap_w;
mipmap_h = bmap_h;
}
for (auto i = 0; i < mipmap_levels + base_level; i++) {
// size of data block (4x4)
dsize = mipmap_h * mipmap_w * byte_mult;
if (i >= base_level) {
glTexSubImage3D(tSlot->texture_target, i - base_level, 0, 0, tSlot->array_index, mipmap_w, mipmap_h, 1,
glFormat, texFormat, (texmem != nullptr) ? texmem : bmp_data + doffset);
}
// adjust the data offset for the next block
doffset += dsize;
// reduce size by half for the next pass
mipmap_w >>= 1;
mipmap_h >>= 1;
if (mipmap_w <= 0) {
mipmap_w = 1;
}
if (mipmap_h <= 0) {
mipmap_h = 1;
}
}
if (texmem != nullptr) {
vm_free(texmem);
}
break;
}
} // end switch
tSlot->bitmap_handle = bitmap_handle;
tSlot->size = (dsize) ? ((doffset + dsize) - skip_size) : (tex_w * tex_h * byte_mult);
tSlot->w = (ushort)tex_w;
tSlot->h = (ushort)tex_h;
tSlot->size = (dsize) ? ((doffset + dsize) - skip_size) : (tex_w * tex_h * byte_mult);
tSlot->w = (ushort)tex_w;
tSlot->h = (ushort)tex_h;
GL_textures_in_frame += tSlot->size;
@@ -780,6 +819,8 @@ void opengl_tex_array_storage(GLenum target, GLint levels, GLenum format, GLint
mip_height = std::max(1, (mip_height / 2));
}
}
// Make sure that the image is complete with the right number of mipmap levels
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels);
}
} else {
if (GLAD_GL_ARB_texture_storage) {
@@ -791,6 +832,8 @@ void opengl_tex_array_storage(GLenum target, GLint levels, GLenum format, GLint
width = std::max(1, (width / 2));
height = std::max(1, (height / 2));
}
// Make sure that the image is complete with the right number of mipmap levels
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels);
}
}
}
@@ -856,6 +899,10 @@ int opengl_create_texture(int bitmap_handle, int bitmap_type, tcache_slot_opengl
}
Assert( (max_levels - base_level) >= 1 );
// Adjust the size to match the size of the used base-mipmap
width >>= base_level;
height >>= base_level;
}
}
@@ -897,19 +944,24 @@ int opengl_create_texture(int bitmap_handle, int bitmap_type, tcache_slot_opengl
GLenum min_filter = GL_LINEAR;
auto mipmap_levels = (ubyte)(max_levels - base_level);
auto mipmap_levels = max_levels - base_level;
// Needed in case we need to allocate more mipmaps than are in the texture file
auto allocated_mipmap_levels = mipmap_levels;
if (mipmap_levels > 1) {
min_filter = (GL_mipmap_filter) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR_MIPMAP_NEAREST;
if ( GLAD_GL_EXT_texture_filter_anisotropic ) {
glTexParameterf(tslot->texture_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_anisotropy);
}
} else if (mipmap_levels == 1 && bitmap_type == TCACHE_TYPE_CUBEMAP) {
Assertion(num_frames == 1, "Cube map arrays are not supported yet!");
// For cubemaps without mipmaps, we will generate them later so we need to make sure that enough space is
// allocated for the generated mipmaps
allocated_mipmap_levels = get_num_mipmap_levels(width, height);
min_filter = GL_LINEAR_MIPMAP_LINEAR;
}
if (base_level != 0) {
glTexParameteri(tslot->texture_target, GL_TEXTURE_BASE_LEVEL, base_level);
}
glTexParameteri(tslot->texture_target, GL_TEXTURE_MAX_LEVEL, mipmap_levels);
glTexParameteri(tslot->texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(tslot->texture_target, GL_TEXTURE_MIN_FILTER, min_filter);
glTexParameteri(tslot->texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -923,7 +975,7 @@ int opengl_create_texture(int bitmap_handle, int bitmap_type, tcache_slot_opengl
opengl_determine_bpp_and_flags(animation_begin, bitmap_type, bitmap_flags, bits_per_pixel);
auto intFormat = opengl_get_internal_format(bitmap_handle, bitmap_type, bits_per_pixel);
opengl_tex_array_storage(tslot->texture_target, max_levels, intFormat, width, height, num_frames);
opengl_tex_array_storage(tslot->texture_target, allocated_mipmap_levels, intFormat, width, height, num_frames);
bool frames_loaded = true;
for (int frame = animation_begin; frame < animation_begin + num_frames; ++frame) {
@@ -961,17 +1013,8 @@ int opengl_create_texture(int bitmap_handle, int bitmap_type, tcache_slot_opengl
frame_slot->array_index = (uint32_t) (frame - animation_begin);
// call the helper
int ret_val = opengl_texture_set_level(frame,
bitmap_type,
bmp->w,
bmp->h,
width,
height,
(ubyte*) bmp->data,
frame_slot,
base_level,
resize,
intFormat);
int ret_val = opengl_texture_set_level(frame, bitmap_type, bmp->w, bmp->h, width, height, (ubyte*)bmp->data,
frame_slot, base_level, mipmap_levels, resize, intFormat);
frames_loaded = frames_loaded && ret_val;
// unlock the bitmap
@@ -980,12 +1023,8 @@ int opengl_create_texture(int bitmap_handle, int bitmap_type, tcache_slot_opengl
if ( tslot->mipmap_levels == 1 && bitmap_type == TCACHE_TYPE_CUBEMAP ) {
Assertion(num_frames == 1, "Cube map arrays are not supported yet!");
// generate mip maps for cube maps so we can get glossy reflections; necessary for gloss maps and physically-based lighting
// OGL_EXT_FRAMEBUFFER_OBJECT required to use glGenerateMipmap()
tslot->mipmap_levels = get_num_mipmap_levels(tslot->w, tslot->h);
glTexParameteri(tslot->texture_target, GL_TEXTURE_MAX_LEVEL, tslot->mipmap_levels - 1);
glTexParameteri(tslot->texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// generate mip maps for cube maps so we can get glossy reflections; necessary for gloss maps and
// physically-based lighting OGL_EXT_FRAMEBUFFER_OBJECT required to use glGenerateMipmap()
glGenerateMipmap(tslot->texture_target);
}
-1
View File
@@ -80,7 +80,6 @@ void opengl_tcache_frame();
void opengl_set_additive_tex_env();
void opengl_set_modulate_tex_env();
void opengl_preload_init();
GLfloat opengl_get_max_anisotropy();
void opengl_kill_render_target(bitmap_slot* slot);
int opengl_make_render_target(int handle, int *w, int *h, int *bpp, int *mm_lvl, int flags);
int opengl_set_render_target(int slot, int face = -1, int is_static = 0);
+39 -18
View File
@@ -12,28 +12,29 @@
#include <windows.h>
#endif
#include "ShaderProgram.h"
#include "gropengldeferred.h"
#include "gropengldraw.h"
#include "gropenglshader.h"
#include "gropenglstate.h"
#include "gropengltexture.h"
#include "gropengltnl.h"
#include "cmdline/cmdline.h"
#include "def_files/def_files.h"
#include "globalincs/alphacolors.h"
#include "globalincs/systemvars.h"
#include "graphics/2d.h"
#include "graphics/matrix.h"
#include "graphics/grinternal.h"
#include "gropengldraw.h"
#include "gropenglshader.h"
#include "gropenglstate.h"
#include "gropengltexture.h"
#include "gropengldeferred.h"
#include "gropengltnl.h"
#include "graphics/light.h"
#include "graphics/material.h"
#include "graphics/matrix.h"
#include "graphics/shadows.h"
#include "lighting/lighting.h"
#include "math/vecmat.h"
#include "options/Option.h"
#include "particle/particle.h"
#include "render/3d.h"
#include "weapon/trails.h"
#include "particle/particle.h"
#include "graphics/shadows.h"
#include "graphics/material.h"
#include "graphics/light.h"
#include "ShaderProgram.h"
extern int GLOWMAP;
extern int CLOAKMAP;
@@ -61,6 +62,7 @@ GLint GL_max_elements_indices = 4096;
GLuint Shadow_map_texture = 0;
GLuint Shadow_map_depth_texture = 0;
GLuint shadow_fbo = 0;
int Shadow_texture_size = 0;
bool Rendering_to_shadow_map = false;
int Transform_buffer_handle = -1;
@@ -421,6 +423,8 @@ static bool opengl_init_shadow_framebuffer(int size, GLenum color_format)
glGenTextures(1, &Shadow_map_depth_texture);
GL_state.Texture.SetActiveUnit(0);
GL_state.Texture.SetTarget(GL_TEXTURE_2D_ARRAY);
GL_state.Texture.Enable(Shadow_map_depth_texture);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -453,6 +457,7 @@ static bool opengl_init_shadow_framebuffer(int size, GLenum color_format)
if (status == GL_FRAMEBUFFER_COMPLETE) {
// Everything is fine
mprintf(("Shadow framebuffer created successfully.\n"));
Shadow_texture_size = size;
return true;
}
@@ -489,13 +494,30 @@ void opengl_tnl_init()
{
Transform_buffer_handle = opengl_create_texture_buffer_object();
if (Cmdline_shadow_quality) {
int size = (Cmdline_shadow_quality == 2 ? 1024 : 512);
if (Shadow_quality != ShadowQuality::Disabled) {
int size;
switch (Shadow_quality) {
case ShadowQuality::Low:
size = 512;
break;
case ShadowQuality::Medium:
size = 1024;
break;
case ShadowQuality::High:
size = 2048;
break;
case ShadowQuality::Ultra:
size = 4096;
break;
default:
size = 256;
break;
}
if (!opengl_init_shadow_framebuffer(size, GL_RGBA32F)) {
if (!opengl_init_shadow_framebuffer(size, GL_RGBA16F)) {
mprintf(("Failed to create either 32 or 16-bit color shadow framebuffer. Disabling shadow support.\n"));
Cmdline_shadow_quality = 0;
Shadow_quality = ShadowQuality::Disabled;
}
}
}
@@ -626,7 +648,7 @@ extern bool gr_htl_projection_matrix_set;
void gr_opengl_shadow_map_start(matrix4 *shadow_view_matrix, const matrix *light_orient)
{
if ( !Cmdline_shadow_quality )
if (Shadow_quality == ShadowQuality::Disabled)
return;
GL_state.PushFramebufferState();
@@ -650,8 +672,7 @@ void gr_opengl_shadow_map_start(matrix4 *shadow_view_matrix, const matrix *light
*shadow_view_matrix = gr_view_matrix;
int size = (Cmdline_shadow_quality == 2 ? 1024 : 512);
glViewport(0, 0, size, size);
glViewport(0, 0, Shadow_texture_size, Shadow_texture_size);
}
void gr_opengl_shadow_map_end()
+5 -3
View File
@@ -490,8 +490,6 @@ int NanoVGRenderer::createTexture(int type, int w, int h, int imageFlags, const
img.width = w;
img.height = h;
bm_get_info(img.bitmap);
auto id = ++_lastImageId;
_textureMap.insert(std::make_pair(id, std::move(img)));
@@ -509,7 +507,11 @@ int NanoVGRenderer::updateTexture(int image, int /*x*/, int /*y*/, int /*w*/,
} else {
bpp = 8;
}
bm_get_info(texture->bitmap);
// Copy the updated data to our internal buffer so that changes in the hardware texture detail don't discard the
// changes NanoVG made to the texture
memcpy(texture->data.get(), data, texture->width * texture->height * bpp / 8);
// TODO: This could probably be done better by only uploading the changed area
gr_update_texture(texture->bitmap, bpp, data, texture->width, texture->height);
+27 -5
View File
@@ -1,21 +1,22 @@
/*
* Copyright (C) Freespace Open 2013. All rights reserved.
*
* All source code herein is the property of Freespace Open. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* All source code herein is the property of Freespace Open. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
*/
#include "graphics/shadows.h"
#include "asteroid/asteroid.h"
#include "cmdline/cmdline.h"
#include "debris/debris.h"
#include "graphics/shadows.h"
#include "graphics/matrix.h"
#include "lighting/lighting.h"
#include "math/vecmat.h"
#include "model/model.h"
#include "model/modelrender.h"
#include "options/Option.h"
#include "render/3d.h"
#include "tracing/tracing.h"
@@ -27,6 +28,27 @@ float Shadow_cascade_distances[MAX_SHADOW_CASCADES];
light_frustum_info Shadow_frustums[MAX_SHADOW_CASCADES];
ShadowQuality Shadow_quality;
auto ShadowQualityOption =
options::OptionBuilder<ShadowQuality>("Graphics.Shadows", "Shadow Quality", "The quality of the shadows")
.values({{ShadowQuality::Disabled, "Disabled"},
{ShadowQuality::Low, "Low"},
{ShadowQuality::Medium, "Medium"},
{ShadowQuality::High, "High"},
{ShadowQuality::Ultra, "Ultra"}})
.change_listener([](ShadowQuality val, bool initial) {
if (initial) {
Shadow_quality = val;
}
return initial; // No dynamic changes implemented
})
.level(options::ExpertLevel::Advanced)
.category("Graphics")
.default_val(ShadowQuality::Disabled)
.importance(80)
.finish();
bool shadows_obj_in_frustum(object *objp, matrix *light_orient, vec3d *min, vec3d *max)
{
vec3d pos, pos_rot;
@@ -402,7 +424,7 @@ void shadows_render_all(float fov, matrix *eye_orient, vec3d *eye_pos)
return;
}
if (!Cmdline_shadow_quality) {
if (Shadow_quality == ShadowQuality::Disabled) {
return;
}
+5 -1
View File
@@ -25,6 +25,10 @@ struct light_frustum_info
float start_dist;
};
enum class ShadowQuality { Disabled = 0, Low = 1, Medium = 2, High = 3, Ultra = 4 };
extern ShadowQuality Shadow_quality;
extern matrix4 Shadow_view_matrix;
extern matrix4 Shadow_proj_matrix[MAX_SHADOW_CASCADES];
extern float Shadow_cascade_distances[MAX_SHADOW_CASCADES];
@@ -36,4 +40,4 @@ void shadows_render_all(float fov, matrix *eye_orient, vec3d *eye_pos);
matrix shadows_start_render(matrix *eye_orient, vec3d *eye_pos, float fov, float aspect, float veryneardist, float neardist, float middist, float fardist);
void shadows_end_render();
#endif
#endif
+43 -9
View File
@@ -5,7 +5,7 @@
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
*/
#include "ai/aigoals.h"
@@ -23,9 +23,10 @@
#include "hud/hudets.h"
#include "hud/hudlock.h"
#include "hud/hudmessage.h"
#include "hud/hudnavigation.h" //kazan
#include "hud/hudnavigation.h" //kazan
#include "hud/hudobserver.h"
#include "hud/hudreticle.h"
#include "hud/hudscripting.h"
#include "hud/hudshield.h"
#include "hud/hudsquadmsg.h"
#include "hud/hudtarget.h"
@@ -50,6 +51,7 @@
#include "radar/radar.h"
#include "radar/radarsetup.h"
#include "render/3d.h"
#include "scripting/scripting.h"
#include "ship/ship.h"
#include "starfield/supernova.h"
#include "weapon/emp.h"
@@ -246,7 +248,7 @@ static int Damage_flash_timer;
HudGauge::HudGauge():
base_w(0), base_h(0), gauge_config(-1), font_num(font::FONT1), lock_color(false), sexp_lock_color(false), reticle_follow(false),
active(false), off_by_default(false), sexp_override(false), pop_up(false), disabled_views(0), custom_gauge(false),
active(false), off_by_default(false), sexp_override(false), pop_up(false), disabled_views(0), only_render_in_chase_view(false), custom_gauge(false),
texture_target(-1), canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1)
{
position[0] = 0;
@@ -271,7 +273,7 @@ texture_target(-1), canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1)
HudGauge::HudGauge(int _gauge_object, int _gauge_config, bool _slew, bool _message, int _disabled_views, int r, int g, int b):
base_w(0), base_h(0), gauge_config(_gauge_config), gauge_object(_gauge_object), font_num(font::FONT1), lock_color(false), sexp_lock_color(false),
reticle_follow(_slew), active(false), off_by_default(false), sexp_override(false), pop_up(false), message_gauge(_message),
disabled_views(_disabled_views), custom_gauge(false), textoffset_x(0), textoffset_y(0), texture_target(-1),
disabled_views(_disabled_views), only_render_in_chase_view(false), custom_gauge(false), textoffset_x(0), textoffset_y(0), texture_target(-1),
canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1)
{
Assert(gauge_config <= NUM_HUD_GAUGES && gauge_config >= 0);
@@ -307,8 +309,8 @@ canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1)
HudGauge::HudGauge(int _gauge_config, bool _slew, int r, int g, int b, char* _custom_name, char* _custom_text, char* frame_fname, int txtoffset_x, int txtoffset_y):
base_w(0), base_h(0), gauge_config(_gauge_config), gauge_object(HUD_OBJECT_CUSTOM), font_num(font::FONT1), lock_color(false), sexp_lock_color(false),
reticle_follow(_slew), active(false), off_by_default(false), sexp_override(false), pop_up(false), message_gauge(false),
disabled_views(VM_EXTERNAL | VM_DEAD_VIEW | VM_WARP_CHASE | VM_PADLOCK_ANY), custom_gauge(true), textoffset_x(txtoffset_x),
textoffset_y(txtoffset_y), texture_target(-1), canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1)
disabled_views(VM_EXTERNAL | VM_DEAD_VIEW | VM_WARP_CHASE | VM_PADLOCK_ANY), only_render_in_chase_view(false), custom_gauge(true), textoffset_x(txtoffset_x),
textoffset_y(txtoffset_y), texture_target(-1), canvas_w(-1), canvas_h(-1), target_w(-1), target_h(-1)
{
position[0] = 0;
position[1] = 0;
@@ -546,6 +548,11 @@ void HudGauge::initRenderStatus(bool do_render)
off_by_default = !do_render;
}
void HudGauge::initChase_view_only(bool chase_view_only)
{
only_render_in_chase_view = chase_view_only;
}
bool HudGauge::isOffbyDefault()
{
return off_by_default;
@@ -917,7 +924,7 @@ void HudGauge::renderRect(int x, int y, int w, int h)
gr_reset_screen_scale();
}
void HudGauge::renderCircle(int x, int y, int diameter)
void HudGauge::renderCircle(int x, int y, int diameter, bool filled)
{
int nx = 0, ny = 0;
@@ -935,8 +942,12 @@ void HudGauge::renderCircle(int x, int y, int diameter)
gr_set_screen_scale(base_w, base_h);
}
}
if (filled) {
gr_circle(x + nx, y + ny, diameter);
} else {
gr_unfilled_circle(x + nx, y + ny, diameter);
}
gr_circle(x+nx, y+ny, diameter);
gr_reset_screen_scale();
}
@@ -1082,6 +1093,10 @@ bool HudGauge::canRender()
return false;
}
if ((Viewer_mode & (VM_CHASE)) == 0 && only_render_in_chase_view) {
return false;
}
if(pop_up) {
if(!popUpActive()) {
return false;
@@ -1222,6 +1237,25 @@ void HUD_init()
default_hud_gauges[j]->resetTimers();
default_hud_gauges[j]->updateSexpOverride(false);
}
Script_system.OnStateDestroy.add(hud_scripting_close);
}
void hud_scripting_close(lua_State*) {
// Clean up Lua references so that we don't have dangling references on to the lua state in the HUD gauges
for (auto it = Ship_info.begin(); it != Ship_info.end(); ++it) {
for (const auto& gauge : it->hud_gauges) {
if (gauge->getObjectType() == HUD_OBJECT_SCRIPTING) {
static_cast<HudGaugeScripting*>(gauge.get())->setRenderFunction(luacpp::LuaFunction());
}
}
}
for (const auto& gauge : default_hud_gauges) {
if (gauge->getObjectType() == HUD_OBJECT_SCRIPTING) {
static_cast<HudGaugeScripting*>(gauge.get())->setRenderFunction(luacpp::LuaFunction());
}
}
}
/**
@@ -3911,7 +3945,7 @@ void HudGaugeSupernova::render(float /*frametime*/)
if (Lcl_pl) {
renderPrintf(position[0], position[1], "Wybuch supernowej: %.2f s", time_left);
} else {
renderPrintf(position[0], position[1], "Supernova Warning: %.2f s", time_left);
renderPrintf(position[0], position[1], XSTR( "Supernova Warning: %.2f s", 1639), time_left);
}
}
+4 -2
View File
@@ -110,6 +110,7 @@ extern int Hud_max_targeting_range;
void HUD_init_colors();
void HUD_init();
void hud_scripting_close(lua_State*);
void hud_close();
void hud_level_close();
void hud_update_frame(float frametime); // updates hud systems not dependant on rendering
@@ -223,6 +224,7 @@ protected:
int flash_duration;
int flash_next;
bool flash_status;
bool only_render_in_chase_view;
// custom gauge specific stuff
bool custom_gauge;
@@ -268,7 +270,7 @@ public:
void updateActive(bool show);
void updatePopUp(bool pop_up_flag);
void updateSexpOverride(bool sexp);
void initChase_view_only(bool chase_view_only);
// SEXP interfacing functions
// For flashing gauges in training missions
@@ -316,7 +318,7 @@ public:
void renderLine(int x1, int y1, int x2, int y2);
void renderGradientLine(int x1, int y1, int x2, int y2);
void renderRect(int x, int y, int w, int h);
void renderCircle(int x, int y, int diameter);
void renderCircle(int x, int y, int diameter, bool filled = true);
void unsize(int *x, int *y);
void unsize(float *x, float *y);
+27 -1
View File
@@ -95,6 +95,32 @@ void parse_ssm(const char *filename)
s.max_count = -1;
}
if (optional_string("+WarpEffect:")) {
int temp;
if (stuff_int_optional(&temp) != 2) {
// We have a string to parse instead.
char unique_id[NAME_LENGTH];
memset(unique_id, 0, NAME_LENGTH);
stuff_string(unique_id, F_NAME, NAME_LENGTH);
int fireball_type = fireball_info_lookup(unique_id);
if (fireball_type < 0) {
error_display(1, "Unknown fireball [%s] to use as warp effect for SSM strike [%s]", unique_id, s.name);
s.fireball_idx = FIREBALL_WARP;
} else {
s.fireball_idx = fireball_type;
}
} else {
if ((temp < 0) || (temp >= Num_fireball_types)) {
error_display(1, "Fireball index [%d] out of range (should be 0-%d) for SSM strike [%s]", temp, Num_fireball_types - 1, s.name);
s.fireball_idx = FIREBALL_WARP;
} else {
s.fireball_idx = temp;
}
}
} else {
s.fireball_idx = FIREBALL_WARP;
}
required_string("+WarpRadius:");
stuff_float(&s.warp_radius);
@@ -422,7 +448,7 @@ void ssm_process()
vm_vec_sub(&temp, &moveup->sinfo.target->pos, &moveup->sinfo.start_pos[idx]);
vm_vec_normalize(&temp);
vm_vector_2_matrix(&orient, &temp, NULL, NULL);
moveup->fireballs[idx] = fireball_create(&moveup->sinfo.start_pos[idx], FIREBALL_WARP, FIREBALL_WARP_EFFECT, -1, si->warp_radius, 0, &vmd_zero_vector, si->warp_time, 0, &orient);
moveup->fireballs[idx] = fireball_create(&moveup->sinfo.start_pos[idx], si->fireball_idx, FIREBALL_WARP_EFFECT, -1, si->warp_radius, false, &vmd_zero_vector, si->warp_time, 0, &orient);
}
}
}
+2 -1
View File
@@ -30,6 +30,7 @@ typedef struct ssm_info {
int count; // # of missiles in this type of strike
int max_count; // Maximum # of missiles in this type of strike (-1 for no variance)
int weapon_info_index; // missile type
int fireball_idx; // Type of fireball to use for warp effect (defaults to FIREBALL_WARP)
float warp_radius; // radius of associated warp effect
float warp_time; // how long the warp effect lasts
float radius; // radius around the target ship
@@ -49,7 +50,7 @@ typedef struct ssm_firing_info {
SCP_vector<vec3d> start_pos; // start positions
int count; // The ssm_info count may be variable; this stores the actual number of projectiles for this strike.
size_t ssm_index; // index info ssm_info array
size_t ssm_index; // index into ssm_info array
class object* target; // target for the strike
int ssm_team; // team that fired the ssm.
float duration; // how far into the warp effect to fire
-367
View File
@@ -46,7 +46,6 @@ void hud_init_brackets()
{
}
// Called by draw_bounding_brackets.
void draw_brackets_square(graphics::line_draw_list* draw_list, int x1, int y1, int x2, int y2, int resize_mode)
{
int width, height;
@@ -140,112 +139,6 @@ void draw_brackets_square_quick(graphics::line_draw_list* draw_list, int x1, int
}
}
#define NUM_DASHES 2
void draw_brackets_dashed_square_quick(graphics::line_draw_list* draw_list, int x1, int y1, int x2, int y2)
{
int width, height, i;
width = x2 - x1;
height = y2 - y1;
// make the brackets extend 25% of the way along the width or height
float bracket_width = width/4.0f;
float bracket_height = height/4.0f;
int dash_width = (int)std::lround(bracket_width / ( NUM_DASHES*2 - 1 ));
if ( dash_width < 1 ) {
draw_brackets_square_quick(draw_list, x1, y1, x2, y2);
return;
}
int dash_height = (int)std::lround(bracket_height / ( NUM_DASHES*2 - 1 ));
if ( dash_height < 1 ) {
draw_brackets_square_quick(draw_list, x1, y1, x2, y2);
return;
}
int dash_x1, dash_x2, dash_y1, dash_y2;
dash_x1 = x1;
dash_x2 = x2;
dash_y1 = y1;
dash_y2 = y2;
for ( i = 0; i < NUM_DASHES; i++ ) {
// top line
draw_list->add_line(dash_x1, y1, dash_x1+(dash_width-1), y1);
draw_list->add_line(dash_x2, y1, dash_x2-(dash_width-1), y1);
// bottom line
draw_list->add_line(dash_x1, y2, dash_x1+(dash_width-1), y2);
draw_list->add_line(dash_x2, y2, dash_x2-(dash_width-1), y2);
dash_x1 += dash_width*2;
dash_x2 -= dash_width*2;
// left line
draw_list->add_line(x1, dash_y1, x1, dash_y1+(dash_height-1));
draw_list->add_line(x1, dash_y2, x1, dash_y2-(dash_height-1));
// right line
draw_list->add_line(x2, dash_y1, x2, dash_y1+(dash_height-1));
draw_list->add_line(x2, dash_y2, x2, dash_y2-(dash_height-1));
dash_y1 += dash_height*2;
dash_y2 -= dash_height*2;
}
}
// draw_brackets_diamond()
// Called by draw_bounding_brackets.
void draw_brackets_diamond(graphics::line_draw_list* draw_list, int x1, int y1, int x2, int y2)
{
int width, height, half_width, half_height;
int center_x, center_y;
int x_delta, y_delta;
float side_len, bracket_len;
width = x2 - x1;
height = y2 - y1;
half_width = (int)std::lround( width/2.0f );
half_height = (int)std::lround( height/2.0f );
side_len = (float)_hypot(half_width, half_height);
bracket_len = side_len / 8;
x_delta = (int)std::lround(bracket_len * width / side_len);
y_delta = (int)std::lround(bracket_len * height / side_len);
center_x = x1 + half_width;
center_y = y1 + half_height;
// top left line
draw_list->add_gradient(center_x - x_delta, y1 + y_delta,center_x, y1);
draw_list->add_gradient(x1 + x_delta, center_y - y_delta, x1, center_y);
// top right line
draw_list->add_gradient(center_x + x_delta, y1 + y_delta,center_x, y1);
draw_list->add_gradient(x2 - x_delta, center_y - y_delta, x2, center_y);
// bottom left line
draw_list->add_gradient(x1 + x_delta, center_y + y_delta, x1, center_y);
draw_list->add_gradient(center_x - x_delta, y2 - y_delta, center_x, y2);
// bottom right line
draw_list->add_gradient(x2 - x_delta, center_y + y_delta, x2, center_y);
draw_list->add_gradient(center_x + x_delta, y2 - y_delta, center_x, y2);
}
void draw_brackets_diamond_quick(graphics::line_draw_list* draw_list, int x1, int y1, int x2, int y2)
{
int width, height, half_width, half_height;
@@ -290,91 +183,6 @@ void draw_brackets_diamond_quick(graphics::line_draw_list* draw_list, int x1, in
draw_list->add_line(center_x-x_delta, center_y+y_delta, center_x+x_delta, center_y-y_delta);
}
// Draw bounding brackets for a subobject.
// unused function, candidate for removal
#if 0
void draw_bounding_brackets_subobject()
{
if (Player_ai->targeted_subsys_parent == Player_ai->target_objnum)
if (Player_ai->targeted_subsys != NULL) {
ship_subsys *subsys;
int target_objnum;
object* targetp;
vertex subobj_vertex;
vec3d subobj_pos;
int x1,x2,y1,y2;
subsys = Player_ai->targeted_subsys;
target_objnum = Player_ai->target_objnum;
Assert(target_objnum != -1);
targetp = &Objects[target_objnum];
Assert( targetp->type == OBJ_SHIP );
get_subsystem_world_pos(targetp, subsys, &subobj_pos);
g3_rotate_vertex(&subobj_vertex,&subobj_pos);
g3_project_vertex(&subobj_vertex);
if (subobj_vertex.flags & PF_OVERFLOW) // if overflow, no point in drawing brackets
return;
int subobj_x = fl2i(subobj_vertex.screen.xyw.x + 0.5f);
int subobj_y = fl2i(subobj_vertex.screen.xyw.y + 0.5f);
int hud_subtarget_w, hud_subtarget_h, bound_rc;
bound_rc = subobj_find_2d_bound(subsys->system_info->radius, &targetp->orient, &subobj_pos, &x1,&y1,&x2,&y2);
if ( bound_rc != 0 )
return;
hud_subtarget_w = x2-x1+1;
if ( hud_subtarget_w > gr_screen.clip_width ) {
hud_subtarget_w = gr_screen.clip_width;
}
hud_subtarget_h = y2-y1+1;
if ( hud_subtarget_h > gr_screen.clip_height ) {
hud_subtarget_h = gr_screen.clip_height;
}
if ( hud_subtarget_w > gr_screen.max_w ) {
x1 = subobj_x - (gr_screen.max_w>>1);
x2 = subobj_x + (gr_screen.max_w>>1);
}
if ( hud_subtarget_h > gr_screen.max_h ) {
y1 = subobj_y - (gr_screen.max_h>>1);
y2 = subobj_y + (gr_screen.max_h>>1);
}
// *** these unsize take care of everything below ***
gr_unsize_screen_pos( &hud_subtarget_w, &hud_subtarget_h );
gr_unsize_screen_pos( &subobj_x, &subobj_y );
gr_unsize_screen_pos( &x1, &y1 );
gr_unsize_screen_pos( &x2, &y2 );
// determine if subsystem is on far or near side of the ship
Player->subsys_in_view = ship_subsystem_in_sight(targetp, subsys, &View_position, &subobj_pos, 0);
// AL 29-3-98: If subsystem is destroyed, draw gray brackets
// Goober5000: this will now execute for fighterbays if the bay has been given a
// percentage subsystem strength in ships.tbl
// Goober5000: this will now execute for any subsys that takes damage and will not
// execute for any subsys that doesn't take damage
if ( (Player_ai->targeted_subsys->current_hits <= 0) && ( ship_subsys_takes_damage(Player_ai->targeted_subsys) ) ) {
gr_set_color_fast(iff_get_color(IFF_COLOR_MESSAGE, 1));
} else {
hud_set_iff_color( targetp, 1 );
}
if ( Player->subsys_in_view ) {
draw_brackets_square_quick(x1, y1, x2, y2);
} else {
draw_brackets_diamond_quick(x1, y1, x2, y2);
}
// mprintf(("Drawing subobject brackets at %4i, %4i\n", sx, sy));
}
}
#endif
extern int HUD_drew_selection_bracket_on_target;
//Do we want to show the ship & class name?
extern int Cmdline_targetinfo;
@@ -414,181 +222,6 @@ int Ships_attacking_bitmap = -1;
int num_ships_attacking(int target_objnum);
// draw_bounding_brackets() will draw the faded brackets that surround the current target
// NOTE: x1, y1, x2 & y2 are assumed to be scaled sizes, w_correction & h_correction are assumed to be unscaled!!
// unused function, candidate for removal
#if 0
void draw_bounding_brackets(int x1, int y1, int x2, int y2, int w_correction, int h_correction, float distance, int target_objnum)
{
int width, height;
if ( ( x1 < 0 && x2 < 0 ) || ( y1 < 0 && y2 < 0 ) )
return;
if ( ( x1 > gr_screen.clip_width && x2 > gr_screen.clip_width ) ||
( y1 > gr_screen.clip_height && y2 > gr_screen.clip_height ) )
return;
// *** everything below is taken care of with this unsize ***
gr_unsize_screen_pos(&x1, &y1);
gr_unsize_screen_pos(&x2, &y2);
width = x2-x1;
Assert(width>=0);
height = y2-y1;
Assert(height>=0);
if ( (width >= (gr_screen.max_w_unscaled)) && (height >= (gr_screen.max_h_unscaled)) ) {
return;
}
if (width < Min_target_box_width[gr_screen.res]) {
x1 = x1 - (Min_target_box_width[gr_screen.res]-width)/2;
x2 = x2 + (Min_target_box_width[gr_screen.res]-width)/2;
}
if (height < Min_target_box_height[gr_screen.res]) {
y1 = y1 - (Min_target_box_height[gr_screen.res]-height)/2;
y2 = y2 + (Min_target_box_height[gr_screen.res]-height)/2;
}
draw_brackets_square(x1-w_correction, y1-h_correction, x2+w_correction, y2+h_correction);
// draw distance to target in lower right corner of box
if ( distance > 0 ) {
hud_target_show_dist_on_bracket(x2+w_correction,y2+h_correction,distance);
}
// Maybe show + for each additional fighter or bomber attacking target.
if ( (target_objnum != -1) && hud_gauge_active(HUD_ATTACKING_TARGET_COUNT) ) {
int num_attacking = num_ships_attacking(target_objnum);
if (Ships_attacking_bitmap == -1){
Ships_attacking_bitmap = bm_load(Ships_attack_fname[gr_screen.res]);
}
if (Ships_attacking_bitmap == -1) {
Int3();
return;
}
// If a ship is attacked by player, show one fewer plus
int k=0;
if (Objects[target_objnum].type == OBJ_SHIP) {
if (iff_x_attacks_y(Player_ship->team, Ships[Objects[target_objnum].instance].team)) {
k = 1;
}
} else {
k = 1;
}
if (num_attacking > k) {
int i, num_blips;
num_blips = num_attacking-k;
if (num_blips > 4){
num_blips = 4;
}
if (Ships_attacking_bitmap >= 0) {
if (num_blips > 3)
y1 -= 3;
for (i=0; i<num_blips; i++) {
GR_AABITMAP(Ships_attacking_bitmap, x2+3, y1+i*7);
}
}
//Increment for the position of ship name/class.
//DEPENDANT ON ATTACKER SIZE (X)
x2 += 7;
}
}
if(Cmdline_targetinfo && (target_objnum != -1))
{
object* t_objp = &Objects[target_objnum];
const char* tinfo_name = NULL;
const char* tinfo_class = NULL;
char temp_name[NAME_LENGTH*2+3];
char temp_class[NAME_LENGTH];
SCP_list<CJumpNode>::iterator jnp;
switch(t_objp->type)
{
case OBJ_SHIP:
hud_stuff_ship_name(temp_name, &Ships[t_objp->instance]);
hud_stuff_ship_class(temp_class, &Ships[t_objp->instance]);
tinfo_name = temp_name;
tinfo_class = temp_class;
// maybe concatenate the callsign
if (*temp_name)
{
char temp_callsign[NAME_LENGTH];
hud_stuff_ship_callsign(temp_callsign, &Ships[t_objp->instance]);
if (*temp_callsign)
sprintf(&temp_name[strlen(temp_name)], " (%s)", temp_callsign);
}
// maybe substitute the callsign
else
{
hud_stuff_ship_callsign(temp_name, &Ships[t_objp->instance]);
}
break;
case OBJ_DEBRIS:
tinfo_name = XSTR("Debris", 348);
break;
case OBJ_WEAPON:
strcpy_s(temp_name, Weapon_info[Weapons[t_objp->instance].weapon_info_index].name);
end_string_at_first_hash_symbol(temp_name);
tinfo_name = temp_name;
break;
case OBJ_ASTEROID:
switch(Asteroids[t_objp->instance].asteroid_type)
{
case ASTEROID_TYPE_SMALL:
case ASTEROID_TYPE_MEDIUM:
case ASTEROID_TYPE_LARGE:
tinfo_name = NOX("Asteroid");
break;
default:
tinfo_name = XSTR("Debris", 348);
}
break;
case OBJ_JUMP_NODE:
for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
if(jnp->GetSCPObject() == t_objp)
break;
}
strcpy_s(temp_name, jnp->GetName());
end_string_at_first_hash_symbol(temp_name);
tinfo_name = temp_name;
break;
}
if(tinfo_name)
{
gr_string(x2+3, y1, tinfo_name);
}
if(tinfo_class)
{
gr_string(x2+3, y1+9, tinfo_class);
}
/*
if(tinfo_callsign)
{
gr_string(x2+3, y1+18, tinfo_callsign);
}
*/
}
}
#endif
int draw_subsys_brackets(graphics::line_draw_list* draw_list, ship_subsys* subsys, int min_width, int min_height, bool draw, bool set_color, int* draw_coords)
{
Assertion(subsys != NULL, "Invalid subsystem pointer passed to draw_subsys_brackets!");
-8
View File
@@ -16,16 +16,9 @@
#include "graphics/line_draw_list.h"
void hud_init_brackets();
// two unused functions, candidates for removal?
#if 0
void draw_bounding_brackets(int x1, int y1, int x2, int y2, int w_correction, int h_correction, float distance=0.0f, int target_objnum=-1);
void draw_bounding_brackets_subobject();
#endif
void draw_brackets_square(graphics::line_draw_list* draw_list, int x1, int y1, int x2, int y2, int resize_mode = GR_RESIZE_FULL);
void draw_brackets_diamond(graphics::line_draw_list* draw_list, int x1, int y1, int x2, int y2);
void draw_brackets_square_quick(graphics::line_draw_list* draw_list, int x1, int y1, int x2, int y2, int thick=0);
void draw_brackets_diamond_quick(graphics::line_draw_list* draw_list, int x1, int y1, int x2, int y2);
void draw_brackets_dashed_square_quick(graphics::line_draw_list* draw_list, int x1, int y1, int x2, int y2);
int draw_subsys_brackets(graphics::line_draw_list* draw_list, ship_subsys* subsys, int min_width, int min_height, bool draw = true, bool set_color = true, int* draw_coords = NULL);
@@ -50,7 +43,6 @@ public:
void renderNavBrackets(vec3d* nav_pos, vertex* nav_point, color* clr, char* string);
void renderBoundingBrackets(int x1, int y1, int x2, int y2, int w_correction, int h_correction, float distance, int target_objnum, int flags);
void renderBoundingBracketsSubobject();
void renderDistance(int x, int y, float distance);
};
#endif
-63
View File
@@ -554,29 +554,6 @@ UI_XSTR HC_text[GR_NUM_RESOLUTIONS][NUM_HUD_TEXT] = {
}
};
void hud_config_set_rgb(int gauge, int r, int g, int b);
void hud_config_set_alpha(int gauge, int a);
/*
#define NUM_HC_SPECIAL_BITMAPS 2
#define HC_SPECIAL_RETICLE 0
#define HC_SPECIAL_TEXT 1
typedef struct HC_special_bitmap
{
char *filename;
int x,y;
int bitmap;
} HC_special_bitmap;
HC_special_bitmap HC_special_bitmaps[NUM_HC_SPECIAL_BITMAPS] =
{
//XSTR:OFF
{"HG_00a", 272, 146, -1},
{"HG_04a", 132, 271, -1},
//XSTR:ON
};
*/
static int HC_background_bitmap;
static int HC_background_bitmap_mask;
static UI_WINDOW HC_ui_window;
@@ -584,46 +561,6 @@ static UI_WINDOW HC_ui_window;
static int HC_gauge_hot; // mouse is over this gauge
static int HC_gauge_selected; // gauge is selected
// slider controls
/*
#define HC_NUM_SLIDERS 1
#define HC_BRIGHTNESS_SLIDER 0
struct hc_sliders {
// base slider
char *filename;
int x, y, xt, yt;
int hotspot;
int dot_w;
int dots;
// left and right buttons
char *left_filename;
int left_mask, left_x, left_y;
char *right_filename;
int right_mask, right_x, right_y;
// slider control
UI_DOT_SLIDER_NEW slider; // because we have a class inside this struct, we need the constructor below..
hc_sliders(char *name, int x1, int y1, int xt1, int yt1, int h, int _dot_w, int _dots, char *_left_filename, int _left_mask, int _left_x, int _left_y, char *_right_filename, int _right_mask, int _right_x, int _right_y) :
filename(name), x(x1), y(y1), xt(xt1), yt(yt1), hotspot(h), dot_w(_dot_w), dots(_dots), left_filename(_left_filename), left_mask(_left_mask), left_x(_left_x), left_y(_left_y), right_filename(_right_filename), right_mask(_right_mask), right_x(_right_x), right_y(_right_y) {}
};
hc_sliders HC_sliders[GR_NUM_RESOLUTIONS][HC_NUM_SLIDERS] = {
{ // GR_640
hc_sliders( "HCB_22", 419, 379, -1, -1, 22, 20, 10,
"HCB_23", 23, 611, 379,
"HCB_21", 21, 391, 379)
},
{ // GR_1024
hc_sliders( "2_HCB_22", 670, 606, -1, -1, 22, 32, 10,
"2_HCB_23", 23, 698, 606,
"2_HCB_21", 21, 625, 606),
}
};
*/
// HUD colors
typedef struct hc_col {
ubyte r, g, b;
-4
View File
@@ -73,11 +73,7 @@ void hud_config_restore();
void hud_config_backup();
void hud_config_as_observer(ship *shipp,ai_info *aif);
void hud_config_as_observer();
void hud_config_as_player();
void hud_config_display_text(char* gauge_text, int x, int y);
void hud_set_display_gauge_cbox();
// leave hud config without accepting changes
void hud_config_cancel();
-89
View File
@@ -51,95 +51,6 @@ escort_info Escort_ships[MAX_COMPLETE_ESCORT_LIST];
int Num_escort_ships;
int Max_escort_ships = 3;
//int Escort_gauge_y[MAX_ESCORT_SHIPS] = { 219, 230, 241 };
/*
int Escort_gauge_text_coords[GR_NUM_RESOLUTIONS][MAX_ESCORT_SHIPS][4][2] =
{
{ // GR_640
{
{489,219},
{599,212},
{604,219},
{474,219}
},
{
{489,230},
{599,223},
{604,230},
{474,230}
},
{
{489,241},
{599,234},
{604,241},
{474,241}
},
},
{ // GR_1024
{
{869,343},
{973,338},
{981,343},
{854,343}
},
{
{869,354},
{973,349},
{981,354},
{854,354}
},
{
{869,365},
{973,360},
{981,365},
{854,365}
},
}
};
// escort gauge coords
int Escort_coords[GR_NUM_RESOLUTIONS][4][2] = {
{ // GR_640
{486, 206},
{486, 219},
{486, 230},
{486, 241}
},
{ // GR_1024
{865, 330},
{865, 343},
{865, 354},
{865, 365}
}
};
// monitoring text coords
int Monitoring_coords[GR_NUM_RESOLUTIONS][2] = {
{ // GR_640
489, 208
},
{ // GR_1024
869, 331
}
};
char *Escort_gauge_filenames[GR_NUM_RESOLUTIONS][MAX_ESCORT_SHIPS] =
{
//XSTR:OFF
{ // GR_640
"escort1",
"escort2",
"escort3"
},
{ // GR_1024
"escort1",
"escort2",
"escort3"
}
//XSTR:ON
};*/
static int Last_target_index; // index into Escort_gauges for last targeted via 'Next Escort Target' key
HudGaugeEscort::HudGaugeEscort():
-1
View File
@@ -24,7 +24,6 @@ class object;
void hud_escort_update_list();
void hud_escort_init();
void hud_setup_escort_list(int level = 1);
void hud_escort_view_toggle();
void hud_add_remove_ship_escort(int objnum, int supress_feedback = 0);
void hud_escort_clear_all(bool clear_flags = false);
void hud_escort_ship_hit(object *objp, int quadrant);
-1
View File
@@ -27,7 +27,6 @@ class object;
#define AI_MODIFY_ETS_INTERVAL 500 // time between ets modifications for ai's (in milliseconds)
#define ZERO_INDEX 0
#define ONE_THIRD_INDEX 4
#define ONE_HALF_INDEX 6
#define ALL_INDEX 12
-2
View File
@@ -15,10 +15,8 @@
#include "hud/hud.h"
void hud_init_missile_lock();
void hud_draw_lock_triangles(int center_x, int center_y, float frametime);
void hud_calculate_lock_position(float frametime);
void hud_calculate_lock_start_pos();
void hud_show_lock_indicator(float frametime, vec3d *lock_point_pos);
void hud_do_lock_indicator(float frametime);
void hud_stop_looped_locking_sounds();
void hud_lock_reset(float lock_time_scale=1.0f);
-38
View File
@@ -551,24 +551,6 @@ void HUD_printf(const char *format, ...)
hud_sourced_print(HUD_SOURCE_COMPUTER, tmp);
}
void HUD_ship_sent_printf(int sh, const char *format, ...)
{
va_list args;
char tmp[HUD_MSG_LENGTH_MAX];
tmp[sizeof(tmp)-1] = '\0';
size_t len;
snprintf(tmp, sizeof(tmp)-1, NOX("%s: "), Ships[sh].get_display_string());
len = strlen(tmp);
va_start(args, format);
vsnprintf(tmp + len, sizeof(tmp)-1-len, format, args);
va_end(args);
Assert(strlen(tmp) < HUD_MSG_LENGTH_MAX); // If greater than this, probably crashed anyway.
hud_sourced_print(HUD_team_get_source(Ships[sh].team), tmp);
}
// --------------------------------------------------------------------------------------
// HUD_sourced_printf()
//
@@ -1235,26 +1217,6 @@ void HudGaugeTalkingHead::initBitmaps(const char *fname)
}
}
/**
* Create a new head animation object
*/
anim_instance* HudGaugeTalkingHead::createAnim(int anim_start_frame, anim* anim_data)
{
anim_play_struct aps;
float scale_x = i2fl(Anim_size[0]) / i2fl(anim_data->width);
float scale_y = i2fl(Anim_size[1]) / i2fl(anim_data->height);
anim_play_init(&aps, anim_data, fl2ir((position[0] + Anim_offsets[0] + HUD_offset_x) / scale_x), fl2ir((position[1] + Anim_offsets[1] + HUD_offset_y) / scale_y), base_w, base_h);
aps.start_at = anim_start_frame;
// aps.color = &HUD_color_defaults[HUD_color_alpha];
aps.color = &HUD_config.clr[HUD_TALKING_HEAD];
// I'd much rather use gr_init_color and retrieve the colors from this object but no, aps.color just happens to be a pointer.
// So, just give it the address from the player's HUD configuration. You win, aps.color. I'll take care of you next time. (Swifty)
return anim_play(&aps);
}
/**
* Renders everything for a head animation
* Also checks for when new head ani's need to start playing
-2
View File
@@ -68,7 +68,6 @@ int HUD_source_get_team(int team);
void HUD_printf(SCP_FORMAT_STRING const char *format, ...) SCP_FORMAT_STRING_ARGS(1, 2);
void hud_sourced_print(int source, const char *msg);
void HUD_sourced_printf(int source, SCP_FORMAT_STRING const char *format, ...) SCP_FORMAT_STRING_ARGS(2, 3); // send hud message from specified source
void HUD_ship_sent_printf(int sh, SCP_FORMAT_STRING const char *format, ...) SCP_FORMAT_STRING_ARGS(2, 3); // send hud message from a specific ship
void HUD_fixed_printf(float duration, color col, SCP_FORMAT_STRING const char *format, ...) SCP_FORMAT_STRING_ARGS(3, 4); // Display a single message for duration seconds.
void HUD_init_fixed_text(); // Clear all pending fixed text.
@@ -140,7 +139,6 @@ public:
void render(float frametime) override;
void initialize() override;
bool canRender() override;
anim_instance* createAnim(int anim_start_frame, anim* anim_data);
};
class HudGaugeFixedMessages: public HudGauge
-24
View File
@@ -58,27 +58,3 @@ void hud_observer_init(ship *shipp, ai_info *aip)
void hud_obs_render_player(int /*loc*/,net_player * /*pl*/)
{
}
void hud_obs_render_players_all()
{
int idx,count;
// render kills and stats information for all players
count = 0;
for(idx=0;idx<MAX_PLAYERS;idx++){
if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_PERM_OBSERVER(Net_players[idx]) ){
hud_obs_render_player(count,&Net_players[idx]);
}
}
}
/**
* Render any specific observer stuff
*/
void hud_render_observer()
{
Assert((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER));
// render individual player text
hud_obs_render_players_all();
}
-2
View File
@@ -22,6 +22,4 @@ extern ai_info Hud_obs_ai;
void hud_observer_init(ship *shipp,ai_info *aip);
void hud_render_observer();
#endif
Loaded 100 of 352 files, more files were not shown because too many files have changed in this diff. Show more