mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-31 05:40:44 +00:00
Merge remote-tracking branch 'gzdoom/master' into ssao
This commit is contained in:
commit
057060022a
104 changed files with 2800 additions and 1999 deletions
|
@ -94,6 +94,15 @@ function( add_pk3 PK3_NAME PK3_DIR )
|
|||
SOURCES ${PK3_SRCS})
|
||||
# Phase 3: Assign source files to a nice folder structure in the IDE
|
||||
assort_pk3_source_folder("Source Files" ${PK3_DIR})
|
||||
# Phase 4: Add the resulting PK3 to the install target.
|
||||
if( WIN32 )
|
||||
set( INSTALL_PK3_PATH . CACHE STRING "Directory where zdoom.pk3 will be placed during install." )
|
||||
else()
|
||||
set( INSTALL_PK3_PATH share/games/doom CACHE STRING "Directory where zdoom.pk3 will be placed during install." )
|
||||
endif()
|
||||
install(FILES "${PROJECT_BINARY_DIR}/${PK3_NAME}"
|
||||
DESTINATION ${INSTALL_PK3_PATH}
|
||||
COMPONENT "Game resources")
|
||||
endfunction()
|
||||
|
||||
# Macro for building libraries without debugging information
|
||||
|
@ -252,6 +261,7 @@ if( ZLIB_FOUND AND NOT FORCE_INTERNAL_ZLIB )
|
|||
message( STATUS "Using system zlib, includes found at ${ZLIB_INCLUDE_DIR}" )
|
||||
else()
|
||||
message( STATUS "Using internal zlib" )
|
||||
set( SKIP_INSTALL_ALL TRUE ) # Avoid installing zlib alongside zdoom
|
||||
add_subdirectory( zlib )
|
||||
set( ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zlib )
|
||||
set( ZLIB_LIBRARIES z )
|
||||
|
@ -295,6 +305,16 @@ if( NOT CMAKE_CROSSCOMPILING )
|
|||
endif()
|
||||
endif()
|
||||
|
||||
# Install the entire docs directory in the distributed zip package
|
||||
if( WIN32 )
|
||||
set( INSTALL_DOCS_PATH docs CACHE STRING "Directory where the documentation will be placed during install." )
|
||||
else()
|
||||
set( INSTALL_DOCS_PATH share/doc/${ZDOOM_EXE_NAME} CACHE STRING "Directory where the zdoom documentation will be placed during install." )
|
||||
endif()
|
||||
install(DIRECTORY docs/
|
||||
DESTINATION ${INSTALL_DOCS_PATH}
|
||||
COMPONENT "Documentation")
|
||||
|
||||
add_subdirectory( lzma )
|
||||
add_subdirectory( tools )
|
||||
add_subdirectory( dumb )
|
||||
|
|
|
@ -87,16 +87,14 @@ conversation // Starts a dialog.
|
|||
|
||||
page // Starts a new page. Pages are automatically numbered starting at 1.
|
||||
{
|
||||
name = <string>; // Name that goes in the upper left hand corner
|
||||
panel = <string>; // Name of lump to render as the background.
|
||||
voice = <string>; // Narration sound lump.
|
||||
dialog = <string>; // Dialog of the page.
|
||||
goodbye = <string>; // Custom goodbye message. If omitted then the
|
||||
// generic goodbyes will be displayed instead.
|
||||
drop = <integer>; // mobj for the object to drop if the actor is
|
||||
// killed.
|
||||
link = <integer>; // Page to jump to if all ifitem conditions are
|
||||
// satisified.
|
||||
name = <string>; // Name that goes in the upper left hand corner
|
||||
panel = <string>; // Name of lump to render as the background.
|
||||
voice = <string>; // Narration sound lump.
|
||||
dialog = <string>; // Dialog of the page.
|
||||
drop = <integer>; // mobj for the object to drop if the actor is
|
||||
// killed.
|
||||
link = <integer>; // Page to jump to if all ifitem conditions are
|
||||
// satisified.
|
||||
|
||||
// jumps to the specified page if the player has the specified amount
|
||||
// or more of item in their inventory. This can be repeated as many
|
||||
|
|
|
@ -76,8 +76,8 @@ namespace = "ZDoom";
|
|||
III.A : Conversations
|
||||
---------------------
|
||||
|
||||
This block only lists the newly added fields. Currently ZDoom only adds one
|
||||
field to the specification:
|
||||
This block only lists the newly added fields. Currently ZDoom only adds a few
|
||||
fields to the specification:
|
||||
|
||||
conversation // Starts a dialog.
|
||||
{
|
||||
|
@ -86,6 +86,35 @@ conversation // Starts a dialog.
|
|||
// the standard conversation ID ('actor' property) is used instead
|
||||
// for this purpose but since 'ZDoom' namespace requires the actor
|
||||
// to be a class name it needs a separate field for this.
|
||||
|
||||
page
|
||||
{
|
||||
goodbye = <string>; // Custom goodbye message. If omitted then the
|
||||
// generic goodbyes will be displayed instead.
|
||||
|
||||
choice
|
||||
{
|
||||
// The amount of an item needed for this option to become available.
|
||||
// You can have as many as needed. All require blocks must be satisfied
|
||||
// to show this option.
|
||||
require
|
||||
{
|
||||
item = <string>; // Item that is required to show this option.
|
||||
amount = <integer>; // Minimum amount of the item needed.
|
||||
}
|
||||
|
||||
// The undesired amount of an item. This option will become available
|
||||
// if you have less than the specified amount. You can have as many
|
||||
// as needed. All exclude blocks must be satisfied to show this option.
|
||||
// Note: if both require and exclude are defined then all require
|
||||
// and all exclude blocks must be satisfied to show this option.
|
||||
exclude
|
||||
{
|
||||
item = <string>; // Item that is unwanted to show this option.
|
||||
amount = <integer>; // Unwanted minimum amount of the item.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
===============================================================================
|
||||
|
|
|
@ -179,8 +179,12 @@ if( WIN32 )
|
|||
comdlg32
|
||||
ws2_32
|
||||
setupapi
|
||||
oleaut32
|
||||
DelayImp )
|
||||
oleaut32 )
|
||||
|
||||
if( NOT ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} DelayImp )
|
||||
endif()
|
||||
|
||||
if( DX_dxguid_LIBRARY )
|
||||
list( APPEND ZDOOM_LIBS "${DX_dxguid_LIBRARY}" )
|
||||
endif()
|
||||
|
@ -190,6 +194,7 @@ else()
|
|||
set( FMOD_INC_PATH_SUFFIXES PATH_SUFFIXES inc )
|
||||
set( FMOD_LIB_PATH_SUFFIXES PATH_SUFFIXES lib )
|
||||
set( NO_GTK ON )
|
||||
set( DYN_GTK OFF )
|
||||
|
||||
# Prevent inclusion of fp.h and FixMath.h from Carbon framework
|
||||
# Declarations from these files are not used but cause the following conflicts:
|
||||
|
@ -198,6 +203,7 @@ else()
|
|||
add_definitions( -D__FP__ -D__FIXMATH__ )
|
||||
else()
|
||||
option( NO_GTK "Disable GTK+ dialogs (Not applicable to Windows)" )
|
||||
option( DYN_GTK "Load GTK+ at runtime instead of compile time" ON )
|
||||
option( VALGRIND "Add special Valgrind sequences to self-modifying code" )
|
||||
|
||||
set( FMOD_SEARCH_PATHS
|
||||
|
@ -213,22 +219,37 @@ else()
|
|||
|
||||
# Use GTK+ for the IWAD picker, if available.
|
||||
if( NOT NO_GTK )
|
||||
pkg_check_modules( GTK2 gtk+-2.0 )
|
||||
if( GTK2_FOUND )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${GTK2_LIBRARIES} )
|
||||
include_directories( ${GTK2_INCLUDE_DIRS} )
|
||||
link_directories( ${GTK2_LIBRARY_DIRS} )
|
||||
pkg_check_modules( GTK3 gtk+-3.0 )
|
||||
if( GTK3_FOUND )
|
||||
if( NOT DYN_GTK )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${GTK3_LIBRARIES} )
|
||||
endif()
|
||||
include_directories( ${GTK3_INCLUDE_DIRS} )
|
||||
link_directories( ${GTK3_LIBRARY_DIRS} )
|
||||
else()
|
||||
set( NO_GTK ON )
|
||||
pkg_check_modules( GTK2 gtk+-2.0 )
|
||||
if( GTK2_FOUND )
|
||||
if( NOT DYN_GTK )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${GTK2_LIBRARIES} )
|
||||
endif()
|
||||
include_directories( ${GTK2_INCLUDE_DIRS} )
|
||||
link_directories( ${GTK2_LIBRARY_DIRS} )
|
||||
else()
|
||||
set( NO_GTK ON )
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
set( NASM_NAMES nasm )
|
||||
|
||||
if( NO_GTK )
|
||||
add_definitions( -DNO_GTK=1 )
|
||||
add_definitions( -DNO_GTK )
|
||||
elseif( DYN_GTK )
|
||||
add_definitions( -DDYN_GTK=1 )
|
||||
else()
|
||||
add_definitions( -DDYN_GTK=0 )
|
||||
endif()
|
||||
|
||||
|
||||
# Non-Windows version also needs SDL except native OS X backend
|
||||
if( NOT APPLE OR NOT OSX_COCOA_BACKEND )
|
||||
find_package( SDL2 REQUIRED )
|
||||
|
@ -291,6 +312,19 @@ if( NOT NO_FMOD )
|
|||
|
||||
if( EXISTS "${FMOD_INCLUDE_DIR}/fmod_common.h" )
|
||||
set( FMOD_STUDIO YES )
|
||||
set( FMOD_VERSION_FILE "fmod_common.h" )
|
||||
else()
|
||||
set( FMOD_STUDIO NO )
|
||||
set( FMOD_VERSION_FILE "fmod.h" )
|
||||
endif()
|
||||
|
||||
file( STRINGS "${FMOD_INCLUDE_DIR}/${FMOD_VERSION_FILE}" FMOD_VERSION_LINE REGEX "^#define[ \t]+FMOD_VERSION[ \t]+0x[0-9]+$" )
|
||||
string( REGEX REPLACE "^#define[ \t]+FMOD_VERSION[ \t]+0x([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])$" "\\1.\\2.\\3" FMOD_VERSION "${FMOD_VERSION_LINE}" )
|
||||
message( STATUS "FMOD version: ${FMOD_VERSION}" )
|
||||
|
||||
# FMOD Ex didn't hide xiph symbols in the past (not applicable to Win32 since symbols are hidden by default there).
|
||||
if( NOT WIN32 AND NOT FMOD_STUDIO AND NOT NO_OPENAL AND "${FMOD_VERSION}" VERSION_LESS "4.36.00")
|
||||
message( SEND_ERROR "Use of FMOD Ex ${FMOD_VERSION} with OpenAL will result in crashes. Either update FMOD to 4.36 or later or set NO_OPENAL." )
|
||||
endif()
|
||||
else()
|
||||
message( STATUS "Could not find FMOD include files" )
|
||||
|
@ -702,7 +736,8 @@ set( PLAT_SDL_SOURCES
|
|||
posix/sdl/sdlglvideo.cpp
|
||||
posix/sdl/st_start.cpp )
|
||||
set( PLAT_UNIX_SOURCES
|
||||
posix/unix/i_specialpaths.cpp )
|
||||
posix/unix/i_specialpaths.cpp
|
||||
posix/unix/iwadpicker_gtk.cpp )
|
||||
set( PLAT_OSX_SOURCES
|
||||
posix/osx/iwadpicker_cocoa.mm
|
||||
posix/osx/i_specialpaths.mm
|
||||
|
@ -724,15 +759,7 @@ if( WIN32 )
|
|||
set( SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} )
|
||||
set( OTHER_SYSTEM_SOURCES ${PLAT_POSIX_SOURCES} ${PLAT_SDL_SOURCES} ${PLAT_OSX_SOURCES} ${PLAT_COCOA_SOURCES} ${PLAT_UNIX_SOURCES} )
|
||||
|
||||
if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
||||
# CMake is not set up to compile and link rc files with GCC. :(
|
||||
add_custom_command( OUTPUT zdoom-rc.o
|
||||
COMMAND windres -o zdoom-rc.o -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zdoom.rc
|
||||
DEPENDS win32/zdoom.rc )
|
||||
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} zdoom-rc.o )
|
||||
else()
|
||||
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} win32/zdoom.rc )
|
||||
endif()
|
||||
set( SYSTEM_SOURCES ${SYSTEM_SOURCES} win32/zdoom.rc )
|
||||
elseif( APPLE )
|
||||
if( OSX_COCOA_BACKEND )
|
||||
set( SYSTEM_SOURCES_DIR posix posix/cocoa )
|
||||
|
@ -1210,6 +1237,7 @@ set (PCH_SOURCES
|
|||
gi.cpp
|
||||
gitinfo.cpp
|
||||
hu_scores.cpp
|
||||
i_module.cpp
|
||||
i_net.cpp
|
||||
info.cpp
|
||||
keysections.cpp
|
||||
|
@ -1565,6 +1593,15 @@ if( APPLE )
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if( WIN32 )
|
||||
set( INSTALL_PATH . CACHE STRING "Directory where the zdoom executable will be placed during install." )
|
||||
else()
|
||||
set( INSTALL_PATH bin CACHE STRING "Directory where the zdoom executable will be placed during install." )
|
||||
endif()
|
||||
install(TARGETS zdoom
|
||||
DESTINATION ${INSTALL_PATH}
|
||||
COMPONENT "Game executable")
|
||||
|
||||
source_group("Assembly Files\\ia32" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/asm_ia32/.+")
|
||||
source_group("Assembly Files\\x86_64" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/asm_x86_64/.+")
|
||||
source_group("Audio Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sound/.+")
|
||||
|
|
|
@ -2046,7 +2046,8 @@ void AM_drawSubsectors()
|
|||
scale / scaley,
|
||||
rotation,
|
||||
colormap,
|
||||
floorlight
|
||||
floorlight,
|
||||
f_y + f_h
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -198,7 +198,10 @@ SetTiltedSpanSize:
|
|||
mov [y8+2],cl
|
||||
mov [y9+2],cl
|
||||
mov [y10+2],cl
|
||||
cmp eax,0 ; if x bits is 0, mask must be 0 too.
|
||||
jz .notted
|
||||
not eax
|
||||
.notted:
|
||||
pop ecx
|
||||
|
||||
mov [m1+2],eax
|
||||
|
|
|
@ -358,7 +358,7 @@ void DBot::WhatToGet (AActor *item)
|
|||
}
|
||||
else if ((typeis (Megasphere) || typeis (Soulsphere) || typeis (HealthBonus)) && player->mo->health >= deh.MaxSoulsphere)
|
||||
return;
|
||||
else if (item->IsKindOf (RUNTIME_CLASS(AHealth)) && player->mo->health >= deh.MaxHealth /*MAXHEALTH*/)
|
||||
else if (item->IsKindOf (RUNTIME_CLASS(AHealth)) && player->mo->health >= player->mo->GetMaxHealth() + player->mo->stamina)
|
||||
return;
|
||||
|
||||
if ((dest == NULL ||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -168,6 +168,9 @@ public:
|
|||
// [CW] Fades for when you are being damaged.
|
||||
PalEntry DamageFade;
|
||||
|
||||
// [SP] ViewBob Multiplier
|
||||
double ViewBob;
|
||||
|
||||
bool UpdateWaterLevel (bool splash);
|
||||
bool ResetAirSupply (bool playgasp = true);
|
||||
|
||||
|
|
|
@ -71,6 +71,9 @@ extern bool netgame;
|
|||
// Bot game? Like netgame, but doesn't involve network communication.
|
||||
extern bool multiplayer;
|
||||
|
||||
// [SP] Map dm/coop implementation - invokes fake multiplayer without bots
|
||||
extern bool multiplayernext;
|
||||
|
||||
// Flag: true only if started as net deathmatch.
|
||||
EXTERN_CVAR (Int, deathmatch)
|
||||
|
||||
|
|
|
@ -164,6 +164,7 @@ bool viewactive;
|
|||
|
||||
bool netgame; // only true if packets are broadcast
|
||||
bool multiplayer;
|
||||
bool multiplayernext = false; // [SP] Map coop/dm implementation
|
||||
player_t players[MAXPLAYERS];
|
||||
bool playeringame[MAXPLAYERS];
|
||||
|
||||
|
@ -1171,7 +1172,7 @@ void G_Ticker ()
|
|||
}
|
||||
|
||||
// check for turbo cheats
|
||||
if (cmd->ucmd.forwardmove > TURBOTHRESHOLD &&
|
||||
if (turbo > 100.f && cmd->ucmd.forwardmove > TURBOTHRESHOLD &&
|
||||
!(gametic&31) && ((gametic>>5)&(MAXPLAYERS-1)) == i )
|
||||
{
|
||||
Printf ("%s is turbo!\n", players[i].userinfo.GetName());
|
||||
|
@ -1655,9 +1656,10 @@ static void G_QueueBody (AActor *body)
|
|||
//
|
||||
// G_DoReborn
|
||||
//
|
||||
EXTERN_CVAR(Bool, sv_singleplayerrespawn)
|
||||
void G_DoReborn (int playernum, bool freshbot)
|
||||
{
|
||||
if (!multiplayer && !(level.flags2 & LEVEL2_ALLOWRESPAWN))
|
||||
if (!multiplayer && !(level.flags2 & LEVEL2_ALLOWRESPAWN) && !sv_singleplayerrespawn)
|
||||
{
|
||||
if (BackupSaveName.Len() > 0 && FileExists (BackupSaveName.GetChars()))
|
||||
{ // Load game from the last point it was saved
|
||||
|
|
|
@ -90,6 +90,8 @@
|
|||
|
||||
#include "g_hub.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void STAT_StartNewGame(const char *lev);
|
||||
void STAT_ChangeLevel(const char *newl);
|
||||
|
||||
|
@ -181,6 +183,16 @@ CCMD (map)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (argv.argc() > 2 && stricmp(argv[2], "coop") == 0)
|
||||
{
|
||||
deathmatch = false;
|
||||
multiplayernext = true;
|
||||
}
|
||||
else if (argv.argc() > 2 && stricmp(argv[2], "dm") == 0)
|
||||
{
|
||||
deathmatch = true;
|
||||
multiplayernext = true;
|
||||
}
|
||||
G_DeferedInitNew (argv[1]);
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +204,7 @@ CCMD (map)
|
|||
}
|
||||
else
|
||||
{
|
||||
Printf ("Usage: map <map name>\n");
|
||||
Printf ("Usage: map <map name> [coop|dm]\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,6 +230,16 @@ CCMD(recordmap)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (argv.argc() > 3 && stricmp(argv[3], "coop") == 0)
|
||||
{
|
||||
deathmatch = false;
|
||||
multiplayernext = true;
|
||||
}
|
||||
else if (argv.argc() > 3 && stricmp(argv[3], "dm") == 0)
|
||||
{
|
||||
deathmatch = true;
|
||||
multiplayernext = true;
|
||||
}
|
||||
G_DeferedInitNew(argv[2]);
|
||||
gameaction = ga_recordgame;
|
||||
newdemoname = argv[1];
|
||||
|
@ -232,7 +254,7 @@ CCMD(recordmap)
|
|||
}
|
||||
else
|
||||
{
|
||||
Printf("Usage: recordmap <filename> <map name>\n");
|
||||
Printf("Usage: recordmap <filename> <map name> [coop|dm]\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,13 +280,23 @@ CCMD (open)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (argv.argc() > 2 && stricmp(argv[2], "coop") == 0)
|
||||
{
|
||||
deathmatch = false;
|
||||
multiplayernext = true;
|
||||
}
|
||||
else if (argv.argc() > 2 && stricmp(argv[2], "dm") == 0)
|
||||
{
|
||||
deathmatch = true;
|
||||
multiplayernext = true;
|
||||
}
|
||||
gameaction = ga_newgame2;
|
||||
d_skill = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf ("Usage: open <map file>\n");
|
||||
Printf ("Usage: open <map file> [coop|dm]\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,7 +325,8 @@ void G_NewInit ()
|
|||
G_ClearSnapshots ();
|
||||
ST_SetNeedRefresh();
|
||||
netgame = false;
|
||||
multiplayer = false;
|
||||
multiplayer = multiplayernext;
|
||||
multiplayernext = false;
|
||||
if (demoplayback)
|
||||
{
|
||||
C_RestoreCVars ();
|
||||
|
@ -526,6 +559,8 @@ static bool unloading;
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
EXTERN_CVAR(Bool, sv_singleplayerrespawn)
|
||||
|
||||
void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill)
|
||||
{
|
||||
level_info_t *nextinfo = NULL;
|
||||
|
@ -634,7 +669,7 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill
|
|||
|
||||
// If this is co-op, respawn any dead players now so they can
|
||||
// keep their inventory on the next map.
|
||||
if ((multiplayer || level.flags2 & LEVEL2_ALLOWRESPAWN) && !deathmatch && player->playerstate == PST_DEAD)
|
||||
if ((multiplayer || level.flags2 & LEVEL2_ALLOWRESPAWN || sv_singleplayerrespawn) && !deathmatch && player->playerstate == PST_DEAD)
|
||||
{
|
||||
// Copied from the end of P_DeathThink [[
|
||||
player->cls = NULL; // Force a new class if the player is using a random class
|
||||
|
|
|
@ -1508,10 +1508,18 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo)
|
|||
|
||||
if (sc.CheckNumber())
|
||||
{ // MAPNAME is a number; assume a Hexen wad
|
||||
char maptemp[8];
|
||||
mysnprintf (maptemp, countof(maptemp), "MAP%02d", sc.Number);
|
||||
mapname = maptemp;
|
||||
HexenHack = true;
|
||||
if (format_type == FMT_New)
|
||||
{
|
||||
mapname = sc.String;
|
||||
}
|
||||
else
|
||||
{
|
||||
char maptemp[8];
|
||||
mysnprintf(maptemp, countof(maptemp), "MAP%02d", sc.Number);
|
||||
mapname = maptemp;
|
||||
HexenHack = true;
|
||||
format_type = FMT_Old;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -640,6 +640,7 @@ void AWeapon::PostMorphWeapon ()
|
|||
|
||||
pspr = Owner->player->GetPSprite(PSP_WEAPON);
|
||||
pspr->y = WEAPONBOTTOM;
|
||||
pspr->ResetInterpolation();
|
||||
pspr->SetState(GetUpState());
|
||||
}
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ class CommandDrawImage : public SBarInfoCommandFlowControl
|
|||
applyscale = false;
|
||||
}
|
||||
if(type == PLAYERICON)
|
||||
texture = TexMan[statusBar->CPlayer->mo->ScoreIcon];
|
||||
texture = TexMan(statusBar->CPlayer->mo->ScoreIcon);
|
||||
else if(type == AMMO1)
|
||||
{
|
||||
AAmmo *ammo = statusBar->ammo1;
|
||||
|
@ -270,7 +270,7 @@ class CommandDrawImage : public SBarInfoCommandFlowControl
|
|||
{
|
||||
AInventory *item = statusBar->CPlayer->mo->FindInventory<ASigil>();
|
||||
if (item != NULL)
|
||||
texture = TexMan[item->Icon];
|
||||
texture = TexMan(item->Icon);
|
||||
}
|
||||
else if(type == HEXENARMOR_ARMOR || type == HEXENARMOR_SHIELD || type == HEXENARMOR_HELM || type == HEXENARMOR_AMULET)
|
||||
{
|
||||
|
@ -290,7 +290,7 @@ class CommandDrawImage : public SBarInfoCommandFlowControl
|
|||
}
|
||||
}
|
||||
else if(type == INVENTORYICON)
|
||||
texture = TexMan[sprite];
|
||||
texture = TexMan(sprite);
|
||||
else if(type == SELECTEDINVENTORYICON && statusBar->CPlayer->mo->InvSel != NULL)
|
||||
texture = TexMan(statusBar->CPlayer->mo->InvSel->Icon);
|
||||
else if(image >= 0)
|
||||
|
@ -312,7 +312,7 @@ class CommandDrawImage : public SBarInfoCommandFlowControl
|
|||
spawnScaleY = item->Scale.Y;
|
||||
}
|
||||
|
||||
texture = TexMan[icon];
|
||||
texture = TexMan(icon);
|
||||
}
|
||||
|
||||
enum ImageType
|
||||
|
@ -2436,22 +2436,22 @@ class CommandDrawKeyBar : public SBarInfoCommand
|
|||
{
|
||||
if(!vertical)
|
||||
{
|
||||
statusBar->DrawGraphic(TexMan[item->Icon], x+slotOffset, y+rowOffset, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets());
|
||||
rowWidth = rowIconSize == -1 ? TexMan[item->Icon]->GetScaledHeight()+2 : rowIconSize;
|
||||
statusBar->DrawGraphic(TexMan(item->Icon), x+slotOffset, y+rowOffset, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets());
|
||||
rowWidth = rowIconSize == -1 ? TexMan(item->Icon)->GetScaledHeight()+2 : rowIconSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
statusBar->DrawGraphic(TexMan[item->Icon], x+rowOffset, y+slotOffset, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets());
|
||||
rowWidth = rowIconSize == -1 ? TexMan[item->Icon]->GetScaledWidth()+2 : rowIconSize;
|
||||
statusBar->DrawGraphic(TexMan(item->Icon), x+rowOffset, y+slotOffset, block->XOffset(), block->YOffset(), block->Alpha(), block->FullScreenOffsets());
|
||||
rowWidth = rowIconSize == -1 ? TexMan(item->Icon)->GetScaledWidth()+2 : rowIconSize;
|
||||
}
|
||||
|
||||
// If cmd.special is -1 then the slot size is auto detected
|
||||
if(iconSize == -1)
|
||||
{
|
||||
if(!vertical)
|
||||
slotOffset += (reverse ? -1 : 1) * (TexMan[item->Icon]->GetScaledWidth() + 2);
|
||||
slotOffset += (reverse ? -1 : 1) * (TexMan(item->Icon)->GetScaledWidth() + 2);
|
||||
else
|
||||
slotOffset += (reverse ? -1 : 1) * (TexMan[item->Icon]->GetScaledHeight() + 2);
|
||||
slotOffset += (reverse ? -1 : 1) * (TexMan(item->Icon)->GetScaledHeight() + 2);
|
||||
}
|
||||
else
|
||||
slotOffset += (reverse ? -iconSize : iconSize);
|
||||
|
|
|
@ -119,6 +119,7 @@ CUSTOM_CVAR(Int, am_showmaplabel, 2, CVAR_ARCHIVE)
|
|||
}
|
||||
|
||||
CVAR (Bool, idmypos, false, 0);
|
||||
CVAR(Float, underwater_fade_scalar, 1.0f, CVAR_ARCHIVE) // [Nash] user-settable underwater blend intensity
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -1544,7 +1545,10 @@ void DBaseStatusBar::DrawPowerups ()
|
|||
|
||||
void DBaseStatusBar::BlendView (float blend[4])
|
||||
{
|
||||
V_AddBlend (BaseBlendR / 255.f, BaseBlendG / 255.f, BaseBlendB / 255.f, BaseBlendA, blend);
|
||||
// [Nash] Allow user to set blend intensity
|
||||
float cnt = (BaseBlendA * underwater_fade_scalar);
|
||||
|
||||
V_AddBlend (BaseBlendR / 255.f, BaseBlendG / 255.f, BaseBlendB / 255.f, cnt, blend);
|
||||
V_AddPlayerBlend(CPlayer, blend, 1.0f, 228);
|
||||
|
||||
if (screen->Accel2D || (CPlayer->camera != NULL && menuactive == MENU_Off && ConsoleState == c_up))
|
||||
|
|
|
@ -1082,6 +1082,7 @@ void gl_AttachLight(AActor *actor, unsigned int count, const FLightDefaults *lig
|
|||
light->target = actor;
|
||||
light->owned = true;
|
||||
light->ObjectFlags |= OF_Transient;
|
||||
light->flags4 |= MF4_ATTENUATE;
|
||||
actor->dynamiclights.Push(light);
|
||||
}
|
||||
light->flags2&=~MF2_DORMANT;
|
||||
|
|
|
@ -50,6 +50,7 @@ enum
|
|||
#define MF4_SUBTRACTIVE MF4_MISSILEEVENMORE
|
||||
#define MF4_ADDITIVE MF4_MISSILEMORE
|
||||
#define MF4_DONTLIGHTSELF MF4_SEESDAGGERS
|
||||
#define MF4_ATTENUATE MF4_INCOMBAT
|
||||
|
||||
enum ELightType
|
||||
{
|
||||
|
|
|
@ -116,7 +116,7 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FD
|
|||
data[4] = r;
|
||||
data[5] = g;
|
||||
data[6] = b;
|
||||
data[7] = 0;
|
||||
data[7] = !!(light->flags4 & MF4_ATTENUATE);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -216,7 +216,7 @@ public:
|
|||
|
||||
void FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley,
|
||||
DAngle rotation, FDynamicColormap *colormap, int lightlevel);
|
||||
DAngle rotation, FDynamicColormap *colormap, int lightlevel, int bottomclip);
|
||||
|
||||
int PTM_BestColor (const uint32 *pal_in, int r, int g, int b, int first, int num);
|
||||
|
||||
|
|
|
@ -140,12 +140,15 @@ static void AddLine (seg_t *seg, bool portalclip)
|
|||
{
|
||||
if (currentsector->sectornum == seg->backsector->sectornum)
|
||||
{
|
||||
FTexture * tex = TexMan(seg->sidedef->GetTexture(side_t::mid));
|
||||
if (!tex || tex->UseType==FTexture::TEX_Null)
|
||||
if (!seg->linedef->isVisualPortal())
|
||||
{
|
||||
// nothing to do here!
|
||||
seg->linedef->validcount=validcount;
|
||||
return;
|
||||
FTexture * tex = TexMan(seg->sidedef->GetTexture(side_t::mid));
|
||||
if (!tex || tex->UseType==FTexture::TEX_Null)
|
||||
{
|
||||
// nothing to do here!
|
||||
seg->linedef->validcount=validcount;
|
||||
return;
|
||||
}
|
||||
}
|
||||
backsector=currentsector;
|
||||
}
|
||||
|
|
|
@ -536,7 +536,7 @@ void GLDrawList::SortSpriteIntoWall(SortNode * head,SortNode * sort)
|
|||
|
||||
const bool drawBillboardFacingCamera = gl_billboard_faces_camera;
|
||||
// [Nash] has +ROLLSPRITE
|
||||
const bool rotated = (ss->actor != nullptr && ss->actor->renderflags & RF_ROLLSPRITE | RF_WALLSPRITE | RF_FLATSPRITE);
|
||||
const bool rotated = (ss->actor != nullptr && ss->actor->renderflags & (RF_ROLLSPRITE | RF_WALLSPRITE | RF_FLATSPRITE));
|
||||
|
||||
// cannot sort them at the moment. This requires more complex splitting.
|
||||
if (drawWithXYBillboard || drawBillboardFacingCamera || rotated)
|
||||
|
|
|
@ -82,6 +82,7 @@ CVAR(Bool, gl_sort_textures, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
|
||||
EXTERN_CVAR (Bool, cl_capfps)
|
||||
EXTERN_CVAR (Bool, r_deathcamera)
|
||||
EXTERN_CVAR (Float, underwater_fade_scalar)
|
||||
|
||||
|
||||
extern int viewpitch;
|
||||
|
@ -633,7 +634,11 @@ void FGLRenderer::DrawBlend(sector_t * viewsector)
|
|||
}
|
||||
else if (blendv.a)
|
||||
{
|
||||
V_AddBlend(blendv.r / 255.f, blendv.g / 255.f, blendv.b / 255.f, blendv.a / 255.0f, blend);
|
||||
// [Nash] allow user to set blend intensity
|
||||
int cnt = blendv.a;
|
||||
cnt = (int)(cnt * underwater_fade_scalar);
|
||||
|
||||
V_AddBlend(blendv.r / 255.f, blendv.g / 255.f, blendv.b / 255.f, cnt / 255.0f, blend);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ struct GLSeg
|
|||
// we do not use the vector math inlines here because they are not optimized for speed but accuracy in the playsim
|
||||
float x = y2 - y1;
|
||||
float y = x1 - x2;
|
||||
float length = sqrt(x*x + y*y);
|
||||
float length = sqrtf(x*x + y*y);
|
||||
return FVector3(x / length, 0, y / length);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -464,7 +464,7 @@ void OpenGLFrameBuffer::Clear(int left, int top, int right, int bottom, int palc
|
|||
|
||||
void OpenGLFrameBuffer::FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley,
|
||||
DAngle rotation, FDynamicColormap *colormap, int lightlevel)
|
||||
DAngle rotation, FDynamicColormap *colormap, int lightlevel, int bottomclip)
|
||||
{
|
||||
if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr && npoints >= 3)
|
||||
{
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
|
||||
void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley,
|
||||
DAngle rotation, FDynamicColormap *colormap, int lightlevel);
|
||||
DAngle rotation, FDynamicColormap *colormap, int lightlevel, int bottomclip);
|
||||
|
||||
FNativePalette *CreatePalette(FRemapTable *remap);
|
||||
|
||||
|
|
101
src/i_module.cpp
Normal file
101
src/i_module.cpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
** i_module.cpp
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2016 Braden Obrzut
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include "i_module.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#define USE_WINDOWS_DWORD
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#define LoadLibrary(x) dlopen((x), RTLD_LAZY)
|
||||
#define GetProcAddress(a,b) dlsym((a),(b))
|
||||
#define FreeLibrary(x) dlclose((x))
|
||||
using HMODULE = void*;
|
||||
#endif
|
||||
|
||||
bool FModule::Load(std::initializer_list<const char*> libnames)
|
||||
{
|
||||
for(auto lib : libnames)
|
||||
{
|
||||
if(!Open(lib))
|
||||
continue;
|
||||
|
||||
StaticProc *proc;
|
||||
for(proc = reqSymbols;proc;proc = proc->Next)
|
||||
{
|
||||
if(!(proc->Call = GetSym(proc->Name)) && !proc->Optional)
|
||||
{
|
||||
Unload();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(IsLoaded())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FModule::Unload()
|
||||
{
|
||||
if(handle)
|
||||
{
|
||||
FreeLibrary((HMODULE)handle);
|
||||
handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool FModule::Open(const char* lib)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if((handle = GetModuleHandle(lib)) != nullptr)
|
||||
return true;
|
||||
#else
|
||||
// Loading an empty string in Linux doesn't do what we expect it to.
|
||||
if(*lib == '\0')
|
||||
return false;
|
||||
#endif
|
||||
handle = LoadLibrary(lib);
|
||||
return handle != nullptr;
|
||||
}
|
||||
|
||||
void *FModule::GetSym(const char* name)
|
||||
{
|
||||
return (void *)GetProcAddress((HMODULE)handle, name);
|
||||
}
|
229
src/i_module.h
Normal file
229
src/i_module.h
Normal file
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
** i_module.h
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2016 Braden Obrzut
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <initializer_list>
|
||||
|
||||
/* FModule Run Time Library Loader
|
||||
*
|
||||
* This provides an interface for loading optional dependencies or detecting
|
||||
* version specific symbols at run time. These classes largely provide an
|
||||
* interface for statically declaring the symbols that are going to be used
|
||||
* ahead of time, thus should not be used on the stack or as part of a
|
||||
* dynamically allocated object. The procedure templates take the FModule
|
||||
* as a template argument largely to make such use of FModule awkward.
|
||||
*
|
||||
* Declared procedures register themselves with FModule and the module will not
|
||||
* be considered loaded unless all required procedures can be resolved. In
|
||||
* order to remove the need for boilerplate code, optional procedures do not
|
||||
* enforce the requirement that the value is null checked before use. As a
|
||||
* debugging aid debug builds will check that operator bool was called at some
|
||||
* point, but this is just a first order sanity check.
|
||||
*/
|
||||
|
||||
class FModule;
|
||||
class FStaticModule;
|
||||
|
||||
template<FModule &Module, typename Proto>
|
||||
class TOptProc;
|
||||
|
||||
template<FModule &Module, typename Proto>
|
||||
class TReqProc;
|
||||
|
||||
template<FStaticModule &Module, typename Proto, Proto Sym>
|
||||
class TStaticProc;
|
||||
|
||||
class FModule
|
||||
{
|
||||
template<FModule &Module, typename Proto>
|
||||
friend class TOptProc;
|
||||
template<FModule &Module, typename Proto>
|
||||
friend class TReqProc;
|
||||
|
||||
struct StaticProc
|
||||
{
|
||||
void *Call;
|
||||
const char* Name;
|
||||
StaticProc *Next;
|
||||
bool Optional;
|
||||
};
|
||||
|
||||
void RegisterStatic(StaticProc &proc)
|
||||
{
|
||||
proc.Next = reqSymbols;
|
||||
reqSymbols = &proc;
|
||||
}
|
||||
|
||||
void *handle = nullptr;
|
||||
|
||||
// Debugging aid
|
||||
const char *name;
|
||||
|
||||
// Since FModule is supposed to be statically allocated it is assumed that
|
||||
// reqSymbols will be initialized to nullptr avoiding initialization order
|
||||
// problems with declaring procedures.
|
||||
StaticProc *reqSymbols;
|
||||
|
||||
bool Open(const char* lib);
|
||||
void *GetSym(const char* name);
|
||||
|
||||
public:
|
||||
template<FModule &Module, typename Proto, Proto Sym>
|
||||
using Opt = TOptProc<Module, Proto>;
|
||||
template<FModule &Module, typename Proto, Proto Sym>
|
||||
using Req = TReqProc<Module, Proto>;
|
||||
|
||||
FModule(const char* name) : name(name) {};
|
||||
~FModule() { Unload(); }
|
||||
|
||||
// Load a shared library using the first library name which satisfies all
|
||||
// of the required symbols.
|
||||
bool Load(std::initializer_list<const char*> libnames);
|
||||
void Unload();
|
||||
|
||||
bool IsLoaded() const { return handle != nullptr; }
|
||||
};
|
||||
|
||||
// Null version of FModule which satisfies the API so the same code can be used
|
||||
// for run time and compile time linking.
|
||||
class FStaticModule
|
||||
{
|
||||
template<FStaticModule &Module, typename Proto, Proto Sym>
|
||||
friend class TStaticProc;
|
||||
|
||||
const char *name;
|
||||
public:
|
||||
template<FStaticModule &Module, typename Proto, Proto Sym>
|
||||
using Opt = TStaticProc<Module, Proto, Sym>;
|
||||
template<FStaticModule &Module, typename Proto, Proto Sym>
|
||||
using Req = TStaticProc<Module, Proto, Sym>;
|
||||
|
||||
FStaticModule(const char* name) : name(name) {};
|
||||
|
||||
bool Load(std::initializer_list<const char*> libnames) { return true; }
|
||||
void Unload() {}
|
||||
|
||||
bool IsLoaded() const { return true; }
|
||||
};
|
||||
|
||||
// Allow FModuleMaybe<DYN_XYZ> to switch based on preprocessor flag.
|
||||
// Use FModuleMaybe<DYN_XYZ>::Opt and FModuleMaybe<DYN_XYZ>::Req for procs.
|
||||
template<bool Dynamic>
|
||||
struct TModuleType { using Type = FModule; };
|
||||
template<>
|
||||
struct TModuleType<false> { using Type = FStaticModule; };
|
||||
|
||||
template<bool Dynamic>
|
||||
using FModuleMaybe = typename TModuleType<Dynamic>::Type;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
template<FModule &Module, typename Proto>
|
||||
class TOptProc
|
||||
{
|
||||
FModule::StaticProc proc;
|
||||
#ifndef NDEBUG
|
||||
mutable bool checked = false;
|
||||
#endif
|
||||
|
||||
// I am not a pointer
|
||||
bool operator==(void*) const;
|
||||
bool operator!=(void*) const;
|
||||
|
||||
public:
|
||||
TOptProc(const char* function)
|
||||
{
|
||||
proc.Name = function;
|
||||
proc.Optional = true;
|
||||
Module.RegisterStatic(proc);
|
||||
}
|
||||
|
||||
operator Proto() const
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
assert(checked);
|
||||
#endif
|
||||
return (Proto)proc.Call;
|
||||
}
|
||||
explicit operator bool() const
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
assert(Module.IsLoaded());
|
||||
checked = true;
|
||||
#endif
|
||||
return proc.Call != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<FModule &Module, typename Proto>
|
||||
class TReqProc
|
||||
{
|
||||
FModule::StaticProc proc;
|
||||
|
||||
// I am not a pointer
|
||||
bool operator==(void*) const;
|
||||
bool operator!=(void*) const;
|
||||
|
||||
public:
|
||||
TReqProc(const char* function)
|
||||
{
|
||||
proc.Name = function;
|
||||
proc.Optional = false;
|
||||
Module.RegisterStatic(proc);
|
||||
}
|
||||
|
||||
operator Proto() const
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
assert(Module.IsLoaded());
|
||||
#endif
|
||||
return (Proto)proc.Call;
|
||||
}
|
||||
explicit operator bool() const { return true; }
|
||||
};
|
||||
|
||||
template<FStaticModule &Module, typename Proto, Proto Sym>
|
||||
class TStaticProc
|
||||
{
|
||||
// I am not a pointer
|
||||
bool operator==(void*) const;
|
||||
bool operator!=(void*) const;
|
||||
|
||||
public:
|
||||
TStaticProc(const char* function) {}
|
||||
|
||||
operator Proto() const { return Sym; }
|
||||
explicit operator bool() const { return Sym != nullptr; }
|
||||
};
|
|
@ -671,6 +671,7 @@ public:
|
|||
{
|
||||
return FOptionMenuItem::MenuEvent(mkey, fromcontroller);
|
||||
}
|
||||
if (fabs(value) < FLT_EPSILON) value = 0;
|
||||
SetSliderValue(clamp(value, mMin, mMax));
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
|
||||
return true;
|
||||
|
|
|
@ -585,6 +585,8 @@ xx(Ifitem)
|
|||
xx(Choice)
|
||||
xx(Link)
|
||||
xx(Goodbye)
|
||||
xx(Require)
|
||||
xx(Exclude)
|
||||
|
||||
// Special menus
|
||||
xx(Mainmenu)
|
||||
|
|
|
@ -375,6 +375,7 @@ void ACSStringPool::Clear()
|
|||
|
||||
int ACSStringPool::AddString(const char *str)
|
||||
{
|
||||
if (str == nullptr) str = "";
|
||||
size_t len = strlen(str);
|
||||
unsigned int h = SuperFastHash(str, len);
|
||||
unsigned int bucketnum = h % NUM_BUCKETS;
|
||||
|
@ -791,6 +792,10 @@ void ACSStringPool::WriteStrings(FSerializer &file, const char *key) const
|
|||
{
|
||||
if (file.BeginObject(nullptr))
|
||||
{
|
||||
if (i == 430)
|
||||
{
|
||||
int a = 0;
|
||||
}
|
||||
file("index", i)
|
||||
("string", entry->Str)
|
||||
("lockcount", entry->LockCount)
|
||||
|
@ -2907,7 +2912,8 @@ FSerializer &Serialize(FSerializer &arc, const char *key, SavingRunningscript &r
|
|||
void DACSThinker::Serialize(FSerializer &arc)
|
||||
{
|
||||
Super::Serialize(arc);
|
||||
arc("scripts", Scripts);
|
||||
arc("scripts", Scripts)
|
||||
("lastscript", LastScript);
|
||||
|
||||
if (arc.isWriting())
|
||||
{
|
||||
|
@ -5344,7 +5350,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
|||
|
||||
case ACSF_PlaySound:
|
||||
case ACSF_PlayActorSound:
|
||||
// PlaySound(tid, "SoundName", channel, volume, looping, attenuation)
|
||||
// PlaySound(tid, "SoundName", channel, volume, looping, attenuation, local)
|
||||
{
|
||||
FSoundID sid;
|
||||
|
||||
|
@ -5365,6 +5371,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
|||
float vol = argCount > 3 ? ACSToFloat(args[3]) : 1.f;
|
||||
INTBOOL looping = argCount > 4 ? args[4] : false;
|
||||
float atten = argCount > 5 ? ACSToFloat(args[5]) : ATTN_NORM;
|
||||
INTBOOL local = argCount > 6 ? args[6] : false;
|
||||
|
||||
if (args[0] == 0)
|
||||
{
|
||||
|
@ -5381,11 +5388,11 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
|||
{
|
||||
if (!looping)
|
||||
{
|
||||
S_Sound(spot, chan, sid, vol, atten);
|
||||
S_PlaySound(spot, chan, sid, vol, atten, local);
|
||||
}
|
||||
else if (!S_IsActorPlayingSomething(spot, chan & 7, sid))
|
||||
{
|
||||
S_Sound(spot, chan | CHAN_LOOP, sid, vol, atten);
|
||||
S_PlaySound(spot, chan | CHAN_LOOP, sid, vol, atten, local);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1032,16 +1032,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PlaySound)
|
|||
PARAM_FLOAT_OPT (volume) { volume = 1; }
|
||||
PARAM_BOOL_OPT (looping) { looping = false; }
|
||||
PARAM_FLOAT_OPT (attenuation) { attenuation = ATTN_NORM; }
|
||||
PARAM_BOOL_OPT (local) { local = false; }
|
||||
|
||||
if (!looping)
|
||||
{
|
||||
S_Sound (self, channel, soundid, (float)volume, (float)attenuation);
|
||||
S_PlaySound(self, channel, soundid, (float)volume, (float)attenuation, local);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!S_IsActorPlayingSomething (self, channel&7, soundid))
|
||||
{
|
||||
S_Sound (self, channel | CHAN_LOOP, soundid, (float)volume, (float)attenuation);
|
||||
S_PlaySound(self, channel | CHAN_LOOP, soundid, (float)volume, (float)attenuation, local);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -252,7 +252,7 @@ static bool LoadScriptFile(int lumpnum, FileReader *lump, int numnodes, bool inc
|
|||
|
||||
if ((type == 1 && !isbinary) || (type == 2 && isbinary))
|
||||
{
|
||||
DPrintf(DMSG_ERROR, "Incorrect data format for %s.", Wads.GetLumpFullName(lumpnum));
|
||||
DPrintf(DMSG_ERROR, "Incorrect data format for conversation script in %s.\n", Wads.GetLumpFullName(lumpnum));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -272,7 +272,7 @@ static bool LoadScriptFile(int lumpnum, FileReader *lump, int numnodes, bool inc
|
|||
// is exactly 1516 bytes long.
|
||||
if (numnodes % 1516 != 0)
|
||||
{
|
||||
DPrintf(DMSG_ERROR, "Incorrect data format for %s.", Wads.GetLumpFullName(lumpnum));
|
||||
DPrintf(DMSG_ERROR, "Incorrect data format for conversation script in %s.\n", Wads.GetLumpFullName(lumpnum));
|
||||
return false;
|
||||
}
|
||||
numnodes /= 1516;
|
||||
|
@ -282,7 +282,7 @@ static bool LoadScriptFile(int lumpnum, FileReader *lump, int numnodes, bool inc
|
|||
// And the teaser version has 1488-byte entries.
|
||||
if (numnodes % 1488 != 0)
|
||||
{
|
||||
DPrintf(DMSG_ERROR, "Incorrect data format for %s.", Wads.GetLumpFullName(lumpnum));
|
||||
DPrintf(DMSG_ERROR, "Incorrect data format for conversation script in %s.\n", Wads.GetLumpFullName(lumpnum));
|
||||
return false;
|
||||
}
|
||||
numnodes /= 1488;
|
||||
|
@ -516,6 +516,8 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
|
|||
reply->ItemCheck[k].Item = dyn_cast<PClassInventory>(GetStrifeType(rsp->Item[k]));
|
||||
reply->ItemCheck[k].Amount = rsp->Count[k];
|
||||
}
|
||||
reply->ItemCheckRequire.Clear();
|
||||
reply->ItemCheckExclude.Clear();
|
||||
|
||||
// If the first item check has a positive amount required, then
|
||||
// add that to the reply string. Otherwise, use the reply as-is.
|
||||
|
@ -656,6 +658,38 @@ CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE)
|
|||
else if (self > 1.f) self = 1.f;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// ShouldSkipReply
|
||||
//
|
||||
// Determines whether this reply should be skipped or not.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
static bool ShouldSkipReply(FStrifeDialogueReply *reply, player_t *player)
|
||||
{
|
||||
if (reply->Reply == nullptr)
|
||||
return true;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < (int)reply->ItemCheckRequire.Size(); ++i)
|
||||
{
|
||||
if (!CheckStrifeItem(player, reply->ItemCheckRequire[i].Item, reply->ItemCheckRequire[i].Amount))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)reply->ItemCheckExclude.Size(); ++i)
|
||||
{
|
||||
if (CheckStrifeItem(player, reply->ItemCheckExclude[i].Item, reply->ItemCheckExclude[i].Amount))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// The conversation menu
|
||||
|
@ -673,6 +707,7 @@ class DConversationMenu : public DMenu
|
|||
bool mShowGold;
|
||||
FStrifeDialogueNode *mCurNode;
|
||||
int mYpos;
|
||||
player_t *mPlayer;
|
||||
|
||||
public:
|
||||
static int mSelection;
|
||||
|
@ -683,9 +718,10 @@ public:
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
DConversationMenu(FStrifeDialogueNode *CurNode)
|
||||
DConversationMenu(FStrifeDialogueNode *CurNode, player_t *player)
|
||||
{
|
||||
mCurNode = CurNode;
|
||||
mPlayer = player;
|
||||
mDialogueLines = NULL;
|
||||
mShowGold = false;
|
||||
|
||||
|
@ -720,7 +756,7 @@ public:
|
|||
int i,j;
|
||||
for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next)
|
||||
{
|
||||
if (reply->Reply == NULL)
|
||||
if (ShouldSkipReply(reply, mPlayer))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -778,6 +814,13 @@ public:
|
|||
}
|
||||
ConversationMenuY = mYpos;
|
||||
//ConversationMenu.indent = 50;
|
||||
|
||||
// Because replies can be selectively hidden mResponses.Size() won't be consistent.
|
||||
// So make sure mSelection doesn't exceed mResponses.Size(). [FishyClockwork]
|
||||
if (mSelection >= (int)mResponses.Size())
|
||||
{
|
||||
mSelection = mResponses.Size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -839,12 +882,24 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
// Send dialogue and reply numbers across the wire.
|
||||
assert((unsigned)mCurNode->ThisNodeNum < StrifeDialogues.Size());
|
||||
assert(StrifeDialogues[mCurNode->ThisNodeNum] == mCurNode);
|
||||
|
||||
// This is needed because mSelection represents the replies currently being displayed which will
|
||||
// not match up with what's supposed to be selected if there are any hidden/skipped replies. [FishyClockwork]
|
||||
FStrifeDialogueReply *reply = mCurNode->Children;
|
||||
int replynum = mSelection;
|
||||
for (int i = 0; i <= mSelection && reply != nullptr; reply = reply->Next)
|
||||
{
|
||||
if (ShouldSkipReply(reply, mPlayer))
|
||||
replynum++;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
// Send dialogue and reply numbers across the wire.
|
||||
Net_WriteByte(DEM_CONVREPLY);
|
||||
Net_WriteWord(mCurNode->ThisNodeNum);
|
||||
Net_WriteByte(mSelection);
|
||||
Net_WriteByte(replynum);
|
||||
}
|
||||
Close();
|
||||
return true;
|
||||
|
@ -1169,7 +1224,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
|
|||
S_Sound (npc, CHAN_VOICE|CHAN_NOPAUSE, CurNode->SpeakerVoice, 1, ATTN_NORM);
|
||||
}
|
||||
|
||||
DConversationMenu *cmenu = new DConversationMenu(CurNode);
|
||||
DConversationMenu *cmenu = new DConversationMenu(CurNode, pc->player);
|
||||
|
||||
|
||||
if (CurNode != PrevNode)
|
||||
|
|
|
@ -45,6 +45,8 @@ struct FStrifeDialogueReply
|
|||
int ActionSpecial;
|
||||
int Args[5];
|
||||
TArray<FStrifeDialogueItemCheck> ItemCheck;
|
||||
TArray<FStrifeDialogueItemCheck> ItemCheckRequire;
|
||||
TArray<FStrifeDialogueItemCheck> ItemCheckExclude;
|
||||
char *Reply;
|
||||
char *QuickYes;
|
||||
int NextNode; // index into StrifeDialogues
|
||||
|
|
|
@ -839,9 +839,11 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
|
|||
|
||||
// If the floor planes on both sides match we should recalculate open.bottom at the actual position we are checking
|
||||
// This is to avoid bumpy movement when crossing a linedef with the same slope on both sides.
|
||||
// This should never narrow down the opening, though, only widen it.
|
||||
if (open.frontfloorplane == open.backfloorplane && open.bottom > LINEOPEN_MIN)
|
||||
{
|
||||
open.bottom = open.frontfloorplane.ZatPoint(cres.Position);
|
||||
auto newopen = open.frontfloorplane.ZatPoint(cres.Position);
|
||||
if (newopen < open.bottom) open.bottom = newopen;
|
||||
}
|
||||
|
||||
if (rail &&
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
|
@ -3373,11 +3373,14 @@ void AActor::Tick ()
|
|||
}
|
||||
}
|
||||
|
||||
UnlinkFromWorld ();
|
||||
flags |= MF_NOBLOCKMAP;
|
||||
SetXYZ(Vec3Offset(Vel));
|
||||
CheckPortalTransition(false);
|
||||
LinkToWorld ();
|
||||
if (!Vel.isZero() || !(flags & MF_NOBLOCKMAP))
|
||||
{
|
||||
UnlinkFromWorld();
|
||||
flags |= MF_NOBLOCKMAP;
|
||||
SetXYZ(Vec3Offset(Vel));
|
||||
CheckPortalTransition(false);
|
||||
LinkToWorld();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4495,6 +4498,7 @@ void AActor::AdjustFloorClip ()
|
|||
// Most of the player structure stays unchanged between levels.
|
||||
//
|
||||
EXTERN_CVAR (Bool, chasedemo)
|
||||
EXTERN_CVAR(Bool, sv_singleplayerrespawn)
|
||||
|
||||
extern bool demonew;
|
||||
|
||||
|
@ -4682,7 +4686,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
|||
{ // Give all cards in death match mode.
|
||||
p->mo->GiveDeathmatchInventory ();
|
||||
}
|
||||
else if ((multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN)) && state == PST_REBORN && oldactor != NULL)
|
||||
else if ((multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN) || sv_singleplayerrespawn) && state == PST_REBORN && oldactor != NULL)
|
||||
{ // Special inventory handling for respawning in coop
|
||||
p->mo->FilterCoopRespawnInventory (oldactor);
|
||||
}
|
||||
|
@ -5059,7 +5063,11 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
|
|||
if (mthing->FloatbobPhase >= 0 && mthing->FloatbobPhase < 64) mobj->FloatBobPhase = mthing->FloatbobPhase;
|
||||
if (mthing->Gravity < 0) mobj->Gravity = -mthing->Gravity;
|
||||
else if (mthing->Gravity > 0) mobj->Gravity *= mthing->Gravity;
|
||||
else mobj->flags &= ~MF_NOGRAVITY;
|
||||
else
|
||||
{
|
||||
mobj->flags |= MF_NOGRAVITY;
|
||||
mobj->Gravity = 0;
|
||||
}
|
||||
|
||||
// For Hexen floatbob 'compatibility' we do not really want to alter the floorz.
|
||||
if (mobj->specialf1 == 0 || !(mobj->flags2 & MF2_FLOATBOB) || !(ib_compatflags & BCOMPATF_FLOATBOB))
|
||||
|
|
|
@ -262,8 +262,7 @@ void DPSprite::NewTick()
|
|||
while (pspr)
|
||||
{
|
||||
pspr->processPending = true;
|
||||
pspr->oldx = pspr->x;
|
||||
pspr->oldy = pspr->y;
|
||||
pspr->ResetInterpolation();
|
||||
|
||||
pspr = pspr->Next;
|
||||
}
|
||||
|
@ -582,8 +581,9 @@ void P_BobWeapon (player_t *player, float *x, float *y, double ticfrac)
|
|||
|
||||
if (curbob != 0)
|
||||
{
|
||||
float bobx = float(player->bob * Rangex);
|
||||
float boby = float(player->bob * Rangey);
|
||||
//[SP] Added in decorate player.viewbob checks
|
||||
float bobx = float(player->bob * Rangex * (float)player->mo->ViewBob);
|
||||
float boby = float(player->bob * Rangey * (float)player->mo->ViewBob);
|
||||
switch (bobstyle)
|
||||
{
|
||||
case AWeapon::BobNormal:
|
||||
|
|
|
@ -29,11 +29,8 @@
|
|||
|
||||
#define WEAPONBOTTOM 128.
|
||||
|
||||
// [RH] +0x6000 helps it meet the screen bottom
|
||||
// at higher resolutions while still being in
|
||||
// the right spot at 320x200.
|
||||
#define WEAPONTOP (32+6./16)
|
||||
|
||||
#define WEAPONTOP 32.
|
||||
#define WEAPON_FUDGE_Y 0.375
|
||||
class AInventory;
|
||||
|
||||
//
|
||||
|
@ -78,6 +75,7 @@ public:
|
|||
DPSprite* GetNext() { return Next; }
|
||||
AActor* GetCaller() { return Caller; }
|
||||
void SetCaller(AActor *newcaller) { Caller = newcaller; }
|
||||
void ResetInterpolation() { oldx = x; oldy = y; }
|
||||
|
||||
double x, y;
|
||||
double oldx, oldy;
|
||||
|
|
|
@ -640,6 +640,12 @@ static void ReadOnePlayer(FSerializer &arc, bool skipload)
|
|||
playerTemp.Serialize(arc);
|
||||
if (!skipload)
|
||||
{
|
||||
// This temp player has undefined pitch limits, so set them to something
|
||||
// that should leave the pitch stored in the savegame intact when
|
||||
// rendering. The real pitch limits will be set by P_SerializePlayers()
|
||||
// via a net command, but that won't be processed in time for a screen
|
||||
// wipe, so we need something here.
|
||||
playerTemp.MaxPitch = playerTemp.MinPitch = playerTemp.mo->Angles.Pitch;
|
||||
CopyPlayer(&players[i], &playerTemp, name);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -76,11 +76,11 @@ class USDFParser : public UDMFParserBase
|
|||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parse a cost block
|
||||
// Parse a cost/require/exclude block
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool ParseCost(FStrifeDialogueReply *response)
|
||||
bool ParseCostRequireExclude(FStrifeDialogueReply *response, FName type)
|
||||
{
|
||||
FStrifeDialogueItemCheck check;
|
||||
check.Item = NULL;
|
||||
|
@ -101,7 +101,12 @@ class USDFParser : public UDMFParserBase
|
|||
}
|
||||
}
|
||||
|
||||
response->ItemCheck.Push(check);
|
||||
switch (type)
|
||||
{
|
||||
case NAME_Cost: response->ItemCheck.Push(check); break;
|
||||
case NAME_Require: response->ItemCheckRequire.Push(check); break;
|
||||
case NAME_Exclude: response->ItemCheckExclude.Push(check); break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -206,8 +211,15 @@ class USDFParser : public UDMFParserBase
|
|||
switch(key)
|
||||
{
|
||||
case NAME_Cost:
|
||||
ParseCost(reply);
|
||||
break;
|
||||
case NAME_Require:
|
||||
case NAME_Exclude:
|
||||
// Require and Exclude are exclusive to namespace ZDoom. [FishyClockwork]
|
||||
if (key == NAME_Cost || namespace_bits == Zd)
|
||||
{
|
||||
ParseCostRequireExclude(reply, key);
|
||||
break;
|
||||
}
|
||||
// Intentional fall-through
|
||||
|
||||
default:
|
||||
sc.UnGet();
|
||||
|
@ -333,7 +345,11 @@ class USDFParser : public UDMFParserBase
|
|||
break;
|
||||
|
||||
case NAME_Goodbye:
|
||||
Goodbye = CheckString(key);
|
||||
// Custom goodbyes are exclusive to namespace ZDoom. [FishyClockwork]
|
||||
if (namespace_bits == Zd)
|
||||
{
|
||||
Goodbye = CheckString(key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,9 @@ static FRandom pr_skullpop ("SkullPop");
|
|||
// [RH] # of ticks to complete a turn180
|
||||
#define TURN180_TICKS ((TICRATE / 4) + 1)
|
||||
|
||||
// [SP] Allows respawn in single player
|
||||
CVAR(Bool, sv_singleplayerrespawn, false, CVAR_SERVERINFO | CVAR_LATCH)
|
||||
|
||||
// Variables for prediction
|
||||
CVAR (Bool, cl_noprediction, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR(Bool, cl_predict_specials, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
@ -651,7 +654,8 @@ void APlayerPawn::Serialize(FSerializer &arc)
|
|||
("fallingscreammaxn", FallingScreamMaxSpeed, def->FallingScreamMaxSpeed)
|
||||
("userange", UseRange, def->UseRange)
|
||||
("aircapacity", AirCapacity, def->AirCapacity)
|
||||
("viewheight", ViewHeight, def->ViewHeight);
|
||||
("viewheight", ViewHeight, def->ViewHeight)
|
||||
("viewbob", ViewBob, def->ViewBob);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -1891,7 +1895,7 @@ void P_CalcHeight (player_t *player)
|
|||
{
|
||||
bob = 0;
|
||||
}
|
||||
player->viewz = player->mo->Z() + player->viewheight + bob;
|
||||
player->viewz = player->mo->Z() + player->viewheight + (bob * player->mo->ViewBob); // [SP] Allow DECORATE changes to view bobbing speed.
|
||||
if (player->mo->Floorclip && player->playerstate != PST_DEAD
|
||||
&& player->mo->Z() <= player->mo->floorz)
|
||||
{
|
||||
|
@ -2210,7 +2214,9 @@ void P_DeathThink (player_t *player)
|
|||
if (level.time >= player->respawn_time || ((player->cmd.ucmd.buttons & BT_USE) && player->Bot == NULL))
|
||||
{
|
||||
player->cls = NULL; // Force a new class if the player is using a random class
|
||||
player->playerstate = (multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN)) ? PST_REBORN : PST_ENTER;
|
||||
player->playerstate =
|
||||
(multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN) || sv_singleplayerrespawn)
|
||||
? PST_REBORN : PST_ENTER;
|
||||
if (player->mo->special1 > 2)
|
||||
{
|
||||
player->mo->special1 = 0;
|
||||
|
@ -2671,10 +2677,11 @@ void P_PlayerThink (player_t *player)
|
|||
// Apply degeneration.
|
||||
if (dmflags2 & DF2_YES_DEGENERATION)
|
||||
{
|
||||
if ((level.time % TICRATE) == 0 && player->health > deh.MaxHealth)
|
||||
int maxhealth = player->mo->GetMaxHealth() + player->mo->stamina;
|
||||
if ((level.time % TICRATE) == 0 && player->health > maxhealth)
|
||||
{
|
||||
if (player->health - 5 < deh.MaxHealth)
|
||||
player->health = deh.MaxHealth;
|
||||
if (player->health - 5 < maxhealth)
|
||||
player->health = maxhealth;
|
||||
else
|
||||
player->health--;
|
||||
|
||||
|
|
|
@ -1024,7 +1024,8 @@ void P_CreateLinkedPortals()
|
|||
{
|
||||
if (sectors[i].GetPortalType(j) == PORTS_LINKEDPORTAL && sectors[i].PortalGroup == 0)
|
||||
{
|
||||
CollectSectors(sectors[i].GetOppositePortalGroup(j), §ors[i]);
|
||||
auto p = sectors[i].GetPortal(j);
|
||||
CollectSectors(p->mOrigin->PortalGroup, §ors[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -526,7 +526,7 @@ void ProcessMouseMoveInGame(NSEvent* theEvent)
|
|||
lastX = x;
|
||||
lastY = y;
|
||||
|
||||
if (0 != event.x | 0 != event.y)
|
||||
if (0 != event.x || 0 != event.y)
|
||||
{
|
||||
event.type = EV_Mouse;
|
||||
|
||||
|
|
|
@ -1018,7 +1018,7 @@ IOKitJoystickManager::~IOKitJoystickManager()
|
|||
if (0 != notification)
|
||||
{
|
||||
IOObjectRelease(notification);
|
||||
notification = NULL;
|
||||
notification = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ static void I_DetectOS()
|
|||
case 12: name = "macOS Sierra"; break;
|
||||
}
|
||||
|
||||
char release[16] = {};
|
||||
char release[16] = "unknown";
|
||||
size_t size = sizeof release - 1;
|
||||
sysctlbyname("kern.osversion", release, &size, nullptr, 0);
|
||||
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
#include <pthread.h>
|
||||
#include <libkern/OSAtomic.h>
|
||||
|
||||
#include "basictypes.h"
|
||||
#include "basicinlines.h"
|
||||
#include "doomdef.h"
|
||||
#include "i_system.h"
|
||||
#include "templates.h"
|
||||
|
|
|
@ -40,9 +40,6 @@
|
|||
#include <signal.h>
|
||||
#include <new>
|
||||
#include <sys/param.h>
|
||||
#ifndef NO_GTK
|
||||
#include <gtk/gtk.h>
|
||||
#endif
|
||||
#include <locale.h>
|
||||
#if defined(__MACH__) && !defined(NOASM)
|
||||
#include <sys/types.h>
|
||||
|
@ -87,10 +84,6 @@ void Mac_I_FatalError(const char* errortext);
|
|||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
#ifndef NO_GTK
|
||||
bool GtkAvailable;
|
||||
#endif
|
||||
|
||||
// The command line arguments.
|
||||
DArgs *Args;
|
||||
|
||||
|
@ -259,10 +252,6 @@ int main (int argc, char **argv)
|
|||
// Note that the LANG environment variable is overridden by LC_*
|
||||
setenv ("LC_NUMERIC", "C", 1);
|
||||
|
||||
#ifndef NO_GTK
|
||||
GtkAvailable = gtk_init_check (&argc, &argv);
|
||||
#endif
|
||||
|
||||
setlocale (LC_ALL, "C");
|
||||
|
||||
if (SDL_Init (0) < 0)
|
||||
|
|
|
@ -34,10 +34,8 @@
|
|||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#ifndef NO_GTK
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#endif
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "doomerrors.h"
|
||||
#include <math.h>
|
||||
|
@ -71,10 +69,6 @@
|
|||
#include "m_fixed.h"
|
||||
#include "g_level.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#endif // __APPLE__
|
||||
|
||||
EXTERN_CVAR (String, language)
|
||||
|
||||
extern "C"
|
||||
|
@ -84,7 +78,8 @@ extern "C"
|
|||
}
|
||||
|
||||
#ifndef NO_GTK
|
||||
extern bool GtkAvailable;
|
||||
bool I_GtkAvailable ();
|
||||
int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad);
|
||||
#elif defined(__APPLE__)
|
||||
int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad);
|
||||
#endif
|
||||
|
@ -262,183 +257,6 @@ void I_PrintStr (const char *cp)
|
|||
fflush (stdout);
|
||||
}
|
||||
|
||||
#ifndef NO_GTK
|
||||
// GtkTreeViews eats return keys. I want this to be like a Windows listbox
|
||||
// where pressing Return can still activate the default button.
|
||||
gint AllowDefault(GtkWidget *widget, GdkEventKey *event, gpointer func_data)
|
||||
{
|
||||
if (event->type == GDK_KEY_PRESS && event->keyval == GDK_Return)
|
||||
{
|
||||
gtk_window_activate_default (GTK_WINDOW(func_data));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Double-clicking an entry in the list is the same as pressing OK.
|
||||
gint DoubleClickChecker(GtkWidget *widget, GdkEventButton *event, gpointer func_data)
|
||||
{
|
||||
if (event->type == GDK_2BUTTON_PRESS)
|
||||
{
|
||||
*(int *)func_data = 1;
|
||||
gtk_main_quit();
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// When the user presses escape, that should be the same as canceling the dialog.
|
||||
gint CheckEscape (GtkWidget *widget, GdkEventKey *event, gpointer func_data)
|
||||
{
|
||||
if (event->type == GDK_KEY_PRESS && event->keyval == GDK_Escape)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void ClickedOK(GtkButton *button, gpointer func_data)
|
||||
{
|
||||
*(int *)func_data = 1;
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
EXTERN_CVAR (Bool, queryiwad);
|
||||
|
||||
int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *bbox;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *tree;
|
||||
GtkWidget *check;
|
||||
GtkListStore *store;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeIter iter, defiter;
|
||||
int close_style = 0;
|
||||
int i;
|
||||
char caption[100];
|
||||
|
||||
// Create the dialog window.
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
mysnprintf(caption, countof(caption), GAMESIG " %s: Select an IWAD to use", GetVersionString());
|
||||
gtk_window_set_title (GTK_WINDOW(window), caption);
|
||||
gtk_window_set_position (GTK_WINDOW(window), GTK_WIN_POS_CENTER);
|
||||
gtk_container_set_border_width (GTK_CONTAINER(window), 10);
|
||||
g_signal_connect (window, "delete_event", G_CALLBACK(gtk_main_quit), NULL);
|
||||
g_signal_connect (window, "key_press_event", G_CALLBACK(CheckEscape), NULL);
|
||||
|
||||
// Create the vbox container.
|
||||
vbox = gtk_vbox_new (FALSE, 10);
|
||||
gtk_container_add (GTK_CONTAINER(window), vbox);
|
||||
|
||||
// Create the top label.
|
||||
widget = gtk_label_new (GAMENAME " found more than one IWAD\nSelect from the list below to determine which one to use:");
|
||||
gtk_box_pack_start (GTK_BOX(vbox), widget, false, false, 0);
|
||||
gtk_misc_set_alignment (GTK_MISC(widget), 0, 0);
|
||||
|
||||
// Create a list store with all the found IWADs.
|
||||
store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT);
|
||||
for (i = 0; i < numwads; ++i)
|
||||
{
|
||||
const char *filepart = strrchr (wads[i].Path, '/');
|
||||
if (filepart == NULL)
|
||||
filepart = wads[i].Path;
|
||||
else
|
||||
filepart++;
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
0, filepart,
|
||||
1, wads[i].Name.GetChars(),
|
||||
2, i,
|
||||
-1);
|
||||
if (i == defaultiwad)
|
||||
{
|
||||
defiter = iter;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the tree view control to show the list.
|
||||
tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store));
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes ("IWAD", renderer, "text", 0, NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW(tree), column);
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes ("Game", renderer, "text", 1, NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW(tree), column);
|
||||
gtk_box_pack_start (GTK_BOX(vbox), GTK_WIDGET(tree), true, true, 0);
|
||||
g_signal_connect(G_OBJECT(tree), "button_press_event", G_CALLBACK(DoubleClickChecker), &close_style);
|
||||
g_signal_connect(G_OBJECT(tree), "key_press_event", G_CALLBACK(AllowDefault), window);
|
||||
|
||||
// Select the default IWAD.
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree));
|
||||
gtk_tree_selection_select_iter (selection, &defiter);
|
||||
|
||||
// Create the hbox for the bottom row.
|
||||
hbox = gtk_hbox_new (FALSE, 0);
|
||||
gtk_box_pack_end (GTK_BOX(vbox), hbox, false, false, 0);
|
||||
|
||||
// Create the "Don't ask" checkbox.
|
||||
check = gtk_check_button_new_with_label ("Don't ask me this again");
|
||||
gtk_box_pack_start (GTK_BOX(hbox), check, false, false, 0);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(check), !showwin);
|
||||
|
||||
// Create the OK/Cancel button box.
|
||||
bbox = gtk_hbutton_box_new ();
|
||||
gtk_button_box_set_layout (GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
|
||||
gtk_box_set_spacing (GTK_BOX(bbox), 10);
|
||||
gtk_box_pack_end (GTK_BOX(hbox), bbox, false, false, 0);
|
||||
|
||||
// Create the OK button.
|
||||
widget = gtk_button_new_from_stock (GTK_STOCK_OK);
|
||||
gtk_box_pack_start (GTK_BOX(bbox), widget, false, false, 0);
|
||||
GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_DEFAULT);
|
||||
gtk_widget_grab_default (widget);
|
||||
g_signal_connect (widget, "clicked", G_CALLBACK(ClickedOK), &close_style);
|
||||
g_signal_connect (widget, "activate", G_CALLBACK(ClickedOK), &close_style);
|
||||
|
||||
// Create the cancel button.
|
||||
widget = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
|
||||
gtk_box_pack_start (GTK_BOX(bbox), widget, false, false, 0);
|
||||
g_signal_connect (widget, "clicked", G_CALLBACK(gtk_main_quit), &window);
|
||||
|
||||
// Finally we can show everything.
|
||||
gtk_widget_show_all (window);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
if (close_style == 1)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GValue value = { 0, { {0} } };
|
||||
|
||||
// Find out which IWAD was selected.
|
||||
gtk_tree_selection_get_selected (selection, &model, &iter);
|
||||
gtk_tree_model_get_value (GTK_TREE_MODEL(model), &iter, 2, &value);
|
||||
i = g_value_get_int (&value);
|
||||
g_value_unset (&value);
|
||||
|
||||
// Set state of queryiwad based on the checkbox.
|
||||
queryiwad = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(check));
|
||||
}
|
||||
else
|
||||
{
|
||||
i = -1;
|
||||
}
|
||||
|
||||
if (GTK_IS_WINDOW(window))
|
||||
{
|
||||
gtk_widget_destroy (window);
|
||||
// If we don't do this, then the X window might not actually disappear.
|
||||
while (g_main_context_iteration (NULL, FALSE)) {}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
||||
{
|
||||
int i;
|
||||
|
@ -448,7 +266,7 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
|||
return defaultiwad;
|
||||
}
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
#ifndef __APPLE__
|
||||
const char *str;
|
||||
if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0)
|
||||
{
|
||||
|
@ -500,12 +318,15 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NO_GTK
|
||||
if (GtkAvailable)
|
||||
if (I_GtkAvailable())
|
||||
{
|
||||
return I_PickIWad_Gtk (wads, numwads, showwin, defaultiwad);
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
return I_PickIWad_Cocoa (wads, numwads, showwin, defaultiwad);
|
||||
#endif
|
||||
|
||||
|
@ -605,139 +426,19 @@ int I_FindAttr (findstate_t *fileinfo)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
static PasteboardRef s_clipboard;
|
||||
|
||||
static CFDataRef GetPasteboardData(const PasteboardItemID itemID, const CFStringRef flavorType)
|
||||
{
|
||||
CFDataRef data = NULL;
|
||||
|
||||
const OSStatus result = PasteboardCopyItemFlavorData(s_clipboard, itemID, flavorType, &data);
|
||||
|
||||
return noErr == result ? data : NULL;
|
||||
}
|
||||
#endif // __APPLE__
|
||||
|
||||
// Clipboard support requires GTK+
|
||||
// TODO: GTK+ uses UTF-8. We don't, so some conversions would be appropriate.
|
||||
void I_PutInClipboard (const char *str)
|
||||
{
|
||||
#ifndef NO_GTK
|
||||
if (GtkAvailable)
|
||||
{
|
||||
GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
||||
if (clipboard != NULL)
|
||||
{
|
||||
gtk_clipboard_set_text(clipboard, str, -1);
|
||||
}
|
||||
/* Should I? I don't know. It's not actually a selection.
|
||||
clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
|
||||
if (clipboard != NULL)
|
||||
{
|
||||
gtk_clipboard_set_text(clipboard, str, -1);
|
||||
}
|
||||
*/
|
||||
}
|
||||
#elif defined __APPLE__
|
||||
if (NULL == s_clipboard)
|
||||
{
|
||||
PasteboardCreate(kPasteboardClipboard, &s_clipboard);
|
||||
}
|
||||
|
||||
PasteboardClear(s_clipboard);
|
||||
PasteboardSynchronize(s_clipboard);
|
||||
|
||||
const CFDataRef textData = CFDataCreate(kCFAllocatorDefault,
|
||||
reinterpret_cast<const UInt8*>(str), strlen(str));
|
||||
|
||||
if (NULL != textData)
|
||||
{
|
||||
PasteboardPutItemFlavor(s_clipboard, PasteboardItemID(1),
|
||||
CFSTR("public.utf8-plain-text"), textData, 0);
|
||||
}
|
||||
#endif
|
||||
SDL_SetClipboardText(str);
|
||||
}
|
||||
|
||||
FString I_GetFromClipboard (bool use_primary_selection)
|
||||
{
|
||||
#ifndef NO_GTK
|
||||
if (GtkAvailable)
|
||||
if(char *ret = SDL_GetClipboardText())
|
||||
{
|
||||
GtkClipboard *clipboard = gtk_clipboard_get(use_primary_selection ?
|
||||
GDK_SELECTION_PRIMARY : GDK_SELECTION_CLIPBOARD);
|
||||
if (clipboard != NULL)
|
||||
{
|
||||
gchar *text = gtk_clipboard_wait_for_text(clipboard);
|
||||
if (text != NULL)
|
||||
{
|
||||
FString copy(text);
|
||||
g_free(text);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
FString text(ret);
|
||||
SDL_free(ret);
|
||||
return text;
|
||||
}
|
||||
#elif defined __APPLE__
|
||||
FString result;
|
||||
|
||||
if (NULL == s_clipboard)
|
||||
{
|
||||
PasteboardCreate(kPasteboardClipboard, &s_clipboard);
|
||||
}
|
||||
|
||||
PasteboardSynchronize(s_clipboard);
|
||||
|
||||
ItemCount itemCount = 0;
|
||||
PasteboardGetItemCount(s_clipboard, &itemCount);
|
||||
|
||||
if (0 == itemCount)
|
||||
{
|
||||
return FString();
|
||||
}
|
||||
|
||||
PasteboardItemID itemID;
|
||||
|
||||
if (0 != PasteboardGetItemIdentifier(s_clipboard, 1, &itemID))
|
||||
{
|
||||
return FString();
|
||||
}
|
||||
|
||||
if (CFDataRef data = GetPasteboardData(itemID, kUTTypeUTF8PlainText))
|
||||
{
|
||||
const CFIndex bufferLength = CFDataGetLength(data);
|
||||
char* const buffer = result.LockNewBuffer(bufferLength);
|
||||
|
||||
memcpy(buffer, CFDataGetBytePtr(data), bufferLength);
|
||||
|
||||
result.UnlockBuffer();
|
||||
}
|
||||
else if (CFDataRef data = GetPasteboardData(itemID, kUTTypeUTF16PlainText))
|
||||
{
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
static const CFStringEncoding ENCODING = kCFStringEncodingUTF16LE;
|
||||
#else // __BIG_ENDIAN__
|
||||
static const CFStringEncoding ENCODING = kCFStringEncodingUTF16BE;
|
||||
#endif // __LITTLE_ENDIAN__
|
||||
|
||||
if (const CFStringRef utf16 = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, data, ENCODING))
|
||||
{
|
||||
const CFRange range = { 0, CFStringGetLength(utf16) };
|
||||
CFIndex bufferLength = 0;
|
||||
|
||||
if (CFStringGetBytes(utf16, range, kCFStringEncodingUTF8, '?', false, NULL, 0, &bufferLength) > 0)
|
||||
{
|
||||
UInt8* const buffer = reinterpret_cast<UInt8*>(result.LockNewBuffer(bufferLength));
|
||||
|
||||
CFStringGetBytes(utf16, range, kCFStringEncodingUTF8, '?', false, buffer, bufferLength, NULL);
|
||||
|
||||
result.UnlockBuffer();
|
||||
}
|
||||
|
||||
CFRelease(utf16);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
#endif
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "basictypes.h"
|
||||
#include "basicinlines.h"
|
||||
#include "m_fixed.h"
|
||||
#include "hardware.h"
|
||||
#include "i_system.h"
|
||||
#include "templates.h"
|
||||
|
|
|
@ -442,6 +442,16 @@ void SDLGLFB::SetVSync( bool vsync )
|
|||
#if defined (__APPLE__)
|
||||
const GLint value = vsync ? 1 : 0;
|
||||
CGLSetParameter( CGLGetCurrentContext(), kCGLCPSwapInterval, &value );
|
||||
#else
|
||||
if (vsync)
|
||||
{
|
||||
if (SDL_GL_SetSwapInterval(-1) == -1)
|
||||
SDL_GL_SetSwapInterval(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_GL_SetSwapInterval(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
339
src/posix/unix/iwadpicker_gtk.cpp
Normal file
339
src/posix/unix/iwadpicker_gtk.cpp
Normal file
|
@ -0,0 +1,339 @@
|
|||
#ifndef NO_GTK
|
||||
|
||||
#if !DYN_GTK
|
||||
// Function addresses will never be NULL, but that's because we're using the
|
||||
// same code for both dynamic and static.
|
||||
#pragma GCC diagnostic ignored "-Waddress"
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#if GTK_MAJOR_VERSION >= 3
|
||||
#include <gdk/gdk.h>
|
||||
#else
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
typedef enum
|
||||
{
|
||||
GTK_ALIGN_FULL,
|
||||
GTK_ALIGN_START,
|
||||
GTK_ALIGN_END,
|
||||
GTK_ALIGN_CENTER,
|
||||
GTK_ALIGN_BASELINE
|
||||
} GtkAlign;
|
||||
#endif
|
||||
|
||||
#include "c_cvars.h"
|
||||
#include "d_main.h"
|
||||
#include "i_module.h"
|
||||
#include "i_system.h"
|
||||
#include "version.h"
|
||||
|
||||
EXTERN_CVAR (Bool, queryiwad);
|
||||
|
||||
namespace Gtk {
|
||||
|
||||
FModuleMaybe<DYN_GTK> GtkModule{"GTK"};
|
||||
static int GtkAvailable = -1;
|
||||
|
||||
#define DYN_GTK_SYM(x) const FModuleMaybe<DYN_GTK>::Req<GtkModule, decltype(::x)*, &x> x{#x};
|
||||
#define DYN_GTK_REQ_SYM(x, proto) const FModuleMaybe<DYN_GTK>::Req<GtkModule, proto, &x> x{#x};
|
||||
#if GTK_MAJOR_VERSION >= 3
|
||||
#define DYN_GTK_OPT2_SYM(x, proto) const FModuleMaybe<DYN_GTK>::Opt<GtkModule, proto, nullptr> x{#x};
|
||||
#define DYN_GTK_OPT3_SYM(x, proto) const FModuleMaybe<DYN_GTK>::Opt<GtkModule, proto, &x> x{#x};
|
||||
#else
|
||||
#define DYN_GTK_OPT2_SYM(x, proto) const FModuleMaybe<DYN_GTK>::Opt<GtkModule, proto, &x> x{#x};
|
||||
#define DYN_GTK_OPT3_SYM(x, proto) const FModuleMaybe<DYN_GTK>::Opt<GtkModule, proto, nullptr> x{#x};
|
||||
#endif
|
||||
|
||||
DYN_GTK_SYM(g_main_context_iteration);
|
||||
DYN_GTK_SYM(g_signal_connect_data);
|
||||
DYN_GTK_SYM(g_type_check_instance_cast);
|
||||
DYN_GTK_SYM(g_type_check_instance_is_a);
|
||||
DYN_GTK_SYM(g_value_get_int);
|
||||
DYN_GTK_SYM(g_value_unset);
|
||||
DYN_GTK_SYM(gtk_box_get_type);
|
||||
DYN_GTK_SYM(gtk_box_pack_end);
|
||||
DYN_GTK_SYM(gtk_box_pack_start);
|
||||
DYN_GTK_SYM(gtk_box_set_spacing);
|
||||
DYN_GTK_SYM(gtk_button_box_get_type);
|
||||
DYN_GTK_SYM(gtk_button_box_set_layout);
|
||||
DYN_GTK_SYM(gtk_button_new_with_label);
|
||||
DYN_GTK_SYM(gtk_cell_renderer_text_new);
|
||||
DYN_GTK_SYM(gtk_check_button_new_with_label);
|
||||
DYN_GTK_SYM(gtk_container_add);
|
||||
DYN_GTK_SYM(gtk_container_get_type);
|
||||
DYN_GTK_SYM(gtk_container_set_border_width);
|
||||
DYN_GTK_SYM(gtk_init_check);
|
||||
DYN_GTK_SYM(gtk_label_new);
|
||||
DYN_GTK_SYM(gtk_list_store_append);
|
||||
DYN_GTK_SYM(gtk_list_store_new);
|
||||
DYN_GTK_SYM(gtk_list_store_set);
|
||||
DYN_GTK_SYM(gtk_toggle_button_get_type);
|
||||
DYN_GTK_SYM(gtk_toggle_button_set_active);
|
||||
DYN_GTK_SYM(gtk_tree_model_get_type);
|
||||
DYN_GTK_SYM(gtk_tree_model_get_value);
|
||||
DYN_GTK_SYM(gtk_tree_selection_get_selected);
|
||||
DYN_GTK_SYM(gtk_tree_selection_select_iter);
|
||||
DYN_GTK_SYM(gtk_tree_view_append_column);
|
||||
// Explicitly give the type so that attributes don't cause a warning.
|
||||
DYN_GTK_REQ_SYM(gtk_tree_view_column_new_with_attributes, GtkTreeViewColumn *(*)(const gchar *, GtkCellRenderer *, ...));
|
||||
DYN_GTK_SYM(gtk_toggle_button_get_active);
|
||||
DYN_GTK_SYM(gtk_tree_view_get_selection);
|
||||
DYN_GTK_SYM(gtk_tree_view_get_type);
|
||||
DYN_GTK_SYM(gtk_tree_view_new_with_model);
|
||||
DYN_GTK_SYM(gtk_main);
|
||||
DYN_GTK_SYM(gtk_main_quit);
|
||||
DYN_GTK_SYM(gtk_widget_destroy);
|
||||
DYN_GTK_SYM(gtk_widget_grab_default);
|
||||
DYN_GTK_SYM(gtk_widget_get_type);
|
||||
DYN_GTK_SYM(gtk_widget_set_can_default);
|
||||
DYN_GTK_SYM(gtk_widget_show_all);
|
||||
DYN_GTK_SYM(gtk_window_activate_default);
|
||||
DYN_GTK_SYM(gtk_window_get_type);
|
||||
DYN_GTK_SYM(gtk_window_new);
|
||||
DYN_GTK_SYM(gtk_window_set_gravity);
|
||||
DYN_GTK_SYM(gtk_window_set_position);
|
||||
DYN_GTK_SYM(gtk_window_set_title);
|
||||
|
||||
// Gtk3 Only
|
||||
DYN_GTK_OPT3_SYM(gtk_box_new, GtkWidget *(*)(GtkOrientation, gint));
|
||||
DYN_GTK_OPT3_SYM(gtk_button_box_new, GtkWidget *(*)(GtkOrientation));
|
||||
DYN_GTK_OPT3_SYM(gtk_widget_set_halign, void(*)(GtkWidget *, GtkAlign));
|
||||
DYN_GTK_OPT3_SYM(gtk_widget_set_valign, void(*)(GtkWidget *, GtkAlign));
|
||||
|
||||
// Gtk2 Only
|
||||
DYN_GTK_OPT2_SYM(gtk_misc_get_type, GType(*)());
|
||||
DYN_GTK_OPT2_SYM(gtk_hbox_new, GtkWidget *(*)(gboolean, gint));
|
||||
DYN_GTK_OPT2_SYM(gtk_hbutton_box_new, GtkWidget *(*)());
|
||||
DYN_GTK_OPT2_SYM(gtk_misc_set_alignment, void(*)(GtkMisc *, gfloat, gfloat));
|
||||
DYN_GTK_OPT2_SYM(gtk_vbox_new, GtkWidget *(*)(gboolean, gint));
|
||||
|
||||
#undef DYN_GTK_SYM
|
||||
#undef DYN_GTK_REQ_SYM
|
||||
#undef DYN_GTK_OPT2_SYM
|
||||
#undef DYN_GTK_OPT3_SYM
|
||||
|
||||
// GtkTreeViews eats return keys. I want this to be like a Windows listbox
|
||||
// where pressing Return can still activate the default button.
|
||||
static gint AllowDefault(GtkWidget *widget, GdkEventKey *event, gpointer func_data)
|
||||
{
|
||||
if (event->type == GDK_KEY_PRESS && event->keyval == GDK_KEY_Return)
|
||||
{
|
||||
gtk_window_activate_default (GTK_WINDOW(func_data));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Double-clicking an entry in the list is the same as pressing OK.
|
||||
static gint DoubleClickChecker(GtkWidget *widget, GdkEventButton *event, gpointer func_data)
|
||||
{
|
||||
if (event->type == GDK_2BUTTON_PRESS)
|
||||
{
|
||||
*(int *)func_data = 1;
|
||||
gtk_main_quit();
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// When the user presses escape, that should be the same as canceling the dialog.
|
||||
static gint CheckEscape (GtkWidget *widget, GdkEventKey *event, gpointer func_data)
|
||||
{
|
||||
if (event->type == GDK_KEY_PRESS && event->keyval == GDK_KEY_Escape)
|
||||
{
|
||||
gtk_main_quit();
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void ClickedOK(GtkButton *button, gpointer func_data)
|
||||
{
|
||||
*(int *)func_data = 1;
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
static int PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *vbox = nullptr;
|
||||
GtkWidget *hbox = nullptr;
|
||||
GtkWidget *bbox = nullptr;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *tree;
|
||||
GtkWidget *check;
|
||||
GtkListStore *store;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeIter iter, defiter;
|
||||
int close_style = 0;
|
||||
int i;
|
||||
char caption[100];
|
||||
|
||||
// Create the dialog window.
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
mysnprintf(caption, countof(caption), GAMESIG " %s: Select an IWAD to use", GetVersionString());
|
||||
gtk_window_set_title (GTK_WINDOW(window), caption);
|
||||
gtk_window_set_position (GTK_WINDOW(window), GTK_WIN_POS_CENTER);
|
||||
gtk_window_set_gravity (GTK_WINDOW(window), GDK_GRAVITY_CENTER);
|
||||
gtk_container_set_border_width (GTK_CONTAINER(window), 10);
|
||||
g_signal_connect (window, "delete_event", G_CALLBACK(gtk_main_quit), NULL);
|
||||
g_signal_connect (window, "key_press_event", G_CALLBACK(CheckEscape), NULL);
|
||||
|
||||
// Create the vbox container.
|
||||
if (gtk_box_new) // Gtk3
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
|
||||
else if (gtk_vbox_new) // Gtk2
|
||||
vbox = gtk_vbox_new (FALSE, 10);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER(window), vbox);
|
||||
|
||||
// Create the top label.
|
||||
widget = gtk_label_new (GAMENAME " found more than one IWAD\nSelect from the list below to determine which one to use:");
|
||||
gtk_box_pack_start (GTK_BOX(vbox), widget, false, false, 0);
|
||||
|
||||
if (gtk_widget_set_halign && gtk_widget_set_valign) // Gtk3
|
||||
{
|
||||
gtk_widget_set_halign (widget, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (widget, GTK_ALIGN_START);
|
||||
}
|
||||
else if (gtk_misc_set_alignment && gtk_misc_get_type) // Gtk2
|
||||
gtk_misc_set_alignment (GTK_MISC(widget), 0, 0);
|
||||
|
||||
// Create a list store with all the found IWADs.
|
||||
store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT);
|
||||
for (i = 0; i < numwads; ++i)
|
||||
{
|
||||
const char *filepart = strrchr (wads[i].Path, '/');
|
||||
if (filepart == NULL)
|
||||
filepart = wads[i].Path;
|
||||
else
|
||||
filepart++;
|
||||
gtk_list_store_append (store, &iter);
|
||||
gtk_list_store_set (store, &iter,
|
||||
0, filepart,
|
||||
1, wads[i].Name.GetChars(),
|
||||
2, i,
|
||||
-1);
|
||||
if (i == defaultiwad)
|
||||
{
|
||||
defiter = iter;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the tree view control to show the list.
|
||||
tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store));
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes ("IWAD", renderer, "text", 0, NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW(tree), column);
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes ("Game", renderer, "text", 1, NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW(tree), column);
|
||||
gtk_box_pack_start (GTK_BOX(vbox), GTK_WIDGET(tree), true, true, 0);
|
||||
g_signal_connect(G_OBJECT(tree), "button_press_event", G_CALLBACK(DoubleClickChecker), &close_style);
|
||||
g_signal_connect(G_OBJECT(tree), "key_press_event", G_CALLBACK(AllowDefault), window);
|
||||
|
||||
// Select the default IWAD.
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree));
|
||||
gtk_tree_selection_select_iter (selection, &defiter);
|
||||
|
||||
// Create the hbox for the bottom row.
|
||||
if (gtk_box_new) // Gtk3
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
else if (gtk_hbox_new) // Gtk2
|
||||
hbox = gtk_hbox_new (FALSE, 0);
|
||||
|
||||
gtk_box_pack_end (GTK_BOX(vbox), hbox, false, false, 0);
|
||||
|
||||
// Create the "Don't ask" checkbox.
|
||||
check = gtk_check_button_new_with_label ("Don't ask me this again");
|
||||
gtk_box_pack_start (GTK_BOX(hbox), check, false, false, 0);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(check), !showwin);
|
||||
|
||||
// Create the OK/Cancel button box.
|
||||
if (gtk_button_box_new) // Gtk3
|
||||
bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
|
||||
else if (gtk_hbutton_box_new) // Gtk2
|
||||
bbox = gtk_hbutton_box_new ();
|
||||
|
||||
gtk_button_box_set_layout (GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
|
||||
gtk_box_set_spacing (GTK_BOX(bbox), 10);
|
||||
gtk_box_pack_end (GTK_BOX(hbox), bbox, false, false, 0);
|
||||
|
||||
// Create the OK button.
|
||||
widget = gtk_button_new_with_label ("OK");
|
||||
|
||||
gtk_box_pack_start (GTK_BOX(bbox), widget, false, false, 0);
|
||||
|
||||
gtk_widget_set_can_default (widget, true);
|
||||
|
||||
gtk_widget_grab_default (widget);
|
||||
g_signal_connect (widget, "clicked", G_CALLBACK(ClickedOK), &close_style);
|
||||
g_signal_connect (widget, "activate", G_CALLBACK(ClickedOK), &close_style);
|
||||
|
||||
// Create the cancel button.
|
||||
widget = gtk_button_new_with_label ("Cancel");
|
||||
|
||||
gtk_box_pack_start (GTK_BOX(bbox), widget, false, false, 0);
|
||||
g_signal_connect (widget, "clicked", G_CALLBACK(gtk_main_quit), &window);
|
||||
|
||||
// Finally we can show everything.
|
||||
gtk_widget_show_all (window);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
if (close_style == 1)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GValue value = { 0, { {0} } };
|
||||
|
||||
// Find out which IWAD was selected.
|
||||
gtk_tree_selection_get_selected (selection, &model, &iter);
|
||||
gtk_tree_model_get_value (GTK_TREE_MODEL(model), &iter, 2, &value);
|
||||
i = g_value_get_int (&value);
|
||||
g_value_unset (&value);
|
||||
|
||||
// Set state of queryiwad based on the checkbox.
|
||||
queryiwad = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(check));
|
||||
}
|
||||
else
|
||||
{
|
||||
i = -1;
|
||||
}
|
||||
|
||||
if (GTK_IS_WINDOW(window))
|
||||
{
|
||||
gtk_widget_destroy (window);
|
||||
// If we don't do this, then the X window might not actually disappear.
|
||||
while (g_main_context_iteration (NULL, FALSE)) {}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
} // namespace Gtk
|
||||
|
||||
int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
||||
{
|
||||
return Gtk::PickIWad (wads, numwads, showwin, defaultiwad);
|
||||
}
|
||||
|
||||
bool I_GtkAvailable()
|
||||
{
|
||||
using namespace Gtk;
|
||||
|
||||
if(GtkAvailable < 0)
|
||||
{
|
||||
if (!GtkModule.Load({"libgtk-3.so.0", "libgtk-x11-2.0.so.0"}))
|
||||
{
|
||||
GtkAvailable = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
int argc = 0;
|
||||
char **argv = nullptr;
|
||||
GtkAvailable = Gtk::gtk_init_check (&argc, &argv);
|
||||
}
|
||||
|
||||
return GtkAvailable != 0;
|
||||
}
|
||||
|
||||
#endif
|
83
src/posix/zdoom.xpm
Normal file
83
src/posix/zdoom.xpm
Normal file
|
@ -0,0 +1,83 @@
|
|||
/* XPM */
|
||||
static char * zdoom_xpm[] = {
|
||||
"48 48 32 1",
|
||||
" c None",
|
||||
". c #ADA990",
|
||||
"+ c #999966",
|
||||
"@ c #666666",
|
||||
"# c #393939",
|
||||
"$ c #555555",
|
||||
"% c #996666",
|
||||
"& c #777777",
|
||||
"* c #5F5F5F",
|
||||
"= c #333333",
|
||||
"- c #4D4D4D",
|
||||
"; c #868686",
|
||||
"> c #969696",
|
||||
", c #1C1C1C",
|
||||
"' c #339933",
|
||||
") c #336633",
|
||||
"! c #66CC66",
|
||||
"~ c #66FF66",
|
||||
"{ c #66CC33",
|
||||
"] c #222222",
|
||||
"^ c #333300",
|
||||
"/ c #292929",
|
||||
"( c #040404",
|
||||
"_ c #0C0C0C",
|
||||
": c #663333",
|
||||
"< c #996633",
|
||||
"[ c #CC9966",
|
||||
"} c #CC6633",
|
||||
"| c #CC9999",
|
||||
"1 c #FFCC99",
|
||||
"2 c #FF9966",
|
||||
"3 c #FFCCCC",
|
||||
" ... ",
|
||||
" ++@##$+ ",
|
||||
" +...+%&+ ",
|
||||
" %*=-*&;$=&* ",
|
||||
" %**=$@;>@=&*% ",
|
||||
" &**@$*@@$-.+& ",
|
||||
" %$%@*..$@.. ",
|
||||
" ,#@+++@@#& ",
|
||||
" $,#$$@@$#=$'' ",
|
||||
" )!!!~!{=],,,,]^)'!{') =/, ",
|
||||
" )){'~!!'')=],=))'{)'')) /=],( ",
|
||||
" )'!!'!)~'{'),)''''''')) @@/==](( ",
|
||||
" ^)''')'{{''')'''''),))) $$@$/,( ",
|
||||
" ,^))),))''''))'')^,__/$$$-#-(( ",
|
||||
" :<[}<,_)))))))),___,]#@@-/]] ",
|
||||
" :<|12<:_,,,,,_,#$$-#/,^^=^}}< ",
|
||||
" :<[1}::,^,,__,#$-==/,,::^:<<< ",
|
||||
" ::&+@#^,,__/)#-=/,,,,-::^<::= ",
|
||||
" :*+12[:==_,$-=/,,,,/,#::::=^ ",
|
||||
" #*}331}-$]-==/,,,,// ##:=^ ",
|
||||
" /]<13[---],,,,,,,]_] ",
|
||||
" ,:--/,___]]]]:^___/ ",
|
||||
" _______,^^,^,__/# ",
|
||||
" ______:::::/$,,/# ",
|
||||
" ____^:::=,^^^^,^^ ",
|
||||
" __,,:=^,,)))^,,= ",
|
||||
" _,,),,,,,^)^^^,, ",
|
||||
" ,^,,),__,^))),,^ ",
|
||||
" ,,,^^,,,,,)))),, ",
|
||||
" ,,,,,,,)^))))^ ",
|
||||
" ,,^,,,^^)))))^ ",
|
||||
" ,^^,,,,)))))), ",
|
||||
" ,^,,,,))^))), ",
|
||||
" ],,,,,$&&&*$# ",
|
||||
" ],,,]#****$# ",
|
||||
" ]]]]]^####, ",
|
||||
" ]]]]*,,,,#* ",
|
||||
" ,_,#@&&@*/ ",
|
||||
" __$####=# ",
|
||||
" ,_/$$$$$# ",
|
||||
" ,,,$*$$$ ",
|
||||
" ],,,$**$# ",
|
||||
" ],,,@&&@# ",
|
||||
" ],,,$**#= ",
|
||||
" ,,=+++%$ ",
|
||||
" *%%%*$ ",
|
||||
" /$*$#/ ",
|
||||
" ],,]] "};
|
|
@ -105,6 +105,7 @@ TArray<PortalDrawseg> WallPortals(1000); // note: this array needs to go away as
|
|||
subsector_t *InSubsector;
|
||||
|
||||
CVAR (Bool, r_drawflat, false, 0) // [RH] Don't texture segs?
|
||||
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
|
||||
|
||||
|
||||
void R_StoreWallRange (int start, int stop);
|
||||
|
@ -1108,7 +1109,7 @@ void R_Subsector (subsector_t *sub)
|
|||
}
|
||||
else
|
||||
{
|
||||
basecolormap = frontsector->ColorMap;
|
||||
basecolormap = (r_fullbrightignoresectorcolor && fixedlightlev >= 0) ? &FullNormalLight : frontsector->ColorMap;
|
||||
}
|
||||
|
||||
portal = frontsector->ValidatePortal(sector_t::ceiling);
|
||||
|
@ -1142,7 +1143,7 @@ void R_Subsector (subsector_t *sub)
|
|||
}
|
||||
else
|
||||
{
|
||||
basecolormap = frontsector->ColorMap;
|
||||
basecolormap = (r_fullbrightignoresectorcolor && fixedlightlev >= 0) ? &FullNormalLight : frontsector->ColorMap;
|
||||
}
|
||||
|
||||
// killough 3/7/98: Add (x,y) offsets to flats, add deep water check
|
||||
|
|
|
@ -59,6 +59,7 @@ static bool R_CheckForFixedLights(const BYTE *colormaps);
|
|||
|
||||
extern "C" {
|
||||
FDynamicColormap NormalLight;
|
||||
FDynamicColormap FullNormalLight; //[SP] Emulate GZDoom brightness
|
||||
}
|
||||
bool NormalLightHasFixedLights;
|
||||
|
||||
|
@ -72,6 +73,7 @@ struct FakeCmap
|
|||
|
||||
TArray<FakeCmap> fakecmaps;
|
||||
BYTE *realcolormaps;
|
||||
BYTE *realfbcolormaps; //[SP] For fullbright use
|
||||
size_t numfakecmaps;
|
||||
|
||||
|
||||
|
@ -459,6 +461,11 @@ void R_DeinitColormaps ()
|
|||
delete[] realcolormaps;
|
||||
realcolormaps = NULL;
|
||||
}
|
||||
if (realfbcolormaps != NULL)
|
||||
{
|
||||
delete[] realfbcolormaps;
|
||||
realfbcolormaps = NULL;
|
||||
}
|
||||
FreeSpecialLights();
|
||||
}
|
||||
|
||||
|
@ -548,9 +555,20 @@ void R_InitColormaps ()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// [SP] Create a copy of the colormap
|
||||
if (!realfbcolormaps)
|
||||
{
|
||||
realfbcolormaps = new BYTE[256*NUMCOLORMAPS*fakecmaps.Size()];
|
||||
memcpy(realfbcolormaps, realcolormaps, 256*NUMCOLORMAPS*fakecmaps.Size());
|
||||
}
|
||||
|
||||
NormalLight.Color = PalEntry (255, 255, 255);
|
||||
NormalLight.Fade = 0;
|
||||
NormalLight.Maps = realcolormaps;
|
||||
FullNormalLight.Color = PalEntry (255, 255, 255);
|
||||
FullNormalLight.Fade = 0;
|
||||
FullNormalLight.Maps = realfbcolormaps;
|
||||
NormalLightHasFixedLights = R_CheckForFixedLights(realcolormaps);
|
||||
numfakecmaps = fakecmaps.Size();
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ extern BYTE DesaturateColormap[31][256];
|
|||
extern "C"
|
||||
{
|
||||
extern FDynamicColormap NormalLight;
|
||||
extern FDynamicColormap FullNormalLight;
|
||||
}
|
||||
extern bool NormalLightHasFixedLights;
|
||||
|
||||
|
|
|
@ -116,7 +116,6 @@ extern void (*R_DrawSpanMaskedAddClamp)(void);
|
|||
|
||||
// [RH] Span blit into an interleaved intermediate buffer
|
||||
extern void (*R_DrawColumnHoriz)(void);
|
||||
void R_DrawMaskedColumnHoriz (const BYTE *column, const FTexture::Span *spans);
|
||||
|
||||
// [RH] Initialize the above pointers
|
||||
void R_InitColumnDrawers ();
|
||||
|
@ -183,6 +182,7 @@ extern void (*rt_map4cols)(int sx, int yl, int yh);
|
|||
#define rt_addclamp4cols rt_addclamp4cols_c
|
||||
#endif
|
||||
|
||||
void rt_flip_posts();
|
||||
void rt_draw4cols (int sx);
|
||||
|
||||
// [RH] Preps the temporary horizontal buffer.
|
||||
|
|
113
src/r_drawt.cpp
113
src/r_drawt.cpp
|
@ -838,6 +838,21 @@ void rt_tlaterevsubclamp4cols (int sx, int yl, int yh)
|
|||
rt_revsubclamp4cols(sx, yl, yh);
|
||||
}
|
||||
|
||||
// Reorder the posts so that they get drawn top-to-bottom instead of bottom-to-top.
|
||||
void rt_flip_posts()
|
||||
{
|
||||
unsigned int *front = horizspan[dc_x & 3];
|
||||
unsigned int *back = dc_ctspan[dc_x & 3] - 2;
|
||||
|
||||
while (front < back)
|
||||
{
|
||||
swapvalues(front[0], back[0]);
|
||||
swapvalues(front[1], back[1]);
|
||||
front += 2;
|
||||
back -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Copies all spans in all four columns to the screen starting at sx.
|
||||
// sx should be dword-aligned.
|
||||
void rt_draw4cols (int sx)
|
||||
|
@ -1103,101 +1118,3 @@ void R_FillColumnHorizP (void)
|
|||
dest += 8;
|
||||
} while (--count);
|
||||
}
|
||||
|
||||
// Same as R_DrawMaskedColumn() except that it always uses R_DrawColumnHoriz().
|
||||
|
||||
void R_DrawMaskedColumnHoriz (const BYTE *column, const FTexture::Span *span)
|
||||
{
|
||||
const fixed_t texturemid = FLOAT2FIXED(dc_texturemid);
|
||||
while (span->Length != 0)
|
||||
{
|
||||
const int length = span->Length;
|
||||
const int top = span->TopOffset;
|
||||
|
||||
// calculate unclipped screen coordinates for post
|
||||
dc_yl = xs_RoundToInt(sprtopscreen + spryscale * top);
|
||||
dc_yh = xs_RoundToInt(sprtopscreen + spryscale * (top + length) - 1);
|
||||
|
||||
if (sprflipvert)
|
||||
{
|
||||
swapvalues (dc_yl, dc_yh);
|
||||
}
|
||||
|
||||
if (dc_yh >= mfloorclip[dc_x])
|
||||
{
|
||||
dc_yh = mfloorclip[dc_x] - 1;
|
||||
}
|
||||
if (dc_yl < mceilingclip[dc_x])
|
||||
{
|
||||
dc_yl = mceilingclip[dc_x];
|
||||
}
|
||||
|
||||
if (dc_yl <= dc_yh)
|
||||
{
|
||||
if (sprflipvert)
|
||||
{
|
||||
dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS)
|
||||
- fixed_t(CenterY * dc_iscale) - texturemid;
|
||||
const fixed_t maxfrac = length << FRACBITS;
|
||||
while (dc_texturefrac >= maxfrac)
|
||||
{
|
||||
if (++dc_yl > dc_yh)
|
||||
goto nextpost;
|
||||
dc_texturefrac += dc_iscale;
|
||||
}
|
||||
fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
|
||||
while (endfrac < 0)
|
||||
{
|
||||
if (--dc_yh < dc_yl)
|
||||
goto nextpost;
|
||||
endfrac -= dc_iscale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dc_texturefrac = texturemid - (top << FRACBITS)
|
||||
+ (dc_yl*dc_iscale) - fixed_t((CenterY-1) * dc_iscale);
|
||||
while (dc_texturefrac < 0)
|
||||
{
|
||||
if (++dc_yl > dc_yh)
|
||||
goto nextpost;
|
||||
dc_texturefrac += dc_iscale;
|
||||
}
|
||||
fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
|
||||
const fixed_t maxfrac = length << FRACBITS;
|
||||
if (dc_yh < mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale)
|
||||
{
|
||||
dc_yh++;
|
||||
}
|
||||
else while (endfrac >= maxfrac)
|
||||
{
|
||||
if (--dc_yh < dc_yl)
|
||||
goto nextpost;
|
||||
endfrac -= dc_iscale;
|
||||
}
|
||||
}
|
||||
dc_source = column + top;
|
||||
dc_dest = ylookup[dc_yl] + dc_x + dc_destorg;
|
||||
dc_count = dc_yh - dc_yl + 1;
|
||||
hcolfunc_pre ();
|
||||
}
|
||||
nextpost:
|
||||
span++;
|
||||
}
|
||||
|
||||
if (sprflipvert)
|
||||
{
|
||||
unsigned int *front = horizspan[dc_x&3];
|
||||
unsigned int *back = dc_ctspan[dc_x&3] - 2;
|
||||
|
||||
// Reorder the posts so that they get drawn top-to-bottom
|
||||
// instead of bottom-to-top.
|
||||
while (front < back)
|
||||
{
|
||||
swapvalues (front[0], back[0]);
|
||||
swapvalues (front[1], back[1]);
|
||||
front += 2;
|
||||
back -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -355,7 +355,7 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight,
|
|||
MaxVisForWall = (InvZtoScale * (SCREENWIDTH*r_Yaspect) /
|
||||
(viewwidth*SCREENHEIGHT * FocalTangent));
|
||||
MaxVisForWall = 32767.0 / MaxVisForWall;
|
||||
MaxVisForFloor = 32767.0 / (viewheight * FocalLengthY / 160);
|
||||
MaxVisForFloor = 32767.0 / (viewheight >> 2) * FocalLengthY / 160;
|
||||
|
||||
// Reset r_*Visibility vars
|
||||
R_SetVisibility(R_GetVisibility());
|
||||
|
@ -455,6 +455,8 @@ void R_CopyStackedViewParameters()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor)
|
||||
|
||||
void R_SetupColormap(player_t *player)
|
||||
{
|
||||
realfixedcolormap = NULL;
|
||||
|
@ -481,6 +483,11 @@ void R_SetupColormap(player_t *player)
|
|||
else if (player->fixedlightlevel >= 0 && player->fixedlightlevel < NUMCOLORMAPS)
|
||||
{
|
||||
fixedlightlev = player->fixedlightlevel * 256;
|
||||
// [SP] Emulate GZDoom's light-amp goggles.
|
||||
if (r_fullbrightignoresectorcolor && fixedlightlev >= 0)
|
||||
{
|
||||
fixedcolormap = FullNormalLight.Maps;
|
||||
}
|
||||
}
|
||||
}
|
||||
// [RH] Inverse light for shooting the Sigil
|
||||
|
|
|
@ -221,10 +221,26 @@ void R_MapPlane (int y, int x1)
|
|||
|
||||
distance = planeheight * yslope[y];
|
||||
|
||||
ds_xstep = xs_ToFixed(32-ds_xbits, distance * xstepscale);
|
||||
ds_ystep = xs_ToFixed(32-ds_ybits, distance * ystepscale);
|
||||
ds_xfrac = xs_ToFixed(32-ds_xbits, distance * basexfrac) + pviewx;
|
||||
ds_yfrac = xs_ToFixed(32-ds_ybits, distance * baseyfrac) + pviewy;
|
||||
if (ds_xbits != 0)
|
||||
{
|
||||
ds_xstep = xs_ToFixed(32 - ds_xbits, distance * xstepscale);
|
||||
ds_xfrac = xs_ToFixed(32 - ds_xbits, distance * basexfrac) + pviewx;
|
||||
}
|
||||
else
|
||||
{
|
||||
ds_xstep = 0;
|
||||
ds_xfrac = 0;
|
||||
}
|
||||
if (ds_ybits != 0)
|
||||
{
|
||||
ds_ystep = xs_ToFixed(32 - ds_ybits, distance * ystepscale);
|
||||
ds_yfrac = xs_ToFixed(32 - ds_ybits, distance * baseyfrac) + pviewy;
|
||||
}
|
||||
else
|
||||
{
|
||||
ds_ystep = 0;
|
||||
ds_yfrac = 0;
|
||||
}
|
||||
|
||||
if (plane_shade)
|
||||
{
|
||||
|
@ -357,7 +373,7 @@ void R_CalcTiltedLighting (double lval, double lend, int width)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void R_MapTiltedPlane (int y, int x1)
|
||||
void R_MapTiltedPlane(int y, int x1)
|
||||
{
|
||||
int x2 = spanend[y];
|
||||
int width = x2 - x1;
|
||||
|
@ -366,18 +382,18 @@ void R_MapTiltedPlane (int y, int x1)
|
|||
DWORD u, v;
|
||||
int i;
|
||||
|
||||
iz = plane_sz[2] + plane_sz[1]*(centery-y) + plane_sz[0]*(x1-centerx);
|
||||
iz = plane_sz[2] + plane_sz[1] * (centery - y) + plane_sz[0] * (x1 - centerx);
|
||||
|
||||
// Lighting is simple. It's just linear interpolation from start to end
|
||||
if (plane_shade)
|
||||
{
|
||||
uz = (iz + plane_sz[0]*width) * planelightfloat;
|
||||
uz = (iz + plane_sz[0] * width) * planelightfloat;
|
||||
vz = iz * planelightfloat;
|
||||
R_CalcTiltedLighting (vz, uz, width);
|
||||
R_CalcTiltedLighting(vz, uz, width);
|
||||
}
|
||||
|
||||
uz = plane_su[2] + plane_su[1]*(centery-y) + plane_su[0]*(x1-centerx);
|
||||
vz = plane_sv[2] + plane_sv[1]*(centery-y) + plane_sv[0]*(x1-centerx);
|
||||
uz = plane_su[2] + plane_su[1] * (centery - y) + plane_su[0] * (x1 - centerx);
|
||||
vz = plane_sv[2] + plane_sv[1] * (centery - y) + plane_sv[0] * (x1 - centerx);
|
||||
|
||||
fb = ylookup[y] + x1 + dc_destorg;
|
||||
|
||||
|
@ -595,9 +611,10 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
|||
fixed_t alpha = FLOAT2FIXED(Alpha);
|
||||
//angle_t angle = (xform.Angle + xform.baseAngle).BAMs();
|
||||
|
||||
FTransform nulltransform;
|
||||
|
||||
if (picnum == skyflatnum) // killough 10/98
|
||||
{ // most skies map together
|
||||
FTransform nulltransform;
|
||||
lightlevel = 0;
|
||||
xform = &nulltransform;
|
||||
nulltransform.xOffs = nulltransform.yOffs = nulltransform.baseyOffs = 0;
|
||||
|
@ -1887,6 +1904,15 @@ void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t
|
|||
}
|
||||
}
|
||||
|
||||
// Hack in support for 1 x Z and Z x 1 texture sizes
|
||||
if (ds_ybits == 0)
|
||||
{
|
||||
plane_sv[2] = plane_sv[1] = plane_sv[0] = 0;
|
||||
}
|
||||
if (ds_xbits == 0)
|
||||
{
|
||||
plane_su[2] = plane_su[1] = plane_su[0] = 0;
|
||||
}
|
||||
#if defined(X86_ASM)
|
||||
if (ds_source != ds_curtiltedsource)
|
||||
R_SetTiltedSpanSource_ASM (ds_source);
|
||||
|
|
824
src/r_segs.cpp
824
src/r_segs.cpp
|
@ -57,6 +57,7 @@
|
|||
|
||||
|
||||
CVAR(Bool, r_np2, true, 0)
|
||||
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
|
||||
|
||||
//CVAR (Int, ty, 8, 0)
|
||||
//CVAR (Int, tx, 8, 0)
|
||||
|
@ -172,7 +173,7 @@ CVAR(Bool, r_drawmirrors, true, 0)
|
|||
float *MaskedSWall;
|
||||
float MaskedScaleY;
|
||||
|
||||
static void BlastMaskedColumn (void (*blastfunc)(const BYTE *pixels, const FTexture::Span *spans), FTexture *tex)
|
||||
static void BlastMaskedColumn (FTexture *tex, bool useRt)
|
||||
{
|
||||
// calculate lighting
|
||||
if (fixedcolormap == NULL && fixedlightlev < 0)
|
||||
|
@ -197,7 +198,7 @@ static void BlastMaskedColumn (void (*blastfunc)(const BYTE *pixels, const FText
|
|||
// draw the texture
|
||||
const FTexture::Span *spans;
|
||||
const BYTE *pixels = tex->GetColumn (maskedtexturecol[dc_x] >> FRACBITS, &spans);
|
||||
blastfunc (pixels, spans);
|
||||
R_DrawMaskedColumn(pixels, spans, useRt);
|
||||
rw_light += rw_lightstep;
|
||||
spryscale += rw_scalestep;
|
||||
}
|
||||
|
@ -313,7 +314,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
|
|||
rw_scalestep = ds->iscalestep;
|
||||
|
||||
if (fixedlightlev >= 0)
|
||||
dc_colormap = basecolormap->Maps + fixedlightlev;
|
||||
dc_colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (basecolormap->Maps + fixedlightlev);
|
||||
else if (fixedcolormap != NULL)
|
||||
dc_colormap = fixedcolormap;
|
||||
|
||||
|
@ -440,7 +441,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
|
|||
{
|
||||
for (dc_x = x1; dc_x < x2; ++dc_x)
|
||||
{
|
||||
BlastMaskedColumn (R_DrawMaskedColumn, tex);
|
||||
BlastMaskedColumn (tex, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -455,24 +456,24 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2)
|
|||
|
||||
while ((dc_x < stop) && (dc_x & 3))
|
||||
{
|
||||
BlastMaskedColumn (R_DrawMaskedColumn, tex);
|
||||
BlastMaskedColumn (tex, false);
|
||||
dc_x++;
|
||||
}
|
||||
|
||||
while (dc_x < stop)
|
||||
{
|
||||
rt_initcols();
|
||||
BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++;
|
||||
BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++;
|
||||
BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++;
|
||||
BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex);
|
||||
BlastMaskedColumn (tex, true); dc_x++;
|
||||
BlastMaskedColumn (tex, true); dc_x++;
|
||||
BlastMaskedColumn (tex, true); dc_x++;
|
||||
BlastMaskedColumn (tex, true);
|
||||
rt_draw4cols (dc_x - 3);
|
||||
dc_x++;
|
||||
}
|
||||
|
||||
while (dc_x < x2)
|
||||
{
|
||||
BlastMaskedColumn (R_DrawMaskedColumn, tex);
|
||||
BlastMaskedColumn (tex, false);
|
||||
dc_x++;
|
||||
}
|
||||
}
|
||||
|
@ -630,7 +631,7 @@ void R_RenderFakeWall(drawseg_t *ds, int x1, int x2, F3DFloor *rover)
|
|||
}
|
||||
|
||||
if (fixedlightlev >= 0)
|
||||
dc_colormap = basecolormap->Maps + fixedlightlev;
|
||||
dc_colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (basecolormap->Maps + fixedlightlev);
|
||||
else if (fixedcolormap != NULL)
|
||||
dc_colormap = fixedcolormap;
|
||||
|
||||
|
@ -1065,50 +1066,188 @@ void R_RenderFakeWallRange (drawseg_t *ds, int x1, int x2)
|
|||
return;
|
||||
}
|
||||
|
||||
// prevlineasm1 is like vlineasm1 but skips the loop if only drawing one pixel
|
||||
inline fixed_t prevline1 (fixed_t vince, BYTE *colormap, int count, fixed_t vplce, const BYTE *bufplce, BYTE *dest)
|
||||
struct WallscanSampler
|
||||
{
|
||||
dc_iscale = vince;
|
||||
dc_colormap = colormap;
|
||||
dc_count = count;
|
||||
dc_texturefrac = vplce;
|
||||
dc_source = bufplce;
|
||||
dc_dest = dest;
|
||||
return doprevline1 ();
|
||||
}
|
||||
WallscanSampler() { }
|
||||
WallscanSampler(int y1, float swal, double yrepeat, fixed_t xoffset, FTexture *texture, const BYTE*(*getcol)(FTexture *texture, int x));
|
||||
|
||||
void wallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal,
|
||||
double yrepeat, const BYTE *(*getcol)(FTexture *tex, int x))
|
||||
uint32_t uv_pos;
|
||||
uint32_t uv_step;
|
||||
uint32_t uv_max;
|
||||
|
||||
const BYTE *source;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
WallscanSampler::WallscanSampler(int y1, float swal, double yrepeat, fixed_t xoffset, FTexture *texture, const BYTE*(*getcol)(FTexture *texture, int x))
|
||||
{
|
||||
int x, fracbits;
|
||||
int y1ve[4], y2ve[4], u4, d4, z;
|
||||
char bad;
|
||||
float light = rw_light - rw_lightstep;
|
||||
SDWORD xoffset;
|
||||
BYTE *basecolormapdata;
|
||||
double iscale;
|
||||
height = texture->GetHeight();
|
||||
|
||||
// This function also gets used to draw skies. Unlike BUILD, skies are
|
||||
// drawn by visplane instead of by bunch, so these checks are invalid.
|
||||
//if ((uwal[x1] > viewheight) && (uwal[x2] > viewheight)) return;
|
||||
//if ((dwal[x1] < 0) && (dwal[x2] < 0)) return;
|
||||
|
||||
if (rw_pic->UseType == FTexture::TEX_Null)
|
||||
int uv_fracbits = 32 - texture->HeightBits;
|
||||
if (uv_fracbits != 32)
|
||||
{
|
||||
return;
|
||||
uv_max = height << uv_fracbits;
|
||||
|
||||
// Find start uv in [0-base_height[ range.
|
||||
// Not using xs_ToFixed because it rounds the result and we need something that always rounds down to stay within the range.
|
||||
double uv_stepd = swal * yrepeat;
|
||||
double v = (dc_texturemid + uv_stepd * (y1 - CenterY + 0.5)) / height;
|
||||
v = v - floor(v);
|
||||
v *= height;
|
||||
v *= (1 << uv_fracbits);
|
||||
|
||||
uv_pos = (uint32_t)v;
|
||||
uv_step = xs_ToFixed(uv_fracbits, uv_stepd);
|
||||
if (uv_step == 0) // To prevent divide by zero elsewhere
|
||||
uv_step = 1;
|
||||
}
|
||||
else
|
||||
{ // Hack for one pixel tall textures
|
||||
uv_pos = 0;
|
||||
uv_step = 0;
|
||||
uv_max = 1;
|
||||
}
|
||||
|
||||
//extern cycle_t WallScanCycles;
|
||||
//clock (WallScanCycles);
|
||||
source = getcol(texture, xoffset >> FRACBITS);
|
||||
}
|
||||
|
||||
rw_pic->GetHeight(); // Make sure texture size is loaded
|
||||
fracbits = 32 - rw_pic->HeightBits;
|
||||
setupvline(fracbits);
|
||||
xoffset = rw_offset;
|
||||
basecolormapdata = basecolormap->Maps;
|
||||
// Draw a column with support for non-power-of-two ranges
|
||||
void wallscan_drawcol1(int x, int y1, int y2, WallscanSampler &sampler, DWORD(*draw1column)())
|
||||
{
|
||||
if (sampler.uv_max == 0 || sampler.uv_step == 0) // power of two
|
||||
{
|
||||
int count = y2 - y1;
|
||||
|
||||
x = x1;
|
||||
//while ((umost[x] > dmost[x]) && (x < x2)) x++;
|
||||
dc_source = sampler.source;
|
||||
dc_dest = (ylookup[y1] + x) + dc_destorg;
|
||||
dc_count = count;
|
||||
dc_iscale = sampler.uv_step;
|
||||
dc_texturefrac = sampler.uv_pos;
|
||||
draw1column();
|
||||
|
||||
uint64_t step64 = sampler.uv_step;
|
||||
uint64_t pos64 = sampler.uv_pos;
|
||||
sampler.uv_pos = (uint32_t)(pos64 + step64 * count);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t uv_pos = sampler.uv_pos;
|
||||
|
||||
uint32_t left = y2 - y1;
|
||||
while (left > 0)
|
||||
{
|
||||
uint32_t available = sampler.uv_max - uv_pos;
|
||||
uint32_t next_uv_wrap = available / sampler.uv_step;
|
||||
if (available % sampler.uv_step != 0)
|
||||
next_uv_wrap++;
|
||||
uint32_t count = MIN(left, next_uv_wrap);
|
||||
|
||||
dc_source = sampler.source;
|
||||
dc_dest = (ylookup[y1] + x) + dc_destorg;
|
||||
dc_count = count;
|
||||
dc_iscale = sampler.uv_step;
|
||||
dc_texturefrac = uv_pos;
|
||||
draw1column();
|
||||
|
||||
left -= count;
|
||||
uv_pos += sampler.uv_step * count;
|
||||
if (uv_pos >= sampler.uv_max)
|
||||
uv_pos -= sampler.uv_max;
|
||||
}
|
||||
|
||||
sampler.uv_pos = uv_pos;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw four columns with support for non-power-of-two ranges
|
||||
void wallscan_drawcol4(int x, int y1, int y2, WallscanSampler *sampler, void(*draw4columns)())
|
||||
{
|
||||
if (sampler[0].uv_max == 0 || sampler[0].uv_step == 0) // power of two, no wrap handling needed
|
||||
{
|
||||
int count = y2 - y1;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
bufplce[i] = sampler[i].source;
|
||||
vplce[i] = sampler[i].uv_pos;
|
||||
vince[i] = sampler[i].uv_step;
|
||||
|
||||
uint64_t step64 = sampler[i].uv_step;
|
||||
uint64_t pos64 = sampler[i].uv_pos;
|
||||
sampler[i].uv_pos = (uint32_t)(pos64 + step64 * count);
|
||||
}
|
||||
dc_dest = (ylookup[y1] + x) + dc_destorg;
|
||||
dc_count = count;
|
||||
draw4columns();
|
||||
}
|
||||
else
|
||||
{
|
||||
dc_dest = (ylookup[y1] + x) + dc_destorg;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
bufplce[i] = sampler[i].source;
|
||||
}
|
||||
|
||||
uint32_t left = y2 - y1;
|
||||
while (left > 0)
|
||||
{
|
||||
// Find which column wraps first
|
||||
uint32_t count = left;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
uint32_t available = sampler[i].uv_max - sampler[i].uv_pos;
|
||||
uint32_t next_uv_wrap = available / sampler[i].uv_step;
|
||||
if (available % sampler[i].uv_step != 0)
|
||||
next_uv_wrap++;
|
||||
count = MIN(next_uv_wrap, count);
|
||||
}
|
||||
|
||||
// Draw until that column wraps
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
vplce[i] = sampler[i].uv_pos;
|
||||
vince[i] = sampler[i].uv_step;
|
||||
}
|
||||
dc_count = count;
|
||||
draw4columns();
|
||||
|
||||
// Wrap the uv position
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
sampler[i].uv_pos += sampler[i].uv_step * count;
|
||||
if (sampler[i].uv_pos >= sampler[i].uv_max)
|
||||
sampler[i].uv_pos -= sampler[i].uv_max;
|
||||
}
|
||||
|
||||
left -= count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef DWORD(*Draw1ColumnFuncPtr)();
|
||||
typedef void(*Draw4ColumnsFuncPtr)();
|
||||
|
||||
void wallscan_any(
|
||||
int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat,
|
||||
const BYTE *(*getcol)(FTexture *tex, int x),
|
||||
void(setupwallscan(int bits, Draw1ColumnFuncPtr &draw1, Draw4ColumnsFuncPtr &draw2)))
|
||||
{
|
||||
if (rw_pic->UseType == FTexture::TEX_Null)
|
||||
return;
|
||||
|
||||
fixed_t xoffset = rw_offset;
|
||||
|
||||
rw_pic->GetHeight(); // To ensure that rw_pic->HeightBits has been set
|
||||
int fracbits = 32 - rw_pic->HeightBits;
|
||||
if (fracbits == 32)
|
||||
{ // Hack for one pixel tall textures
|
||||
fracbits = 0;
|
||||
yrepeat = 0;
|
||||
dc_texturemid = 0;
|
||||
}
|
||||
|
||||
DWORD(*draw1column)();
|
||||
void(*draw4columns)();
|
||||
setupwallscan(fracbits, draw1column, draw4columns);
|
||||
|
||||
bool fixed = (fixedcolormap != NULL || fixedlightlev >= 0);
|
||||
if (fixed)
|
||||
|
@ -1119,128 +1258,175 @@ void wallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *l
|
|||
palookupoffse[3] = dc_colormap;
|
||||
}
|
||||
|
||||
for(; (x < x2) && (x & 3); ++x)
|
||||
if (fixedcolormap)
|
||||
dc_colormap = fixedcolormap;
|
||||
else
|
||||
dc_colormap = basecolormap->Maps;
|
||||
|
||||
float light = rw_light;
|
||||
|
||||
// Calculate where 4 column alignment begins and ends:
|
||||
int aligned_x1 = clamp((x1 + 3) / 4 * 4, x1, x2);
|
||||
int aligned_x2 = clamp(x2 / 4 * 4, x1, x2);
|
||||
|
||||
// First unaligned columns:
|
||||
for (int x = x1; x < aligned_x1; x++, light += rw_lightstep)
|
||||
{
|
||||
light += rw_lightstep;
|
||||
y1ve[0] = uwal[x];//max(uwal[x],umost[x]);
|
||||
y2ve[0] = dwal[x];//min(dwal[x],dmost[x]);
|
||||
if (y2ve[0] <= y1ve[0]) continue;
|
||||
assert (y1ve[0] < viewheight);
|
||||
assert (y2ve[0] <= viewheight);
|
||||
int y1 = uwal[x];
|
||||
int y2 = dwal[x];
|
||||
if (y2 <= y1)
|
||||
continue;
|
||||
|
||||
if (!fixed)
|
||||
{ // calculate lighting
|
||||
dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
|
||||
}
|
||||
dc_colormap = basecolormap->Maps + (GETPALOOKUP(light, wallshade) << COLORMAPSHIFT);
|
||||
|
||||
dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS);
|
||||
dc_dest = ylookup[y1ve[0]] + x + dc_destorg;
|
||||
dc_count = y2ve[0] - y1ve[0];
|
||||
iscale = swal[x] * yrepeat;
|
||||
dc_iscale = xs_ToFixed(fracbits, iscale);
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 0.5));
|
||||
|
||||
dovline1();
|
||||
WallscanSampler sampler(y1, swal[x], yrepeat, lwal[x] + xoffset, rw_pic, getcol);
|
||||
wallscan_drawcol1(x, y1, y2, sampler, draw1column);
|
||||
}
|
||||
|
||||
for(; x < x2-3; x += 4)
|
||||
// The aligned columns
|
||||
for (int x = aligned_x1; x < aligned_x2; x += 4)
|
||||
{
|
||||
bad = 0;
|
||||
for (z = 3; z>= 0; --z)
|
||||
{
|
||||
y1ve[z] = uwal[x+z];//max(uwal[x+z],umost[x+z]);
|
||||
y2ve[z] = dwal[x+z];//min(dwal[x+z],dmost[x+z])-1;
|
||||
if (y2ve[z] <= y1ve[z]) { bad += 1<<z; continue; }
|
||||
assert (y1ve[z] < viewheight);
|
||||
assert (y2ve[z] <= viewheight);
|
||||
// Find y1, y2, light and uv values for four columns:
|
||||
int y1[4] = { uwal[x], uwal[x + 1], uwal[x + 2], uwal[x + 3] };
|
||||
int y2[4] = { dwal[x], dwal[x + 1], dwal[x + 2], dwal[x + 3] };
|
||||
|
||||
bufplce[z] = getcol (rw_pic, (lwal[x+z] + xoffset) >> FRACBITS);
|
||||
iscale = swal[x + z] * yrepeat;
|
||||
vince[z] = xs_ToFixed(fracbits, iscale);
|
||||
vplce[z] = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[z] - CenterY + 0.5));
|
||||
}
|
||||
if (bad == 15)
|
||||
float lights[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
light += rw_lightstep * 4;
|
||||
continue;
|
||||
lights[i] = light;
|
||||
light += rw_lightstep;
|
||||
}
|
||||
|
||||
if (!fixed)
|
||||
WallscanSampler sampler[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
sampler[i] = WallscanSampler(y1[i], swal[x + i], yrepeat, lwal[x + i] + xoffset, rw_pic, getcol);
|
||||
|
||||
// Figure out where we vertically can start and stop drawing 4 columns in one go
|
||||
int middle_y1 = y1[0];
|
||||
int middle_y2 = y2[0];
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
for (z = 0; z < 4; ++z)
|
||||
middle_y1 = MAX(y1[i], middle_y1);
|
||||
middle_y2 = MIN(y2[i], middle_y2);
|
||||
}
|
||||
|
||||
// If we got an empty column in our set we cannot draw 4 columns in one go:
|
||||
bool empty_column_in_set = false;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (y2[i] <= y1[i])
|
||||
empty_column_in_set = true;
|
||||
}
|
||||
|
||||
if (empty_column_in_set || middle_y2 <= middle_y1)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
light += rw_lightstep;
|
||||
palookupoffse[z] = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
|
||||
}
|
||||
}
|
||||
if (y2[i] <= y1[i])
|
||||
continue;
|
||||
|
||||
u4 = MAX(MAX(y1ve[0],y1ve[1]),MAX(y1ve[2],y1ve[3]));
|
||||
d4 = MIN(MIN(y2ve[0],y2ve[1]),MIN(y2ve[2],y2ve[3]));
|
||||
|
||||
if ((bad != 0) || (u4 >= d4))
|
||||
{
|
||||
for (z = 0; z < 4; ++z)
|
||||
{
|
||||
if (!(bad & 1))
|
||||
{
|
||||
prevline1(vince[z],palookupoffse[z],y2ve[z]-y1ve[z],vplce[z],bufplce[z],ylookup[y1ve[z]]+x+z+dc_destorg);
|
||||
}
|
||||
bad >>= 1;
|
||||
if (!fixed)
|
||||
dc_colormap = basecolormap->Maps + (GETPALOOKUP(lights[i], wallshade) << COLORMAPSHIFT);
|
||||
wallscan_drawcol1(x + i, y1[i], y2[i], sampler[i], draw1column);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (z = 0; z < 4; ++z)
|
||||
// Draw the first rows where not all 4 columns are active
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (u4 > y1ve[z])
|
||||
{
|
||||
vplce[z] = prevline1(vince[z],palookupoffse[z],u4-y1ve[z],vplce[z],bufplce[z],ylookup[y1ve[z]]+x+z+dc_destorg);
|
||||
}
|
||||
if (!fixed)
|
||||
dc_colormap = basecolormap->Maps + (GETPALOOKUP(lights[i], wallshade) << COLORMAPSHIFT);
|
||||
|
||||
if (y1[i] < middle_y1)
|
||||
wallscan_drawcol1(x + i, y1[i], middle_y1, sampler[i], draw1column);
|
||||
}
|
||||
|
||||
if (d4 > u4)
|
||||
// Draw the area where all 4 columns are active
|
||||
if (!fixed)
|
||||
{
|
||||
dc_count = d4-u4;
|
||||
dc_dest = ylookup[u4]+x+dc_destorg;
|
||||
dovline4();
|
||||
}
|
||||
|
||||
BYTE *i = x+ylookup[d4]+dc_destorg;
|
||||
for (z = 0; z < 4; ++z)
|
||||
{
|
||||
if (y2ve[z] > d4)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
prevline1(vince[z],palookupoffse[0],y2ve[z]-d4,vplce[z],bufplce[z],i+z);
|
||||
palookupoffse[i] = basecolormap->Maps + (GETPALOOKUP(lights[i], wallshade) << COLORMAPSHIFT);
|
||||
}
|
||||
}
|
||||
wallscan_drawcol4(x, middle_y1, middle_y2, sampler, draw4columns);
|
||||
|
||||
// Draw the last rows where not all 4 columns are active
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (!fixed)
|
||||
dc_colormap = basecolormap->Maps + (GETPALOOKUP(lights[i], wallshade) << COLORMAPSHIFT);
|
||||
|
||||
if (middle_y2 < y2[i])
|
||||
wallscan_drawcol1(x + i, middle_y2, y2[i], sampler[i], draw1column);
|
||||
}
|
||||
}
|
||||
for(;x<x2;x++)
|
||||
|
||||
// The last unaligned columns:
|
||||
for (int x = aligned_x2; x < x2; x++, light += rw_lightstep)
|
||||
{
|
||||
light += rw_lightstep;
|
||||
y1ve[0] = uwal[x];//max(uwal[x],umost[x]);
|
||||
y2ve[0] = dwal[x];//min(dwal[x],dmost[x]);
|
||||
if (y2ve[0] <= y1ve[0]) continue;
|
||||
assert (y1ve[0] < viewheight);
|
||||
assert (y2ve[0] <= viewheight);
|
||||
int y1 = uwal[x];
|
||||
int y2 = dwal[x];
|
||||
if (y2 <= y1)
|
||||
continue;
|
||||
|
||||
if (!fixed)
|
||||
{ // calculate lighting
|
||||
dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
|
||||
}
|
||||
dc_colormap = basecolormap->Maps + (GETPALOOKUP(light, wallshade) << COLORMAPSHIFT);
|
||||
|
||||
dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS);
|
||||
dc_dest = ylookup[y1ve[0]] + x + dc_destorg;
|
||||
dc_count = y2ve[0] - y1ve[0];
|
||||
iscale = swal[x] * yrepeat;
|
||||
dc_iscale = xs_ToFixed(fracbits, iscale);
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 0.5));
|
||||
|
||||
dovline1();
|
||||
WallscanSampler sampler(y1, swal[x], yrepeat, lwal[x] + xoffset, rw_pic, getcol);
|
||||
wallscan_drawcol1(x, y1, y2, sampler, draw1column);
|
||||
}
|
||||
|
||||
//unclock (WallScanCycles);
|
||||
NetUpdate();
|
||||
}
|
||||
|
||||
NetUpdate ();
|
||||
void wallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int x))
|
||||
{
|
||||
wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4)
|
||||
{
|
||||
setupvline(bits);
|
||||
line1 = dovline1;
|
||||
line4 = dovline4;
|
||||
});
|
||||
}
|
||||
|
||||
void maskwallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int x))
|
||||
{
|
||||
if (!rw_pic->bMasked) // Textures that aren't masked can use the faster wallscan.
|
||||
{
|
||||
wallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol);
|
||||
}
|
||||
else
|
||||
{
|
||||
wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4)
|
||||
{
|
||||
setupmvline(bits);
|
||||
line1 = domvline1;
|
||||
line4 = domvline4;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void transmaskwallscan(int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat, const BYTE *(*getcol)(FTexture *tex, int x))
|
||||
{
|
||||
static fixed_t(*tmvline1)();
|
||||
static void(*tmvline4)();
|
||||
if (!R_GetTransMaskDrawers(&tmvline1, &tmvline4))
|
||||
{
|
||||
// The current translucency is unsupported, so draw with regular maskwallscan instead.
|
||||
maskwallscan(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol);
|
||||
}
|
||||
else
|
||||
{
|
||||
wallscan_any(x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol, [](int bits, Draw1ColumnFuncPtr &line1, Draw4ColumnsFuncPtr &line4)
|
||||
{
|
||||
setuptmvline(bits);
|
||||
line1 = reinterpret_cast<DWORD(*)()>(tmvline1);
|
||||
line4 = tmvline4;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void wallscan_striped (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal, double yrepeat)
|
||||
|
@ -1416,358 +1602,6 @@ static void wallscan_np2_ds(drawseg_t *ds, int x1, int x2, short *uwal, short *d
|
|||
}
|
||||
}
|
||||
|
||||
inline fixed_t mvline1 (fixed_t vince, BYTE *colormap, int count, fixed_t vplce, const BYTE *bufplce, BYTE *dest)
|
||||
{
|
||||
dc_iscale = vince;
|
||||
dc_colormap = colormap;
|
||||
dc_count = count;
|
||||
dc_texturefrac = vplce;
|
||||
dc_source = bufplce;
|
||||
dc_dest = dest;
|
||||
return domvline1 ();
|
||||
}
|
||||
|
||||
void maskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal,
|
||||
double yrepeat, const BYTE *(*getcol)(FTexture *tex, int x))
|
||||
{
|
||||
int x, fracbits;
|
||||
BYTE *p;
|
||||
int y1ve[4], y2ve[4], u4, d4, startx, dax, z;
|
||||
char bad;
|
||||
float light = rw_light - rw_lightstep;
|
||||
SDWORD xoffset;
|
||||
BYTE *basecolormapdata;
|
||||
double iscale;
|
||||
|
||||
if (rw_pic->UseType == FTexture::TEX_Null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rw_pic->bMasked)
|
||||
{ // Textures that aren't masked can use the faster wallscan.
|
||||
wallscan (x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol);
|
||||
return;
|
||||
}
|
||||
|
||||
//extern cycle_t WallScanCycles;
|
||||
//clock (WallScanCycles);
|
||||
|
||||
rw_pic->GetHeight(); // Make sure texture size is loaded
|
||||
fracbits = 32- rw_pic->HeightBits;
|
||||
setupmvline(fracbits);
|
||||
xoffset = rw_offset;
|
||||
basecolormapdata = basecolormap->Maps;
|
||||
|
||||
x = startx = x1;
|
||||
p = x + dc_destorg;
|
||||
|
||||
bool fixed = (fixedcolormap != NULL || fixedlightlev >= 0);
|
||||
if (fixed)
|
||||
{
|
||||
palookupoffse[0] = dc_colormap;
|
||||
palookupoffse[1] = dc_colormap;
|
||||
palookupoffse[2] = dc_colormap;
|
||||
palookupoffse[3] = dc_colormap;
|
||||
}
|
||||
|
||||
for(; (x < x2) && ((size_t)p & 3); ++x, ++p)
|
||||
{
|
||||
light += rw_lightstep;
|
||||
y1ve[0] = uwal[x];//max(uwal[x],umost[x]);
|
||||
y2ve[0] = dwal[x];//min(dwal[x],dmost[x]);
|
||||
if (y2ve[0] <= y1ve[0]) continue;
|
||||
|
||||
if (!fixed)
|
||||
{ // calculate lighting
|
||||
dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
|
||||
}
|
||||
|
||||
dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS);
|
||||
dc_dest = ylookup[y1ve[0]] + p;
|
||||
dc_count = y2ve[0] - y1ve[0];
|
||||
iscale = swal[x] * yrepeat;
|
||||
dc_iscale = xs_ToFixed(fracbits, iscale);
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 0.5));
|
||||
|
||||
domvline1();
|
||||
}
|
||||
|
||||
for(; x < x2-3; x += 4, p+= 4)
|
||||
{
|
||||
bad = 0;
|
||||
for (z = 3, dax = x+3; z >= 0; --z, --dax)
|
||||
{
|
||||
y1ve[z] = uwal[dax];
|
||||
y2ve[z] = dwal[dax];
|
||||
if (y2ve[z] <= y1ve[z]) { bad += 1<<z; continue; }
|
||||
|
||||
bufplce[z] = getcol (rw_pic, (lwal[dax] + xoffset) >> FRACBITS);
|
||||
iscale = swal[dax] * yrepeat;
|
||||
vince[z] = xs_ToFixed(fracbits, iscale);
|
||||
vplce[z] = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[z] - CenterY + 0.5));
|
||||
}
|
||||
if (bad == 15)
|
||||
{
|
||||
light += rw_lightstep * 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!fixed)
|
||||
{
|
||||
for (z = 0; z < 4; ++z)
|
||||
{
|
||||
light += rw_lightstep;
|
||||
palookupoffse[z] = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
u4 = MAX(MAX(y1ve[0],y1ve[1]),MAX(y1ve[2],y1ve[3]));
|
||||
d4 = MIN(MIN(y2ve[0],y2ve[1]),MIN(y2ve[2],y2ve[3]));
|
||||
|
||||
if ((bad != 0) || (u4 >= d4))
|
||||
{
|
||||
for (z = 0; z < 4; ++z)
|
||||
{
|
||||
if (!(bad & 1))
|
||||
{
|
||||
mvline1(vince[z],palookupoffse[z],y2ve[z]-y1ve[z],vplce[z],bufplce[z],ylookup[y1ve[z]]+p+z);
|
||||
}
|
||||
bad >>= 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (z = 0; z < 4; ++z)
|
||||
{
|
||||
if (u4 > y1ve[z])
|
||||
{
|
||||
vplce[z] = mvline1(vince[z],palookupoffse[z],u4-y1ve[z],vplce[z],bufplce[z],ylookup[y1ve[z]]+p+z);
|
||||
}
|
||||
}
|
||||
|
||||
if (d4 > u4)
|
||||
{
|
||||
dc_count = d4-u4;
|
||||
dc_dest = ylookup[u4]+p;
|
||||
domvline4();
|
||||
}
|
||||
|
||||
BYTE *i = p+ylookup[d4];
|
||||
for (z = 0; z < 4; ++z)
|
||||
{
|
||||
if (y2ve[z] > d4)
|
||||
{
|
||||
mvline1(vince[z],palookupoffse[0],y2ve[z]-d4,vplce[z],bufplce[z],i+z);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(; x < x2; ++x, ++p)
|
||||
{
|
||||
light += rw_lightstep;
|
||||
y1ve[0] = uwal[x];
|
||||
y2ve[0] = dwal[x];
|
||||
if (y2ve[0] <= y1ve[0]) continue;
|
||||
|
||||
if (!fixed)
|
||||
{ // calculate lighting
|
||||
dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
|
||||
}
|
||||
|
||||
dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS);
|
||||
dc_dest = ylookup[y1ve[0]] + p;
|
||||
dc_count = y2ve[0] - y1ve[0];
|
||||
iscale = swal[x] * yrepeat;
|
||||
dc_iscale = xs_ToFixed(fracbits, iscale);
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 0.5));
|
||||
|
||||
domvline1();
|
||||
}
|
||||
|
||||
//unclock(WallScanCycles);
|
||||
|
||||
NetUpdate ();
|
||||
}
|
||||
|
||||
inline void preptmvline1 (fixed_t vince, BYTE *colormap, int count, fixed_t vplce, const BYTE *bufplce, BYTE *dest)
|
||||
{
|
||||
dc_iscale = vince;
|
||||
dc_colormap = colormap;
|
||||
dc_count = count;
|
||||
dc_texturefrac = vplce;
|
||||
dc_source = bufplce;
|
||||
dc_dest = dest;
|
||||
}
|
||||
|
||||
void transmaskwallscan (int x1, int x2, short *uwal, short *dwal, float *swal, fixed_t *lwal,
|
||||
double yrepeat, const BYTE *(*getcol)(FTexture *tex, int x))
|
||||
{
|
||||
fixed_t (*tmvline1)();
|
||||
void (*tmvline4)();
|
||||
int x, fracbits;
|
||||
BYTE *p;
|
||||
int y1ve[4], y2ve[4], u4, d4, startx, dax, z;
|
||||
char bad;
|
||||
float light = rw_light - rw_lightstep;
|
||||
SDWORD xoffset;
|
||||
BYTE *basecolormapdata;
|
||||
double iscale;
|
||||
|
||||
if (rw_pic->UseType == FTexture::TEX_Null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!R_GetTransMaskDrawers (&tmvline1, &tmvline4))
|
||||
{
|
||||
// The current translucency is unsupported, so draw with regular maskwallscan instead.
|
||||
maskwallscan (x1, x2, uwal, dwal, swal, lwal, yrepeat, getcol);
|
||||
return;
|
||||
}
|
||||
|
||||
//extern cycle_t WallScanCycles;
|
||||
//clock (WallScanCycles);
|
||||
|
||||
rw_pic->GetHeight(); // Make sure texture size is loaded
|
||||
fracbits = 32 - rw_pic->HeightBits;
|
||||
setuptmvline(fracbits);
|
||||
xoffset = rw_offset;
|
||||
basecolormapdata = basecolormap->Maps;
|
||||
fixed_t centeryfrac = FLOAT2FIXED(CenterY);
|
||||
|
||||
x = startx = x1;
|
||||
p = x + dc_destorg;
|
||||
|
||||
bool fixed = (fixedcolormap != NULL || fixedlightlev >= 0);
|
||||
if (fixed)
|
||||
{
|
||||
palookupoffse[0] = dc_colormap;
|
||||
palookupoffse[1] = dc_colormap;
|
||||
palookupoffse[2] = dc_colormap;
|
||||
palookupoffse[3] = dc_colormap;
|
||||
}
|
||||
|
||||
for(; (x < x2) && ((size_t)p & 3); ++x, ++p)
|
||||
{
|
||||
light += rw_lightstep;
|
||||
y1ve[0] = uwal[x];//max(uwal[x],umost[x]);
|
||||
y2ve[0] = dwal[x];//min(dwal[x],dmost[x]);
|
||||
if (y2ve[0] <= y1ve[0]) continue;
|
||||
|
||||
if (!fixed)
|
||||
{ // calculate lighting
|
||||
dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
|
||||
}
|
||||
|
||||
dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS);
|
||||
dc_dest = ylookup[y1ve[0]] + p;
|
||||
dc_count = y2ve[0] - y1ve[0];
|
||||
iscale = swal[x] * yrepeat;
|
||||
dc_iscale = xs_ToFixed(fracbits, iscale);
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 0.5));
|
||||
|
||||
tmvline1();
|
||||
}
|
||||
|
||||
for(; x < x2-3; x += 4, p+= 4)
|
||||
{
|
||||
bad = 0;
|
||||
for (z = 3, dax = x+3; z >= 0; --z, --dax)
|
||||
{
|
||||
y1ve[z] = uwal[dax];
|
||||
y2ve[z] = dwal[dax];
|
||||
if (y2ve[z] <= y1ve[z]) { bad += 1<<z; continue; }
|
||||
|
||||
bufplce[z] = getcol (rw_pic, (lwal[dax] + xoffset) >> FRACBITS);
|
||||
iscale = swal[dax] * yrepeat;
|
||||
vince[z] = xs_ToFixed(fracbits, iscale);
|
||||
vplce[z] = xs_ToFixed(fracbits, dc_texturemid + vince[z] * (y1ve[z] - CenterY + 0.5));
|
||||
}
|
||||
if (bad == 15)
|
||||
{
|
||||
light += rw_lightstep * 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!fixed)
|
||||
{
|
||||
for (z = 0; z < 4; ++z)
|
||||
{
|
||||
light += rw_lightstep;
|
||||
palookupoffse[z] = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
u4 = MAX(MAX(y1ve[0],y1ve[1]),MAX(y1ve[2],y1ve[3]));
|
||||
d4 = MIN(MIN(y2ve[0],y2ve[1]),MIN(y2ve[2],y2ve[3]));
|
||||
|
||||
if ((bad != 0) || (u4 >= d4))
|
||||
{
|
||||
for (z = 0; z < 4; ++z)
|
||||
{
|
||||
if (!(bad & 1))
|
||||
{
|
||||
preptmvline1(vince[z],palookupoffse[z],y2ve[z]-y1ve[z],vplce[z],bufplce[z],ylookup[y1ve[z]]+p+z);
|
||||
tmvline1();
|
||||
}
|
||||
bad >>= 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (z = 0; z < 4; ++z)
|
||||
{
|
||||
if (u4 > y1ve[z])
|
||||
{
|
||||
preptmvline1(vince[z],palookupoffse[z],u4-y1ve[z],vplce[z],bufplce[z],ylookup[y1ve[z]]+p+z);
|
||||
vplce[z] = tmvline1();
|
||||
}
|
||||
}
|
||||
|
||||
if (d4 > u4)
|
||||
{
|
||||
dc_count = d4-u4;
|
||||
dc_dest = ylookup[u4]+p;
|
||||
tmvline4();
|
||||
}
|
||||
|
||||
BYTE *i = p+ylookup[d4];
|
||||
for (z = 0; z < 4; ++z)
|
||||
{
|
||||
if (y2ve[z] > d4)
|
||||
{
|
||||
preptmvline1(vince[z],palookupoffse[0],y2ve[z]-d4,vplce[z],bufplce[z],i+z);
|
||||
tmvline1();
|
||||
}
|
||||
}
|
||||
}
|
||||
for(; x < x2; ++x, ++p)
|
||||
{
|
||||
light += rw_lightstep;
|
||||
y1ve[0] = uwal[x];
|
||||
y2ve[0] = dwal[x];
|
||||
if (y2ve[0] <= y1ve[0]) continue;
|
||||
|
||||
if (!fixed)
|
||||
{ // calculate lighting
|
||||
dc_colormap = basecolormapdata + (GETPALOOKUP (light, wallshade) << COLORMAPSHIFT);
|
||||
}
|
||||
|
||||
dc_source = getcol (rw_pic, (lwal[x] + xoffset) >> FRACBITS);
|
||||
dc_dest = ylookup[y1ve[0]] + p;
|
||||
dc_count = y2ve[0] - y1ve[0];
|
||||
iscale = swal[x] * yrepeat;
|
||||
dc_iscale = xs_ToFixed(fracbits, iscale);
|
||||
dc_texturefrac = xs_ToFixed(fracbits, dc_texturemid + iscale * (y1ve[0] - CenterY + 0.5));
|
||||
|
||||
tmvline1();
|
||||
}
|
||||
|
||||
//unclock(WallScanCycles);
|
||||
|
||||
NetUpdate ();
|
||||
}
|
||||
|
||||
//
|
||||
// R_RenderSegLoop
|
||||
// Draws zero, one, or two textures for walls.
|
||||
|
@ -1788,7 +1622,7 @@ void R_RenderSegLoop ()
|
|||
fixed_t xoffset = rw_offset;
|
||||
|
||||
if (fixedlightlev >= 0)
|
||||
dc_colormap = basecolormap->Maps + fixedlightlev;
|
||||
dc_colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (basecolormap->Maps + fixedlightlev);
|
||||
else if (fixedcolormap != NULL)
|
||||
dc_colormap = fixedcolormap;
|
||||
|
||||
|
@ -2520,7 +2354,7 @@ void R_StoreWallRange (int start, int stop)
|
|||
lwal = (fixed_t *)(openings + ds_p->maskedtexturecol);
|
||||
swal = (float *)(openings + ds_p->swall);
|
||||
FTexture *pic = TexMan(sidedef->GetTexture(side_t::mid), true);
|
||||
double yscale = pic->Scale.X * sidedef->GetTextureYScale(side_t::mid);
|
||||
double yscale = pic->Scale.Y * sidedef->GetTextureYScale(side_t::mid);
|
||||
fixed_t xoffset = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::mid));
|
||||
|
||||
if (pic->bWorldPanning)
|
||||
|
@ -3185,13 +3019,13 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
|
|||
rereadcolormap = false;
|
||||
}
|
||||
|
||||
rw_light = rw_lightleft + (x1 - WallC.sx1) * rw_lightstep;
|
||||
rw_light = rw_lightleft + (x1 - savecoord.sx1) * rw_lightstep;
|
||||
if (fixedlightlev >= 0)
|
||||
dc_colormap = usecolormap->Maps + fixedlightlev;
|
||||
dc_colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (usecolormap->Maps + fixedlightlev);
|
||||
else if (fixedcolormap != NULL)
|
||||
dc_colormap = fixedcolormap;
|
||||
else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT))
|
||||
dc_colormap = usecolormap->Maps;
|
||||
dc_colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : usecolormap->Maps;
|
||||
else
|
||||
calclighting = true;
|
||||
|
||||
|
@ -3244,7 +3078,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
|
|||
{ // calculate lighting
|
||||
dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT);
|
||||
}
|
||||
R_WallSpriteColumn (R_DrawMaskedColumn);
|
||||
R_WallSpriteColumn (false);
|
||||
dc_x++;
|
||||
}
|
||||
|
||||
|
@ -3257,7 +3091,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
|
|||
rt_initcols();
|
||||
for (int zz = 4; zz; --zz)
|
||||
{
|
||||
R_WallSpriteColumn (R_DrawMaskedColumnHoriz);
|
||||
R_WallSpriteColumn (true);
|
||||
dc_x++;
|
||||
}
|
||||
rt_draw4cols (dc_x - 4);
|
||||
|
@ -3269,7 +3103,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper,
|
|||
{ // calculate lighting
|
||||
dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT);
|
||||
}
|
||||
R_WallSpriteColumn (R_DrawMaskedColumn);
|
||||
R_WallSpriteColumn (false);
|
||||
dc_x++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,10 +76,20 @@ void R_InitSkyMap ()
|
|||
int skyheight;
|
||||
FTexture *skytex1, *skytex2;
|
||||
|
||||
// Do not allow the null texture which has no bitmap and will crash.
|
||||
if (sky1texture.isNull())
|
||||
{
|
||||
sky1texture = TexMan.CheckForTexture("-noflat-", FTexture::TEX_Any);
|
||||
}
|
||||
if (sky2texture.isNull())
|
||||
{
|
||||
sky2texture = TexMan.CheckForTexture("-noflat-", FTexture::TEX_Any);
|
||||
}
|
||||
|
||||
skytex1 = TexMan(sky1texture, true);
|
||||
skytex2 = TexMan(sky2texture, true);
|
||||
|
||||
if (skytex1 == NULL)
|
||||
if (skytex1 == nullptr)
|
||||
return;
|
||||
|
||||
if ((level.flags & LEVEL_DOUBLESKY) && skytex1->GetHeight() != skytex2->GetHeight())
|
||||
|
|
122
src/r_things.cpp
122
src/r_things.cpp
|
@ -99,6 +99,7 @@ EXTERN_CVAR (Bool, st_scale)
|
|||
EXTERN_CVAR(Bool, r_shadercolormaps)
|
||||
EXTERN_CVAR(Int, r_drawfuzz)
|
||||
EXTERN_CVAR(Bool, r_deathcamera);
|
||||
CVAR(Bool, r_fullbrightignoresectorcolor, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||
|
||||
//
|
||||
// Sprite rotation 0 is facing the viewer,
|
||||
|
@ -249,18 +250,16 @@ double sprtopscreen;
|
|||
|
||||
bool sprflipvert;
|
||||
|
||||
void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span)
|
||||
void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span, bool useRt)
|
||||
{
|
||||
const fixed_t centeryfrac = FLOAT2FIXED(CenterY);
|
||||
const fixed_t texturemid = FLOAT2FIXED(dc_texturemid);
|
||||
while (span->Length != 0)
|
||||
{
|
||||
const int length = span->Length;
|
||||
const int top = span->TopOffset;
|
||||
|
||||
// calculate unclipped screen coordinates for post
|
||||
dc_yl = xs_RoundToInt(sprtopscreen + spryscale * top);
|
||||
dc_yh = xs_RoundToInt(sprtopscreen + spryscale * (top + length)) - 1;
|
||||
dc_yl = (int)(sprtopscreen + spryscale * top + 0.5);
|
||||
dc_yh = (int)(sprtopscreen + spryscale * (top + length) + 0.5) - 1;
|
||||
|
||||
if (sprflipvert)
|
||||
{
|
||||
|
@ -278,56 +277,29 @@ void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span)
|
|||
|
||||
if (dc_yl <= dc_yh)
|
||||
{
|
||||
if (sprflipvert)
|
||||
{
|
||||
dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS)
|
||||
- FixedMul (centeryfrac, dc_iscale) - texturemid;
|
||||
const fixed_t maxfrac = length << FRACBITS;
|
||||
while (dc_texturefrac >= maxfrac)
|
||||
{
|
||||
if (++dc_yl > dc_yh)
|
||||
goto nextpost;
|
||||
dc_texturefrac += dc_iscale;
|
||||
}
|
||||
fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
|
||||
while (endfrac < 0)
|
||||
{
|
||||
if (--dc_yh < dc_yl)
|
||||
goto nextpost;
|
||||
endfrac -= dc_iscale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dc_texturefrac = texturemid - (top << FRACBITS)
|
||||
+ (dc_yl*dc_iscale) - FixedMul (centeryfrac-FRACUNIT, dc_iscale);
|
||||
while (dc_texturefrac < 0)
|
||||
{
|
||||
if (++dc_yl > dc_yh)
|
||||
goto nextpost;
|
||||
dc_texturefrac += dc_iscale;
|
||||
}
|
||||
fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale;
|
||||
const fixed_t maxfrac = length << FRACBITS;
|
||||
if (dc_yh < mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale)
|
||||
{
|
||||
dc_yh++;
|
||||
}
|
||||
else while (endfrac >= maxfrac)
|
||||
{
|
||||
if (--dc_yh < dc_yl)
|
||||
goto nextpost;
|
||||
endfrac -= dc_iscale;
|
||||
}
|
||||
}
|
||||
dc_source = column + top;
|
||||
dc_dest = ylookup[dc_yl] + dc_x + dc_destorg;
|
||||
dc_texturefrac = FLOAT2FIXED((dc_yl + 0.5 - sprtopscreen) / spryscale);
|
||||
dc_source = column;
|
||||
dc_dest = (ylookup[dc_yl] + dc_x) + dc_destorg;
|
||||
dc_count = dc_yh - dc_yl + 1;
|
||||
colfunc ();
|
||||
|
||||
fixed_t maxfrac = ((top + length) << FRACBITS) - 1;
|
||||
dc_texturefrac = MAX(dc_texturefrac, 0);
|
||||
dc_texturefrac = MIN(dc_texturefrac, maxfrac);
|
||||
if (dc_iscale > 0)
|
||||
dc_count = MIN(dc_count, (maxfrac - dc_texturefrac + dc_iscale - 1) / dc_iscale);
|
||||
else if (dc_iscale < 0)
|
||||
dc_count = MIN(dc_count, (dc_texturefrac - dc_iscale) / (-dc_iscale));
|
||||
|
||||
if (useRt)
|
||||
hcolfunc_pre();
|
||||
else
|
||||
colfunc ();
|
||||
}
|
||||
nextpost:
|
||||
span++;
|
||||
}
|
||||
|
||||
if (sprflipvert && useRt)
|
||||
rt_flip_posts();
|
||||
}
|
||||
|
||||
// [ZZ]
|
||||
|
@ -469,7 +441,7 @@ void R_DrawVisSprite (vissprite_t *vis)
|
|||
{
|
||||
pixels = tex->GetColumn (frac >> FRACBITS, &spans);
|
||||
if (ispsprite || !R_ClipSpriteColumnWithPortals(vis))
|
||||
R_DrawMaskedColumn (pixels, spans);
|
||||
R_DrawMaskedColumn (pixels, spans, false);
|
||||
dc_x++;
|
||||
frac += xiscale;
|
||||
}
|
||||
|
@ -481,7 +453,7 @@ void R_DrawVisSprite (vissprite_t *vis)
|
|||
{
|
||||
pixels = tex->GetColumn (frac >> FRACBITS, &spans);
|
||||
if (ispsprite || !R_ClipSpriteColumnWithPortals(vis))
|
||||
R_DrawMaskedColumnHoriz (pixels, spans);
|
||||
R_DrawMaskedColumn (pixels, spans, true);
|
||||
dc_x++;
|
||||
frac += xiscale;
|
||||
}
|
||||
|
@ -492,7 +464,7 @@ void R_DrawVisSprite (vissprite_t *vis)
|
|||
{
|
||||
pixels = tex->GetColumn (frac >> FRACBITS, &spans);
|
||||
if (ispsprite || !R_ClipSpriteColumnWithPortals(vis))
|
||||
R_DrawMaskedColumn (pixels, spans);
|
||||
R_DrawMaskedColumn (pixels, spans, false);
|
||||
dc_x++;
|
||||
frac += xiscale;
|
||||
}
|
||||
|
@ -548,7 +520,7 @@ void R_DrawWallSprite(vissprite_t *spr)
|
|||
else if (fixedcolormap != NULL)
|
||||
dc_colormap = fixedcolormap;
|
||||
else if (!foggy && (spr->renderflags & RF_FULLBRIGHT))
|
||||
dc_colormap = usecolormap->Maps;
|
||||
dc_colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : usecolormap->Maps;
|
||||
else
|
||||
calclighting = true;
|
||||
|
||||
|
@ -602,7 +574,7 @@ void R_DrawWallSprite(vissprite_t *spr)
|
|||
dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT);
|
||||
}
|
||||
if (!R_ClipSpriteColumnWithPortals(spr))
|
||||
R_WallSpriteColumn(R_DrawMaskedColumn);
|
||||
R_WallSpriteColumn(false);
|
||||
dc_x++;
|
||||
}
|
||||
|
||||
|
@ -616,7 +588,7 @@ void R_DrawWallSprite(vissprite_t *spr)
|
|||
for (int zz = 4; zz; --zz)
|
||||
{
|
||||
if (!R_ClipSpriteColumnWithPortals(spr))
|
||||
R_WallSpriteColumn(R_DrawMaskedColumnHoriz);
|
||||
R_WallSpriteColumn(true);
|
||||
dc_x++;
|
||||
}
|
||||
rt_draw4cols(dc_x - 4);
|
||||
|
@ -629,14 +601,14 @@ void R_DrawWallSprite(vissprite_t *spr)
|
|||
dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT);
|
||||
}
|
||||
if (!R_ClipSpriteColumnWithPortals(spr))
|
||||
R_WallSpriteColumn(R_DrawMaskedColumn);
|
||||
R_WallSpriteColumn(false);
|
||||
dc_x++;
|
||||
}
|
||||
}
|
||||
R_FinishSetPatchStyle();
|
||||
}
|
||||
|
||||
void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans))
|
||||
void R_WallSpriteColumn (bool useRt)
|
||||
{
|
||||
float iscale = swall[dc_x] * MaskedScaleY;
|
||||
dc_iscale = FLOAT2FIXED(iscale);
|
||||
|
@ -650,7 +622,7 @@ void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Sp
|
|||
const FTexture::Span *spans;
|
||||
column = WallSpriteTile->GetColumn (lwall[dc_x] >> FRACBITS, &spans);
|
||||
dc_texturefrac = 0;
|
||||
drawfunc (column, spans);
|
||||
R_DrawMaskedColumn(column, spans, useRt);
|
||||
rw_light += rw_lightstep;
|
||||
}
|
||||
|
||||
|
@ -983,7 +955,8 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
|
|||
const double thingxscalemul = spriteScale.X / tex->Scale.X;
|
||||
|
||||
tx -= ((renderflags & RF_XFLIP) ? (tex->GetWidth() - tex->LeftOffset - 1) : tex->LeftOffset) * thingxscalemul;
|
||||
x1 = centerx + xs_RoundToInt(tx * xscale);
|
||||
double dtx1 = tx * xscale;
|
||||
x1 = centerx + xs_RoundToInt(dtx1);
|
||||
|
||||
// off the right side?
|
||||
if (x1 >= WindowRight)
|
||||
|
@ -997,7 +970,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
|
|||
return;
|
||||
|
||||
xscale = spriteScale.X * xscale / tex->Scale.X;
|
||||
iscale = (tex->GetWidth() << FRACBITS) / (x2 - x1);
|
||||
iscale = (fixed_t)(FRACUNIT / xscale); // Round towards zero to avoid wrapping in edge cases
|
||||
|
||||
double yscale = spriteScale.Y / tex->Scale.Y;
|
||||
|
||||
|
@ -1025,8 +998,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
|
|||
vis->xiscale = iscale;
|
||||
}
|
||||
|
||||
if (vis->x1 > x1)
|
||||
vis->startfrac += vis->xiscale * (vis->x1 - x1);
|
||||
vis->startfrac += (fixed_t)(vis->xiscale * (vis->x1 - centerx + 0.5 - dtx1));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1066,7 +1038,8 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
|
|||
vis->deltax = float(pos.X - ViewPos.X);
|
||||
vis->deltay = float(pos.Y - ViewPos.Y);
|
||||
vis->renderflags = renderflags;
|
||||
if(thing->flags5 & MF5_BRIGHT) vis->renderflags |= RF_FULLBRIGHT; // kg3D
|
||||
if(thing->flags5 & MF5_BRIGHT)
|
||||
vis->renderflags |= RF_FULLBRIGHT; // kg3D
|
||||
vis->Style.RenderStyle = thing->RenderStyle;
|
||||
vis->FillColor = thing->fillcolor;
|
||||
vis->Translation = thing->Translation; // [RH] thing translation table
|
||||
|
@ -1140,7 +1113,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor
|
|||
}
|
||||
else if (!foggy && ((renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT)))
|
||||
{ // full bright
|
||||
vis->Style.colormap = mybasecolormap->Maps;
|
||||
vis->Style.colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps;
|
||||
}
|
||||
else
|
||||
{ // diminished light
|
||||
|
@ -1337,7 +1310,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double
|
|||
}
|
||||
|
||||
sx = pspr->oldx + (pspr->x - pspr->oldx) * ticfrac;
|
||||
sy = pspr->oldy + (pspr->y - pspr->oldy) * ticfrac;
|
||||
sy = pspr->oldy + (pspr->y - pspr->oldy) * ticfrac + WEAPON_FUDGE_Y;
|
||||
|
||||
if (pspr->Flags & PSPF_ADDBOB)
|
||||
{
|
||||
|
@ -1462,11 +1435,11 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double
|
|||
}
|
||||
if (fixedlightlev >= 0)
|
||||
{
|
||||
vis->Style.colormap = mybasecolormap->Maps + fixedlightlev;
|
||||
vis->Style.colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (mybasecolormap->Maps + fixedlightlev);
|
||||
}
|
||||
else if (!foggy && pspr->GetState()->GetFullbright())
|
||||
{ // full bright
|
||||
vis->Style.colormap = mybasecolormap->Maps; // [RH] use basecolormap
|
||||
vis->Style.colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps; // [RH] use basecolormap
|
||||
}
|
||||
else
|
||||
{ // local light
|
||||
|
@ -1516,6 +1489,11 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double
|
|||
{
|
||||
noaccel = true;
|
||||
}
|
||||
// [SP] If emulating GZDoom fullbright, disable acceleration
|
||||
if (r_fullbrightignoresectorcolor && fixedlightlev >= 0)
|
||||
mybasecolormap = &FullNormalLight;
|
||||
if (r_fullbrightignoresectorcolor && !foggy && pspr->GetState()->GetFullbright())
|
||||
mybasecolormap = &FullNormalLight;
|
||||
colormap_to_use = mybasecolormap;
|
||||
}
|
||||
else
|
||||
|
@ -1640,7 +1618,7 @@ void R_DrawPlayerSprites ()
|
|||
else
|
||||
{
|
||||
wx = weapon->oldx + (weapon->x - weapon->oldx) * r_TicFracF;
|
||||
wy = weapon->oldy + (weapon->y - weapon->oldy) * r_TicFracF;
|
||||
wy = weapon->oldy + (weapon->y - weapon->oldy) * r_TicFracF + WEAPON_FUDGE_Y;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2057,7 +2035,7 @@ void R_DrawSprite (vissprite_t *spr)
|
|||
}
|
||||
else if (!foggy && (spr->renderflags & RF_FULLBRIGHT))
|
||||
{ // full bright
|
||||
spr->Style.colormap = mybasecolormap->Maps;
|
||||
spr->Style.colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps;
|
||||
}
|
||||
else
|
||||
{ // diminished light
|
||||
|
@ -2615,7 +2593,7 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade,
|
|||
}
|
||||
else if (particle->bright)
|
||||
{
|
||||
vis->Style.colormap = map;
|
||||
vis->Style.colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : map;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -124,8 +124,8 @@ extern double pspriteyscale;
|
|||
extern FTexture *WallSpriteTile;
|
||||
|
||||
|
||||
void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *spans);
|
||||
void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans));
|
||||
void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *spans, bool useRt);
|
||||
void R_WallSpriteColumn (bool useRt);
|
||||
|
||||
void R_CacheSprite (spritedef_t *sprite);
|
||||
void R_SortVisSprites (int (*compare)(const void *, const void *), size_t first);
|
||||
|
|
|
@ -577,7 +577,7 @@ bool WriteZip(const char *filename, TArray<FString> &filenames, TArray<FCompress
|
|||
dirend.DiskNumber = 0;
|
||||
dirend.FirstDisk = 0;
|
||||
dirend.NumEntriesOnAllDisks = dirend.NumEntries = LittleShort(filenames.Size());
|
||||
dirend.DirectoryOffset = dirofs;
|
||||
dirend.DirectoryOffset = LittleLong(dirofs);
|
||||
dirend.DirectorySize = LittleLong(ftell(f) - dirofs);
|
||||
dirend.ZipCommentLength = 0;
|
||||
if (fwrite(&dirend, sizeof(dirend), 1, f) != 1)
|
||||
|
|
|
@ -95,7 +95,8 @@ void FResourceLump::LumpNameSetup(FString iname)
|
|||
{
|
||||
long slash = iname.LastIndexOf('/');
|
||||
FString base = (slash >= 0) ? iname.Mid(slash + 1) : iname;
|
||||
base.Truncate(base.LastIndexOf('.'));
|
||||
auto dot = base.LastIndexOf('.');
|
||||
if (dot >= 0) base.Truncate(dot);
|
||||
uppercopy(Name, base);
|
||||
Name[8] = 0;
|
||||
FullName = iname;
|
||||
|
|
|
@ -1301,6 +1301,32 @@ void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, float volume, fl
|
|||
S_StartSound (NULL, sec, NULL, NULL, channel, sfxid, volume, attenuation);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// S_PlaySound - Subfunction used by ACS and DECORATE
|
||||
//
|
||||
// Has a local parameter to make the sound audible only to the source
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void S_PlaySound(AActor *a, int chan, FSoundID sid, float vol, float atten, bool local)
|
||||
{
|
||||
if (a == nullptr)
|
||||
return;
|
||||
|
||||
if (!local)
|
||||
{
|
||||
S_Sound(a, chan, sid, vol, atten);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a->CheckLocalView(consoleplayer))
|
||||
{
|
||||
S_Sound(chan, sid, vol, ATTN_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// S_LoadSound
|
||||
|
|
|
@ -241,6 +241,9 @@ void S_Sound (const FPolyObj *poly, int channel, FSoundID sfxid, float volume, f
|
|||
void S_Sound (const sector_t *sec, int channel, FSoundID sfxid, float volume, float attenuation);
|
||||
void S_Sound(const DVector3 &pos, int channel, FSoundID sfxid, float volume, float attenuation);
|
||||
|
||||
// [Nash] Used by ACS and DECORATE
|
||||
void S_PlaySound(AActor *a, int chan, FSoundID sid, float vol, float atten, bool local);
|
||||
|
||||
// sound channels
|
||||
// channel 0 never willingly overrides
|
||||
// other channels (1-7) always override a playing sound on that channel
|
||||
|
|
|
@ -67,6 +67,143 @@
|
|||
char nulspace[1024 * 1024 * 4];
|
||||
bool save_full = false; // for testing. Should be removed afterward.
|
||||
|
||||
int utf8_encode(int32_t codepoint, char *buffer, int *size)
|
||||
{
|
||||
if (codepoint < 0)
|
||||
return -1;
|
||||
else if (codepoint < 0x80)
|
||||
{
|
||||
buffer[0] = (char)codepoint;
|
||||
*size = 1;
|
||||
}
|
||||
else if (codepoint < 0x800)
|
||||
{
|
||||
buffer[0] = 0xC0 + ((codepoint & 0x7C0) >> 6);
|
||||
buffer[1] = 0x80 + ((codepoint & 0x03F));
|
||||
*size = 2;
|
||||
}
|
||||
else if (codepoint < 0x10000)
|
||||
{
|
||||
buffer[0] = 0xE0 + ((codepoint & 0xF000) >> 12);
|
||||
buffer[1] = 0x80 + ((codepoint & 0x0FC0) >> 6);
|
||||
buffer[2] = 0x80 + ((codepoint & 0x003F));
|
||||
*size = 3;
|
||||
}
|
||||
else if (codepoint <= 0x10FFFF)
|
||||
{
|
||||
buffer[0] = 0xF0 + ((codepoint & 0x1C0000) >> 18);
|
||||
buffer[1] = 0x80 + ((codepoint & 0x03F000) >> 12);
|
||||
buffer[2] = 0x80 + ((codepoint & 0x000FC0) >> 6);
|
||||
buffer[3] = 0x80 + ((codepoint & 0x00003F));
|
||||
*size = 4;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int utf8_decode(const char *src, int *size)
|
||||
{
|
||||
int c = src[0] & 255;
|
||||
int r;
|
||||
|
||||
*size = 1;
|
||||
if ((c & 0x80) == 0)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
|
||||
int c1 = src[1] & 255;
|
||||
|
||||
if ((c & 0xE0) == 0xC0)
|
||||
{
|
||||
r = ((c & 0x1F) << 6) | c1;
|
||||
if (r >= 128)
|
||||
{
|
||||
*size = 2;
|
||||
return r;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int c2 = src[2] & 255;
|
||||
|
||||
if ((c & 0xF0) == 0xE0)
|
||||
{
|
||||
r = ((c & 0x0F) << 12) | (c1 << 6) | c2;
|
||||
if (r >= 2048 && (r < 55296 || r > 57343))
|
||||
{
|
||||
*size = 3;
|
||||
return r;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int c3 = src[3] & 255;
|
||||
|
||||
if ((c & 0xF8) == 0xF0)
|
||||
{
|
||||
r = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
|
||||
if (r >= 65536 && r <= 1114111)
|
||||
{
|
||||
*size = 4;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static TArray<char> out;
|
||||
static const char *StringToUnicode(const char *cc, int size = -1)
|
||||
{
|
||||
int ch;
|
||||
const char *c = cc;
|
||||
int count = 0;
|
||||
int count1 = 0;
|
||||
out.Clear();
|
||||
while ((ch = (*c++) & 255))
|
||||
{
|
||||
count1++;
|
||||
if (ch >= 128)
|
||||
{
|
||||
if (ch < 0x800) count += 2;
|
||||
else count += 3;
|
||||
// The source cannot contain 4-byte chars.
|
||||
}
|
||||
else count++;
|
||||
if (count1 == size && size > 0) break;
|
||||
}
|
||||
if (count == count1) return cc; // string is pure ASCII.
|
||||
// we need to convert
|
||||
out.Resize(count + 1);
|
||||
out.Last() = 0;
|
||||
c = cc;
|
||||
int i = 0;
|
||||
while ((ch = (*c++) & 255))
|
||||
{
|
||||
utf8_encode(ch, &out[i], &count1);
|
||||
i += count1;
|
||||
}
|
||||
return &out[0];
|
||||
}
|
||||
|
||||
static const char *UnicodeToString(const char *cc)
|
||||
{
|
||||
out.Resize((unsigned)strlen(cc) + 1);
|
||||
int ndx = 0;
|
||||
while (*cc != 0)
|
||||
{
|
||||
int size;
|
||||
int c = utf8_decode(cc, &size);
|
||||
if (c < 0 || c > 255) c = '?';
|
||||
out[ndx++] = c;
|
||||
cc += size;
|
||||
}
|
||||
out[ndx] = 0;
|
||||
return &out[0];
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -99,8 +236,8 @@ struct FJSONObject
|
|||
|
||||
struct FWriter
|
||||
{
|
||||
typedef rapidjson::Writer<rapidjson::StringBuffer, rapidjson::ASCII<> > Writer;
|
||||
typedef rapidjson::PrettyWriter<rapidjson::StringBuffer, rapidjson::ASCII<> > PrettyWriter;
|
||||
typedef rapidjson::Writer<rapidjson::StringBuffer, rapidjson::UTF8<> > Writer;
|
||||
typedef rapidjson::PrettyWriter<rapidjson::StringBuffer, rapidjson::UTF8<> > PrettyWriter;
|
||||
|
||||
Writer *mWriter1;
|
||||
PrettyWriter *mWriter2;
|
||||
|
@ -173,14 +310,16 @@ struct FWriter
|
|||
|
||||
void String(const char *k)
|
||||
{
|
||||
k = StringToUnicode(k);
|
||||
if (mWriter1) mWriter1->String(k);
|
||||
else if (mWriter2) mWriter2->String(k);
|
||||
}
|
||||
|
||||
void String(const char *k, int size)
|
||||
{
|
||||
if (mWriter1) mWriter1->String(k, size);
|
||||
else if (mWriter2) mWriter2->String(k, size);
|
||||
k = StringToUnicode(k, size);
|
||||
if (mWriter1) mWriter1->String(k);
|
||||
else if (mWriter2) mWriter2->String(k);
|
||||
}
|
||||
|
||||
void Bool(bool k)
|
||||
|
@ -602,7 +741,7 @@ FSerializer &FSerializer::Args(const char *key, int *args, int *defargs, int spe
|
|||
}
|
||||
else if (i == 0 && aval.IsString())
|
||||
{
|
||||
args[i] = -FName(aval.GetString());
|
||||
args[i] = -FName(UnicodeToString(aval.GetString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -654,7 +793,7 @@ FSerializer &FSerializer::ScriptNum(const char *key, int &num)
|
|||
}
|
||||
else if (val->IsString())
|
||||
{
|
||||
num = -FName(val->GetString());
|
||||
num = -FName(UnicodeToString(val->GetString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -709,7 +848,7 @@ FSerializer &FSerializer::Sprite(const char *key, int32_t &spritenum, int32_t *d
|
|||
{
|
||||
if (val->IsString())
|
||||
{
|
||||
uint32_t name = *reinterpret_cast<const uint32_t*>(val->GetString());
|
||||
uint32_t name = *reinterpret_cast<const uint32_t*>(UnicodeToString(val->GetString()));
|
||||
for (auto hint = NumStdSprites; hint-- != 0; )
|
||||
{
|
||||
if (sprites[hint].dwName == name)
|
||||
|
@ -747,7 +886,7 @@ FSerializer &FSerializer::StringPtr(const char *key, const char *&charptr)
|
|||
{
|
||||
if (val->IsString())
|
||||
{
|
||||
charptr = val->GetString();
|
||||
charptr = UnicodeToString(val->GetString());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1403,7 +1542,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe
|
|||
assert(nameval.IsString() && typeval.IsInt());
|
||||
if (nameval.IsString() && typeval.IsInt())
|
||||
{
|
||||
value = TexMan.GetTexture(nameval.GetString(), typeval.GetInt());
|
||||
value = TexMan.GetTexture(UnicodeToString(nameval.GetString()), typeval.GetInt());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1553,7 +1692,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FName &value, FName *d
|
|||
assert(val->IsString());
|
||||
if (val->IsString())
|
||||
{
|
||||
value = val->GetString();
|
||||
value = UnicodeToString(val->GetString());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1638,7 +1777,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundI
|
|||
assert(val->IsString() || val->IsNull());
|
||||
if (val->IsString())
|
||||
{
|
||||
sid = val->GetString();
|
||||
sid = UnicodeToString(val->GetString());
|
||||
}
|
||||
else if (val->IsNull())
|
||||
{
|
||||
|
@ -1687,7 +1826,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, PClassActor
|
|||
assert(val->IsString() || val->IsNull());
|
||||
if (val->IsString())
|
||||
{
|
||||
clst = PClass::FindActor(val->GetString());
|
||||
clst = PClass::FindActor(UnicodeToString(val->GetString()));
|
||||
}
|
||||
else if (val->IsNull())
|
||||
{
|
||||
|
@ -1735,7 +1874,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, PClass *&cl
|
|||
{
|
||||
if (val->IsString())
|
||||
{
|
||||
clst = PClass::FindClass(val->GetString());
|
||||
clst = PClass::FindClass(UnicodeToString(val->GetString()));
|
||||
}
|
||||
else if (val->IsNull())
|
||||
{
|
||||
|
@ -1810,7 +1949,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FState *&state, FState
|
|||
assert(cls.IsString() && ndx.IsUint());
|
||||
if (cls.IsString() && ndx.IsUint())
|
||||
{
|
||||
PClassActor *clas = PClass::FindActor(cls.GetString());
|
||||
PClassActor *clas = PClass::FindActor(UnicodeToString(cls.GetString()));
|
||||
if (clas && ndx.GetUint() < (unsigned)clas->NumOwnedStates)
|
||||
{
|
||||
state = clas->OwnedStates + ndx.GetUint();
|
||||
|
@ -1932,7 +2071,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FString *&p
|
|||
}
|
||||
else if (val->IsString())
|
||||
{
|
||||
pstr = AActor::mStringPropertyData.Alloc(val->GetString());
|
||||
pstr = AActor::mStringPropertyData.Alloc(UnicodeToString(val->GetString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1974,7 +2113,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FString &pstr, FString
|
|||
}
|
||||
else if (val->IsString())
|
||||
{
|
||||
pstr = val->GetString();
|
||||
pstr = UnicodeToString(val->GetString());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2023,7 +2162,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, char *&pstr
|
|||
}
|
||||
else if (val->IsString())
|
||||
{
|
||||
pstr = copystring(val->GetString());
|
||||
pstr = copystring(UnicodeToString(val->GetString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -238,8 +238,8 @@ static const FEnumList ResamplerNames[] =
|
|||
{ "No Interpolation", FMOD_DSP_RESAMPLER_NOINTERP },
|
||||
{ "NoInterp", FMOD_DSP_RESAMPLER_NOINTERP },
|
||||
{ "Linear", FMOD_DSP_RESAMPLER_LINEAR },
|
||||
// [BL] 64-bit version of FMOD Ex 4.26 crashes with these resamplers.
|
||||
#if FMOD_STUDIO || !(defined(_M_X64) || defined(__amd64__)) || !(FMOD_VERSION >= 0x42600 && FMOD_VERSION <= 0x426FF)
|
||||
// [BL] 64-bit versions of FMOD Ex between 4.24 and 4.26 crash with these resamplers.
|
||||
#if FMOD_STUDIO || !(defined(_M_X64) || defined(__amd64__)) || !(FMOD_VERSION >= 0x42400 && FMOD_VERSION <= 0x426FF)
|
||||
{ "Cubic", FMOD_DSP_RESAMPLER_CUBIC },
|
||||
{ "Spline", FMOD_DSP_RESAMPLER_SPLINE },
|
||||
#endif
|
||||
|
|
|
@ -359,6 +359,9 @@ protected:
|
|||
#ifndef DYN_FLUIDSYNTH
|
||||
#include <fluidsynth.h>
|
||||
#else
|
||||
#include "i_module.h"
|
||||
extern FModule FluidSynthModule;
|
||||
|
||||
struct fluid_settings_t;
|
||||
struct fluid_synth_t;
|
||||
#endif
|
||||
|
@ -386,40 +389,35 @@ protected:
|
|||
|
||||
#ifdef DYN_FLUIDSYNTH
|
||||
enum { FLUID_FAILED = -1, FLUID_OK = 0 };
|
||||
fluid_settings_t *(*new_fluid_settings)();
|
||||
fluid_synth_t *(*new_fluid_synth)(fluid_settings_t *);
|
||||
int (*delete_fluid_synth)(fluid_synth_t *);
|
||||
void (*delete_fluid_settings)(fluid_settings_t *);
|
||||
int (*fluid_settings_setnum)(fluid_settings_t *, const char *, double);
|
||||
int (*fluid_settings_setstr)(fluid_settings_t *, const char *, const char *);
|
||||
int (*fluid_settings_setint)(fluid_settings_t *, const char *, int);
|
||||
int (*fluid_settings_getstr)(fluid_settings_t *, const char *, char **);
|
||||
int (*fluid_settings_getint)(fluid_settings_t *, const char *, int *);
|
||||
void (*fluid_synth_set_reverb_on)(fluid_synth_t *, int);
|
||||
void (*fluid_synth_set_chorus_on)(fluid_synth_t *, int);
|
||||
int (*fluid_synth_set_interp_method)(fluid_synth_t *, int, int);
|
||||
int (*fluid_synth_set_polyphony)(fluid_synth_t *, int);
|
||||
int (*fluid_synth_get_polyphony)(fluid_synth_t *);
|
||||
int (*fluid_synth_get_active_voice_count)(fluid_synth_t *);
|
||||
double (*fluid_synth_get_cpu_load)(fluid_synth_t *);
|
||||
int (*fluid_synth_system_reset)(fluid_synth_t *);
|
||||
int (*fluid_synth_noteon)(fluid_synth_t *, int, int, int);
|
||||
int (*fluid_synth_noteoff)(fluid_synth_t *, int, int);
|
||||
int (*fluid_synth_cc)(fluid_synth_t *, int, int, int);
|
||||
int (*fluid_synth_program_change)(fluid_synth_t *, int, int);
|
||||
int (*fluid_synth_channel_pressure)(fluid_synth_t *, int, int);
|
||||
int (*fluid_synth_pitch_bend)(fluid_synth_t *, int, int);
|
||||
int (*fluid_synth_write_float)(fluid_synth_t *, int, void *, int, int, void *, int, int);
|
||||
int (*fluid_synth_sfload)(fluid_synth_t *, const char *, int);
|
||||
void (*fluid_synth_set_reverb)(fluid_synth_t *, double, double, double, double);
|
||||
void (*fluid_synth_set_chorus)(fluid_synth_t *, int, double, double, double, int);
|
||||
int (*fluid_synth_sysex)(fluid_synth_t *, const char *, int, char *, int *, int *, int);
|
||||
static TReqProc<FluidSynthModule, fluid_settings_t *(*)()> new_fluid_settings;
|
||||
static TReqProc<FluidSynthModule, fluid_synth_t *(*)(fluid_settings_t *)> new_fluid_synth;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *)> delete_fluid_synth;
|
||||
static TReqProc<FluidSynthModule, void (*)(fluid_settings_t *)> delete_fluid_settings;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_settings_t *, const char *, double)> fluid_settings_setnum;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_settings_t *, const char *, const char *)> fluid_settings_setstr;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_settings_t *, const char *, int)> fluid_settings_setint;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_settings_t *, const char *, char **)> fluid_settings_getstr;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_settings_t *, const char *, int *)> fluid_settings_getint;
|
||||
static TReqProc<FluidSynthModule, void (*)(fluid_synth_t *, int)> fluid_synth_set_reverb_on;
|
||||
static TReqProc<FluidSynthModule, void (*)(fluid_synth_t *, int)> fluid_synth_set_chorus_on;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int)> fluid_synth_set_interp_method;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int)> fluid_synth_set_polyphony;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *)> fluid_synth_get_polyphony;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *)> fluid_synth_get_active_voice_count;
|
||||
static TReqProc<FluidSynthModule, double (*)(fluid_synth_t *)> fluid_synth_get_cpu_load;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *)> fluid_synth_system_reset;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int, int)> fluid_synth_noteon;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int)> fluid_synth_noteoff;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int, int)> fluid_synth_cc;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int)> fluid_synth_program_change;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int)> fluid_synth_channel_pressure;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int)> fluid_synth_pitch_bend;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, void *, int, int, void *, int, int)> fluid_synth_write_float;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, const char *, int)> fluid_synth_sfload;
|
||||
static TReqProc<FluidSynthModule, void (*)(fluid_synth_t *, double, double, double, double)> fluid_synth_set_reverb;
|
||||
static TReqProc<FluidSynthModule, void (*)(fluid_synth_t *, int, double, double, double, int)> fluid_synth_set_chorus;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, const char *, int, char *, int *, int *, int)> fluid_synth_sysex;
|
||||
|
||||
#ifdef _WIN32
|
||||
HMODULE FluidSynthDLL;
|
||||
#else
|
||||
void *FluidSynthSO;
|
||||
#endif
|
||||
bool LoadFluidSynth();
|
||||
void UnloadFluidSynth();
|
||||
#endif
|
||||
|
|
|
@ -60,9 +60,9 @@
|
|||
#include <dlfcn.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define FLUIDSYNTHLIB "libfluidsynth.1.dylib"
|
||||
#define FLUIDSYNTHLIB1 "libfluidsynth.1.dylib"
|
||||
#else // !__APPLE__
|
||||
#define FLUIDSYNTHLIB "libfluidsynth.so.1"
|
||||
#define FLUIDSYNTHLIB1 "libfluidsynth.so.1"
|
||||
#endif // __APPLE__
|
||||
#endif
|
||||
|
||||
|
@ -644,12 +644,6 @@ FString FluidSynthMIDIDevice::GetStats()
|
|||
|
||||
#ifdef DYN_FLUIDSYNTH
|
||||
|
||||
struct LibFunc
|
||||
{
|
||||
void **FuncPointer;
|
||||
const char *FuncName;
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FluidSynthMIDIDevice :: LoadFluidSynth
|
||||
|
@ -658,124 +652,65 @@ struct LibFunc
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FModuleMaybe<DYN_FLUIDSYNTH> FluidSynthModule{"FluidSynth"};
|
||||
|
||||
#define DYN_FLUID_SYM(x) decltype(FluidSynthMIDIDevice::x) FluidSynthMIDIDevice::x{#x}
|
||||
DYN_FLUID_SYM(new_fluid_settings);
|
||||
DYN_FLUID_SYM(new_fluid_synth);
|
||||
DYN_FLUID_SYM(delete_fluid_synth);
|
||||
DYN_FLUID_SYM(delete_fluid_settings);
|
||||
DYN_FLUID_SYM(fluid_settings_setnum);
|
||||
DYN_FLUID_SYM(fluid_settings_setstr);
|
||||
DYN_FLUID_SYM(fluid_settings_setint);
|
||||
DYN_FLUID_SYM(fluid_settings_getstr);
|
||||
DYN_FLUID_SYM(fluid_settings_getint);
|
||||
DYN_FLUID_SYM(fluid_synth_set_reverb_on);
|
||||
DYN_FLUID_SYM(fluid_synth_set_chorus_on);
|
||||
DYN_FLUID_SYM(fluid_synth_set_interp_method);
|
||||
DYN_FLUID_SYM(fluid_synth_set_polyphony);
|
||||
DYN_FLUID_SYM(fluid_synth_get_polyphony);
|
||||
DYN_FLUID_SYM(fluid_synth_get_active_voice_count);
|
||||
DYN_FLUID_SYM(fluid_synth_get_cpu_load);
|
||||
DYN_FLUID_SYM(fluid_synth_system_reset);
|
||||
DYN_FLUID_SYM(fluid_synth_noteon);
|
||||
DYN_FLUID_SYM(fluid_synth_noteoff);
|
||||
DYN_FLUID_SYM(fluid_synth_cc);
|
||||
DYN_FLUID_SYM(fluid_synth_program_change);
|
||||
DYN_FLUID_SYM(fluid_synth_channel_pressure);
|
||||
DYN_FLUID_SYM(fluid_synth_pitch_bend);
|
||||
DYN_FLUID_SYM(fluid_synth_write_float);
|
||||
DYN_FLUID_SYM(fluid_synth_sfload);
|
||||
DYN_FLUID_SYM(fluid_synth_set_reverb);
|
||||
DYN_FLUID_SYM(fluid_synth_set_chorus);
|
||||
DYN_FLUID_SYM(fluid_synth_sysex);
|
||||
|
||||
bool FluidSynthMIDIDevice::LoadFluidSynth()
|
||||
{
|
||||
LibFunc imports[] =
|
||||
{
|
||||
{ (void **)&new_fluid_settings, "new_fluid_settings" },
|
||||
{ (void **)&new_fluid_synth, "new_fluid_synth" },
|
||||
{ (void **)&delete_fluid_synth, "delete_fluid_synth" },
|
||||
{ (void **)&delete_fluid_settings, "delete_fluid_settings" },
|
||||
{ (void **)&fluid_settings_setnum, "fluid_settings_setnum" },
|
||||
{ (void **)&fluid_settings_setstr, "fluid_settings_setstr" },
|
||||
{ (void **)&fluid_settings_setint, "fluid_settings_setint" },
|
||||
{ (void **)&fluid_settings_getstr, "fluid_settings_getstr" },
|
||||
{ (void **)&fluid_settings_getint, "fluid_settings_getint" },
|
||||
{ (void **)&fluid_synth_set_reverb_on, "fluid_synth_set_reverb_on" },
|
||||
{ (void **)&fluid_synth_set_chorus_on, "fluid_synth_set_chorus_on" },
|
||||
{ (void **)&fluid_synth_set_interp_method, "fluid_synth_set_interp_method" },
|
||||
{ (void **)&fluid_synth_set_polyphony, "fluid_synth_set_polyphony" },
|
||||
{ (void **)&fluid_synth_get_polyphony, "fluid_synth_get_polyphony" },
|
||||
{ (void **)&fluid_synth_get_active_voice_count, "fluid_synth_get_active_voice_count" },
|
||||
{ (void **)&fluid_synth_get_cpu_load, "fluid_synth_get_cpu_load" },
|
||||
{ (void **)&fluid_synth_system_reset, "fluid_synth_system_reset" },
|
||||
{ (void **)&fluid_synth_noteon, "fluid_synth_noteon" },
|
||||
{ (void **)&fluid_synth_noteoff, "fluid_synth_noteoff" },
|
||||
{ (void **)&fluid_synth_cc, "fluid_synth_cc" },
|
||||
{ (void **)&fluid_synth_program_change, "fluid_synth_program_change" },
|
||||
{ (void **)&fluid_synth_channel_pressure, "fluid_synth_channel_pressure" },
|
||||
{ (void **)&fluid_synth_pitch_bend, "fluid_synth_pitch_bend" },
|
||||
{ (void **)&fluid_synth_write_float, "fluid_synth_write_float" },
|
||||
{ (void **)&fluid_synth_sfload, "fluid_synth_sfload" },
|
||||
{ (void **)&fluid_synth_set_reverb, "fluid_synth_set_reverb" },
|
||||
{ (void **)&fluid_synth_set_chorus, "fluid_synth_set_chorus" },
|
||||
{ (void **)&fluid_synth_sysex, "fluid_synth_sysex" },
|
||||
};
|
||||
int fail = 0;
|
||||
const char *libname;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (strlen(fluid_lib) > 0)
|
||||
{
|
||||
FluidSynthDLL = LoadLibrary(libname = fluid_lib);
|
||||
if (nullptr == FluidSynthDLL)
|
||||
if(!FluidSynthModule.Load({fluid_lib}))
|
||||
{
|
||||
const char* libname = fluid_lib;
|
||||
Printf(TEXTCOLOR_RED "Could not load %s\n", libname);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FluidSynthDLL = nullptr;
|
||||
}
|
||||
|
||||
if (nullptr == FluidSynthDLL)
|
||||
{
|
||||
FluidSynthDLL = LoadLibrary(libname = FLUIDSYNTHLIB1);
|
||||
if (nullptr == FluidSynthDLL)
|
||||
{
|
||||
FluidSynthDLL = LoadLibrary(libname = FLUIDSYNTHLIB2);
|
||||
if (nullptr == FluidSynthDLL)
|
||||
{
|
||||
Printf(TEXTCOLOR_RED "Could not load " FLUIDSYNTHLIB1 " or " FLUIDSYNTHLIB2 "\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (strlen(fluid_lib) > 0)
|
||||
{
|
||||
FluidSynthSO = dlopen(libname = fluid_lib, RTLD_LAZY);
|
||||
if (nullptr == FluidSynthSO)
|
||||
{
|
||||
Printf(TEXTCOLOR_RED "Could not load %s: %s\n", libname, dlerror());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FluidSynthSO = nullptr;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nullptr == FluidSynthSO)
|
||||
#ifdef FLUIDSYNTHLIB2
|
||||
if(!FluidSynthModule.Load({FLUIDSYNTHLIB1, FLUIDSYNTHLIB2}))
|
||||
{
|
||||
FluidSynthSO = dlopen(libname = FLUIDSYNTHLIB, RTLD_LAZY);
|
||||
if (nullptr == FluidSynthSO)
|
||||
{
|
||||
Printf(TEXTCOLOR_RED "Could not load " FLUIDSYNTHLIB ": %s\n", dlerror());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < countof(imports); ++i)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FARPROC proc = GetProcAddress(FluidSynthDLL, imports[i].FuncName);
|
||||
#else
|
||||
void *proc = dlsym(FluidSynthSO, imports[i].FuncName);
|
||||
#endif
|
||||
if (proc == NULL)
|
||||
{
|
||||
Printf(TEXTCOLOR_RED"Failed to find %s in %s\n", imports[i].FuncName, libname);
|
||||
fail++;
|
||||
}
|
||||
*imports[i].FuncPointer = (void *)proc;
|
||||
}
|
||||
if (fail == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FreeLibrary(FluidSynthDLL);
|
||||
FluidSynthDLL = NULL;
|
||||
#else
|
||||
dlclose(FluidSynthSO);
|
||||
FluidSynthSO = NULL;
|
||||
#endif
|
||||
Printf(TEXTCOLOR_RED "Could not load " FLUIDSYNTHLIB1 " or " FLUIDSYNTHLIB2 "\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
if(!FluidSynthModule.Load({fluid_lib, FLUIDSYNTHLIB1}))
|
||||
{
|
||||
Printf(TEXTCOLOR_RED "Could not load " FLUIDSYNTHLIB1 ": %s\n", dlerror());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -786,19 +721,7 @@ bool FluidSynthMIDIDevice::LoadFluidSynth()
|
|||
|
||||
void FluidSynthMIDIDevice::UnloadFluidSynth()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (FluidSynthDLL != NULL)
|
||||
{
|
||||
FreeLibrary(FluidSynthDLL);
|
||||
FluidSynthDLL = NULL;
|
||||
}
|
||||
#else
|
||||
if (FluidSynthSO != NULL)
|
||||
{
|
||||
dlclose(FluidSynthSO);
|
||||
FluidSynthSO = NULL;
|
||||
}
|
||||
#endif
|
||||
FluidSynthModule.Unload();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,24 +3,9 @@
|
|||
|
||||
#if !defined NO_OPENAL && defined DYN_OPENAL
|
||||
|
||||
#ifndef _WIN32
|
||||
typedef void* FARPROC;
|
||||
#endif
|
||||
|
||||
#define DEFINE_ENTRY(type, name) static type p_##name;
|
||||
#define DEFINE_ENTRY(type, name) static TReqProc<OpenALModule, type> p_##name{#name};
|
||||
#include "oaldef.h"
|
||||
#undef DEFINE_ENTRY
|
||||
struct oalloadentry
|
||||
{
|
||||
const char *name;
|
||||
FARPROC *funcaddr;
|
||||
};
|
||||
static oalloadentry oalfuncs[] = {
|
||||
#define DEFINE_ENTRY(type, name) { #name, (FARPROC*)&p_##name },
|
||||
#include "oaldef.h"
|
||||
#undef DEFINE_ENTRY
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
#ifndef IN_IDE_PARSER
|
||||
#define alEnable p_alEnable
|
||||
|
|
|
@ -55,29 +55,25 @@
|
|||
#include "actor.h"
|
||||
#include "r_state.h"
|
||||
#include "w_wad.h"
|
||||
#include "i_module.h"
|
||||
#include "i_music.h"
|
||||
#include "i_musicinterns.h"
|
||||
#include "tempfiles.h"
|
||||
|
||||
FModule OpenALModule{"OpenAL"};
|
||||
|
||||
#include "oalload.h"
|
||||
|
||||
CVAR (String, snd_aldevice, "Default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Bool, snd_efx, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
#ifdef _WIN32
|
||||
static HMODULE hmodOpenAL;
|
||||
#define OPENALLIB "openal32.dll"
|
||||
#else
|
||||
static void* hmodOpenAL;
|
||||
#ifdef __APPLE__
|
||||
#elif defined(__APPLE__)
|
||||
#define OPENALLIB "OpenAL.framework/OpenAL"
|
||||
#else
|
||||
#define OPENALLIB "libopenal.so.1"
|
||||
#endif
|
||||
#define LoadLibrary(x) dlopen((x), RTLD_LAZY)
|
||||
#define GetProcAddress(a,b) dlsym((a),(b))
|
||||
#define FreeLibrary(x) dlclose((x))
|
||||
#endif
|
||||
|
||||
bool IsOpenALPresent()
|
||||
{
|
||||
|
@ -92,29 +88,7 @@ bool IsOpenALPresent()
|
|||
if (!done)
|
||||
{
|
||||
done = true;
|
||||
if (hmodOpenAL == NULL)
|
||||
{
|
||||
hmodOpenAL = LoadLibrary(NicePath("$PROGDIR/" OPENALLIB));
|
||||
if (hmodOpenAL == NULL)
|
||||
{
|
||||
hmodOpenAL = LoadLibrary(OPENALLIB);
|
||||
if (hmodOpenAL == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for(int i = 0; oalfuncs[i].name != NULL; i++)
|
||||
{
|
||||
*oalfuncs[i].funcaddr = GetProcAddress(hmodOpenAL, oalfuncs[i].name);
|
||||
if (*oalfuncs[i].funcaddr == NULL)
|
||||
{
|
||||
FreeLibrary(hmodOpenAL);
|
||||
hmodOpenAL = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
cached_result = true;
|
||||
cached_result = OpenALModule.Load({NicePath("$PROGDIR/" OPENALLIB), OPENALLIB});
|
||||
}
|
||||
return cached_result;
|
||||
#endif
|
||||
|
|
|
@ -1002,7 +1002,7 @@ void FTextureManager::UpdateAnimations (DWORD mstime)
|
|||
|
||||
template<> FSerializer &Serialize(FSerializer &arc, const char *key, FDoorAnimation *&p, FDoorAnimation **def)
|
||||
{
|
||||
FTextureID tex = p->BaseTexture;
|
||||
FTextureID tex = p? p->BaseTexture : FNullTextureID();
|
||||
Serialize(arc, key, tex, def ? &(*def)->BaseTexture : nullptr);
|
||||
if (arc.isReading())
|
||||
{
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "v_palette.h"
|
||||
#include "v_video.h"
|
||||
#include "v_text.h"
|
||||
#include "cmdlib.h"
|
||||
#include "m_fixed.h"
|
||||
#include "textures/textures.h"
|
||||
#include "r_data/colormaps.h"
|
||||
|
@ -138,7 +139,6 @@ struct strifemaptexture_t
|
|||
struct FPatchLookup
|
||||
{
|
||||
FString Name;
|
||||
FTexture *Texture;
|
||||
};
|
||||
|
||||
|
||||
|
@ -166,6 +166,7 @@ public:
|
|||
int GetSourceLump() { return DefinitionLump; }
|
||||
FTexture *GetRedirect(bool wantwarped);
|
||||
FTexture *GetRawTexture();
|
||||
void ResolvePatches();
|
||||
|
||||
protected:
|
||||
BYTE *Pixels;
|
||||
|
@ -185,8 +186,19 @@ protected:
|
|||
TexPart();
|
||||
};
|
||||
|
||||
struct TexInit
|
||||
{
|
||||
FString TexName;
|
||||
int UseType = TEX_Null;
|
||||
bool Silent = false;
|
||||
bool HasLine = false;
|
||||
bool UseOffsets = false;
|
||||
FScriptPosition sc;
|
||||
};
|
||||
|
||||
int NumParts;
|
||||
TexPart *Parts;
|
||||
TexInit *Inits;
|
||||
bool bRedirect:1;
|
||||
bool bTranslucentPatches:1;
|
||||
|
||||
|
@ -194,7 +206,7 @@ protected:
|
|||
|
||||
private:
|
||||
void CheckForHacks ();
|
||||
void ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype);
|
||||
void ParsePatch(FScanner &sc, TexPart & part, TexInit &init);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -204,7 +216,7 @@ private:
|
|||
//==========================================================================
|
||||
|
||||
FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflumpnum)
|
||||
: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false)
|
||||
: Pixels (0), Spans(0), Parts(nullptr), Inits(nullptr), bRedirect(false), bTranslucentPatches(false)
|
||||
{
|
||||
union
|
||||
{
|
||||
|
@ -240,7 +252,8 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl
|
|||
}
|
||||
|
||||
UseType = FTexture::TEX_Wall;
|
||||
Parts = NumParts > 0 ? new TexPart[NumParts] : NULL;
|
||||
Parts = NumParts > 0 ? new TexPart[NumParts] : nullptr;
|
||||
Inits = NumParts > 0 ? new TexInit[NumParts] : nullptr;
|
||||
Width = SAFESHORT(mtexture.d->width);
|
||||
Height = SAFESHORT(mtexture.d->height);
|
||||
Name = (char *)mtexture.d->name;
|
||||
|
@ -272,17 +285,9 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl
|
|||
}
|
||||
Parts[i].OriginX = LittleShort(mpatch.d->originx);
|
||||
Parts[i].OriginY = LittleShort(mpatch.d->originy);
|
||||
Parts[i].Texture = patchlookup[LittleShort(mpatch.d->patch)].Texture;
|
||||
if (Parts[i].Texture == NULL)
|
||||
{
|
||||
Printf(TEXTCOLOR_RED "Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name.GetChars(), Name.GetChars());
|
||||
NumParts--;
|
||||
i--;
|
||||
}
|
||||
else
|
||||
{
|
||||
Parts[i].Texture->bKeepAround = true;
|
||||
}
|
||||
Parts[i].Texture = nullptr;
|
||||
Inits[i].TexName = patchlookup[LittleShort(mpatch.d->patch)].Name;
|
||||
Inits[i].UseType = TEX_WallPatch;
|
||||
if (strife)
|
||||
mpatch.s++;
|
||||
else
|
||||
|
@ -293,19 +298,6 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl
|
|||
Printf ("Texture %s is left without any patches\n", Name.GetChars());
|
||||
}
|
||||
|
||||
CheckForHacks ();
|
||||
|
||||
// If this texture is just a wrapper around a single patch, we can simply
|
||||
// forward GetPixels() and GetColumn() calls to that patch.
|
||||
if (NumParts == 1)
|
||||
{
|
||||
if (Parts->OriginX == 0 && Parts->OriginY == 0 &&
|
||||
Parts->Texture->GetWidth() == Width &&
|
||||
Parts->Texture->GetHeight() == Height)
|
||||
{
|
||||
bRedirect = true;
|
||||
}
|
||||
}
|
||||
DefinitionLump = deflumpnum;
|
||||
}
|
||||
|
||||
|
@ -327,6 +319,11 @@ FMultiPatchTexture::~FMultiPatchTexture ()
|
|||
delete[] Parts;
|
||||
Parts = NULL;
|
||||
}
|
||||
if (Inits != nullptr)
|
||||
{
|
||||
delete[] Inits;
|
||||
Inits = nullptr;
|
||||
}
|
||||
if (Spans != NULL)
|
||||
{
|
||||
FreeSpans (Spans);
|
||||
|
@ -864,19 +861,6 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int d
|
|||
pnames.Read(pname, 8);
|
||||
pname[8] = '\0';
|
||||
patchlookup[i].Name = pname;
|
||||
FTextureID j = CheckForTexture (patchlookup[i].Name, FTexture::TEX_WallPatch);
|
||||
if (j.isValid())
|
||||
{
|
||||
patchlookup[i].Texture = Textures[j.GetIndex()].Texture;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shareware Doom has the same PNAMES lump as the registered
|
||||
// Doom, so printing warnings for patches that don't really
|
||||
// exist isn't such a good idea.
|
||||
//Printf ("Patch %s not found.\n", patchlookup[i].Name);
|
||||
patchlookup[i].Texture = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -997,35 +981,13 @@ void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype)
|
||||
void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, TexInit &init)
|
||||
{
|
||||
FString patchname;
|
||||
int Mirror = 0;
|
||||
sc.MustGetString();
|
||||
|
||||
FTextureID texno = TexMan.CheckForTexture(sc.String, usetype);
|
||||
int Mirror = 0;
|
||||
|
||||
if (!texno.isValid())
|
||||
{
|
||||
if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./"))
|
||||
{
|
||||
int lumpnum = Wads.CheckNumForName(sc.String, usetype == TEX_MiscPatch? ns_graphics : ns_patches);
|
||||
if (lumpnum >= 0)
|
||||
{
|
||||
part.Texture = FTexture::CreateTexture(lumpnum, usetype);
|
||||
TexMan.AddTexture(part.Texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
part.Texture = TexMan[texno];
|
||||
bComplex |= part.Texture->bComplex;
|
||||
}
|
||||
if (part.Texture == NULL)
|
||||
{
|
||||
if (!silent) sc.ScriptMessage(TEXTCOLOR_RED "Unknown patch '%s' in texture '%s'\n", sc.String, Name.GetChars());
|
||||
}
|
||||
init.TexName = sc.String;
|
||||
sc.MustGetStringName(",");
|
||||
sc.MustGetNumber();
|
||||
part.OriginX = sc.Number;
|
||||
|
@ -1179,11 +1141,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, i
|
|||
}
|
||||
else if (sc.Compare("useoffsets"))
|
||||
{
|
||||
if (part.Texture != NULL)
|
||||
{
|
||||
part.OriginX -= part.Texture->LeftOffset;
|
||||
part.OriginY -= part.Texture->TopOffset;
|
||||
}
|
||||
init.UseOffsets = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1208,6 +1166,7 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
|
|||
: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false)
|
||||
{
|
||||
TArray<TexPart> parts;
|
||||
TArray<TexInit> inits;
|
||||
bool bSilent = false;
|
||||
|
||||
bMultiPatch = true;
|
||||
|
@ -1268,16 +1227,51 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
|
|||
else if (sc.Compare("Patch"))
|
||||
{
|
||||
TexPart part;
|
||||
ParsePatch(sc, part, bSilent, TEX_WallPatch);
|
||||
if (part.Texture != NULL) parts.Push(part);
|
||||
TexInit init;
|
||||
ParsePatch(sc, part, init);
|
||||
if (init.TexName.IsNotEmpty())
|
||||
{
|
||||
parts.Push(part);
|
||||
init.UseType = TEX_WallPatch;
|
||||
init.Silent = bSilent;
|
||||
init.HasLine = true;
|
||||
init.sc = sc;
|
||||
inits.Push(init);
|
||||
}
|
||||
part.Texture = NULL;
|
||||
part.Translation = NULL;
|
||||
}
|
||||
else if (sc.Compare("Sprite"))
|
||||
{
|
||||
TexPart part;
|
||||
TexInit init;
|
||||
ParsePatch(sc, part, init);
|
||||
if (init.TexName.IsNotEmpty())
|
||||
{
|
||||
parts.Push(part);
|
||||
init.UseType = TEX_Sprite;
|
||||
init.Silent = bSilent;
|
||||
init.HasLine = true;
|
||||
init.sc = sc;
|
||||
inits.Push(init);
|
||||
}
|
||||
part.Texture = NULL;
|
||||
part.Translation = NULL;
|
||||
}
|
||||
else if (sc.Compare("Graphic"))
|
||||
{
|
||||
TexPart part;
|
||||
ParsePatch(sc, part, bSilent, TEX_MiscPatch);
|
||||
if (part.Texture != NULL) parts.Push(part);
|
||||
TexInit init;
|
||||
ParsePatch(sc, part, init);
|
||||
if (init.TexName.IsNotEmpty())
|
||||
{
|
||||
parts.Push(part);
|
||||
init.UseType = TEX_MiscPatch;
|
||||
init.Silent = bSilent;
|
||||
init.HasLine = true;
|
||||
init.sc = sc;
|
||||
inits.Push(init);
|
||||
}
|
||||
part.Texture = NULL;
|
||||
part.Translation = NULL;
|
||||
}
|
||||
|
@ -1298,21 +1292,10 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
|
|||
NumParts = parts.Size();
|
||||
Parts = new TexPart[NumParts];
|
||||
memcpy(Parts, &parts[0], NumParts * sizeof(*Parts));
|
||||
|
||||
//CalcBitSize ();
|
||||
|
||||
// If this texture is just a wrapper around a single patch, we can simply
|
||||
// forward GetPixels() and GetColumn() calls to that patch.
|
||||
if (NumParts == 1)
|
||||
Inits = new TexInit[NumParts];
|
||||
for (int i = 0; i < NumParts; i++)
|
||||
{
|
||||
if (Parts->OriginX == 0 && Parts->OriginY == 0 &&
|
||||
Parts->Texture->GetWidth() == Width &&
|
||||
Parts->Texture->GetHeight() == Height &&
|
||||
Parts->Rotate == 0 &&
|
||||
!bComplex)
|
||||
{
|
||||
bRedirect = true;
|
||||
}
|
||||
Inits[i] = inits[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1329,6 +1312,89 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
|
|||
}
|
||||
|
||||
|
||||
void FMultiPatchTexture::ResolvePatches()
|
||||
{
|
||||
if (Inits != nullptr)
|
||||
{
|
||||
for (int i = 0; i < NumParts; i++)
|
||||
{
|
||||
FTextureID texno = TexMan.CheckForTexture(Inits[i].TexName, Inits[i].UseType);
|
||||
if (texno == id) // we found ourselves. Try looking for another one with the same name which is not a multipatch texture itself.
|
||||
{
|
||||
TArray<FTextureID> list;
|
||||
TexMan.ListTextures(Inits[i].TexName, list, true);
|
||||
for (int i = list.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (list[i] != id && !TexMan[list[i]]->bMultiPatch)
|
||||
{
|
||||
texno = list[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (texno == id)
|
||||
{
|
||||
if (Inits[i].HasLine) Inits[i].sc.Message(MSG_WARNING, "Texture '%s' references itself as patch\n", Inits[i].TexName.GetChars());
|
||||
else Printf(TEXTCOLOR_YELLOW "Texture '%s' references itself as patch\n", Inits[i].TexName.GetChars());
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it could be resolved, just print a developer warning.
|
||||
DPrintf(DMSG_WARNING, "Resolved self-referencing texture by picking an older entry for %s\n", Inits[i].TexName.GetChars());
|
||||
}
|
||||
}
|
||||
|
||||
if (!texno.isValid())
|
||||
{
|
||||
if (!Inits[i].Silent)
|
||||
{
|
||||
if (Inits[i].HasLine) Inits[i].sc.Message(MSG_WARNING, "Unknown patch '%s' in texture '%s'\n", Inits[i].TexName.GetChars(), Name.GetChars());
|
||||
else Printf(TEXTCOLOR_YELLOW "Unknown patch '%s' in texture '%s'\n", Inits[i].TexName.GetChars(), Name.GetChars());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Parts[i].Texture = TexMan[texno];
|
||||
bComplex |= Parts[i].Texture->bComplex;
|
||||
Parts[i].Texture->bKeepAround = true;
|
||||
if (Inits[i].UseOffsets)
|
||||
{
|
||||
Parts[i].OriginX -= Parts[i].Texture->LeftOffset;
|
||||
Parts[i].OriginY -= Parts[i].Texture->TopOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < NumParts; i++)
|
||||
{
|
||||
if (Parts[i].Texture == nullptr)
|
||||
{
|
||||
memcpy(&Parts[i], &Parts[i + 1], NumParts - i - 1);
|
||||
i--;
|
||||
NumParts--;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] Inits;
|
||||
Inits = nullptr;
|
||||
|
||||
CheckForHacks();
|
||||
|
||||
// If this texture is just a wrapper around a single patch, we can simply
|
||||
// forward GetPixels() and GetColumn() calls to that patch.
|
||||
|
||||
if (NumParts == 1)
|
||||
{
|
||||
if (Parts->OriginX == 0 && Parts->OriginY == 0 &&
|
||||
Parts->Texture->GetWidth() == Width &&
|
||||
Parts->Texture->GetHeight() == Height &&
|
||||
Parts->Rotate == 0 &&
|
||||
!bComplex)
|
||||
{
|
||||
bRedirect = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FTextureManager::ParseXTexture(FScanner &sc, int usetype)
|
||||
{
|
||||
|
|
|
@ -210,8 +210,9 @@ void FTexture::CalcBitSize ()
|
|||
}
|
||||
WidthMask = (1 << WidthBits) - 1;
|
||||
|
||||
// The minimum height is 2, because we cannot shift right 32 bits.
|
||||
for (i = 1; (1 << i) < Height; ++i)
|
||||
// <hr>The minimum height is 2, because we cannot shift right 32 bits.</hr>
|
||||
// Scratch that. Somebody actually made a 1x1 texture, so now we have to handle it.
|
||||
for (i = 0; (1 << i) < Height; ++i)
|
||||
{ }
|
||||
|
||||
HeightBits = i;
|
||||
|
@ -615,8 +616,6 @@ namespace
|
|||
PalEntry FTexture::GetSkyCapColor(bool bottom)
|
||||
{
|
||||
PalEntry col;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
if (!bSWSkyColorDone)
|
||||
{
|
||||
|
|
|
@ -267,7 +267,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, int usetype, BITF
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int FTextureManager::ListTextures (const char *name, TArray<FTextureID> &list)
|
||||
int FTextureManager::ListTextures (const char *name, TArray<FTextureID> &list, bool listall)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -293,11 +293,14 @@ int FTextureManager::ListTextures (const char *name, TArray<FTextureID> &list)
|
|||
// NULL textures must be ignored.
|
||||
if (tex->UseType!=FTexture::TEX_Null)
|
||||
{
|
||||
unsigned int j;
|
||||
for(j = 0; j < list.Size(); j++)
|
||||
unsigned int j = list.Size();
|
||||
if (!listall)
|
||||
{
|
||||
// Check for overriding definitions from newer WADs
|
||||
if (Textures[list[j].GetIndex()].Texture->UseType == tex->UseType) break;
|
||||
for (j = 0; j < list.Size(); j++)
|
||||
{
|
||||
// Check for overriding definitions from newer WADs
|
||||
if (Textures[list[j].GetIndex()].Texture->UseType == tex->UseType) break;
|
||||
}
|
||||
}
|
||||
if (j==list.Size()) list.Push(FTextureID(i));
|
||||
}
|
||||
|
@ -981,6 +984,10 @@ void FTextureManager::Init()
|
|||
{
|
||||
AddTexturesForWad(i);
|
||||
}
|
||||
for (unsigned i = 0; i < Textures.Size(); i++)
|
||||
{
|
||||
Textures[i].Texture->ResolvePatches();
|
||||
}
|
||||
|
||||
// Add one marker so that the last WAD is easier to handle and treat
|
||||
// Build tiles as a completely separate block.
|
||||
|
|
|
@ -232,6 +232,7 @@ public:
|
|||
int GetScaledTopOffset () { int foo = int((TopOffset * 2) / Scale.Y); return (foo >> 1) + (foo & 1); }
|
||||
double GetScaledLeftOffsetDouble() { return LeftOffset / Scale.X; }
|
||||
double GetScaledTopOffsetDouble() { return TopOffset / Scale.Y; }
|
||||
virtual void ResolvePatches() {}
|
||||
|
||||
virtual void SetFrontSkyLayer();
|
||||
|
||||
|
@ -411,7 +412,7 @@ public:
|
|||
|
||||
FTextureID CheckForTexture (const char *name, int usetype, BITFIELD flags=TEXMAN_TryAny);
|
||||
FTextureID GetTexture (const char *name, int usetype, BITFIELD flags=0);
|
||||
int ListTextures (const char *name, TArray<FTextureID> &list);
|
||||
int ListTextures (const char *name, TArray<FTextureID> &list, bool listall = false);
|
||||
|
||||
void AddTexturesLump (const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup=0, bool texture1=false);
|
||||
void AddTexturesLumps (int lump1, int lump2, int patcheslump);
|
||||
|
|
|
@ -2945,6 +2945,26 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, weaponslot, ISsssssssssssssssssssssssssssss
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// [SP] Player.Viewbob
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_CLASS_PROPERTY_PREFIX(player, viewbob, F, PlayerPawn)
|
||||
{
|
||||
PROP_DOUBLE_PARM(z, 0);
|
||||
// [SP] Hard limits. This is to prevent terrywads from making players sick.
|
||||
// Remember - this messes with a user option who probably has it set a
|
||||
// certain way for a reason. I think a 1.5 limit is pretty generous, but
|
||||
// it may be safe to increase it. I really need opinions from people who
|
||||
// could be affected by this.
|
||||
if (z < 0.0 || z > 1.5)
|
||||
{
|
||||
I_Error("ViewBob must be between 0.0 and 1.5.");
|
||||
}
|
||||
defaults->ViewBob = z;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
|
|
|
@ -299,7 +299,7 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms)
|
|||
while ((dc_x < stop4) && (dc_x & 3))
|
||||
{
|
||||
pixels = img->GetColumn(frac >> FRACBITS, spanptr);
|
||||
R_DrawMaskedColumn(pixels, spans);
|
||||
R_DrawMaskedColumn(pixels, spans, false);
|
||||
dc_x++;
|
||||
frac += xiscale_i;
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms)
|
|||
for (int zz = 4; zz; --zz)
|
||||
{
|
||||
pixels = img->GetColumn(frac >> FRACBITS, spanptr);
|
||||
R_DrawMaskedColumnHoriz(pixels, spans);
|
||||
R_DrawMaskedColumn(pixels, spans, true);
|
||||
dc_x++;
|
||||
frac += xiscale_i;
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms)
|
|||
while (dc_x < x2_i)
|
||||
{
|
||||
pixels = img->GetColumn(frac >> FRACBITS, spanptr);
|
||||
R_DrawMaskedColumn(pixels, spans);
|
||||
R_DrawMaskedColumn(pixels, spans, false);
|
||||
dc_x++;
|
||||
frac += xiscale_i;
|
||||
}
|
||||
|
@ -1282,7 +1282,7 @@ void DCanvas::FinishSimplePolys()
|
|||
|
||||
void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley, DAngle rotation,
|
||||
FDynamicColormap *colormap, int lightlevel)
|
||||
FDynamicColormap *colormap, int lightlevel, int bottomclip)
|
||||
{
|
||||
#ifndef NO_SWRENDER
|
||||
// Use an equation similar to player sprites to determine shade
|
||||
|
@ -1300,6 +1300,11 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
|||
return;
|
||||
}
|
||||
|
||||
if (bottomclip <= 0)
|
||||
{
|
||||
bottomclip = Height;
|
||||
}
|
||||
|
||||
// Find the extents of the polygon, in particular the highest and lowest points.
|
||||
for (botpt = toppt = 0, boty = topy = points[0].Y, leftx = rightx = points[0].X, i = 1; i <= npoints; ++i)
|
||||
{
|
||||
|
@ -1322,7 +1327,7 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
|||
rightx = points[i].X;
|
||||
}
|
||||
}
|
||||
if (topy >= Height || // off the bottom of the screen
|
||||
if (topy >= bottomclip || // off the bottom of the screen
|
||||
boty <= 0 || // off the top of the screen
|
||||
leftx >= Width || // off the right of the screen
|
||||
rightx <= 0) // off the left of the screen
|
||||
|
@ -1330,6 +1335,13 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
|||
return;
|
||||
}
|
||||
|
||||
BYTE *destorgsave = dc_destorg;
|
||||
dc_destorg = screen->GetBuffer();
|
||||
if (dc_destorg == NULL)
|
||||
{
|
||||
I_FatalError("Attempt to write to buffer of hardware canvas");
|
||||
}
|
||||
|
||||
scalex /= tex->Scale.X;
|
||||
scaley /= tex->Scale.Y;
|
||||
|
||||
|
@ -1341,10 +1353,26 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
|||
R_SetupSpanBits(tex);
|
||||
R_SetSpanColormap(colormap != NULL ? &colormap->Maps[clamp(shade >> FRACBITS, 0, NUMCOLORMAPS-1) * 256] : identitymap);
|
||||
R_SetSpanSource(tex->GetPixels());
|
||||
scalex = double(1u << (32 - ds_xbits)) / scalex;
|
||||
scaley = double(1u << (32 - ds_ybits)) / scaley;
|
||||
ds_xstep = xs_RoundToInt(cosrot * scalex);
|
||||
ds_ystep = xs_RoundToInt(sinrot * scaley);
|
||||
if (ds_xbits != 0)
|
||||
{
|
||||
scalex = double(1u << (32 - ds_xbits)) / scalex;
|
||||
ds_xstep = xs_RoundToInt(cosrot * scalex);
|
||||
}
|
||||
else
|
||||
{ // Texture is one pixel wide.
|
||||
scalex = 0;
|
||||
ds_xstep = 0;
|
||||
}
|
||||
if (ds_ybits != 0)
|
||||
{
|
||||
scaley = double(1u << (32 - ds_ybits)) / scaley;
|
||||
ds_ystep = xs_RoundToInt(sinrot * scaley);
|
||||
}
|
||||
else
|
||||
{ // Texture is one pixel tall.
|
||||
scaley = 0;
|
||||
ds_ystep = 0;
|
||||
}
|
||||
|
||||
// Travel down the right edge and create an outline of that edge.
|
||||
pt1 = toppt;
|
||||
|
@ -1354,13 +1382,13 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
|||
{
|
||||
x = FLOAT2FIXED(points[pt1].X + 0.5f);
|
||||
y2 = xs_RoundToInt(points[pt2].Y + 0.5f);
|
||||
if (y1 >= y2 || (y1 < 0 && y2 < 0) || (y1 >= Height && y2 >= Height))
|
||||
if (y1 >= y2 || (y1 < 0 && y2 < 0) || (y1 >= bottomclip && y2 >= bottomclip))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
fixed_t xinc = FLOAT2FIXED((points[pt2].X - points[pt1].X) / (points[pt2].Y - points[pt1].Y));
|
||||
int y3 = MIN(y2, Height);
|
||||
int y3 = MIN(y2, bottomclip);
|
||||
if (y1 < 0)
|
||||
{
|
||||
x += xinc * -y1;
|
||||
|
@ -1385,13 +1413,13 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
|||
{
|
||||
x = FLOAT2FIXED(points[pt1].X + 0.5f);
|
||||
y2 = xs_RoundToInt(points[pt2].Y + 0.5f);
|
||||
if (y1 >= y2 || (y1 < 0 && y2 < 0) || (y1 >= Height && y2 >= Height))
|
||||
if (y1 >= y2 || (y1 < 0 && y2 < 0) || (y1 >= bottomclip && y2 >= bottomclip))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
fixed_t xinc = FLOAT2FIXED((points[pt2].X - points[pt1].X) / (points[pt2].Y - points[pt1].Y));
|
||||
int y3 = MIN(y2, Height);
|
||||
int y3 = MIN(y2, bottomclip);
|
||||
if (y1 < 0)
|
||||
{
|
||||
x += xinc * -y1;
|
||||
|
@ -1432,6 +1460,7 @@ void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
|||
pt1 = pt2;
|
||||
pt2--; if (pt2 < 0) pt2 = npoints;
|
||||
} while (pt1 != botpt);
|
||||
dc_destorg = destorgsave;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ FRenderer *Renderer;
|
|||
IMPLEMENT_ABSTRACT_CLASS (DCanvas)
|
||||
IMPLEMENT_ABSTRACT_CLASS (DFrameBuffer)
|
||||
|
||||
#if defined(_DEBUG) && defined(_M_IX86)
|
||||
#if defined(_DEBUG) && defined(_M_IX86) && !defined(__MINGW32__)
|
||||
#define DBGBREAK { __asm int 3 }
|
||||
#else
|
||||
#define DBGBREAK
|
||||
|
@ -877,8 +877,6 @@ void DFrameBuffer::DrawRateStuff ()
|
|||
int rate_x;
|
||||
|
||||
int textScale = active_con_scale();
|
||||
if (textScale == 0)
|
||||
textScale = CleanXfac;
|
||||
|
||||
chars = mysnprintf (fpsbuff, countof(fpsbuff), "%2u ms (%3u fps)", howlong, LastCount);
|
||||
rate_x = Width / textScale - ConFont->StringWidth(&fpsbuff[0]);
|
||||
|
|
|
@ -224,7 +224,7 @@ public:
|
|||
// Fill a simple polygon with a texture
|
||||
virtual void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley, DAngle rotation,
|
||||
struct FDynamicColormap *colormap, int lightlevel);
|
||||
struct FDynamicColormap *colormap, int lightlevel, int bottomclip);
|
||||
|
||||
// Set an area to a specified color
|
||||
virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32 color);
|
||||
|
|
|
@ -1092,6 +1092,7 @@ void D3DFB::Update ()
|
|||
DrawRateStuff();
|
||||
DrawPackedTextures(d3d_showpacks);
|
||||
EndBatch(); // Make sure all batched primitives are drawn.
|
||||
In2D = 0;
|
||||
Flip();
|
||||
}
|
||||
In2D = 0;
|
||||
|
@ -3083,11 +3084,16 @@ void D3DFB::FlatFill(int left, int top, int right, int bottom, FTexture *src, bo
|
|||
//
|
||||
// Here, "simple" means that a simple triangle fan can draw it.
|
||||
//
|
||||
// Bottomclip is ignored by this implementation, since the hardware renderer
|
||||
// will unconditionally draw the status bar border every frame on top of the
|
||||
// polygons, so there's no need to waste time setting up a special scissor
|
||||
// rectangle here and needlessly forcing separate batches.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void D3DFB::FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley,
|
||||
DAngle rotation, FDynamicColormap *colormap, int lightlevel)
|
||||
DAngle rotation, FDynamicColormap *colormap, int lightlevel, int bottomclip)
|
||||
{
|
||||
// Use an equation similar to player sprites to determine shade
|
||||
double fadelevel = clamp((LIGHT2SHADE(lightlevel)/65536. - 12) / NUMCOLORMAPS, 0.0, 1.0);
|
||||
|
@ -3108,7 +3114,7 @@ void D3DFB::FillSimplePoly(FTexture *texture, FVector2 *points, int npoints,
|
|||
}
|
||||
if (In2D < 2)
|
||||
{
|
||||
Super::FillSimplePoly(texture, points, npoints, originx, originy, scalex, scaley, rotation, colormap, lightlevel);
|
||||
Super::FillSimplePoly(texture, points, npoints, originx, originy, scalex, scaley, rotation, colormap, lightlevel, bottomclip);
|
||||
return;
|
||||
}
|
||||
if (!InScene)
|
||||
|
|
|
@ -75,54 +75,6 @@
|
|||
#include <time.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#if defined(_WIN64) && defined(__GNUC__)
|
||||
struct KNONVOLATILE_CONTEXT_POINTERS {
|
||||
union {
|
||||
PDWORD64 IntegerContext[16];
|
||||
struct {
|
||||
PDWORD64 Rax;
|
||||
PDWORD64 Rcx;
|
||||
PDWORD64 Rdx;
|
||||
PDWORD64 Rbx;
|
||||
PDWORD64 Rsp;
|
||||
PDWORD64 Rbp;
|
||||
PDWORD64 Rsi;
|
||||
PDWORD64 Rdi;
|
||||
PDWORD64 R8;
|
||||
PDWORD64 R9;
|
||||
PDWORD64 R10;
|
||||
PDWORD64 R11;
|
||||
PDWORD64 R12;
|
||||
PDWORD64 R13;
|
||||
PDWORD64 R14;
|
||||
PDWORD64 R15;
|
||||
};
|
||||
};
|
||||
};
|
||||
typedef
|
||||
EXCEPTION_DISPOSITION
|
||||
NTAPI
|
||||
EXCEPTION_ROUTINE (
|
||||
struct _EXCEPTION_RECORD *ExceptionRecord,
|
||||
PVOID EstablisherFrame,
|
||||
struct _CONTEXT *ContextRecord,
|
||||
PVOID DispatcherContext
|
||||
);
|
||||
NTSYSAPI
|
||||
EXCEPTION_ROUTINE *
|
||||
NTAPI
|
||||
RtlVirtualUnwind (
|
||||
DWORD HandlerType,
|
||||
DWORD64 ImageBase,
|
||||
DWORD64 ControlPc,
|
||||
PRUNTIME_FUNCTION FunctionEntry,
|
||||
PCONTEXT ContextRecord,
|
||||
PVOID *HandlerData,
|
||||
PDWORD64 EstablisherFrame,
|
||||
KNONVOLATILE_CONTEXT_POINTERS *ContextPointers
|
||||
);
|
||||
#endif
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
#define REMOTE_HOST "localhost"
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
|
||||
#define DINPUT_BUFFERSIZE 32
|
||||
|
||||
// MinGW-w64 (TDM5.1 - 2016/11/21)
|
||||
#ifndef DIK_PREVTRACK
|
||||
#define DIK_PREVTRACK DIK_CIRCUMFLEX
|
||||
#endif
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
class FDInputKeyboard : public FKeyboard
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include "doomtype.h"
|
||||
#include "m_argv.h"
|
||||
#include "d_main.h"
|
||||
#include "i_module.h"
|
||||
#include "i_system.h"
|
||||
#include "c_console.h"
|
||||
#include "version.h"
|
||||
|
@ -84,6 +85,8 @@
|
|||
#include "stats.h"
|
||||
#include "st_start.h"
|
||||
|
||||
#include "optwin32.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
@ -143,6 +146,21 @@ LONG GameTitleFontHeight;
|
|||
LONG DefaultGUIFontHeight;
|
||||
LONG ErrorIconChar;
|
||||
|
||||
FModule Kernel32Module{"Kernel32"};
|
||||
FModule Shell32Module{"Shell32"};
|
||||
FModule User32Module{"User32"};
|
||||
|
||||
namespace OptWin32 {
|
||||
#define DYN_WIN32_SYM(x) decltype(x) x{#x}
|
||||
|
||||
DYN_WIN32_SYM(SHGetFolderPathA);
|
||||
DYN_WIN32_SYM(SHGetKnownFolderPath);
|
||||
DYN_WIN32_SYM(GetLongPathNameA);
|
||||
DYN_WIN32_SYM(GetMonitorInfoA);
|
||||
|
||||
#undef DYN_WIN32_SYM
|
||||
} // namespace OptWin32
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
static const char WinClassName[] = GAMENAME "MainWindow";
|
||||
|
@ -818,6 +836,11 @@ void DoMain (HINSTANCE hInstance)
|
|||
|
||||
Args = new DArgs(__argc, __argv);
|
||||
|
||||
// Load Win32 modules
|
||||
Kernel32Module.Load({"kernel32.dll"});
|
||||
Shell32Module.Load({"shell32.dll"});
|
||||
User32Module.Load({"user32.dll"});
|
||||
|
||||
// Under XP, get our session ID so we can know when the user changes/locks sessions.
|
||||
// Since we need to remain binary compatible with older versions of Windows, we
|
||||
// need to extract the ProcessIdToSessionId function from kernel32.dll manually.
|
||||
|
|
|
@ -389,7 +389,7 @@ bool FRawPS2Controller::ProcessInput(RAWHID *raw, int code)
|
|||
{
|
||||
// w32api has an incompatible definition of bRawData.
|
||||
// (But the version that comes with MinGW64 is fine.)
|
||||
#if defined(__GNUC__) && !defined(_WIN64)
|
||||
#if defined(__GNUC__) && !defined(__MINGW64_VERSION_MAJOR)
|
||||
BYTE *rawdata = &raw->bRawData;
|
||||
#else
|
||||
BYTE *rawdata = raw->bRawData;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
**
|
||||
*/
|
||||
|
||||
#define _WIN32_WINNT 0x0601
|
||||
#include <windows.h>
|
||||
#include <lmcons.h>
|
||||
#include <shlobj.h>
|
||||
|
@ -43,7 +44,16 @@
|
|||
#include "version.h" // for GAMENAME
|
||||
#include "i_system.h"
|
||||
|
||||
typedef HRESULT (WINAPI *GKFP)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *);
|
||||
#include "optwin32.h"
|
||||
|
||||
// Vanilla MinGW does not have folder ids
|
||||
#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
|
||||
static const GUID FOLDERID_LocalAppData = { 0xf1b32785, 0x6fba, 0x4fcf, 0x9d, 0x55, 0x7b, 0x8e, 0x7f, 0x15, 0x70, 0x91 };
|
||||
static const GUID FOLDERID_RoamingAppData = { 0x3eb685db, 0x65f9, 0x4cf6, 0xa0, 0x3a, 0xe3, 0xef, 0x65, 0x72, 0x9f, 0x3d };
|
||||
static const GUID FOLDERID_SavedGames = { 0x4c5c32ff, 0xbb9d, 0x43b0, 0xb5, 0xb4, 0x2d, 0x72, 0xe5, 0x4e, 0xaa, 0xa4 };
|
||||
static const GUID FOLDERID_Documents = { 0xfdd39ad0, 0x238f, 0x46af, 0xad, 0xb4, 0x6c, 0x85, 0x48, 0x03, 0x69, 0xc7 };
|
||||
static const GUID FOLDERID_Pictures = { 0x33e28130, 0x4e1e, 0x4676, 0x83, 0x5a, 0x98, 0x39, 0x5c, 0x3b, 0xc3, 0xbb };
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -94,19 +104,17 @@ bool UseKnownFolders()
|
|||
|
||||
bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create, FString &path)
|
||||
{
|
||||
static TOptWin32Proc<GKFP> SHGetKnownFolderPath("shell32.dll", "SHGetKnownFolderPath");
|
||||
using OptWin32::SHGetFolderPathA;
|
||||
using OptWin32::SHGetKnownFolderPath;
|
||||
|
||||
char pathstr[MAX_PATH];
|
||||
|
||||
// SHGetKnownFolderPath knows about more folders than SHGetFolderPath, but is
|
||||
// new to Vista, hence the reason we support both.
|
||||
if (SHGetKnownFolderPath == NULL)
|
||||
if (!SHGetKnownFolderPath)
|
||||
{
|
||||
static TOptWin32Proc<HRESULT(WINAPI*)(HWND, int, HANDLE, DWORD, LPTSTR)>
|
||||
SHGetFolderPathA("shell32.dll", "SHGetFolderPathA");
|
||||
|
||||
// NT4 doesn't even have this function.
|
||||
if (SHGetFolderPathA == NULL)
|
||||
if (!SHGetFolderPathA)
|
||||
return false;
|
||||
|
||||
if (shell_folder < 0)
|
||||
|
@ -117,7 +125,7 @@ bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create
|
|||
{
|
||||
shell_folder |= CSIDL_FLAG_CREATE;
|
||||
}
|
||||
if (FAILED(SHGetFolderPathA.Call(NULL, shell_folder, NULL, 0, pathstr)))
|
||||
if (FAILED(SHGetFolderPathA(NULL, shell_folder, NULL, 0, pathstr)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -127,7 +135,7 @@ bool GetKnownFolder(int shell_folder, REFKNOWNFOLDERID known_folder, bool create
|
|||
else
|
||||
{
|
||||
PWSTR wpath;
|
||||
if (FAILED(SHGetKnownFolderPath.Call(known_folder, create ? KF_FLAG_CREATE : 0, NULL, &wpath)))
|
||||
if (FAILED(SHGetKnownFolderPath(known_folder, create ? KF_FLAG_CREATE : 0, NULL, &wpath)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,8 @@
|
|||
#include "textures/bitmap.h"
|
||||
#include "textures/textures.h"
|
||||
|
||||
#include "optwin32.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -1312,7 +1314,7 @@ static HCURSOR CreateCompatibleCursor(FTexture *cursorpic)
|
|||
HDC dc = GetDC(NULL);
|
||||
if (dc == NULL)
|
||||
{
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
HDC and_mask_dc = CreateCompatibleDC(dc);
|
||||
HDC xor_mask_dc = CreateCompatibleDC(dc);
|
||||
|
@ -1716,20 +1718,19 @@ unsigned int I_MakeRNGSeed()
|
|||
|
||||
FString I_GetLongPathName(FString shortpath)
|
||||
{
|
||||
static TOptWin32Proc<DWORD (WINAPI*)(LPCTSTR, LPTSTR, DWORD)>
|
||||
GetLongPathNameA("kernel32.dll", "GetLongPathNameA");
|
||||
using OptWin32::GetLongPathNameA;
|
||||
|
||||
// Doesn't exist on NT4
|
||||
if (GetLongPathName == NULL)
|
||||
if (!GetLongPathNameA)
|
||||
return shortpath;
|
||||
|
||||
DWORD buffsize = GetLongPathNameA.Call(shortpath.GetChars(), NULL, 0);
|
||||
DWORD buffsize = GetLongPathNameA(shortpath.GetChars(), NULL, 0);
|
||||
if (buffsize == 0)
|
||||
{ // nothing to change (it doesn't exist, maybe?)
|
||||
return shortpath;
|
||||
}
|
||||
TCHAR *buff = new TCHAR[buffsize];
|
||||
DWORD buffsize2 = GetLongPathNameA.Call(shortpath.GetChars(), buff, buffsize);
|
||||
DWORD buffsize2 = GetLongPathNameA(shortpath.GetChars(), buff, buffsize);
|
||||
if (buffsize2 >= buffsize)
|
||||
{ // Failure! Just return the short path
|
||||
delete[] buff;
|
||||
|
|
|
@ -51,30 +51,6 @@ typedef enum {
|
|||
|
||||
extern os_t OSPlatform;
|
||||
|
||||
// Helper template so that we can access newer Win32 functions with a single static
|
||||
// variable declaration. If this were C++11 it could be totally transparent.
|
||||
template<typename Proto>
|
||||
class TOptWin32Proc
|
||||
{
|
||||
static Proto GetOptionalWin32Proc(const char* module, const char* function)
|
||||
{
|
||||
HMODULE hmodule = GetModuleHandle(module);
|
||||
if (hmodule == NULL)
|
||||
return NULL;
|
||||
|
||||
return (Proto)GetProcAddress(hmodule, function);
|
||||
}
|
||||
|
||||
public:
|
||||
const Proto Call;
|
||||
|
||||
TOptWin32Proc(const char* module, const char* function)
|
||||
: Call(GetOptionalWin32Proc(module, function)) {}
|
||||
|
||||
// Wrapper object can be tested against NULL, but not directly called.
|
||||
operator const void*() const { return Call; }
|
||||
};
|
||||
|
||||
// Called by DoomMain.
|
||||
void I_Init (void);
|
||||
|
||||
|
|
|
@ -33,6 +33,17 @@
|
|||
#define XUSER_MAX_COUNT 4
|
||||
#endif
|
||||
|
||||
// MinGW
|
||||
#ifndef XINPUT_DLL
|
||||
#define XINPUT_DLL_A "xinput1_3.dll"
|
||||
#define XINPUT_DLL_W L"xinput1_3.dll"
|
||||
#ifdef UNICODE
|
||||
#define XINPUT_DLL XINPUT_DLL_W
|
||||
#else
|
||||
#define XINPUT_DLL XINPUT_DLL_A
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
typedef DWORD (WINAPI *XInputGetStateType)(DWORD index, XINPUT_STATE *state);
|
||||
|
|
24
src/win32/optwin32.h
Normal file
24
src/win32/optwin32.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
// Forward declarations for optional Win32 API procedures
|
||||
// implemented in i_main.cpp
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
#define USE_WINDOWS_DWORD
|
||||
|
||||
#include "i_module.h"
|
||||
|
||||
extern FModule Kernel32Module;
|
||||
extern FModule Shell32Module;
|
||||
extern FModule User32Module;
|
||||
|
||||
namespace OptWin32 {
|
||||
|
||||
extern TOptProc<Shell32Module, HRESULT(WINAPI*)(HWND, int, HANDLE, DWORD, LPTSTR)> SHGetFolderPathA;
|
||||
extern TOptProc<Shell32Module, HRESULT(WINAPI*)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *)> SHGetKnownFolderPath;
|
||||
extern TOptProc<Kernel32Module, DWORD (WINAPI*)(LPCTSTR, LPTSTR, DWORD)> GetLongPathNameA;
|
||||
extern TOptProc<User32Module, BOOL(WINAPI*)(HMONITOR, LPMONITORINFO)> GetMonitorInfoA;
|
||||
|
||||
} // namespace OptWin32
|
|
@ -265,7 +265,7 @@ public:
|
|||
void DrawPixel(int x, int y, int palcolor, uint32 rgbcolor);
|
||||
void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley,
|
||||
DAngle rotation, FDynamicColormap *colormap, int lightlevel);
|
||||
DAngle rotation, FDynamicColormap *colormap, int lightlevel, int bottomclip) override;
|
||||
bool WipeStartScreen(int type);
|
||||
void WipeEndScreen();
|
||||
bool WipeDo(int ticks);
|
||||
|
|
|
@ -74,6 +74,8 @@
|
|||
|
||||
#include "win32iface.h"
|
||||
|
||||
#include "optwin32.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
@ -387,6 +389,8 @@ void Win32Video::BlankForGDI ()
|
|||
|
||||
void Win32Video::DumpAdapters()
|
||||
{
|
||||
using OptWin32::GetMonitorInfoA;
|
||||
|
||||
if (D3D == NULL)
|
||||
{
|
||||
Printf("Multi-monitor support requires Direct3D.\n");
|
||||
|
@ -415,9 +419,8 @@ void Win32Video::DumpAdapters()
|
|||
MONITORINFOEX mi;
|
||||
mi.cbSize = sizeof(mi);
|
||||
|
||||
TOptWin32Proc<BOOL(WINAPI*)(HMONITOR, LPMONITORINFO)> GetMonitorInfo("user32.dll", "GetMonitorInfoW");
|
||||
assert(GetMonitorInfo != NULL); // Missing in NT4, but so is D3D
|
||||
if (GetMonitorInfo.Call(hm, &mi))
|
||||
assert(GetMonitorInfo); // Missing in NT4, but so is D3D
|
||||
if (GetMonitorInfo(hm, &mi))
|
||||
{
|
||||
mysnprintf(moreinfo, countof(moreinfo), " [%ldx%ld @ (%ld,%ld)]%s",
|
||||
mi.rcMonitor.right - mi.rcMonitor.left,
|
||||
|
|
|
@ -11,21 +11,21 @@
|
|||
|
||||
#if COMPGOTO
|
||||
#define OP(x) x
|
||||
#define NEXTOP do { unsigned op = pc->op; a = pc->a; pc++; goto *ops[op]; } while(0)
|
||||
#define NEXTOP do { pc++; unsigned op = pc->op; a = pc->a; goto *ops[op]; } while(0)
|
||||
#else
|
||||
#define OP(x) case OP_##x
|
||||
#define NEXTOP break
|
||||
#define NEXTOP pc++; break
|
||||
#endif
|
||||
|
||||
#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
|
||||
|
||||
#define A (pc[-1].a)
|
||||
#define B (pc[-1].b)
|
||||
#define C (pc[-1].c)
|
||||
#define Cs (pc[-1].cs)
|
||||
#define BC (pc[-1].i16u)
|
||||
#define BCs (pc[-1].i16)
|
||||
#define ABCs (pc[-1].i24)
|
||||
#define A (pc[0].a)
|
||||
#define B (pc[0].b)
|
||||
#define C (pc[0].c)
|
||||
#define Cs (pc[0].cs)
|
||||
#define BC (pc[0].i16u)
|
||||
#define BCs (pc[0].i16)
|
||||
#define ABCs (pc[0].i24)
|
||||
#define JMPOFS(x) ((x)->i24)
|
||||
|
||||
#define KC (konstd[C])
|
||||
|
@ -48,8 +48,8 @@
|
|||
|
||||
#define CMPJMP(test) \
|
||||
if ((test) == (a & CMP_CHECK)) { \
|
||||
assert(pc->op == OP_JMP); \
|
||||
pc += 1 + JMPOFS(pc); \
|
||||
assert(pc[1].op == OP_JMP); \
|
||||
pc += 1 + JMPOFS(pc+1); \
|
||||
} else { \
|
||||
pc += 1; \
|
||||
}
|
||||
|
|
|
@ -52,11 +52,17 @@ begin:
|
|||
{
|
||||
#if !COMPGOTO
|
||||
VM_UBYTE op;
|
||||
for(;;) switch(op = pc->op, a = pc->a, pc++, op)
|
||||
for(;;) switch(op = pc->op, a = pc->a, op)
|
||||
#else
|
||||
pc--;
|
||||
NEXTOP;
|
||||
#endif
|
||||
{
|
||||
#if !COMPGOTO
|
||||
default:
|
||||
assert(0 && "Undefined opcode hit");
|
||||
NEXTOP;
|
||||
#endif
|
||||
OP(LI):
|
||||
ASSERTD(a);
|
||||
reg.d[a] = BCs;
|
||||
|
@ -367,13 +373,13 @@ begin:
|
|||
}
|
||||
NEXTOP;
|
||||
OP(JMP):
|
||||
pc += JMPOFS(pc - 1);
|
||||
pc += JMPOFS(pc);
|
||||
NEXTOP;
|
||||
OP(IJMP):
|
||||
ASSERTD(a);
|
||||
pc += (BCs + reg.d[a]);
|
||||
assert(pc->op == OP_JMP);
|
||||
pc += 1 + JMPOFS(pc);
|
||||
assert(pc[1].op == OP_JMP);
|
||||
pc += 1 + JMPOFS(pc+1);
|
||||
NEXTOP;
|
||||
OP(PARAMI):
|
||||
assert(f->NumParam < sfunc->MaxParam);
|
||||
|
@ -490,7 +496,7 @@ begin:
|
|||
VMReturn returns[MAX_RETURNS];
|
||||
int numret;
|
||||
|
||||
FillReturns(reg, f, returns, pc, C);
|
||||
FillReturns(reg, f, returns, pc+1, C);
|
||||
if (call->Native)
|
||||
{
|
||||
numret = static_cast<VMNativeFunction *>(call)->NativeCall(stack, reg.param + f->NumParam - B, B, returns, C);
|
||||
|
@ -603,8 +609,8 @@ begin:
|
|||
{
|
||||
THROW(X_TOO_MANY_TRIES);
|
||||
}
|
||||
assert((pc + JMPOFS(pc - 1))->op == OP_CATCH);
|
||||
exception_frames[try_depth++] = pc + JMPOFS(pc - 1);
|
||||
assert((pc + JMPOFS(pc) + 1)->op == OP_CATCH);
|
||||
exception_frames[try_depth++] = pc + JMPOFS(pc) + 1;
|
||||
NEXTOP;
|
||||
OP(UNTRY):
|
||||
assert(a <= try_depth);
|
||||
|
@ -704,8 +710,8 @@ begin:
|
|||
}
|
||||
if (cmp == (a & CMP_CHECK))
|
||||
{
|
||||
assert(pc->op == OP_JMP);
|
||||
pc += 1 + JMPOFS(pc);
|
||||
assert(pc[1].op == OP_JMP);
|
||||
pc += 1 + JMPOFS(pc+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
142
src/zstring.cpp
142
src/zstring.cpp
|
@ -343,28 +343,74 @@ FString &FString::operator += (char tail)
|
|||
|
||||
FString &FString::AppendCStrPart (const char *tail, size_t tailLen)
|
||||
{
|
||||
size_t len1 = Len();
|
||||
ReallocBuffer (len1 + tailLen);
|
||||
StrCopy (Chars + len1, tail, tailLen);
|
||||
if (tailLen > 0)
|
||||
{
|
||||
size_t len1 = Len();
|
||||
ReallocBuffer(len1 + tailLen);
|
||||
StrCopy(Chars + len1, tail, tailLen);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
FString &FString::CopyCStrPart(const char *tail, size_t tailLen)
|
||||
{
|
||||
ReallocBuffer(tailLen);
|
||||
StrCopy(Chars, tail, tailLen);
|
||||
if (tailLen > 0)
|
||||
{
|
||||
ReallocBuffer(tailLen);
|
||||
StrCopy(Chars, tail, tailLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
Data()->Release();
|
||||
NullString.RefCount++;
|
||||
Chars = &NullString.Nothing[0];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void FString::Truncate(long newlen)
|
||||
{
|
||||
if (newlen >= 0 && newlen < (long)Len())
|
||||
if (newlen <= 0)
|
||||
{
|
||||
Data()->Release();
|
||||
NullString.RefCount++;
|
||||
Chars = &NullString.Nothing[0];
|
||||
}
|
||||
else if (newlen < (long)Len())
|
||||
{
|
||||
ReallocBuffer (newlen);
|
||||
Chars[newlen] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void FString::Remove(size_t index, size_t remlen)
|
||||
{
|
||||
if (index < Len())
|
||||
{
|
||||
if (index + remlen >= Len())
|
||||
{
|
||||
Truncate((long)index);
|
||||
}
|
||||
else
|
||||
{
|
||||
remlen = Len() - remlen < remlen ? Len() - remlen : remlen;
|
||||
if (Data()->RefCount == 1)
|
||||
{ // Can do this in place
|
||||
memmove(Chars + index, Chars + index + remlen, Len() - index - remlen);
|
||||
Data()->Len -= (unsigned)remlen;
|
||||
}
|
||||
else
|
||||
{ // Must do it in a copy
|
||||
FStringData *old = Data();
|
||||
AllocBuffer(old->Len - remlen);
|
||||
StrCopy(Chars, old->Chars(), index);
|
||||
StrCopy(Chars + index, old->Chars() + index + remlen, old->Len - index - remlen);
|
||||
old->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FString FString::Left (size_t numChars) const
|
||||
{
|
||||
size_t len = Len();
|
||||
|
@ -586,9 +632,13 @@ void FString::StripLeft ()
|
|||
if (max == 0) return;
|
||||
for (i = 0; i < max; ++i)
|
||||
{
|
||||
if (!isspace(Chars[i]))
|
||||
if (!isspace((unsigned char)Chars[i]))
|
||||
break;
|
||||
}
|
||||
if (i == 0)
|
||||
{ // Nothing to strip.
|
||||
return;
|
||||
}
|
||||
if (Data()->RefCount <= 1)
|
||||
{
|
||||
for (j = 0; i <= max; ++j, ++i)
|
||||
|
@ -620,6 +670,10 @@ void FString::StripLeft (const char *charset)
|
|||
if (!strchr (charset, Chars[i]))
|
||||
break;
|
||||
}
|
||||
if (i == 0)
|
||||
{ // Nothing to strip.
|
||||
return;
|
||||
}
|
||||
if (Data()->RefCount <= 1)
|
||||
{
|
||||
for (j = 0; i <= max; ++j, ++i)
|
||||
|
@ -640,11 +694,16 @@ void FString::StripLeft (const char *charset)
|
|||
void FString::StripRight ()
|
||||
{
|
||||
size_t max = Len(), i;
|
||||
for (i = max; i-- > 0; )
|
||||
if (max == 0) return;
|
||||
for (i = --max; i-- > 0; )
|
||||
{
|
||||
if (!isspace(Chars[i]))
|
||||
if (!isspace((unsigned char)Chars[i]))
|
||||
break;
|
||||
}
|
||||
if (i == max)
|
||||
{ // Nothing to strip.
|
||||
return;
|
||||
}
|
||||
if (Data()->RefCount <= 1)
|
||||
{
|
||||
Chars[i+1] = '\0';
|
||||
|
@ -668,11 +727,15 @@ void FString::StripRight (const char *charset)
|
|||
{
|
||||
size_t max = Len(), i;
|
||||
if (max == 0) return;
|
||||
for (i = max; i-- > 0; )
|
||||
for (i = --max; i-- > 0; )
|
||||
{
|
||||
if (!strchr (charset, Chars[i]))
|
||||
break;
|
||||
}
|
||||
if (i == max)
|
||||
{ // Nothing to strip.
|
||||
return;
|
||||
}
|
||||
if (Data()->RefCount <= 1)
|
||||
{
|
||||
Chars[i+1] = '\0';
|
||||
|
@ -693,14 +756,18 @@ void FString::StripLeftRight ()
|
|||
if (max == 0) return;
|
||||
for (i = 0; i < max; ++i)
|
||||
{
|
||||
if (!isspace(Chars[i]))
|
||||
if (!isspace((unsigned char)Chars[i]))
|
||||
break;
|
||||
}
|
||||
for (j = max - 1; j >= i; --j)
|
||||
{
|
||||
if (!isspace(Chars[j]))
|
||||
if (!isspace((unsigned char)Chars[j]))
|
||||
break;
|
||||
}
|
||||
if (i == 0 && j == max - 1)
|
||||
{ // Nothing to strip.
|
||||
return;
|
||||
}
|
||||
if (Data()->RefCount <= 1)
|
||||
{
|
||||
for (k = 0; i <= j; ++i, ++k)
|
||||
|
@ -713,8 +780,8 @@ void FString::StripLeftRight ()
|
|||
else
|
||||
{
|
||||
FStringData *old = Data();
|
||||
AllocBuffer (j - i);
|
||||
StrCopy (Chars, old->Chars(), j - i);
|
||||
AllocBuffer(j - i + 1);
|
||||
StrCopy(Chars, old->Chars(), j - i + 1);
|
||||
old->Release();
|
||||
}
|
||||
}
|
||||
|
@ -768,25 +835,28 @@ void FString::Insert (size_t index, const char *instr)
|
|||
|
||||
void FString::Insert (size_t index, const char *instr, size_t instrlen)
|
||||
{
|
||||
size_t mylen = Len();
|
||||
if (index > mylen)
|
||||
if (instrlen > 0)
|
||||
{
|
||||
index = mylen;
|
||||
}
|
||||
if (Data()->RefCount <= 1)
|
||||
{
|
||||
ReallocBuffer (mylen + instrlen);
|
||||
memmove (Chars + index + instrlen, Chars + index, (mylen - index + 1)*sizeof(char));
|
||||
memcpy (Chars + index, instr, instrlen*sizeof(char));
|
||||
}
|
||||
else
|
||||
{
|
||||
FStringData *old = Data();
|
||||
AllocBuffer (mylen + instrlen);
|
||||
StrCopy (Chars, old->Chars(), index);
|
||||
StrCopy (Chars + index, instr, instrlen);
|
||||
StrCopy (Chars + index + instrlen, old->Chars() + index, mylen - index);
|
||||
old->Release();
|
||||
size_t mylen = Len();
|
||||
if (index >= mylen)
|
||||
{
|
||||
AppendCStrPart(instr, instrlen);
|
||||
}
|
||||
else if (Data()->RefCount <= 1)
|
||||
{
|
||||
ReallocBuffer(mylen + instrlen);
|
||||
memmove(Chars + index + instrlen, Chars + index, (mylen - index + 1) * sizeof(char));
|
||||
memcpy(Chars + index, instr, instrlen * sizeof(char));
|
||||
}
|
||||
else
|
||||
{
|
||||
FStringData *old = Data();
|
||||
AllocBuffer(mylen + instrlen);
|
||||
StrCopy(Chars, old->Chars(), index);
|
||||
StrCopy(Chars + index, instr, instrlen);
|
||||
StrCopy(Chars + index + instrlen, old->Chars() + index, mylen - index);
|
||||
old->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -970,7 +1040,7 @@ octdigits = [0-7];
|
|||
yych = *YYCURSOR;
|
||||
|
||||
// Skip preceding whitespace
|
||||
while (yych != '\0' && isspace(yych)) { yych = *++YYCURSOR; }
|
||||
while (yych != '\0' && isspace((unsigned char)yych)) { yych = *++YYCURSOR; }
|
||||
|
||||
// Check for sign
|
||||
if (yych == '+' || yych == '-') { yych = *++YYCURSOR; }
|
||||
|
@ -1008,7 +1078,7 @@ octdigits = [0-7];
|
|||
}
|
||||
|
||||
// The rest should all be whitespace
|
||||
while (yych != '\0' && isspace(yych)) { yych = *++YYCURSOR; }
|
||||
while (yych != '\0' && isspace((unsigned char)yych)) { yych = *++YYCURSOR; }
|
||||
return yych == '\0';
|
||||
}
|
||||
|
||||
|
@ -1028,7 +1098,7 @@ digits = [0-9];
|
|||
yych = *YYCURSOR;
|
||||
|
||||
// Skip preceding whitespace
|
||||
while (yych != '\0' && isspace(yych)) { yych = *++YYCURSOR; }
|
||||
while (yych != '\0' && isspace((unsigned char)yych)) { yych = *++YYCURSOR; }
|
||||
|
||||
// Check for sign
|
||||
if (yych == '+' || yych == '-') { yych = *++YYCURSOR; }
|
||||
|
@ -1059,7 +1129,7 @@ digits = [0-9];
|
|||
}
|
||||
|
||||
// The rest should all be whitespace
|
||||
while (yych != '\0' && isspace(yych)) { yych = *++YYCURSOR; }
|
||||
while (yych != '\0' && isspace((unsigned char)yych)) { yych = *++YYCURSOR; }
|
||||
return yych == '\0';
|
||||
}
|
||||
|
||||
|
|
|
@ -268,6 +268,7 @@ public:
|
|||
bool IsNotEmpty() const { return Len() != 0; }
|
||||
|
||||
void Truncate (long newlen);
|
||||
void Remove(size_t index, size_t remlen);
|
||||
|
||||
int Compare (const FString &other) const { return strcmp (Chars, other.Chars); }
|
||||
int Compare (const char *other) const { return strcmp (Chars, other); }
|
||||
|
|
|
@ -1,19 +1,12 @@
|
|||
cmake_minimum_required( VERSION 2.8.7 )
|
||||
|
||||
if( WIN32 )
|
||||
if( ZD_CMAKE_COMPILER_IS_GNUC_COMPATIBLE OR ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
||||
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/trustinfo.o
|
||||
COMMAND windres -o ${CMAKE_CURRENT_BINARY_DIR}/trustinfo.o -i ${CMAKE_CURRENT_SOURCE_DIR}/trustinfo.rc
|
||||
DEPENDS trustinfo.rc )
|
||||
set( TRUSTINFO trustinfo.o )
|
||||
if( MSVC_VERSION GREATER 1399 )
|
||||
# VC 8+ adds a manifest automatically to the executable. We need to
|
||||
# merge ours with it.
|
||||
set( MT_MERGE ON )
|
||||
else()
|
||||
if( MSVC_VERSION GREATER 1399 )
|
||||
# VC 8+ adds a manifest automatically to the executable. We need to
|
||||
# merge ours with it.
|
||||
set( MT_MERGE ON )
|
||||
else( MSVC_VERSION GREATER 1399 )
|
||||
set( TRUSTINFO trustinfo.rc )
|
||||
endif( MSVC_VERSION GREATER 1399 )
|
||||
set( TRUSTINFO trustinfo.rc )
|
||||
endif()
|
||||
else( WIN32 )
|
||||
set( TRUSTINFO "" )
|
||||
|
|
|
@ -191,7 +191,7 @@ ACTOR Actor native //: Thinker
|
|||
action native A_ComboAttack();
|
||||
action native A_BulletAttack();
|
||||
action native A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", float snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, float runspeed = 160.0, class<Actor> pufftype = "BulletPuff");
|
||||
action native A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, float volume = 1.0, bool looping = false, float attenuation = ATTN_NORM);
|
||||
action native A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, float volume = 1.0, bool looping = false, float attenuation = ATTN_NORM, bool local = false);
|
||||
native void A_PlayWeaponSound(sound whattoplay);
|
||||
action native A_FLoopActiveSound();
|
||||
action native A_LoopActiveSound();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue