From 16b97e1c836e7f1877521759a785e2d370eb94b8 Mon Sep 17 00:00:00 2001 From: MaxED Date: Fri, 1 Jun 2012 10:17:47 +0000 Subject: [PATCH] Added GLDEFS and (Z)MAPINFO parsers. Dynamic lights defined in GLDEFS are now rendered in Visual modes (currently only one light per Thing is supported). Several values from (Z)MAPINFO are now used in Visual modes. Added "Reload GLDEFS", "Reload (Z)MAPINFO" and "Reload MODELDEF" menu options (in "Tools" section). MODELDEF parser now checks which model(s) is/are used in first frame. Dynamic lights are now created with more meaningful default parameters. Added errors and warnings indicator to main window. --- Build/Configurations/Includes/Common.cfg | 2 +- .../Configurations/Includes/ZDoom_common.cfg | 6 + Build/Gldefs/Readme.txt | 2 + Build/Gldefs/doomdefs.txt | 410 +++++++++ Build/Gldefs/hexndefs.txt | 444 +++++++++ Build/Gldefs/hticdefs.txt | 405 ++++++++ Build/Gldefs/strfdefs.txt | 862 ++++++++++++++++++ Source/Core/Builder.csproj | 4 + Source/Core/Builder.sln | 12 + Source/Core/Config/GameConfiguration.cs | 12 + Source/Core/Data/DataManager.cs | 260 +++++- Source/Core/Data/DataReader.cs | 12 +- Source/Core/Data/PK3StructuredReader.cs | 69 ++ Source/Core/Data/WADReader.cs | 68 +- Source/Core/GZBuilder/Data/GZDoomLight.cs | 72 +- Source/Core/GZBuilder/Data/GameType.cs | 18 + Source/Core/GZBuilder/Data/MapInfo.cs | 27 + Source/Core/GZBuilder/Data/TextureData.cs | 11 + Source/Core/GZBuilder/GZDoom/GldefsParser.cs | 346 ++++--- Source/Core/GZBuilder/GZDoom/MapinfoParser.cs | 348 +++++++ .../Core/GZBuilder/GZDoom/ModeldefParser.cs | 18 +- .../GZBuilder/GZDoom/ModeldefStructure.cs | 210 +++-- Source/Core/GZBuilder/GZGeneral.cs | 24 +- Source/Core/GZBuilder/md3/ModelReader.cs | 4 +- Source/Core/General/ErrorLogger.cs | 6 + Source/Core/Map/MapSet.cs | 4 +- Source/Core/Map/Thing.cs | 4 +- Source/Core/Rendering/IRenderer3D.cs | 3 + Source/Core/Rendering/Renderer.cs | 28 + Source/Core/Rendering/Renderer3D.cs | 93 +- Source/Core/Resources/Actions.cfg | 36 +- Source/Core/VisualModes/VisualGeometry.cs | 24 +- Source/Core/VisualModes/VisualThing.cs | 64 +- Source/Core/Windows/ErrorsForm.cs | 2 + Source/Core/Windows/MainForm.Designer.cs | 72 +- Source/Core/Windows/MainForm.cs | 46 +- Source/Core/Windows/MainForm.resx | 30 +- Source/Core/Windows/ThingEditForm.cs | 32 +- Source/Core/ZDoom/ZDTextParser.cs | 30 + .../Plugins/ColorPicker/Resources/Actions.cfg | 4 +- .../VisualModes/BaseVisualGeometrySidedef.cs | 10 +- .../VisualModes/BaseVisualMode.cs | 5 + .../GZDoomEditing/VisualModes/VisualLower.cs | 4 +- .../VisualModes/VisualMiddle3D.cs | 4 +- .../VisualModes/VisualMiddleDouble.cs | 4 +- .../VisualModes/VisualMiddleSingle.cs | 4 +- .../GZDoomEditing/VisualModes/VisualUpper.cs | 4 +- 47 files changed, 3780 insertions(+), 379 deletions(-) create mode 100644 Build/Gldefs/Readme.txt create mode 100644 Build/Gldefs/doomdefs.txt create mode 100644 Build/Gldefs/hexndefs.txt create mode 100644 Build/Gldefs/hticdefs.txt create mode 100644 Build/Gldefs/strfdefs.txt create mode 100644 Source/Core/GZBuilder/Data/GameType.cs create mode 100644 Source/Core/GZBuilder/Data/MapInfo.cs create mode 100644 Source/Core/GZBuilder/Data/TextureData.cs create mode 100644 Source/Core/GZBuilder/GZDoom/MapinfoParser.cs diff --git a/Build/Configurations/Includes/Common.cfg b/Build/Configurations/Includes/Common.cfg index 981eefa4..4f3877cc 100644 --- a/Build/Configurations/Includes/Common.cfg +++ b/Build/Configurations/Includes/Common.cfg @@ -13,7 +13,7 @@ start3dmode = 32000; // Flat used as sky -skyflatname = "F_SKY1"; +//skyflatname = "F_SKY1"; //mxd: moved to game_xxx sections of ZDoom_common.cfg because different games use different skyflatname // Map boundaries. Map objects can only be placed within these boundaries // WARNING: changing this may mess your map up, so only change it when you diff --git a/Build/Configurations/Includes/ZDoom_common.cfg b/Build/Configurations/Includes/ZDoom_common.cfg index 109e8c63..1e3fb24b 100644 --- a/Build/Configurations/Includes/ZDoom_common.cfg +++ b/Build/Configurations/Includes/ZDoom_common.cfg @@ -365,6 +365,7 @@ game_doom { // Default lump name for new map defaultlumpname = "MAP01"; + basegame = 0; //mxd: 0 - DOOM, 1 - HERETIC, 2 - HEXEN, 3 - STRIFE, 4 - UNKNOWN // Decorate actors to include depending on actor game property decorategames = "doom"; @@ -403,6 +404,7 @@ game_heretic { // Default lump name for new map defaultlumpname = "MAP01"; + basegame = 1; // Decorate actors to include depending on actor game property decorategames = "heretic raven"; @@ -441,6 +443,8 @@ game_hexen { // Default lump name for new map defaultlumpname = "MAP01"; + skyflatname = "F_SKY"; + basegame = 2; // Decorate actors to include depending on actor game property decorategames = "hexen raven"; @@ -479,6 +483,8 @@ game_strife { // Default lump name for new map defaultlumpname = "MAP01"; + skyflatname = "F_SKY001"; + basegame = 3; // Decorate actors to include depending on actor game property decorategames = "strife"; diff --git a/Build/Gldefs/Readme.txt b/Build/Gldefs/Readme.txt new file mode 100644 index 00000000..85399d69 --- /dev/null +++ b/Build/Gldefs/Readme.txt @@ -0,0 +1,2 @@ +This folder holds default GZDoom light definitions, taken from lights.pk3 +I've removed "Monsters" and "Weapons" sections from all of them to speed up parsing times. \ No newline at end of file diff --git a/Build/Gldefs/doomdefs.txt b/Build/Gldefs/doomdefs.txt new file mode 100644 index 00000000..2bb6351d --- /dev/null +++ b/Build/Gldefs/doomdefs.txt @@ -0,0 +1,410 @@ +// ---------------------- +// -- Doom Decorations -- +// ---------------------- + +// Barrel +pulselight BARREL +{ + color 0.0 0.5 0.0 + size 20 + secondarySize 21 + interval 0.5 + offset 0 36 0 + dontlightself 1 +} + +object ExplosiveBarrel +{ + frame BAR1 { light BARREL } + + frame BEXPC { light ROCKET_X1 } + frame BEXPD { light ROCKET_X2 } + frame BEXPE { light ROCKET_X3 } +} + +// Floor lamp +pointlight LAMP +{ + color 1.0 1.0 0.8 + size 56 + offset 0 44 0 +} + +object Column +{ + frame COLU { light LAMP } +} + +// Short tech lamp +pulselight SMALLLAMP +{ + color 0.8 0.8 1.0 + size 56 + secondarySize 58 + interval 0.4 + offset 0 44 0 +} + +object TechLamp2 +{ + frame TLP2 { light SMALLLAMP } +} + +// Tall tech lamp +pulselight BIGLAMP +{ + color 0.8 0.8 1.0 + size 64 + secondarySize 66 + interval 0.4 + offset 0 72 0 +} + +object TechLamp +{ + frame TLMP { light BIGLAMP } +} + +// Tall red torch +flickerlight2 BIGREDTORCH +{ + color 1.0 0.3 0.0 + size 64 + secondarySize 72 + interval 0.1 + offset 0 60 0 +} + +object RedTorch +{ + frame TRED { light BIGREDTORCH } +} + +// Tall green torch +flickerlight2 BIGGREENTORCH +{ + color 0.0 1.0 0.0 + size 64 + secondarySize 72 + interval 0.1 + offset 0 60 0 +} + +object GreenTorch +{ + frame TGRN { light BIGGREENTORCH } +} + +// Tall blue torch +flickerlight2 BIGBLUETORCH +{ + color 0.0 0.0 1.0 + size 64 + secondarySize 72 + interval 0.1 + offset 0 60 0 +} + +object BlueTorch +{ + frame TBLU { light BIGBLUETORCH } +} + +// Small red torch +flickerlight2 SMALLREDTORCH +{ + color 1.0 0.3 0.0 + size 48 + secondarySize 54 + interval 0.1 + offset 0 35 0 +} + +object ShortRedTorch +{ + frame SMRT { light SMALLREDTORCH } +} + +// Small green torch +flickerlight2 SMALLGREENTORCH +{ + color 0.0 1.0 0.0 + size 48 + secondarySize 54 + interval 0.1 + offset 0 35 0 +} + +object ShortGreenTorch +{ + frame SMGT { light SMALLGREENTORCH } +} + +// Small blue torch +flickerlight2 SMALLBLUETORCH +{ + color 0.0 0.0 1.0 + size 48 + secondarySize 54 + interval 0.1 + offset 0 35 0 +} + +object ShortBlueTorch +{ + frame SMBT { light SMALLBLUETORCH } +} + +// Burning barrel +flickerlight2 FIREBARREL +{ + color 1.0 0.9 0.0 + size 48 + secondarySize 54 + interval 0.1 + offset 0 32 0 +} + +object BurningBarrel +{ + frame FCAN { light FIREBARREL } +} + +// Skulls w/candles +flickerlight2 SKULLCANDLES +{ + color 1.0 1.0 0.0 + size 32 + secondarySize 34 + interval 0.1 + offset 0 24 0 +} + +object HeadCandles +{ + frame POL3 { light SKULLCANDLES } +} + +// Candle +pointlight CANDLE +{ + color 1.0 1.0 0.0 + size 16 + offset 0 16 0 +} + +object Candlestick +{ + frame CAND { light CANDLE } +} + +// Candelabra +pointlight CANDELABRA +{ + color 1.0 1.0 0.0 + size 48 + offset 0 52 0 +} + +object Candelabra +{ + frame CBRA { light CANDELABRA } +} + + + +// ---------------- +// -- Doom Items -- +// ---------------- + +// Soul Sphere +pulselight SOULSPHERE +{ + color 0.0 0.0 1.0 + size 40 + secondarySize 42 + interval 2.0 + offset 0 16 0 +} + +object SoulSphere +{ + frame SOUL { light SOULSPHERE } +} + +// Invulnerability Sphere +pulselight INVULN +{ + color 0.0 1.0 0.0 + size 40 + secondarySize 42 + interval 2.0 + offset 0 16 0 +} + +object InvulnerabilitySphere +{ + frame PINV { light INVULN } +} + +// Blur Sphere +pointlight BLURSPHERE1 +{ + color 1.0 0.0 0.0 + size 40 + offset 0 16 0 +} + +pointlight BLURSPHERE2 +{ + color 0.0 0.0 1.0 + size 32 + offset 0 16 0 +} + +pointlight BLURSPHERE3 +{ + color 0.0 0.0 1.0 + size 24 + offset 0 16 0 +} + +pointlight BLURSPHERE4 +{ + color 0.0 0.0 1.0 + size 16 + offset 0 16 0 +} + +pointlight BLURSPHERE5 +{ + color 0.0 0.0 1.0 + size 8 + offset 0 16 0 +} + +object BlurSphere +{ + frame PINS { light BLURSPHERE1 } + + frame PINSA { light BLURSPHERE2 } + frame PINSB { light BLURSPHERE3 } + frame PINSC { light BLURSPHERE4 } + frame PINSD { light BLURSPHERE5 } +} + +// Health Potion +pulselight HEALTHPOTION +{ + color 0.0 0.0 0.6 + size 16 + secondarySize 18 + interval 2.0 +} + +object HealthBonus +{ + frame BON1 { light HEALTHPOTION } +} + +// Armour Helmet +pulselight ARMORBONUS +{ + color 0.0 0.6 0.0 + size 16 + secondarySize 14 + interval 1.0 + dontlightself 1 +} + +object ArmorBonus +{ + frame BON2 { light ARMORBONUS } +} + +// Blue Keys +object BlueCard +{ + frame BKEY { light HEALTHPOTION } +} + +object BlueSkull +{ + frame BSKU { light HEALTHPOTION } +} + +// Yellow Keys +pulselight YELLOWKEY +{ + color 0.6 0.6 0.0 + size 16 + secondarySize 18 + interval 2.0 +} + +object YellowCard +{ + frame YKEY { light YELLOWKEY } +} + +object YellowSkull +{ + frame YSKU { light YELLOWKEY } +} + +// Red Keys +pulselight REDKEY +{ + color 0.6 0.0 0.0 + size 16 + secondarySize 18 + interval 2.0 +} + +object RedCard +{ + frame RKEY { light REDKEY } +} + +object RedSkull +{ + frame RSKU { light REDKEY } +} + +// Green armour +pointlight GREENARMOR1 +{ + color 0.0 0.6 0.0 + size 48 +} + +pointlight GREENARMOR2 +{ + color 0.0 0.6 0.0 + size 32 +} + +object GreenArmor +{ + frame ARM1A { light GREENARMOR1 } + frame ARM1B { light GREENARMOR2 } +} + +// Blue armour +pointlight BLUEARMOR1 +{ + color 0.0 0.0 0.6 + size 48 +} + +pointlight BLUEARMOR2 +{ + color 0.0 0.0 0.6 + size 32 +} + +object BlueArmor +{ + frame ARM2A { light BLUEARMOR1 } + frame ARM2B { light BLUEARMOR2 } +} \ No newline at end of file diff --git a/Build/Gldefs/hexndefs.txt b/Build/Gldefs/hexndefs.txt new file mode 100644 index 00000000..c8f433d5 --- /dev/null +++ b/Build/Gldefs/hexndefs.txt @@ -0,0 +1,444 @@ +// ----------------------- +// -- Hexen Decorations -- +// ----------------------- + +// Candles +flickerlight2 HCANDLES +{ + color 1.0 1.0 0.0 + size 16 + secondarySize 20 + interval 0.1 +} + +object ZCandle +{ + frame CNDL { light HCANDLES } +} + +// Twined torch +flickerlight2 TWINETORCH +{ + color 1.0 0.7 0.0 + size 46 + secondarySize 52 + interval 0.1 + offset 0 64 0 +} + +object ZTwinedTorch +{ + frame TWTRA { light TWINETORCH } + frame TWTRB { light TWINETORCH } + frame TWTRC { light TWINETORCH } + frame TWTRD { light TWINETORCH } + frame TWTRE { light TWINETORCH } + frame TWTRF { light TWINETORCH } + frame TWTRG { light TWINETORCH } + frame TWTRH { light TWINETORCH } +} + +object ZTwinedTorchUnlit +{ + frame TWTRA { light TWINETORCH } + frame TWTRB { light TWINETORCH } + frame TWTRC { light TWINETORCH } + frame TWTRD { light TWINETORCH } + frame TWTRE { light TWINETORCH } + frame TWTRF { light TWINETORCH } + frame TWTRG { light TWINETORCH } + frame TWTRH { light TWINETORCH } +} + + +// Wall torch +flickerlight2 WALLTORCH2 +{ + color 1.0 0.7 0.0 + size 24 + secondarySize 28 + interval 0.1 + offset 0 24 0 +} + +object ZWallTorch +{ + frame WLTRA { light WALLTORCH2 } + frame WLTRB { light WALLTORCH2 } + frame WLTRC { light WALLTORCH2 } + frame WLTRD { light WALLTORCH2 } + frame WLTRE { light WALLTORCH2 } + frame WLTRF { light WALLTORCH2 } + frame WLTRG { light WALLTORCH2 } + frame WLTRH { light WALLTORCH2 } +} + + +object ZWallTorchUnlit +{ + frame WLTRA { light WALLTORCH2 } + frame WLTRB { light WALLTORCH2 } + frame WLTRC { light WALLTORCH2 } + frame WLTRD { light WALLTORCH2 } + frame WLTRE { light WALLTORCH2 } + frame WLTRF { light WALLTORCH2 } + frame WLTRG { light WALLTORCH2 } + frame WLTRH { light WALLTORCH2 } +} + + +// Fire bull +flickerlight2 FIREBULL +{ + color 1.0 0.7 0.0 + size 64 + secondarySize 70 + interval 0.1 + offset 0 40 0 +} + +object ZFireBull +{ + frame FBULA { light FIREBULL } + frame FBULB { light FIREBULL } + frame FBULC { light FIREBULL } + frame FBULD { light FIREBULL } + frame FBULE { light FIREBULL } + frame FBULF { light FIREBULL } + frame FBULG { light FIREBULL } + frame FBULH { light FIREBULL } +} + +object ZFireBullUnlit +{ + frame FBULA { light FIREBULL } + frame FBULB { light FIREBULL } + frame FBULC { light FIREBULL } + frame FBULD { light FIREBULL } + frame FBULE { light FIREBULL } + frame FBULF { light FIREBULL } + frame FBULG { light FIREBULL } + frame FBULH { light FIREBULL } +} + + +// Cauldron +flickerlight2 CAULFLAME +{ + color 1.0 0.9 0.0 + size 24 + secondarySize 26 + interval 0.1 +} + +object ZCauldron +{ + frame CDRNB { light CAULFLAME } + frame CDRNC { light CAULFLAME } + frame CDRND { light CAULFLAME } + frame CDRNE { light CAULFLAME } + frame CDRNF { light CAULFLAME } + frame CDRNG { light CAULFLAME } + frame CDRNH { light CAULFLAME } +} + +object ZCauldronUnlit +{ + frame CDRNB { light CAULFLAME } + frame CDRNC { light CAULFLAME } + frame CDRND { light CAULFLAME } + frame CDRNE { light CAULFLAME } + frame CDRNF { light CAULFLAME } + frame CDRNG { light CAULFLAME } + frame CDRNH { light CAULFLAME } +} + +// Blue candle +flickerlight2 BCANDLE +{ + color 0.3 0.3 1.0 + size 14 + secondarySize 16 + interval 0.1 +} + +object ZBlueCandle +{ + frame CAND { light BCANDLE } +} + +// Small flame +object FlameSmall +{ + frame FFSM { light HCANDLES } +} + +object FlameSmallTemp +{ + frame FFSM { light HCANDLES } +} + +// Large flame +flickerlight2 LARGEFLAME +{ + color 1.0 0.7 0.0 + size 40 + secondarySize 48 + interval 0.1 +} + +object FlameLarge +{ + frame FFLG { light LARGEFLAME } +} + +object FlameLargeTemp +{ + frame FFLG { light LARGEFLAME } +} + +// Chandelier +flickerlight2 CHANDELIER +{ + color 1.0 1.0 0.0 + size 64 + secondarySize 68 + interval 0.1 +} + +object ZChandelier +{ + frame CDLR { light CHANDELIER } +} + +// Brass torch +flickerlight2 BRASSTORCH +{ + color 1.0 0.7 0.0 + size 40 + secondarySize 48 + interval 0.1 + offset 0 32 0 +} + +object BrassTorch +{ + frame BRTR { light BRASSTORCH } +} + +// Skull flame +object FireThing +{ + frame FSKL { light BRASSTORCH } +} + +// Teleport smoke +flickerlight2 TELESMOKE +{ + color 1.0 0.0 0.0 + size 64 + secondarySize 72 + interval 0.1 + offset 0 44 0 +} + +object TeleSmoke +{ + frame TSMK { light TELESMOKE } +} + +// Fireball +pointlight HFIREBALL +{ + color 1.0 0.4 0.0 + size 48 +} + +object FireBall +{ + frame FBL1A { light HFIREBALL } + frame FBL1B { light HFIREBALL } +} + +// ----------------- +// -- Hexen Items -- +// ----------------- + +// Blue mana +pointlight MANA1 +{ + color 0.0 0.0 0.7 + size 24 + offset 0 36 0 +} + +object Mana1 +{ + frame MAN1 { light MANA1 } +} + +// Green mana +pointlight MANA2 +{ + color 0.0 0.6 0.0 + size 24 + offset 0 36 0 +} + +object Mana2 +{ + frame MAN2 { light MANA2 } +} + +// Combined mana +pointlight MANA3 +{ + color 0.7 0.0 0.0 + size 24 + offset 0 36 0 +} + +object Mana3 +{ + frame MAN3 { light MANA3 } +} + +// ZXmasTree +flickerlight2 XMASFIRE1 +{ + color 1.0 0.7 0.0 + size 16 + secondarySize 24 + interval 0.1 + offset 0 48 0 +} + + +flickerlight2 XMASFIRE2 +{ + color 1.0 0.8 0.0 + size 32 + secondarySize 48 + interval 0.1 + offset 0 48 0 +} + + +flickerlight2 XMASFIRE3 +{ + color 1.0 0.9 0.0 + size 48 + secondarySize 64 + interval 0.1 + offset 0 32 0 +} + + +flickerlight2 XMASFIRE4 +{ + color 1.0 0.8 0.0 + size 32 + secondarySize 40 + interval 0.1 + offset 0 120 0 +} + + +flickerlight2 XMASFIRE5 +{ + color 1.0 0.7 0.0 + size 12 + secondarySize 20 + interval 0.1 + offset 0 140 0 +} + + +flickerlight2 XMASFIRE6 +{ + color 1.0 0.8 0.0 + size 10 + secondarySize 14 + interval 0.1 + offset 0 148 0 +} + + +object ZXmasTree +{ + frame XMASB { light XMASFIRE1 } + frame XMASC { light XMASFIRE2 } + frame XMASD { light XMASFIRE3 } + frame XMASE { light XMASFIRE3 } + frame XMASF { light XMASFIRE4 } + frame XMASG { light XMASFIRE5 } + frame XMASH { light XMASFIRE6 } +} + + + + +// TreeDestructible +flickerlight2 TDESTRUCT1 +{ + color 1.0 0.8 0.0 + size 48 + secondarySize 56 + interval 0.1 + offset 0 32 0 +} + + +flickerlight2 TDESTRUCT2 +{ + color 1.0 0.9 0.0 + size 56 + secondarySize 72 + interval 0.1 + offset 0 32 0 +} + + +flickerlight2 TDESTRUCT3 +{ + color 1.0 0.8 0.0 + size 40 + secondarySize 48 + interval 0.1 + offset 0 20 0 +} + + +flickerlight2 TDESTRUCT4 +{ + color 1.0 0.7 0.0 + size 16 + secondarySize 24 + interval 0.1 + offset 0 12 0 +} + +flickerlight2 TDESTRUCT5 +{ + color 1.0 0.7 0.0 + size 8 + secondarySize 12 + interval 0.1 + offset 0 4 0 +} + + + + +object TreeDestructible +{ + frame TRDTH { light TDESTRUCT1 } + frame TRDTI { light TDESTRUCT2 } + frame TRDTJ { light TDESTRUCT2 } + frame TRDTK { light TDESTRUCT2 } + frame TRDTL { light TDESTRUCT2 } + frame TRDTM { light TDESTRUCT3 } + frame TRDTN { light TDESTRUCT4 } + frame TRDTO { light TDESTRUCT4 } + frame TRDTP { light TDESTRUCT5 } +} diff --git a/Build/Gldefs/hticdefs.txt b/Build/Gldefs/hticdefs.txt new file mode 100644 index 00000000..c883a8ce --- /dev/null +++ b/Build/Gldefs/hticdefs.txt @@ -0,0 +1,405 @@ +// ------------------------- +// -- Heretic Decorations -- +// ------------------------- + +// Wall Torch +flickerlight2 WALLTORCH +{ + color 1.0 0.8 0.0 + size 32 + secondarySize 36 + interval 0.1 + offset 0 70 0 +} + +object WallTorch +{ + frame WTRH { light WALLTORCH } +} + +// Fire Brazier +flickerlight2 FIREBRAZ +{ + color 1.0 0.8 0.0 + size 68 + secondarySize 76 + interval 0.1 + offset 0 48 0 +} + +object FireBrazier +{ + frame KFR1 { light FIREBRAZ } +} + +// Serpent torch +flickerlight2 SERPTORCH +{ + color 1.0 0.8 0.0 + size 48 + secondarySize 56 + interval 0.1 + offset 0 48 0 +} + +object SerpentTorch +{ + frame SRTC { light SERPTORCH } +} + +// Chandelier +flickerlight2 CHANDELIER +{ + color 1.0 1.0 0.0 + size 64 + secondarySize 68 + interval 0.1 +} + +object Chandelier +{ + frame CHDL { light CHANDELIER } +} + +// Pod +flickerlight POD_X1 +{ + color 0.0 1.0 0.0 + size 48 + secondarySize 56 + chance 0.3 +} + +flickerlight POD_X2 +{ + color 0.0 0.7 0.0 + size 64 + secondarySize 72 + chance 0.3 +} + +flickerlight POD_X3 +{ + color 0.0 0.4 0.0 + size 72 + secondarySize 80 + chance 0.3 +} + +flickerlight POD_X4 +{ + color 0.0 0.2 0.0 + size 80 + secondarySize 88 + chance 0.3 +} + +object Pod +{ + frame PPODC { light POD_X1 } + frame PPODD { light POD_X2 } + frame PPODE { light POD_X3 } + frame PPODF { light POD_X4 } +} + +// Big volcano fireball +flickerlight VOLCANOBALL1 +{ + color 1.0 0.5 0.0 + size 56 + secondarySize 64 + chance 0.5 +} + +object VolcanoBlast +{ + frame VFBL { light VOLCANOBALL1 } +} + +// Small volcano fireball +flickerlight VOLCANOBALL1 +{ + color 1.0 0.5 0.0 + size 40 + secondarySize 48 + chance 0.5 +} + +object VolcanoTBlast +{ + frame VTFB { light VOLCANOBALL1 } +} + +// Blue Key Statue +pointlight BLUESTATUE +{ + color 0.0 0.0 1.0 + size 32 + offset 0 64 0 +} + +object KeyGizmoBlue +{ + frame KGZ1 { light BLUESTATUE } +} + +// Yellow Key Statue +pointlight YELLOWSTATUE +{ + color 1.0 1.0 0.0 + size 32 + offset 0 64 0 +} + +object KeyGizmoYellow +{ + frame KGZ1 { light YELLOWSTATUE } +} + +// Green Key Statue +pointlight GREENSTATUE +{ + color 0.0 1.0 0.0 + size 32 + offset 0 64 0 +} + +object KeyGizmoGreen +{ + frame KGZ1 { light GREENSTATUE } +} + +// ------------------- +// -- Heretic Items -- +// ------------------- + +// Time bomb explosion +flickerlight TIMEBOMB_X1 +{ + color 1.0 0.6 0.0 + size 48 + secondarySize 56 + chance 0.3 +} + +flickerlight TIMEBOMB_X1 +{ + color 0.8 0.4 0.0 + size 56 + secondarySize 64 + chance 0.3 +} + +flickerlight TIMEBOMB_X1 +{ + color 0.6 0.2 0.0 + size 64 + secondarySize 72 + chance 0.3 +} + +flickerlight TIMEBOMB_X1 +{ + color 0.4 0.0 0.0 + size 72 + secondarySize 80 + chance 0.3 +} + +flickerlight TIMEBOMB_X1 +{ + color 0.2 0.0 0.0 + size 80 + secondarySize 88 + chance 0.3 +} + +object ActivatedTimeBomb +{ + frame XPL1A { light TIMEBOMB_X1 } + frame XPL1B { light TIMEBOMB_X2 } + frame XPL1C { light TIMEBOMB_X3 } + frame XPL1D { light TIMEBOMB_X4 } + frame XPL1E { light TIMEBOMB_X5 } + frame XPL1F { light TIMEBOMB_X5 } +} + +// Small wand ammo +pointlight SWANDAMMO +{ + color 1.0 1.0 0.0 + size 8 +} + +object GoldWandAmmo +{ + frame AMG1 { light SWANDAMMO } +} + +// Large wand ammo +pulselight LWANDAMMO +{ + color 1.0 1.0 0.0 + size 16 + secondarySize 18 + interval 2.0 +} + +object GoldWandHefty +{ + frame AMG2 { light LWANDAMMO } +} + +// Ethereal arrows +pointlight ETHARROWS +{ + color 0.0 1.0 0.0 + size 12 + offset 0 8 0 +} + +object CrossbowAmmo +{ + frame AMC1 { light ETHARROWS } +} + +// Quiver of ethereal arrows +pulselight ETHQUIVER +{ + color 0.0 1.0 0.0 + size 16 + secondarySize 18 + interval 2.0 + offset 0 16 0 +} + +object CrossbowHefty +{ + frame AMC2 { light ETHQUIVER } +} + +// Small claw ammo +pulselight SCLAWAMMO +{ + color 0.0 0.0 1.0 + size 8 + secondarySize 10 + interval 2.0 +} + +object BlasterAmmo +{ + frame AMB1 { light SCLAWAMMO } +} + +// Large claw ammo +pulselight LCLAWAMMO +{ + color 0.0 0.0 1.0 + size 16 + secondarySize 18 + interval 2.0 + offset 0 6 0 +} + +object BlasterHefty +{ + frame AMB2 { light LCLAWAMMO } +} + +// Small hellstaff ammo +pulselight SSTAFFAMMO +{ + color 1.0 0.0 0.0 + size 8 + secondarySize 10 + interval 2.0 +} + +object SkullRodAmmo +{ + frame AMS1 { light SSTAFFAMMO } +} + +// Large hellstaff ammo +pulselight LSTAFFAMMO +{ + color 1.0 0.0 0.0 + size 16 + secondarySize 18 + interval 2.0 +} + +object SkullRodHefty +{ + frame AMS2 { light LSTAFFAMMO } +} + +// Small phoenix rod ammo +pulselight SRODAMMO +{ + color 1.0 0.6 0.0 + size 8 + secondarySize 10 + interval 2.0 +} + +object PhoenixRodAmmo +{ + frame AMP1 { light SRODAMMO } +} + +// Large phoenix rod ammo +pulselight LRODAMMO +{ + color 1.0 0.6 0.0 + size 16 + secondarySize 18 + interval 2.0 +} + +object PhoenixRodHefty +{ + frame AMP2 { light LRODAMMO } +} + +// Yellow Key +pulselight HYELLOWKEY +{ + color 1.0 1.0 0.0 + size 24 + secondarySize 26 + interval 2.0 +} +object KeyYellow +{ + frame CKYY { light HYELLOWKEY } +} + +// Blue Key +pulselight HBLUEKEY +{ + color 0.0 0.0 1.0 + size 24 + secondarySize 26 + interval 2.0 +} + +object KeyBlue +{ + frame BKYY { light HBLUEKEY } +} + +// Green Key +pulselight HGREENKEY +{ + color 0.0 1.0 0.0 + size 24 + secondarySize 26 + interval 2.0 +} + +object KeyGreen +{ + frame AKYY { light HGREENKEY } +} \ No newline at end of file diff --git a/Build/Gldefs/strfdefs.txt b/Build/Gldefs/strfdefs.txt new file mode 100644 index 00000000..a779fdea --- /dev/null +++ b/Build/Gldefs/strfdefs.txt @@ -0,0 +1,862 @@ +// ------------------ +// -- Strife Items -- +// ------------------ + +// Degnin Ore +flickerlight DEGORE_X1 +{ + color 1.0 0.6 0.0 + size 32 + secondarySize 40 + chance 0.3 +} + +flickerlight DEGORE_X2 +{ + color 1.0 0.8 0.0 + size 40 + secondarySize 48 + chance 0.3 +} + +flickerlight DEGORE_X3 +{ + color 1.0 0.8 0.0 + size 44 + secondarySize 52 + chance 0.3 +} + +flickerlight DEGORE_X4 +{ + color 1.0 0.75 0.0 + size 48 + secondarySize 56 + chance 0.3 +} + +flickerlight DEGORE_X5 +{ + color 1.0 0.7 0.0 + size 52 + secondarySize 60 + chance 0.3 +} + +flickerlight DEGORE_X6 +{ + color 1.0 0.5 0.0 + size 56 + secondarySize 64 + chance 0.3 +} + +flickerlight DEGORE_X7 +{ + color 0.5 0.125 0.0 + size 60 + secondarySize 68 + chance 0.3 +} + +flickerlight DEGORE_X8 +{ + color 0.25 0.05 0.0 + size 64 + secondarySize 72 + chance 0.3 +} + +object DegninOre +{ + frame BNG3A { light DEGORE_X1 } + frame BNG3B { light DEGORE_X2 } + frame BNG3C { light DEGORE_X3 } + frame BNG3D { light DEGORE_X4 } + frame BNG3E { light DEGORE_X5 } + frame BNG3F { light DEGORE_X6 } + frame BNG3G { light DEGORE_X7 } + frame BNG3H { light DEGORE_X8 } +} + +// Power Coupling +pointlight POWCOUP1 +{ + color 0.5 0.5 1.0 + size 24 +} + +pointlight POWCOUP2 +{ + color 0.7 0.7 1.0 + size 32 +} + +object PowerCoupling +{ + frame COUPA { light POWCOUP1 } + frame COUPB { light POWCOUP2 } +} + +// Energy Ammo +pointlight ENERGY1 +{ + color 0.4 1.0 0.4 + size 16 +} + +pointlight ENERGY2 +{ + color 0.4 1.0 0.4 + size 32 +} + +object EnergyPod +{ + frame BRY1B { light ENERGY1 } +} + +object EnergyPack +{ + frame CPACB { light ENERGY2 } +} + +// ------------------ +// - Strife Objects - +// ------------------ + +// Lights +pointlight LIGHT1 +{ + color 1.0 1.0 1.0 + size 56 + offset 0 30 0 +} + +pointlight LIGHT2 +{ + color 1.0 1.0 1.0 + size 40 + offset 0 72 0 +} + +pointlight LIGHT3 +{ + color 1.0 1.0 1.0 + size 64 +} + +pointlight LIGHT4 +{ + color 1.0 1.0 1.0 + size 64 + offset 0 80 0 +} + +pointlight LIGHT5 +{ + color 1.0 1.0 1.0 + size 56 + offset 0 72 0 +} + +pointlight CLIGHT1 +{ + color 1.0 1.0 0.0 + size 24 + offset 0 12 0 +} + +pulselight CLIGHT2 +{ + color 1.0 1.0 0.0 + size 48 + secondarySize 50 + interval 8.0 + offset 0 64 0 +} + +pulselight LLIGHT +{ + color 1.0 0.5 0.0 + size 24 + secondarySize 32 + interval 12.0 + offset 0 76 0 +} + +pulselight TLLIGHT1 +{ + color 0.9 0.9 1.0 + size 56 + secondarySize 64 + interval 3.0 + offset 0 48 0 +} + +pointlight TLLIGHT2 +{ + color 1.0 1.0 0.5 + size 80 + offset 0 56 0 +} + +flickerlight HTECH +{ + color 0.3 1.0 0.3 + size 96 + secondarySize 104 + chance 0.5 + offset 0 80 0 +} + +pulselight BCOLUMN +{ + color 0.5 1.0 0.5 + size 120 + secondarySize 128 + interval 10.0 + offset 0 64 0 +} + +pulselight FBUBBLE +{ + color 0.5 1.0 0.5 + size 60 + secondarySize 64 + interval 10.0 + offset 0 32 0 +} + +pulselight CBUBBLE +{ + color 0.5 1.0 0.5 + size 60 + secondarySize 64 + interval 10.0 +} + +pointlight SPIDLGHT1 +{ + color 0.5 1.0 0.5 + size 64 + offset 0 10 0 +} + +pointlight SPIDLGHT2 +{ + color 0.2 0.75 0.2 + size 56 + offset 0 10 0 +} + +pointlight SPIDLGHT3 +{ + color 0.0 0.25 0.0 + size 48 + offset 0 10 0 +} + +object LightSilverFluorescent +{ + frame LITS { light LIGHT1 } +} + +object LightBrownFluorescent +{ + frame LITB { light LIGHT1 } +} + +object LightGoldFluorescent +{ + frame LITG { light LIGHT1 } +} + +object LightGlobe +{ + frame LITE { light LIGHT5 } +} + +object PillarHugeTech +{ + frame HUGE { light HTECH } +} + +object Candle +{ + frame KNDL { light CLIGHT1 } +} + +object StrifeCandelabra +{ + frame CLBR { light CLIGHT2 } +} + +object CageLight +{ + frame CAGE { light LIGHT3 } +} + +object OutsideLamp +{ + frame LAMP { light LIGHT4 } +} + +object PoleLantern +{ + frame LANT { light LLIGHT } +} + +object TechLampSilver +{ + frame TECHA { light TLLIGHT1 } +} + +object TechLampBrass +{ + frame TECHB { light TLLIGHT2 } +} + +object AlienBubbleColumn +{ + frame BUBB { light BCOLUMN } +} + +object AlienFloorBubble +{ + frame BUBF { light FBUBBLE } +} + +object AlienCeilingBubble +{ + frame BUBC { light CBUBBLE } +} + +object AlienSpiderLight +{ + frame SPDLA { light SPIDLGHT1 } + frame SPDLB { light SPIDLGHT2 } + frame SPDLC { light SPIDLGHT3 } +} + +// Burning Things +flickerlight BBARREL +{ + color 1.0 0.6 0.0 + size 32 + secondarySize 40 + chance 0.8 + offset 0 32 0 +} + +flickerlight BBOWL +{ + color 1.0 0.7 0.0 + size 24 + secondarySize 32 + chance 0.5 + offset 0 10 0 +} + +flickerlight BBRAZIER +{ + color 1.0 0.8 0.0 + size 40 + secondarySize 48 + chance 0.2 + offset 0 32 0 +} + +pulselight STORCH +{ + color 1.0 0.6 0.0 + size 28 + secondarySize 32 + interval 5.0 + offset 0 56 0 +} + +pulselight MTORCH +{ + color 1.0 0.6 0.0 + size 56 + secondarySize 64 + interval 5.0 + offset 0 64 0 +} + +pulselight LTORCH +{ + color 1.0 0.8 0.0 + size 64 + secondarySize 72 + interval 2.0 + offset 0 64 0 +} + +pulselight HTORCH +{ + color 1.0 0.6 0.0 + size 72 + secondarySize 76 + interval 3.0 + offset 0 72 0 +} + +object StrifeBurningBarrel +{ + frame BBAR { light BBARREL } +} + +object BurningBowl +{ + frame BOWL { light BBOWL } +} + +object BurningBrazier +{ + frame BRAZ { light BBRAZIER } +} + +object SmallTorchLit +{ + frame TRHL { light STORCH } +} + +object MediumTorch +{ + frame LTRH { light MTORCH } +} + +object LargeTorch +{ + frame LMPC { light LTORCH } +} + +object HugeTorch +{ + frame LOGS { light HTORCH } +} + +// Power Crystal +pointlight PCRYSTAL +{ + color 1.0 1.0 0.0 + size 40 + offset 0 16 0 +} + +pointlight PCRYSTAL1 +{ + color 0.4 0.4 1.0 + size 24 + offset 0 12 0 +} + +pointlight PCRYSTAL2 +{ + color 0.5 0.5 1.0 + size 30 + offset 0 18 0 +} + +pointlight PCRYSTAL3 +{ + color 0.45 0.45 1.0 + size 32 + offset 0 24 0 +} + +pointlight PCRYSTAL4 +{ + color 0.35 0.35 1.0 + size 28 + offset 0 32 0 +} + +pointlight PCRYSTAL5 +{ + color 0.1 0.1 1.0 + size 18 + offset 0 40 0 +} + +flickerlight POWCRYS_X1 +{ + color 1.0 0.7 0.1 + size 108 + secondarySize 112 + chance 0.3 +} + +flickerlight POWCRYS_X2 +{ + color 1.0 0.75 0.2 + size 112 + secondarySize 116 + chance 0.3 +} + +flickerlight POWCRYS_X3 +{ + color 1.0 0.8 0.4 + size 116 + secondarySize 120 + chance 0.3 +} + +flickerlight POWCRYS_X4 +{ + color 1.0 0.75 0.3 + size 115 + secondarySize 117 + chance 0.3 +} + +flickerlight POWCRYS_X5 +{ + color 1.0 0.7 0.27 + size 114 + secondarySize 113 + chance 0.3 +} + +flickerlight POWCRYS_X6 +{ + color 1.0 0.65 0.24 + size 113 + secondarySize 115 + chance 0.3 +} + +flickerlight POWCRYS_X6 +{ + color 1.0 0.62 0.22 + size 112 + secondarySize 114 + chance 0.3 +} + +flickerlight POWCRYS_X7 +{ + color 1.0 0.6 0.20 + size 111 + secondarySize 113 + chance 0.3 +} + +flickerlight POWCRYS_X8 +{ + color 1.0 0.58 0.18 + size 110 + secondarySize 112 + chance 0.3 +} + +flickerlight POWCRYS_X9 +{ + color 1.0 0.56 0.16 + size 109 + secondarySize 111 + chance 0.3 +} + +flickerlight POWCRYS_X10 +{ + color 1.0 0.54 0.14 + size 108 + secondarySize 110 + chance 0.3 +} + +flickerlight POWCRYS_X11 +{ + color 1.0 0.52 0.12 + size 107 + secondarySize 109 + chance 0.3 +} + +flickerlight POWCRYS_X12 +{ + color 1.0 0.5 0.10 + size 106 + secondarySize 108 + chance 0.3 +} + +flickerlight POWCRYS_X13 +{ + color 1.0 0.48 0.10 + size 105 + secondarySize 106 + chance 0.3 +} + +flickerlight POWCRYS_X14 +{ + color 1.0 0.46 0.08 + size 103 + secondarySize 104 + chance 0.3 +} + +flickerlight POWCRYS_X15 +{ + color 1.0 0.44 0.06 + size 102 + secondarySize 104 + chance 0.3 +} + +flickerlight POWCRYS_X16 +{ + color 1.0 0.42 0.04 + size 101 + secondarySize 103 + chance 0.3 +} + +flickerlight POWCRYS_X15 +{ + color 1.0 0.4 0.02 + size 100 + secondarySize 102 + chance 0.3 +} + +flickerlight POWCRYS_X16 +{ + color 1.0 0.38 0.0 + size 99 + secondarySize 101 + chance 0.3 +} + +flickerlight POWCRYS_X17 +{ + color 1.0 0.36 0.02 + size 98 + secondarySize 100 + chance 0.3 +} + +flickerlight POWCRYS_X18 +{ + color 1.0 0.34 0.0 + size 97 + secondarySize 100 + chance 0.3 +} + +flickerlight POWCRYS_X19 +{ + color 1.0 0.32 0.0 + size 96 + secondarySize 99 + chance 0.3 +} + +flickerlight POWCRYS_X20 +{ + color 1.0 0.3 0.0 + size 95 + secondarySize 98 + chance 0.3 +} + +flickerlight POWCRYS_X21 +{ + color 1.0 0.28 0.0 + size 94 + secondarySize 93 + chance 0.3 +} + +flickerlight POWCRYS_X22 +{ + color 1.0 0.26 0.0 + size 93 + secondarySize 92 + chance 0.3 +} + +flickerlight POWCRYS_X23 +{ + color 1.0 0.24 0.0 + size 92 + secondarySize 91 + chance 0.3 +} + +flickerlight POWCRYS_X24 +{ + color 1.0 0.22 0.0 + size 90 + secondarySize 92 + chance 0.3 +} + +flickerlight POWCRYS_X25 +{ + color 1.0 0.2 0.0 + size 86 + secondarySize 90 + chance 0.3 +} + +object PowerCrystal +{ + frame CRYS { light PCRYSTAL } + + frame CRYSB { light PCRYSTAL1 } + frame CRYSC { light PCRYSTAL2 } + frame CRYSD { light PCRYSTAL3 } + frame CRYSE { light PCRYSTAL4 } + frame CRYSF { light PCRYSTAL5 } + + frame BOOMA { light POWCRYS_X1 } + frame BOOMB { light POWCRYS_X2 } + frame BOOMC { light POWCRYS_X3 } + frame BOOMD { light POWCRYS_X4 } + frame BOOME { light POWCRYS_X5 } + frame BOOMF { light POWCRYS_X6 } + frame BOOMG { light POWCRYS_X7 } + frame BOOMH { light POWCRYS_X8 } + frame BOOMI { light POWCRYS_X9 } + frame BOOMJ { light POWCRYS_X10 } + frame BOOMK { light POWCRYS_X11 } + frame BOOML { light POWCRYS_X12 } + frame BOOMM { light POWCRYS_X13 } + frame BOOMN { light POWCRYS_X14 } + frame BOOMO { light POWCRYS_X15 } + frame BOOMP { light POWCRYS_X16 } + frame BOOMQ { light POWCRYS_X17 } + frame BOOMR { light POWCRYS_X18 } + frame BOOMS { light POWCRYS_X19 } + frame BOOMT { light POWCRYS_X20 } + frame BOOMU { light POWCRYS_X21 } + frame BOOMV { light POWCRYS_X22 } + frame BOOMW { light POWCRYS_X23 } + frame BOOMX { light POWCRYS_X24 } + frame BOOMY { light POWCRYS_X25 } +} + +// Computer +pulselight COMPUTER +{ + color 0.25 1.0 0.25 + size 112 + secondarySize 128 + interval 0.25 + offset 0 64 0 +} + +object Computer +{ + frame SECRA { light COMPUTER } + frame SECRB { light COMPUTER } + frame SECRC { light COMPUTER } + frame SECRD { light COMPUTER } +} + +// Strife Explosive Barrel +flickerlight BARREL_X1 +{ + color 1.0 0.6 0.1 + size 48 + secondarySize 56 + chance 0.3 +} + +flickerlight BARREL_X2 +{ + color 1.0 0.8 0.0 + size 56 + secondarySize 64 + chance 0.3 +} + +flickerlight BARREL_X3 +{ + color 1.0 0.7 0.0 + size 72 + secondarySize 80 + chance 0.3 +} + +flickerlight BARREL_X4 +{ + color 1.0 0.6 0.0 + size 80 + secondarySize 88 + chance 0.3 +} + +flickerlight BARREL_X5 +{ + color 1.0 0.5 0.0 + size 72 + secondarySize 76 + chance 0.3 +} + +flickerlight BARREL_X6 +{ + color 1.0 0.45 0.0 + size 56 + secondarySize 60 + chance 0.3 +} + +flickerlight BARREL_X7 +{ + color 1.0 0.4 0.0 + size 52 + secondarySize 56 + chance 0.3 + offset 0 24 0 +} + +flickerlight BARREL_X8 +{ + color 1.0 0.35 0.0 + size 36 + secondarySize 40 + chance 0.3 + offset 0 40 0 +} + +flickerlight BARREL_X9 +{ + color 1.0 0.3 0.0 + size 16 + secondarySize 24 + chance 0.3 + offset 0 56 0 +} + +object ExplosiveBarrel2 +{ + frame BARTC { light BARREL_X1 } + frame BARTD { light BARREL_X2 } + frame BARTE { light BARREL_X3 } + frame BARTF { light BARREL_X4 } + frame BARTG { light BARREL_X5 } + frame BARTH { light BARREL_X6 } + frame BARTI { light BARREL_X7 } + frame BARTJ { light BARREL_X8 } + frame BARTK { light BARREL_X9 } +} + +// Alarm +pointlight KLAXON +{ + color 1.0 0.0 0.0 + size 24 +} + +object KlaxonWarningLight +{ + frame KLAXC { light KLAXON } +} \ No newline at end of file diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj index 0bdd93ea..7dfd99b4 100644 --- a/Source/Core/Builder.csproj +++ b/Source/Core/Builder.csproj @@ -712,10 +712,14 @@ ConsoleDocker.cs + + + + diff --git a/Source/Core/Builder.sln b/Source/Core/Builder.sln index 9a59c636..87f1bad7 100644 --- a/Source/Core/Builder.sln +++ b/Source/Core/Builder.sln @@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 10.00 # Visual C# Express 2008 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Builder", "Builder.csproj", "{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GZDoomEditing", "..\Plugins\GZDoomEditing\GZDoomEditing.csproj", "{760A9BC7-CB73-4C36-858B-994C14996FCD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -23,6 +25,16 @@ Global {818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|Mixed Platforms.Build.0 = Release|x86 {818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.ActiveCfg = Release|x86 {818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.Build.0 = Release|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Any CPU.ActiveCfg = Debug|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|x86.ActiveCfg = Debug|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|x86.Build.0 = Debug|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Any CPU.ActiveCfg = Release|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.Build.0 = Release|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.ActiveCfg = Release|x86 + {760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Source/Core/Config/GameConfiguration.cs b/Source/Core/Config/GameConfiguration.cs index b5912efc..5bf75cff 100644 --- a/Source/Core/Config/GameConfiguration.cs +++ b/Source/Core/Config/GameConfiguration.cs @@ -29,6 +29,8 @@ using System.Windows.Forms; using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Editing; +using CodeImp.DoomBuilder.GZBuilder.Data; + #endregion namespace CodeImp.DoomBuilder.Config @@ -131,6 +133,9 @@ namespace CodeImp.DoomBuilder.Config // Defaults private List texturesets; private List thingfilters; + + //mxd. Holds base game type (doom, heretic, hexen or strife) + private GameType gameType; #endregion @@ -221,6 +226,9 @@ namespace CodeImp.DoomBuilder.Config // Defaults internal List TextureSets { get { return texturesets; } } public List ThingsFilters { get { return thingfilters; } } + + //mxd + public GameType GameType { get { return gameType; } } #endregion @@ -260,6 +268,10 @@ namespace CodeImp.DoomBuilder.Config // Read general settings configname = cfg.ReadSetting("game", ""); + + //mxd + gameType = (GameType)(cfg.ReadSetting("basegame", (int)GameType.UNKNOWN)); + enginename = cfg.ReadSetting("engine", ""); defaultsavecompiler = cfg.ReadSetting("defaultsavecompiler", ""); defaulttestcompiler = cfg.ReadSetting("defaulttestcompiler", ""); diff --git a/Source/Core/Data/DataManager.cs b/Source/Core/Data/DataManager.cs index bca1ac74..85fe3f1b 100644 --- a/Source/Core/Data/DataManager.cs +++ b/Source/Core/Data/DataManager.cs @@ -32,6 +32,7 @@ using System.Threading; using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Windows; using CodeImp.DoomBuilder.ZDoom; +using CodeImp.DoomBuilder.VisualModes; using CodeImp.DoomBuilder.GZBuilder.Data; using CodeImp.DoomBuilder.GZBuilder.GZDoom; @@ -68,11 +69,10 @@ namespace CodeImp.DoomBuilder.Data private List resourcetextures; private AllTextureSet alltextures; - //mxd Folders - //private List folders; - - //mxd modeldefs - private Dictionary modeldefEntries; + //mxd + private Dictionary modeldefEntries; //Thing.Type, Model entry + private Dictionary gldefsEntries; //Thing.Type, Light entry + private MapInfo mapInfo; //mapinfo // Background loading private Queue imageque; @@ -114,8 +114,9 @@ namespace CodeImp.DoomBuilder.Data #region ================== Properties //mxd - //public List Folders { get { return folders; } } public Dictionary ModeldefEntries { get { return modeldefEntries; } } + public Dictionary GldefsEntries { get { return gldefsEntries; } } + public MapInfo MapInfo { get { return mapInfo; } } public Playpal Palette { get { return palette; } } public PreviewManager Previews { get { return previews; } } @@ -207,6 +208,14 @@ namespace CodeImp.DoomBuilder.Data //thingbox = null; whitetexture.Dispose(); whitetexture = null; + + //mxd + if (modeldefEntries != null) { + foreach (KeyValuePair group in modeldefEntries) + group.Value.Dispose(); + modeldefEntries = null; + } + mapInfo = null; // Done isdisposed = true; @@ -325,7 +334,16 @@ namespace CodeImp.DoomBuilder.Data LoadInternalSprites(); //mxd - loadModeldefs(); + General.MainWindow.DisplayStatus(StatusType.Busy, "Parsing MAPINFO..."); + loadMapInfo(); + Dictionary actorsByClass = createActorsByClassList(); + General.MainWindow.DisplayStatus(StatusType.Busy, "Parsing model definitions..."); + loadModeldefs(actorsByClass); + General.MainWindow.DisplayStatus(StatusType.Busy, "Parsing GLDEFS..."); + loadGldefs(actorsByClass, true); + General.MainWindow.DisplayReady(); + //don't need them any more + actorsByClass = null; // Process colormaps (we just put them in as textures) foreach(KeyValuePair t in colormapsonly) @@ -1354,8 +1372,9 @@ namespace CodeImp.DoomBuilder.Data #endregion - #region ================== Modeldef and models + #region ================== Modeldef, Gldefs, Mapinfo and models loading + //mxd public void LoadModels() { General.MainWindow.DisplayStatus(StatusType.Busy, "Loading models..."); @@ -1365,6 +1384,7 @@ namespace CodeImp.DoomBuilder.Data General.MainWindow.RedrawDisplay(); } + //mxd public bool LoadModelForThing(Thing t) { if (modeldefEntries.ContainsKey(t.Type)) { if (modeldefEntries[t.Type].Model == null) { @@ -1381,11 +1401,11 @@ namespace CodeImp.DoomBuilder.Data currentreader = null; if (mde.Model != null) { - GZBuilder.GZGeneral.LogAndTraceWarning("Loaded model for Thing ¹" + t.Type); + //GZBuilder.GZGeneral.Trace("Loaded model for Thing ¹" + t.Type); return true; } else { modeldefEntries.Remove(t.Type); - GZBuilder.GZGeneral.LogAndTraceWarning("Failed to load model(s) for Thing ¹" + t.Type + ", model(s) location is "+mde.Location+ "\\" + mde.Path +". MODELDEF node removed."); + GZBuilder.GZGeneral.LogAndTraceWarning("Failed to load model" + (mde.ModelNames.Count > 1 ? "s" : "") + " for Thing ¹" + t.Type + " from '"+mde.Location+ "\\" + mde.Path +"'"); return false; } } @@ -1394,25 +1414,83 @@ namespace CodeImp.DoomBuilder.Data return false; } - //mxd. This parses modeldefs. Should be called after all DECORATE actors are parsed - private void loadModeldefs() { - General.MainWindow.DisplayStatus(StatusType.Busy, "Parsing model definitions..."); + //mxd. This creates dictionary. Should be called after all DECORATE actors are parsed + private Dictionary createActorsByClassList() { + Dictionary actors = new Dictionary(); - Dictionary Actors = new Dictionary(); Dictionary things = General.Map.Config.GetThingTypes(); //read our new shiny ClassNames for default game things foreach (KeyValuePair ti in things) { if (ti.Value.ClassName != null) - Actors.Add(ti.Value.ClassName, ti.Key); + actors.Add(ti.Value.ClassName, ti.Key); } //and for actors defined in DECORATE - ICollection ac = decorate.Actors; //General.Map.Data.Decorate.Actors; + ICollection ac = decorate.Actors; foreach (ActorStructure actor in ac) { + if (actor.DoomEdNum == -1) //we don't need actors without DoomEdNum + continue; + string className = actor.ClassName.ToLower(); - if (actor.DoomEdNum != -1 && !Actors.ContainsKey(className)) //we don't need actors without DoomEdNum - Actors.Add(className, actor.DoomEdNum); + if (!actors.ContainsKey(className)) + actors.Add(className, actor.DoomEdNum); + } + + return actors; + } + + //mxd + public void ReloadModeldef() { + if (modeldefEntries != null) { + foreach (KeyValuePair group in modeldefEntries) + group.Value.Dispose(); + } + General.MainWindow.DisplayStatus(StatusType.Busy, "Reloading model definitions..."); + loadModeldefs(createActorsByClassList()); + + //rebuild geometry if in Visual mode + if (General.Editing.Mode != null && General.Editing.Mode.GetType().Name == "BaseVisualMode") { + General.Editing.Mode.OnReloadResources(); + } + + General.MainWindow.DisplayReady(); + } + + //mxd + public void ReloadGldefs() { + General.MainWindow.DisplayStatus(StatusType.Busy, "Reloading GLDEFS..."); + loadGldefs(createActorsByClassList(), false); + + //rebuild geometry if in Visual mode + if (General.Editing.Mode != null && General.Editing.Mode.GetType().Name == "BaseVisualMode") { + General.Editing.Mode.OnReloadResources(); + } + + General.MainWindow.DisplayReady(); + } + + //mxd + public void ReloadMapInfo() { + General.MainWindow.DisplayStatus(StatusType.Busy, "Reloading (Z)MAPINFO..."); + loadMapInfo(); + + //rebuild geometry if in Visual mode + if (General.Editing.Mode != null && General.Editing.Mode.GetType().Name == "BaseVisualMode") { + General.Editing.Mode.OnReloadResources(); + } + + General.MainWindow.DisplayReady(); + } + + //mxd. This parses modeldefs. Should be called after all DECORATE actors are parsed and actorsByClass dictionary created + private void loadModeldefs(Dictionary actorsByClass) { + modeldefEntries = new Dictionary(); //create it in all cases, so we don't have to check if it's null every time we need to access it + + //if no actors defined in DECORATE or game config... + if (actorsByClass == null || actorsByClass.Count == 0) { + GZBuilder.GZGeneral.Trace("Warning: current game has no Actors!"); + return; } Dictionary modelDefEntriesByName = new Dictionary(); @@ -1424,7 +1502,6 @@ namespace CodeImp.DoomBuilder.Data Dictionary streams = dr.GetModeldefData(); foreach (KeyValuePair group in streams) { // Parse the data - group.Value.Seek(0, SeekOrigin.Begin); if (mdeParser.Parse(group.Value, currentreader.Location.location + "\\" + group.Key)) { foreach (KeyValuePair g in mdeParser.ModelDefEntries) { g.Value.Location = currentreader.Location.location; @@ -1435,14 +1512,153 @@ namespace CodeImp.DoomBuilder.Data } currentreader = null; - modeldefEntries = new Dictionary(); foreach (KeyValuePair e in modelDefEntriesByName) { - if (Actors.ContainsKey(e.Key)) - modeldefEntries[Actors[e.Key]] = modelDefEntriesByName[e.Key]; + if (actorsByClass.ContainsKey(e.Key)) + modeldefEntries[actorsByClass[e.Key]] = modelDefEntriesByName[e.Key]; else GZBuilder.GZGeneral.LogAndTraceWarning("Got MODELDEF override for class '" + e.Key + "', but haven't found such class in Decorate"); } + + //dbg + /*foreach (KeyValuePair group in modeldefEntries) { + GZBuilder.GZGeneral.Trace("MDE for thing " + group.Key + ":"); + GZBuilder.GZGeneral.Trace("Name: " + group.Value.ClassName); + GZBuilder.GZGeneral.Trace("Path: " + group.Value.Path); + + foreach (string d in group.Value.ModelNames) + GZBuilder.GZGeneral.Trace("ModelName: " + d); + + foreach (string d in group.Value.TextureNames) + GZBuilder.GZGeneral.Trace("TextureName: " + d); + + GZBuilder.GZGeneral.Trace("Scale: " + group.Value.Scale.X + "," + group.Value.Scale.Y + "," + group.Value.Scale.Z); + GZBuilder.GZGeneral.Trace("zOffset: " + group.Value.zOffset); + }*/ + } + + //mxd. This parses gldefs. Should be called after all DECORATE actors are parsed and actorsByClass dictionary created + private void loadGldefs(Dictionary actorsByClass, bool loadDefaultDefinitions) { + gldefsEntries = new Dictionary();//create it in all cases, so we don't have to check if it's null every time we need to access it + + //if no actors defined in DECORATE or game config... + if (actorsByClass == null || actorsByClass.Count == 0) { + GZBuilder.GZGeneral.Trace("Warning: current game has no Actors!"); + return; + } + + GldefsParser parser = new GldefsParser(); + parser.OnInclude = loadGldefsFromLocation; + + //load default GZDoom gldefs for current game + if (loadDefaultDefinitions && General.Map.Config.GameType != GameType.UNKNOWN) { + string defaultGldefsPath = Gldefs.GLDEFS_LUMPS_PER_GAME[(int)General.Map.Config.GameType].ToLowerInvariant() + ".txt"; + defaultGldefsPath = Path.Combine(Path.Combine(General.AppPath, "Gldefs"), defaultGldefsPath); + + if (File.Exists(defaultGldefsPath)) { + StreamReader s = File.OpenText(defaultGldefsPath); + parser.Parse(s.BaseStream, defaultGldefsPath); + } else { + GZBuilder.GZGeneral.LogAndTraceWarning("Unable to load default GLDEFS for current game: unable to load file '" + defaultGldefsPath + "'"); + } + } else { + GZBuilder.GZGeneral.LogAndTraceWarning("Default GLDEFS for current game not found."); + } + + //load gldefs from resources + foreach (DataReader dr in containers) { + currentreader = dr; + Dictionary streams = dr.GetGldefsData(General.Map.Config.GameType); + + foreach (KeyValuePair group in streams) + parser.Parse(group.Value, group.Key); + } + + //create gldefsEntries dictionary + foreach (KeyValuePair e in parser.Objects) { //ClassName, Light name + + //if we have decorate actor and light definition for given ClassName... + if (actorsByClass.ContainsKey(e.Key) && parser.LightsByName.ContainsKey(e.Value)) { + int thingType = actorsByClass[e.Key]; + if (gldefsEntries.ContainsKey(thingType)) { + gldefsEntries[thingType] = parser.LightsByName[e.Value]; + }else{ + gldefsEntries.Add(thingType, parser.LightsByName[e.Value]); + } + } else { + GZBuilder.GZGeneral.LogAndTraceWarning("Got GLDEFS for class '" + e.Key + "', but haven't found such class in Decorate"); + } + } + + //dbg + GZBuilder.GZGeneral.Trace("******************************************"); + foreach (KeyValuePair group in gldefsEntries) { + if (group.Key == 2015) { + GZBuilder.GZGeneral.Trace("----------------------------------------"); + GZBuilder.GZGeneral.Trace("gldefsEntry for id " + group.Key + ":"); + GZBuilder.GZGeneral.Trace("Color: " + group.Value.Color.Red + "," + group.Value.Color.Green + "," + group.Value.Color.Blue); + GZBuilder.GZGeneral.Trace("PrimaryRadius: " + group.Value.PrimaryRadius); + GZBuilder.GZGeneral.Trace("SecondaryRadius: " + group.Value.SecondaryRadius); + GZBuilder.GZGeneral.Trace("Interval: " + group.Value.Interval); + GZBuilder.GZGeneral.Trace("Offset: " + group.Value.Offset.X + "," + group.Value.Offset.Y + "," + group.Value.Offset.Z); + //GZBuilder.GZGeneral.Trace("Scale: " + group.Value.Scale); + GZBuilder.GZGeneral.Trace("Type: " + group.Value.Type); + //GZBuilder.GZGeneral.Trace("Chance: " + group.Value.Chance); + + GZBuilder.GZGeneral.Trace("Subtractive: " + group.Value.Subtractive); + GZBuilder.GZGeneral.Trace("DontLightSelf: " + group.Value.DontLightSelf); + } + } + } + + //mxd. This loads (Z)MAPINFO + private void loadMapInfo() { + //dbg + //GZBuilder.GZGeneral.Trace("Loading MAPINFO for map " + General.Map.Options.LevelName); + + MapinfoParser parser = new MapinfoParser(); + + foreach (DataReader dr in containers) { + currentreader = dr; + + Dictionary streams = dr.GetMapinfoData(); + foreach (KeyValuePair group in streams) { + // Parse the data + //group.Value.Seek(0, SeekOrigin.Begin); + parser.Parse(group.Value, Path.Combine(currentreader.Location.location, group.Key), General.Map.Options.LevelName); + } + } + currentreader = null; + + if (parser.MapInfo != null) + mapInfo = parser.MapInfo; + else + mapInfo = new MapInfo(); + + //dbg + /*GZBuilder.GZGeneral.Trace("********************************"); + GZBuilder.GZGeneral.Trace("MAPINFO for map " + General.Map.Options.LevelName + ":"); + GZBuilder.GZGeneral.Trace("EvenLighting: " + mapInfo.EvenLighting); + GZBuilder.GZGeneral.Trace("HasFadeColor: " + mapInfo.HasFadeColor); + GZBuilder.GZGeneral.Trace("FadeColor: " + mapInfo.FadeColor.Red + "," + mapInfo.FadeColor.Green + "," + mapInfo.FadeColor.Blue); + GZBuilder.GZGeneral.Trace("HasOutsideFogColor: " + mapInfo.HasOutsideFogColor); + GZBuilder.GZGeneral.Trace("OutsideFogColor: " + mapInfo.OutsideFogColor.Red + "," + mapInfo.OutsideFogColor.Green + "," + mapInfo.OutsideFogColor.Blue); + GZBuilder.GZGeneral.Trace("Sky1: " + mapInfo.Sky1); + GZBuilder.GZGeneral.Trace("Sky1ScrollSpeed: " + mapInfo.Sky1ScrollSpeed); + GZBuilder.GZGeneral.Trace("Sky2: " + mapInfo.Sky2); + GZBuilder.GZGeneral.Trace("Sky2ScrollSpeed: " + mapInfo.Sky2ScrollSpeed); + GZBuilder.GZGeneral.Trace("DoubleSky: " + mapInfo.DoubleSky); + //GZBuilder.GZGeneral.Trace("SmoothLighting: " + mapInfo.SmoothLighting); + GZBuilder.GZGeneral.Trace("HorizWallShade: " + mapInfo.HorizWallShade); + GZBuilder.GZGeneral.Trace("VertWallShade: " + mapInfo.VertWallShade); + GZBuilder.GZGeneral.Trace("********************************");*/ + } + + private void loadGldefsFromLocation(GldefsParser parser, string location) { + Dictionary streams = currentreader.GetGldefsData(location); + + foreach (KeyValuePair group in streams) + parser.Parse(group.Value, group.Key); } #endregion diff --git a/Source/Core/Data/DataReader.cs b/Source/Core/Data/DataReader.cs index 0cecb7b1..f8afb602 100644 --- a/Source/Core/Data/DataReader.cs +++ b/Source/Core/Data/DataReader.cs @@ -27,6 +27,7 @@ using System.IO; using CodeImp.DoomBuilder.Config; using CodeImp.DoomBuilder.IO; using CodeImp.DoomBuilder.Rendering; +using CodeImp.DoomBuilder.GZBuilder.Data; #endregion @@ -151,14 +152,21 @@ namespace CodeImp.DoomBuilder.Data #endregion - #region ================== Decorate + #region ================== Decorate, Modeldef, Mapinfo, Gldefs // When implemented, this returns the decorate lump public virtual List GetDecorateData(string pname) { return new List(); } - //mxd. When implemented, this returns the modeldef lump + //mxd. When implemented, this returns the Modeldef lump public virtual Dictionary GetModeldefData() { return new Dictionary(); } + //mxd. When implemented, this returns the Mapinfo lump + public virtual Dictionary GetMapinfoData() { return new Dictionary(); } + + //mxd. When implemented, this returns the Gldefs lump + public virtual Dictionary GetGldefsData(GameType gameType) { return new Dictionary(); } + public virtual Dictionary GetGldefsData(string location) { return new Dictionary(); } + #endregion } } diff --git a/Source/Core/Data/PK3StructuredReader.cs b/Source/Core/Data/PK3StructuredReader.cs index af3cbcc1..8fdaebde 100644 --- a/Source/Core/Data/PK3StructuredReader.cs +++ b/Source/Core/Data/PK3StructuredReader.cs @@ -25,6 +25,7 @@ using System.Drawing; using System.Drawing.Imaging; using System.IO; using CodeImp.DoomBuilder.IO; +using CodeImp.DoomBuilder.GZBuilder.Data; #endregion @@ -440,6 +441,74 @@ namespace CodeImp.DoomBuilder.Data #endregion + #region ================== (Z)MAPINFO + + //mxd + public override Dictionary GetMapinfoData() { + Dictionary streams = new Dictionary(); + // Error when suspended + if (issuspended) throw new Exception("Data reader is suspended"); + + //mapinfo should be in root folder + string[] allFiles = GetAllFiles("", false); + string fileName; + + //try to find (z)mapinfo + foreach (string s in allFiles) { + fileName = s.ToLowerInvariant(); + if (fileName.IndexOf("zmapinfo") != -1 || fileName.IndexOf("mapinfo") != -1) + streams.Add(s, LoadFile(s)); + } + + return streams; + } + + #endregion + + #region ================== GLDEFS + + //mxd + public override Dictionary GetGldefsData(GameType gameType) { + Dictionary streams = new Dictionary(); + // Error when suspended + if (issuspended) throw new Exception("Data reader is suspended"); + + //at least one of gldefs should be in root folder + string[] allFiles = GetAllFiles("", false); + + //try to load game specific GLDEFS first + string lumpName = Gldefs.GLDEFS_LUMPS_PER_GAME[(int)gameType].ToLowerInvariant(); + foreach (string s in allFiles) { + if (s.ToLowerInvariant().IndexOf(lumpName) != -1) + streams.Add(s, LoadFile(s)); + } + + //can be several entries + lumpName = "gldefs"; + foreach (string s in allFiles) { + if (s.ToLowerInvariant().IndexOf(lumpName) != -1) + streams.Add(s, LoadFile(s)); + } + + return streams; + } + + //mxd + public override Dictionary GetGldefsData(string location) { + Dictionary streams = new Dictionary(); + // Error when suspended + if (issuspended) throw new Exception("Data reader is suspended"); + + Stream s = LoadFile(location); + + if (s != null) + streams.Add(location, s); + + return streams; + } + + #endregion + #region ================== Methods // This loads the images in this directory diff --git a/Source/Core/Data/WADReader.cs b/Source/Core/Data/WADReader.cs index 80d77c21..b37aa74d 100644 --- a/Source/Core/Data/WADReader.cs +++ b/Source/Core/Data/WADReader.cs @@ -27,6 +27,7 @@ using System.IO; using CodeImp.DoomBuilder.IO; using CodeImp.DoomBuilder.ZDoom; using CodeImp.DoomBuilder.Rendering; +using CodeImp.DoomBuilder.GZBuilder.Data; #endregion @@ -793,7 +794,7 @@ namespace CodeImp.DoomBuilder.Data #endregion - #region ================== Things + #region ================== Decorate, Gldefs, Mapinfo // This finds and returns a sprite stream public override List GetDecorateData(string pname) @@ -816,6 +817,71 @@ namespace CodeImp.DoomBuilder.Data return streams; } + + //mxd + public override Dictionary GetMapinfoData() { + if (issuspended) throw new Exception("Data reader is suspended"); + + Dictionary streams = new Dictionary(); + int lumpindex; + string src = "ZMAPINFO"; + + //should be only one entry per wad + //first look for ZMAPINFO + lumpindex = file.FindLumpIndex(src); + + //then for MAPINFO + if (lumpindex == -1) { + src = "MAPINFO"; + lumpindex = file.FindLumpIndex(src); + } + + if(lumpindex != -1) + streams.Add(src, file.Lumps[lumpindex].Stream); + + return streams; + } + + //mxd + public override Dictionary GetGldefsData(GameType gameType) { + if (issuspended) throw new Exception("Data reader is suspended"); + + Dictionary streams = new Dictionary(); + int lumpindex; + + //try to load game specific GLDEFS first + if (gameType != GameType.UNKNOWN) { + string lumpName = Gldefs.GLDEFS_LUMPS_PER_GAME[(int)gameType]; + lumpindex = file.FindLumpIndex(lumpName); + + if (lumpindex != -1) + streams.Add(lumpName, file.Lumps[lumpindex].Stream); + } + + //should be only one entry per wad + lumpindex = file.FindLumpIndex("GLDEFS"); + + if (lumpindex != -1) + streams.Add("GLDEFS", file.Lumps[lumpindex].Stream); + + return streams; + } + + //mxd + public override Dictionary GetGldefsData(string location) { + if (issuspended) throw new Exception("Data reader is suspended"); + + Dictionary streams = new Dictionary(); + int lumpindex; + + lumpindex = file.FindLumpIndex(location); + + if (lumpindex != -1) + streams.Add(location, file.Lumps[lumpindex].Stream); + + return streams; + } + #endregion } } diff --git a/Source/Core/GZBuilder/Data/GZDoomLight.cs b/Source/Core/GZBuilder/Data/GZDoomLight.cs index c680c4ae..9457554f 100644 --- a/Source/Core/GZBuilder/Data/GZDoomLight.cs +++ b/Source/Core/GZBuilder/Data/GZDoomLight.cs @@ -1,18 +1,64 @@ -//using SlimDX; +using System; +using SlimDX; namespace CodeImp.DoomBuilder.GZBuilder.Data { - /*public struct GZDoomLight - { + public class GZDoomLight { + public int Type; //holds GZDoomLightType public Color3 Color; - public Vector4 PosAndRadius; - public int MinRadius; - public int MaxRadius; - public int Type; //listed in GZDoomLightType - public int RenderStyle; //normal, additive, negative - public int CameraDistance; - public float AnimationSpeed; - }*/ + public int PrimaryRadius; + public int SecondaryRadius; + public int Interval; + public Vector3 Offset; + public bool Subtractive; + public bool DontLightSelf; + + public GZDoomLight() { + Color = new Color3(); + Offset = new Vector3(); + } + + public static int[] GetDefaultLightSettings(int type) { + int light_id = Array.IndexOf(GZBuilder.GZGeneral.GZ_LIGHTS, type); + if (light_id != -1) { + int[] args = new int[5]; + + if (light_id == (int)GZDoomLightType.VAVOOM_COLORED) { + args[0] = 16; + args[1] = 255; + args[2] = 255; + args[3] = 255; + } else if (light_id == (int)GZDoomLightType.VAVOOM) { + args[0] = 16; + } else { + int n; + if (light_id < GZBuilder.GZGeneral.GZ_LIGHT_TYPES[0]) { + n = 0; + } else if (light_id < GZBuilder.GZGeneral.GZ_LIGHT_TYPES[1]) { + n = 10; + } else { + n = 20; + } + light_id = type - 9800 - n; + + args[0] = 255; + args[1] = 255; + args[2] = 255; + + if (light_id == (int)GZDoomLightType.SECTOR) + args[3] = 4; + else + args[3] = 64; + + if (Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, light_id) != -1) { + args[4] = 32; + } + } + return args; + } + return null; + } + } public enum GZDoomLightType : int { @@ -22,7 +68,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data SECTOR = 3, RANDOM = 4, VAVOOM = 1502, - VAVOOM_COLORED = 1503 + VAVOOM_COLORED = 1503, } //divide these by 100 to get light color alpha @@ -31,6 +77,6 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data NORMAL = 99, VAVOOM = 50, ADDITIVE = 25, - NEGATIVE = 100 + NEGATIVE = 100, } } diff --git a/Source/Core/GZBuilder/Data/GameType.cs b/Source/Core/GZBuilder/Data/GameType.cs new file mode 100644 index 00000000..2e086c5e --- /dev/null +++ b/Source/Core/GZBuilder/Data/GameType.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace CodeImp.DoomBuilder.GZBuilder.Data { + public enum GameType : int { + DOOM = 0, + HERETIC = 1, + HEXEN = 2, + STRIFE = 3, + UNKNOWN = 4, + } + + public struct Gldefs { + public static string[] GLDEFS_LUMPS_PER_GAME = { "DOOMDEFS", "HTICDEFS", "HEXNDEFS", "STRFDEFS" }; + } +} diff --git a/Source/Core/GZBuilder/Data/MapInfo.cs b/Source/Core/GZBuilder/Data/MapInfo.cs new file mode 100644 index 00000000..ee556f8b --- /dev/null +++ b/Source/Core/GZBuilder/Data/MapInfo.cs @@ -0,0 +1,27 @@ +using System; +using SlimDX; +using SlimDX.Direct3D9; + +namespace CodeImp.DoomBuilder.GZBuilder.Data { + public class MapInfo { + public string Sky1; + public float Sky1ScrollSpeed; + public string Sky2; + public float Sky2ScrollSpeed; + public bool DoubleSky; + public bool HasFadeColor; + public Color4 FadeColor; + public bool HasOutsideFogColor; + public Color4 OutsideFogColor; + + public bool EvenLighting; + public bool SmoothLighting; + public int VertWallShade; + public int HorizWallShade; + + public MapInfo() { + VertWallShade = 16; + HorizWallShade = -16; + } + } +} diff --git a/Source/Core/GZBuilder/Data/TextureData.cs b/Source/Core/GZBuilder/Data/TextureData.cs new file mode 100644 index 00000000..2cbd3e9b --- /dev/null +++ b/Source/Core/GZBuilder/Data/TextureData.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace CodeImp.DoomBuilder.GZBuilder.Data { + public struct TextureData { + public const string INVALID_TEXTURE = "**INVALID_TEXTURE**"; + public static string[] SUPPORTED_TEXTURE_EXTENSIONS = { ".jpg", ".tga", ".png", ".dds" }; + } +} diff --git a/Source/Core/GZBuilder/GZDoom/GldefsParser.cs b/Source/Core/GZBuilder/GZDoom/GldefsParser.cs index 4cb07a72..711d8b7b 100644 --- a/Source/Core/GZBuilder/GZDoom/GldefsParser.cs +++ b/Source/Core/GZBuilder/GZDoom/GldefsParser.cs @@ -5,52 +5,80 @@ using System.Globalization; using System.Text; using CodeImp.DoomBuilder.ZDoom; +using CodeImp.DoomBuilder.GZBuilder.Data; using SlimDX; using SlimDX.Direct3D9; namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { public class GldefsParser : ZDTextParser { - private Dictionary gldefsEntries; - public Dictionary GldefsEntries { get { return gldefsEntries; } } - public string Source { get { return sourcename; } } + + public delegate void IncludeDelegate(GldefsParser parser, string includefile); + public IncludeDelegate OnInclude; + + private Dictionary lightsByName; //LightName, light definition + private Dictionary objects; //ClassName, LightName + + public Dictionary LightsByName { get { return lightsByName; } } + public Dictionary Objects { get { return objects; } } + + private List parsedLumps; + + private struct GldefsLightType { + public const string POINT = "pointlight"; + public const string PULSE = "pulselight"; + public const string FLICKER = "flickerlight"; + public const string FLICKER2 = "flickerlight2"; + public const string SECTOR = "sectorlight"; + + public static Dictionary GLDEFS_TO_GZDOOM_LIGHT_TYPE = new Dictionary() { { POINT, 0 }, { PULSE, 1 }, { FLICKER, 2 }, { FLICKER2, 4 }, { SECTOR, 3 } }; + } + + public GldefsParser() { + parsedLumps = new List(); + lightsByName = new Dictionary(); //LightName, Light params + objects = new Dictionary(); //ClassName, LightName + } public override bool Parse(Stream stream, string sourcefilename) { base.Parse(stream, sourcefilename); - gldefsEntries = new Dictionary(); - Dictionary lightsByName = new Dictionary(); - List objects = new List(); + if (parsedLumps.IndexOf(sourcefilename) != -1) { + GZBuilder.GZGeneral.LogAndTraceWarning("Error: already parsed '" + sourcefilename + "'. Check your #include directives!"); + return false; + } + parsedLumps.Add(sourcefilename); + + // Keep local data + Stream localstream = datastream; + string localsourcename = sourcename; + BinaryReader localreader = datareader; // Continue until at the end of the stream while (SkipWhitespace(true)) { string token = ReadToken(); if (!string.IsNullOrEmpty(token)) { - token = token.ToLowerInvariant(); + token = StripTokenQuotes(token.ToLowerInvariant()); //Quotes can be anywhere! ANYWHERE!!! And GZDoom will still parse data correctly //got light structure if (token == GldefsLightType.POINT || token == GldefsLightType.PULSE || token == GldefsLightType.FLICKER || token == GldefsLightType.FLICKER2 || token == GldefsLightType.SECTOR) { bool gotErrors = false; - string lightType = token; //todo: set correct type - GldefsLight light = new GldefsLight(); + string lightType = token; + + GZDoomLight light = new GZDoomLight(); + light.Type = GldefsLightType.GLDEFS_TO_GZDOOM_LIGHT_TYPE[lightType]; //find classname SkipWhitespace(true); - string lightName = ReadToken().ToLowerInvariant(); + string lightName = StripTokenQuotes(ReadToken()).ToLowerInvariant(); if (!string.IsNullOrEmpty(lightName)) { - if (lightsByName.ContainsKey(lightName)) { - GZBuilder.GZGeneral.LogAndTraceWarning("Already got light '" + lightName + "'; entry skipped"); - continue; //already got this light; continue to next one - } - //now find opening brace SkipWhitespace(true); token = ReadToken(); if (token != "{") { - //Form1.Trace("Unexpected token found in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected '{', but got " + token); - GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected '{', but got " + token); - continue; //something wrong with modeldef declaration, continue to next one + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected '{', but got " + token); + continue; //something wrong with gldefs declaration, continue to next one } //read gldefs light structure @@ -59,11 +87,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { if (!string.IsNullOrEmpty(token)) { token = token.ToLowerInvariant(); - //color +//color if (token == "color") { SkipWhitespace(true); - token = ReadToken(); + token = StripTokenQuotes(ReadToken()); if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Red)) { // Not numeric! GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Red Color value, but got '" + token + "'"); @@ -73,7 +101,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { SkipWhitespace(true); - token = ReadToken(); + token = StripTokenQuotes(ReadToken()); if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Green)) { // Not numeric! GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Green Color value, but got '" + token + "'"); @@ -83,30 +111,38 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { SkipWhitespace(true); - token = ReadToken(); + token = StripTokenQuotes(ReadToken()); if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Blue)) { // Not numeric! GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Blue Color value, but got '" + token + "'"); gotErrors = true; break; } - //size +//size } else if (token == "size") { - SkipWhitespace(true); + if (lightType != GldefsLightType.SECTOR) { + SkipWhitespace(true); - token = ReadToken(); - if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.Size)) { - // Not numeric! - GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Size value, but got '" + token + "'"); + token = StripTokenQuotes(ReadToken()); + if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.PrimaryRadius)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Size value, but got '" + token + "'"); + gotErrors = true; + break; + } + light.PrimaryRadius *= 2; + + } else { + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType); gotErrors = true; break; } - //offset +//offset } else if (token == "offset") { SkipWhitespace(true); - token = ReadToken(); - if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Offset.X)) { + token = StripTokenQuotes(ReadToken()); + if (!ReadSignedFloat(token, ref light.Offset.X)) { // Not numeric! GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset X value, but got '" + token + "'"); gotErrors = true; @@ -115,28 +151,28 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { SkipWhitespace(true); - token = ReadToken(); - if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Offset.Y)) { + token = StripTokenQuotes(ReadToken()); + if (!ReadSignedFloat(token, ref light.Offset.Z)) { // Not numeric! - GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset Y value, but got '" + token + "'"); + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset X value, but got '" + token + "'"); gotErrors = true; break; } SkipWhitespace(true); - token = ReadToken(); - if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Offset.Z)) { + token = StripTokenQuotes(ReadToken()); + if (!ReadSignedFloat(token, ref light.Offset.Y)) { // Not numeric! - GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset Z value, but got '" + token + "'"); + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset X value, but got '" + token + "'"); gotErrors = true; break; } - //subtractive +//subtractive } else if (token == "subtractive") { SkipWhitespace(true); - token = ReadToken(); + token = StripTokenQuotes(ReadToken()); int i; if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) { // Not numeric! @@ -146,11 +182,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { } light.Subtractive = i == 1; - //dontlightself +//dontlightself } else if (token == "dontlightself") { SkipWhitespace(true); - token = ReadToken(); + token = StripTokenQuotes(ReadToken()); int i; if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) { // Not numeric! @@ -159,74 +195,136 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { break; } - light.DontLightSelf = i == 1; - //interval - } else if (token == "interval" && (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER2)) { - SkipWhitespace(true); + light.DontLightSelf = (i == 1); +//interval + } else if (token == "interval") { + if (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER2) { + SkipWhitespace(true); - token = ReadToken(); - if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Interval)) { - // Not numeric! - GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Interval value, but got '" + token + "'"); + token = StripTokenQuotes(ReadToken()); + float interval; + if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out interval)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Interval value, but got '" + token + "'"); + gotErrors = true; + break; + } + + //I wrote logic for dynamic lights animation first, so here I modify gldefs settings to fit in existing logic + if (lightType == GldefsLightType.PULSE) { + light.Interval = (int)(interval * 35); //measured in tics (35 per second) in PointLightPulse, measured in seconds in gldefs' PulseLight + } else { //FLICKER2. Seems like PointLightFlickerRandom to me + light.Interval = (int)(interval * 350); //0.1 is one second for FlickerLight2 + } + } else { + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '"+token+"' is not valid property for " + lightType); gotErrors = true; break; } - //todo: modify Interval based on light type +//secondarysize + } else if (token == "secondarysize") { + if (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER || lightType == GldefsLightType.FLICKER2) { + SkipWhitespace(true); - //secondarysize - } else if (token == "secondarysize" && (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER || lightType == GldefsLightType.FLICKER2)) { - SkipWhitespace(true); + token = StripTokenQuotes(ReadToken()); + if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.SecondaryRadius)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected SecondarySize value, but got '" + token + "'"); + gotErrors = true; + break; + } + light.SecondaryRadius *= 2; - token = ReadToken(); - if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.SecondarySize)) { - // Not numeric! - GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected SecondarySize value, but got '" + token + "'"); + } else { + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType); gotErrors = true; break; } - //chance - } else if (token == "chance" && lightType == GldefsLightType.FLICKER) { - SkipWhitespace(true); +//chance + } else if (token == "chance") { + if (lightType == GldefsLightType.FLICKER) { + SkipWhitespace(true); - token = ReadToken(); - if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Chance)) { - // Not numeric! - GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Chance value, but got '" + token + "'"); + token = StripTokenQuotes(ReadToken()); + float chance; + if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out chance)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Chance value, but got '" + token + "'"); + gotErrors = true; + break; + } + + //transforming from 0.0 .. 1.0 to 0 .. 359 to fit in existing logic + light.Interval = (int)(chance * 359.0f); + } else { + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType); gotErrors = true; break; } - //scale - } else if (token == "scale" && lightType == GldefsLightType.SECTOR) { - SkipWhitespace(true); +//scale + } else if (token == "scale") { + if (lightType == GldefsLightType.SECTOR) { + SkipWhitespace(true); - token = ReadToken(); - if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Scale)) { - // Not numeric! - GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Scale value, but got '" + token + "'"); + token = StripTokenQuotes(ReadToken()); + float scale; + if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Scale value, but got '" + token + "'"); + gotErrors = true; + break; + } + + if (scale < 0.0f || scale > 1.0f) { + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": scale must be in 0.0 - 1.0 range, but is " + scale); + gotErrors = true; + break; + } + + //sector light doesn't have animation, so we will store it's size in Interval + //transforming from 0.0 .. 1.0 to 0 .. 10 to preserve value. + light.Interval = (int)(scale * 10.0f); + } else { + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType); gotErrors = true; break; } - if (light.Scale < 0 || light.Scale > 1) { - GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": scale must be in 0.0 - 1.0 range, but is " + light.Scale); - gotErrors = true; - break; - } //end of structure } else if (token == "}") { if (!gotErrors) { - //check light - bool valid = true; + //general checks if (light.Color.Red == 0.0f && light.Color.Green == 0.0f && light.Color.Blue == 0.0f) { - GZBuilder.GZGeneral.LogAndTraceWarning("'" + lightName + "' light Color is 0,0,0. It won't be shown in GZDoom!"); - valid = false; - } - if (light.Size == 0) { - GZBuilder.GZGeneral.LogAndTraceWarning("'" + lightName + "' light Size is 0. It won't be shown in GZDoom!"); - valid = false; + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": light Color is " + light.Color.Red + "," + light.Color.Green + "," + light.Color.Blue + ". It won't be shown in GZDoom!"); + gotErrors = true; } - if (valid) lightsByName.Add(lightName, light); + //light-type specific checks + if (light.Type == (int)GZDoomLightType.NORMAL) { + if (light.PrimaryRadius == 0) { + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": light Size is 0. It won't be shown in GZDoom!"); + gotErrors = true; + } + } + + if (light.Type == (int)GZDoomLightType.FLICKER || light.Type == (int)GZDoomLightType.PULSE || light.Type == (int)GZDoomLightType.RANDOM) { + if (light.PrimaryRadius == 0 && light.SecondaryRadius == 0) { + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": 'Size' and 'SecondarySize' are 0. This light won't be shown in GZDoom!"); + gotErrors = true; + } + } + + //offset it slightly to avoid shading glitches + if (light.Offset.Y == 0) + light.Offset.Y = 0.1f; + + if (!gotErrors) { + if (lightsByName.ContainsKey(lightName)) { + lightsByName[lightName] = light; + } else { + lightsByName.Add(lightName, light); + } + } } break; //break out of this parsing loop } @@ -238,58 +336,68 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { SkipWhitespace(true); //read object class - string objectClass = ReadToken().ToLowerInvariant(); + string objectClass = StripTokenQuotes(ReadToken()).ToLowerInvariant(); if (!string.IsNullOrEmpty(objectClass)) { - if (objects.Contains(objectClass)) { - GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": already got object '" + objectClass + "'; entry skipped"); - continue; //already got this object; continue to next one - } - - objects.Add(objectClass); - //now find opening brace SkipWhitespace(true); token = ReadToken(); + if (token != "{") { - GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected '{', but got " + token); + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected '{', but got " + token); continue; } + int bracesCount = 1; + bool foundLight = false; + //read frames structure while (SkipWhitespace(true)) { token = ReadToken(); if (!string.IsNullOrEmpty(token)) { - token = token.ToLowerInvariant(); + token = StripTokenQuotes(token).ToLowerInvariant(); - if (token == "light") { //just use first light from first frame and be done with it + if (!foundLight && token == "light") { //just use first light from first frame and be done with it SkipWhitespace(true); token = ReadToken().ToLowerInvariant(); //should be light name if (!string.IsNullOrEmpty(token)) { if (lightsByName.ContainsKey(token)) { - gldefsEntries.Add(objectClass, lightsByName[token]); + if (objects.ContainsKey(objectClass)) + objects[objectClass] = token; + else + objects.Add(objectClass, token); + foundLight = true; } else { - GZBuilder.GZGeneral.LogAndTraceWarning("Light declaration not found for light '" + token + "' in '" + sourcefilename+"'"); + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": light declaration not found for light '" + token + "'"); } - break; } + } else if (token == "{") { //continue in this loop until object structure ends + bracesCount++; + } else if (token == "}") { + if (--bracesCount <= 0) + break; //This was Cave Johnson. And we are done here. } - } } - } } else if (token == "#include") { SkipWhitespace(true); string includeLump = StripTokenQuotes(ReadToken()).ToLowerInvariant(); - if (!string.IsNullOrEmpty(includeLump) && includeLump.IndexOf(".gl") != -1) { - //todo: load included file. check for recursive includes? + if (!string.IsNullOrEmpty(includeLump)) { + // Callback to parse this file + if (OnInclude != null) + OnInclude(this, includeLump.Replace("/", "\\")); + + // Set our buffers back to continue parsing + datastream = localstream; + datareader = localreader; + sourcename = localsourcename; } else { - GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": got #include directive with missing or incorrect include path: '" + includeLump + "'"); + GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": got #include directive with missing or incorrect path: '" + includeLump + "'"); } } else { @@ -314,35 +422,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { } } - if (gldefsEntries.Count > 0) + if (objects.Count > 0) return true; return false; } } - - public class GldefsLight { - public int Type; - public Color3 Color; - public int Size; - public int SecondarySize; - public float Interval; - public Vector3 Offset; - public float Chance; - public float Scale; - public bool Subtractive; - public bool DontLightSelf; - - public GldefsLight() { - Color = new Color3(); - Offset = new Vector3(); - } - } - - public struct GldefsLightType { - public const string POINT = "pointlight"; - public const string PULSE = "pulselight"; - public const string FLICKER = "flickerlight"; - public const string FLICKER2 = "flickerlight2"; - public const string SECTOR = "sectorlight"; - } -} +} \ No newline at end of file diff --git a/Source/Core/GZBuilder/GZDoom/MapinfoParser.cs b/Source/Core/GZBuilder/GZDoom/MapinfoParser.cs new file mode 100644 index 00000000..f60223dc --- /dev/null +++ b/Source/Core/GZBuilder/GZDoom/MapinfoParser.cs @@ -0,0 +1,348 @@ +using System; +using System.Drawing; +using System.Globalization; +using System.IO; +using System.Collections.Generic; +using System.Text; + +using SlimDX; +using SlimDX.Direct3D9; + +using CodeImp.DoomBuilder.ZDoom; +using CodeImp.DoomBuilder.GZBuilder.Data; + +namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { + public class MapinfoParser : ZDTextParser { + + private MapInfo mapInfo; + public MapInfo MapInfo { get { return mapInfo; } } + + public bool Parse(Stream stream, string sourcefilename, string mapName) { + base.Parse(stream, sourcefilename); + + mapName = mapName.ToLowerInvariant(); + mapInfo = new MapInfo(); + + while (SkipWhitespace(true)) { + string token = ReadToken(); + if (token != null) { + token = token.ToLowerInvariant(); + + if (parseBlock(token, mapName)) + break; + } + } + + //check values + if (mapInfo.FadeColor != null && (mapInfo.FadeColor.Red > 0 || mapInfo.FadeColor.Green > 0 || mapInfo.FadeColor.Blue > 0)) + mapInfo.HasFadeColor = true; + + if (mapInfo.OutsideFogColor != null && (mapInfo.OutsideFogColor.Red > 0 || mapInfo.OutsideFogColor.Green > 0 || mapInfo.OutsideFogColor.Blue > 0)) + mapInfo.HasOutsideFogColor = true; + + //Cannot fail here + return true; + } + + //returns true if parsing is finished + private bool parseBlock(string token, string mapName) { + string curBlockName; + mapName = mapName.ToLowerInvariant(); + + if (token == "map" || token == "defaultmap" || token == "adddefaultmap") { + curBlockName = token; + + if (token == "map") { //check map name + //get map name + SkipWhitespace(true); + token = ReadToken().ToLowerInvariant(); + + if (token != mapName) + return false; //not finished, search for next "map", "defaultmap" or "adddefaultmap" block + } else if (token == "defaultmap") { + //reset MapInfo + mapInfo = new MapInfo(); + } + + //search for required keys + while (SkipWhitespace(true)) { + token = ReadToken().ToLowerInvariant(); + + //sky1 or sky2 + if (token == "sky1" || token == "sky2") { + //Form1.Trace("Got sky " + token); + + string skyType = token; + SkipWhitespace(true); + token = StripTokenQuotes(ReadToken()).ToLowerInvariant(); + + //new format + if (token == "=") { + SkipWhitespace(true); + + //should be sky texture name + token = StripTokenQuotes(ReadToken()); + bool gotComma = (token.IndexOf(",") != -1); + if (gotComma) + token = token.Replace(",", ""); + string skyTexture = StripTokenQuotes(token).ToLowerInvariant(); + + if (!string.IsNullOrEmpty(skyTexture)) { + if (skyType == "sky1") + mapInfo.Sky1 = skyTexture; + else + mapInfo.Sky2 = skyTexture; + + //check if we have scrollspeed + SkipWhitespace(true); + token = StripTokenQuotes(ReadToken()); + + if (!gotComma && token == ",") { + gotComma = true; + SkipWhitespace(true); + token = ReadToken(); + } + + if (gotComma) { + float scrollSpeed = 0; + + /*if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scrollSpeed)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + skyType + " scroll speed value, but got '" + token + "'"); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + continue; + }*/ + + if (!ReadSignedFloat(token, ref scrollSpeed)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + skyType + " scroll speed value, but got '" + token + "'"); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + continue; + } + + if (skyType == "sky1") + mapInfo.Sky1ScrollSpeed = scrollSpeed; + else + mapInfo.Sky2ScrollSpeed = scrollSpeed; + } else { + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + } + } else { + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + skyType + " texture name."); + } + //old format + } else { + //token should be sky1/2 name + if (!string.IsNullOrEmpty(token)) { + if (skyType == "sky1") + mapInfo.Sky1 = token; + else + mapInfo.Sky2 = token; + + //try to read scroll speed + SkipWhitespace(true); + token = StripTokenQuotes(ReadToken()); + + float scrollSpeed = 0; + /*if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scrollSpeed)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + skyType + " scroll speed value, but got '" + token + "'"); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + continue; + }*/ + if (!ReadSignedFloat(token, ref scrollSpeed)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + skyType + " scroll speed value, but got '" + token + "'"); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + continue; + } + + if (skyType == "sky1") + mapInfo.Sky1ScrollSpeed = scrollSpeed; + else + mapInfo.Sky2ScrollSpeed = scrollSpeed; + + } else { + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + skyType + " texture name."); + } + } + //fade or outsidefog + } else if (token == "fade" || token == "outsidefog") { + string fadeType = token; + SkipWhitespace(true); + token = StripTokenQuotes(ReadToken()).ToLowerInvariant(); + + //new format + if (token == "=") { + SkipWhitespace(true); + + //red color value or color name... + token = ReadToken(); + string colorVal = StripTokenQuotes(token).ToLowerInvariant(); + if (!string.IsNullOrEmpty(colorVal)) { + Color4 color = new Color4(); + //color.Alpha = 1.0f; + + //is it color name? + if (getColorByName(colorVal, ref color)) { + if (fadeType == "fade") + mapInfo.FadeColor = color; + else + mapInfo.OutsideFogColor = color; + } else { //no, it's not + //try to get color values + int r, g, b; + string[] parts = colorVal.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); + + if (parts.Length != 3) { + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " color values, but got '" + token + "'"); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + continue; + } + + if (!int.TryParse(parts[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out r)) { + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " red value, but got '" + parts[0] + "'"); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + continue; + } + if (!int.TryParse(parts[1], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out g)) { + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " green value, but got '" + parts[1] + "'"); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + continue; + } + if (!int.TryParse(parts[2], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out b)) { + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " blue value, but got '" + parts[2] + "'"); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + continue; + } + + color.Red = (float)r / 255; + color.Green = (float)g / 255; + color.Blue = (float)b / 255; + + if (fadeType == "fade") + mapInfo.FadeColor = color; + else + mapInfo.OutsideFogColor = color; + } + } else { + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " color value."); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + } + + //old format + } else { + //token should contain red color value or color name... + if (!string.IsNullOrEmpty(token)) { + int r, g, b; + Color4 color = new Color4(); + + if (!int.TryParse(token, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out r)) { + //Not numeric! Maybe it's a color name? + if (getColorByName(token, ref color)) { + if (fadeType == "fade") + mapInfo.FadeColor = color; + else + mapInfo.OutsideFogColor = color; + } else { + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + } + continue; + } + + SkipWhitespace(true); + token = ReadToken(); + + //should be color, let's continue parsing it. + if (!int.TryParse(token, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out g)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " green value, but got '" + token + "'"); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + continue; + } + + SkipWhitespace(true); + token = StripTokenQuotes(ReadToken()); + + if (!int.TryParse(token, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out b)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " blue value, but got '" + token + "'"); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + continue; + } + + color.Red = (float)r / 255; + color.Green = (float)g / 255; + color.Blue = (float)b / 255; + + if (fadeType == "fade") + mapInfo.FadeColor = color; + else + mapInfo.OutsideFogColor = color; + + } else { + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + fadeType + " color value."); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + } + } + //vertwallshade or horizwallshade + } else if (token == "vertwallshade" || token == "horizwallshade") { + string shadeType = token; + SkipWhitespace(true); + token = StripTokenQuotes(ReadToken()); + + //new format + if (token == "=") { + SkipWhitespace(true); + token = StripTokenQuotes(ReadToken()); + } + + int val = 0; + if (!ReadSignedInt(token, ref val)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcename + "' at line " + GetCurrentLineNumber() + ": expected " + shadeType + " value, but got '" + token + "'"); + datastream.Seek(-token.Length - 1, SeekOrigin.Current); //step back and try parsing this token again + continue; + } + + if (shadeType == "vertwallshade") + mapInfo.VertWallShade = General.Clamp(val, -255, 255); + else + mapInfo.HorizWallShade = General.Clamp(val, -255, 255); + //doublesky + } else if (token == "doublesky") { + mapInfo.DoubleSky = true; + //evenlighting + } else if (token == "evenlighting") { + mapInfo.EvenLighting = true; + //smoothlighting + } else if (token == "smoothlighting") { + mapInfo.SmoothLighting = true; + //block end + } else if (token == "}") { + if (curBlockName == "map") { + return true; //we are done here + } else { + return parseBlock(token, mapName); + } + } + } + } + return false; + } + + private bool getColorByName(string name, ref Color4 color) { + if (name == "black") + return true; + + Color c = Color.FromName(name); //should be similar to C++ color name detection, I suppose + if (c.IsKnownColor) { + color = new Color4(c); + return true; + } + return false; + } + } +} diff --git a/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs b/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs index e5ecbc11..e7efe80a 100644 --- a/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs +++ b/Source/Core/GZBuilder/GZDoom/ModeldefParser.cs @@ -10,13 +10,18 @@ using CodeImp.DoomBuilder.GZBuilder.GZDoom; namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { public class ModeldefParser : ZDTextParser { - public static string INVALID_TEXTURE = "**INVALID_TEXTURE**"; - private Dictionary modelDefEntries; //classname, entry public Dictionary ModelDefEntries { get { return modelDefEntries; } } + private List classNames; + public string Source { get { return sourcename; } } + public ModeldefParser() { + modelDefEntries = new Dictionary(); + classNames = new List(); + } + //should be called after all decorate actors are parsed public override bool Parse(Stream stream, string sourcefilename) { base.Parse(stream, sourcefilename); @@ -27,7 +32,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { string token = ReadToken(); if (token != null) { - token = token.ToLowerInvariant(); + token = StripTokenQuotes(token).ToLowerInvariant(); if (token == "model") { //model structure start //find classname @@ -35,8 +40,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { string className = StripTokenQuotes(ReadToken()).ToLowerInvariant(); if (!string.IsNullOrEmpty(className)) { - if (modelDefEntries.ContainsKey(className)) + if (classNames.IndexOf(className) != -1) { continue; //already got this class; continue to next one + } + classNames.Add(className); //now find opening brace SkipWhitespace(true); @@ -50,7 +57,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { ModeldefEntry mde = mds.Parse(this); if (mde != null) { mde.ClassName = className; - modelDefEntries.Add(className, mde); + modelDefEntries.Add(className, mde); + classNames.Add(mde.ClassName); } } diff --git a/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs b/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs index 7296b762..cc161e24 100644 --- a/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs +++ b/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Collections.Generic; using System.Globalization; using System.Text; @@ -10,11 +11,11 @@ using CodeImp.DoomBuilder.GZBuilder.Data; namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { public sealed class ModeldefStructure { - private string[] supportedTextureExtensions = { ".jpg", ".tga", ".png", ".dds" }; + private const int MAX_MODELS = 3; //maximum models per modeldef entry, zero-based public ModeldefEntry Parse(ModeldefParser parser) { - string[] textureNames = new string[16]; - string[] modelNames = new string[16]; + string[] textureNames = new string[4]; + string[] modelNames = new string[4]; string path = ""; Vector3 scale = new Vector3(1, 1, 1); float zOffset = 0; @@ -26,24 +27,24 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { token = parser.ReadToken(); if (!string.IsNullOrEmpty(token)) { - token = token.ToLowerInvariant(); -//path + token = parser.StripTokenQuotes(token).ToLowerInvariant(); //ANYTHING can be quoted... + //path if (token == "path") { parser.SkipWhitespace(true); path = parser.StripTokenQuotes(parser.ReadToken()).Replace("/", "\\"); if (string.IsNullOrEmpty(path)) { - GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line "+parser.GetCurrentLineNumber()+": expected path to model, but got '" + token + "'"); + GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected path to model, but got '" + token + "'"); gotErrors = true; break; } -//model + //model } else if (token == "model") { parser.SkipWhitespace(true); //model index int modelIndex; - token = parser.ReadToken(); + token = parser.StripTokenQuotes(parser.ReadToken()); if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out modelIndex)) { // Not numeric! GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected model index, but got '" + token + "'"); @@ -51,6 +52,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { break; } + if (modelIndex > MAX_MODELS) { + GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": GZDoom doesn't allow more than " + MAX_MODELS + " per MODELDEF entry!"); + break; + } + //model path token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant(); if (string.IsNullOrEmpty(token)) { @@ -62,26 +68,21 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { int dotPos = token.LastIndexOf("."); string fileExt = token.Substring(token.LastIndexOf("."), token.Length - dotPos); if (fileExt != ".md3" && fileExt != ".md2") { - GZBuilder.GZGeneral.LogAndTraceWarning("Model '" + token + "' not parsed in " + parser.Source + " at line " + parser.GetCurrentLineNumber() +". Only MD3 and MD2 models are supported."); + GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": model '" + token + "' not parsed. Only MD3 and MD2 models are supported."); gotErrors = true; break; } - if (modelNames[modelIndex] != null) { - GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": already got model for index " + modelIndex); - gotErrors = true; - break; - } else { - modelNames[modelIndex] = token; - } + //GZDoom allows models with identical modelIndex, it uses the last one encountered + modelNames[modelIndex] = token; } -//skin + //skin } else if (token == "skin") { parser.SkipWhitespace(true); //skin index int skinIndex; - token = parser.ReadToken(); + token = parser.StripTokenQuotes(parser.ReadToken()); if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out skinIndex)) { // Not numeric! GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected skin index, but got '" + token + "'"); @@ -89,6 +90,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { break; } + if (skinIndex > MAX_MODELS) { + GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": GZDoom doesn't allow more than " + MAX_MODELS + " per MODELDEF entry!"); + break; + } + //skin path token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant(); if (string.IsNullOrEmpty(token)) { @@ -99,95 +105,151 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { //check extension int dotPos = token.LastIndexOf("."); string fileExt = token.Substring(token.LastIndexOf("."), token.Length - dotPos); - if(Array.IndexOf(supportedTextureExtensions, fileExt) == -1) - token = ModeldefParser.INVALID_TEXTURE; + if (Array.IndexOf(TextureData.SUPPORTED_TEXTURE_EXTENSIONS, fileExt) == -1) + token = TextureData.INVALID_TEXTURE; - if (textureNames[skinIndex] != null) { - GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": already got model for index " + skinIndex); - gotErrors = true; - break; - } else { - textureNames[skinIndex] = token; - } + //GZDoom allows skins with identical modelIndex, it uses the last one encountered + textureNames[skinIndex] = token; } -//scale + //scale } else if (token == "scale") { parser.SkipWhitespace(true); - token = parser.ReadToken(); - - int sign = 1; - if (token == "-") { - sign = -1; - token = parser.ReadToken(); - } - - if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale.X)) { + token = parser.StripTokenQuotes(parser.ReadToken()); + if (!parser.ReadSignedFloat(token, ref scale.X)) { // Not numeric! GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected scale X value, but got '" + token + "'"); gotErrors = true; break; } - scale.X *= sign; parser.SkipWhitespace(true); - token = parser.ReadToken(); - - sign = 1; - if (token == "-") { - sign = -1; - token = parser.ReadToken(); - } - - if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale.Y)) { + token = parser.StripTokenQuotes(parser.ReadToken()); + if (!parser.ReadSignedFloat(token, ref scale.Y)) { // Not numeric! GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected scale Y value, but got '" + token + "'"); gotErrors = true; break; } - scale.Y *= sign; - parser.SkipWhitespace(true); - token = parser.ReadToken(); - - sign = 1; - if (token == "-") { - sign = -1; - token = parser.ReadToken(); - } - - if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale.Z)) { + token = parser.StripTokenQuotes(parser.ReadToken()); + if (!parser.ReadSignedFloat(token, ref scale.Z)) { // Not numeric! GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected scale Z value, but got '" + token + "'"); gotErrors = true; break; } - scale.Z *= sign; -//zoffset + //zoffset } else if (token == "zoffset") { parser.SkipWhitespace(true); - token = parser.ReadToken(); - - int sign = 1; - if (token == "-") { - sign = -1; - token = parser.ReadToken(); - } - - if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out zOffset)) { + token = parser.StripTokenQuotes(parser.ReadToken()); + if (!parser.ReadSignedFloat(token, ref zOffset)) { // Not numeric! GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected ZOffset value, but got '" + token + "'"); gotErrors = true; break; } - zOffset *= sign; -//frameindex + //frameindex } else if (token == "frameindex") { - //parsed all required fields + //parsed all required fields. if got more than one model - find which one(s) should be displayed + int len = modelNames.GetLength(0); + if (!gotErrors && len > 1) { + string spriteLump = null; + string spriteFrame = null; + bool[] modelsUsed = new bool[MAX_MODELS]; + + //step back + parser.DataStream.Seek(-token.Length - 1, SeekOrigin.Current); + + //here we check which models are used in first encountered lump and frame + while (parser.SkipWhitespace(true)) { + token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant(); + + if (token == "frameindex") { + parser.SkipWhitespace(true); + + //should be sprite lump + token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant(); + + if (string.IsNullOrEmpty(spriteLump)) { + spriteLump = token; + } else if (spriteLump != token) { //got another lump + for (int i = 0; i < modelsUsed.Length; i++) { + if (!modelsUsed[i]) { + modelNames[i] = null; + textureNames[i] = null; + } + } + break; + } + + parser.SkipWhitespace(true); + + //should be sprite frame + token = parser.StripTokenQuotes(parser.ReadToken()).ToLowerInvariant(); + + if (string.IsNullOrEmpty(spriteFrame)) { + spriteFrame = token; + } else if (spriteFrame != token) { //got another frame + for (int i = 0; i < modelsUsed.Length; i++) { + if (!modelsUsed[i]) { + modelNames[i] = null; + textureNames[i] = null; + } + } + break; + } + + parser.SkipWhitespace(true); + + //should be model index + token = parser.StripTokenQuotes(parser.ReadToken()); + + int modelIndex; + if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out modelIndex)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected model index, but got '" + token + "'"); + gotErrors = true; + break; + } + + if (modelIndex > MAX_MODELS) { + GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": GZDoom doesn't allow more than " + MAX_MODELS + " per MODELDEF entry!"); + gotErrors = true; + break; + } + + if (modelNames[modelIndex] == null) { + GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": got model index, which doesn't correspond to any defined model!"); + gotErrors = true; + break; + } + + modelsUsed[modelIndex] = true; + + parser.SkipWhitespace(true); + + //should be frame index. Currently I have no use for it + token = parser.StripTokenQuotes(parser.ReadToken()); + int frame; + if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out frame)) { + // Not numeric! + GZBuilder.GZGeneral.LogAndTraceWarning("Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected model frame, but got '" + token + "'"); + gotErrors = true; + break; + } + + } else { + //must be "}", step back + parser.DataStream.Seek(-token.Length - 1, SeekOrigin.Current); + break; + } + } + } break; } } @@ -201,7 +263,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { } if (gotErrors) - return null; + return null; //classname is set in ModeldefParser ModeldefEntry mde = new ModeldefEntry(); @@ -209,7 +271,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom { mde.Scale = scale; mde.zOffset = zOffset; - for (int i = 0; i < textureNames.Length; i++ ) { + for (int i = 0; i < textureNames.Length; i++) { if (textureNames[i] != null && modelNames[i] != null) { mde.TextureNames.Add(textureNames[i]); mde.ModelNames.Add(modelNames[i]); diff --git a/Source/Core/GZBuilder/GZGeneral.cs b/Source/Core/GZBuilder/GZGeneral.cs index e0b4b8eb..d339cb61 100644 --- a/Source/Core/GZBuilder/GZGeneral.cs +++ b/Source/Core/GZBuilder/GZGeneral.cs @@ -21,7 +21,7 @@ namespace CodeImp.DoomBuilder.GZBuilder //gzdoom light types private static int[] gzLights = { /* normal lights */ 9800, 9801, 9802, 9803, 9804, /* additive lights */ 9810, 9811, 9812, 9813, 9814, /* negative lights */ 9820, 9821, 9822, 9823, 9824, /* vavoom lights */ 1502, 1503}; public static int[] GZ_LIGHTS { get { return gzLights; } } - private static int[] gzLightTypes = { 5, 10, 15 }; //this is actually offsets in gz_lights + private static int[] gzLightTypes = { 5, 10, 15 }; //these are actually offsets in gz_lights public static int[] GZ_LIGHT_TYPES { get { return gzLightTypes; } } private static int[] gzAnimatedLightTypes = { (int)GZDoomLightType.FLICKER, (int)GZDoomLightType.RANDOM, (int)GZDoomLightType.PULSE }; public static int[] GZ_ANIMATED_LIGHT_TYPES { get { return gzAnimatedLightTypes; } } @@ -31,7 +31,7 @@ namespace CodeImp.DoomBuilder.GZBuilder //public static float[] FogTable; // light to fog conversion table for black fog //version - public const float Version = 1.06f; + public const float Version = 1.07f; //debug console #if DEBUG @@ -87,7 +87,6 @@ namespace CodeImp.DoomBuilder.GZBuilder //debug public static void LogAndTraceWarning(string message) { General.ErrorLogger.Add(ErrorType.Warning, message); - General.WriteLogLine(message); #if DEBUG Trace(message); #endif @@ -173,5 +172,24 @@ namespace CodeImp.DoomBuilder.GZBuilder General.MainWindow.RedrawDisplay(); General.MainWindow.UpdateGZDoomPannel(); } + + //main menu actions + [BeginAction("gzreloadmodeldef")] + private static void reloadModeldef() { + if(General.Map != null) + General.Map.Data.ReloadModeldef(); + } + + [BeginAction("gzreloadgldefs")] + private static void reloadGldefs() { + if (General.Map != null) + General.Map.Data.ReloadGldefs(); + } + + [BeginAction("gzreloadmapinfo")] + private static void reloadMapInfo() { + if (General.Map != null) + General.Map.Data.ReloadMapInfo(); + } } } diff --git a/Source/Core/GZBuilder/md3/ModelReader.cs b/Source/Core/GZBuilder/md3/ModelReader.cs index 23c03004..d022d0e7 100644 --- a/Source/Core/GZBuilder/md3/ModelReader.cs +++ b/Source/Core/GZBuilder/md3/ModelReader.cs @@ -55,11 +55,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 if (string.IsNullOrEmpty(error)) { string texturePath = Path.Combine(mde.Path, textureNames[i]); - if (textureNames[i] != ModeldefParser.INVALID_TEXTURE && reader.FileExists(texturePath)) { + if (textureNames[i] != TextureData.INVALID_TEXTURE && reader.FileExists(texturePath)) { mde.Model.Textures.Add(Texture.FromStream(D3DDevice, reader.LoadFile(texturePath))); } else { mde.Model.Textures.Add(General.Map.Data.UnknownTexture3D.Texture); - if (textureNames[i] != ModeldefParser.INVALID_TEXTURE) + if (textureNames[i] != TextureData.INVALID_TEXTURE) GZBuilder.GZGeneral.LogAndTraceWarning("MD3Reader: unable to load texture '" + texturePath + "' - no such file"); } } else { diff --git a/Source/Core/General/ErrorLogger.cs b/Source/Core/General/ErrorLogger.cs index d8e224cc..b1445086 100644 --- a/Source/Core/General/ErrorLogger.cs +++ b/Source/Core/General/ErrorLogger.cs @@ -73,6 +73,9 @@ namespace CodeImp.DoomBuilder erroradded = false; warningadded = false; errors.Clear(); + + //mxd + General.MainWindow.SetWarningsCount(0); } } @@ -98,6 +101,9 @@ namespace CodeImp.DoomBuilder } changed = true; General.WriteLogLine(prefix + message); + + //mxd + General.MainWindow.SetWarningsCount(errors.Count); } } diff --git a/Source/Core/Map/MapSet.cs b/Source/Core/Map/MapSet.cs index 920ecb74..43c71cb1 100644 --- a/Source/Core/Map/MapSet.cs +++ b/Source/Core/Map/MapSet.cs @@ -654,7 +654,7 @@ namespace CodeImp.DoomBuilder.Map /// This creates a new thing and returns it. public Thing CreateThing() { - if(numthings == General.Map.FormatInterface.MaxThings) + if(numthings == General.Map.FormatInterface.MaxThings) { General.Interface.DisplayStatus(StatusType.Warning, "Failed to complete operation: maximum number of things reached."); return null; @@ -669,7 +669,7 @@ namespace CodeImp.DoomBuilder.Map /// This creates a new thing and returns it. public Thing CreateThing(int index) { - if(numthings == General.Map.FormatInterface.MaxThings) + if(numthings == General.Map.FormatInterface.MaxThings) { General.Interface.DisplayStatus(StatusType.Warning, "Failed to complete operation: maximum number of things reached."); return null; diff --git a/Source/Core/Map/Thing.cs b/Source/Core/Map/Thing.cs index 061985f4..e4eb08a4 100644 --- a/Source/Core/Map/Thing.cs +++ b/Source/Core/Map/Thing.cs @@ -28,6 +28,8 @@ using System.Drawing; using CodeImp.DoomBuilder.IO; using CodeImp.DoomBuilder.VisualModes; +using CodeImp.DoomBuilder.GZBuilder.Data; + #endregion namespace CodeImp.DoomBuilder.Map @@ -72,7 +74,7 @@ namespace CodeImp.DoomBuilder.Map #region ================== Properties public MapSet Map { get { return map; } } - public int Type { get { return type; } set { BeforePropsChange(); type = value; } } + public int Type { get { return type; } set { BeforePropsChange(); type = value; } } public Vector3D Position { get { return pos; } } public float Angle { get { return anglerad; } } public int AngleDoom { get { return angledoom; } } diff --git a/Source/Core/Rendering/IRenderer3D.cs b/Source/Core/Rendering/IRenderer3D.cs index f28a90f9..ef4f6c50 100644 --- a/Source/Core/Rendering/IRenderer3D.cs +++ b/Source/Core/Rendering/IRenderer3D.cs @@ -59,6 +59,9 @@ namespace CodeImp.DoomBuilder.Rendering // Rendering methods int CalculateBrightness(int level); + //mxd + int CalculateBrightness(int level, Sidedef sd); + void SetHighlightedObject(IVisualPickable obj); void AddSectorGeometry(VisualGeometry g); void AddThingGeometry(VisualThing t); diff --git a/Source/Core/Rendering/Renderer.cs b/Source/Core/Rendering/Renderer.cs index d42ed2e8..f5ef3394 100644 --- a/Source/Core/Rendering/Renderer.cs +++ b/Source/Core/Rendering/Renderer.cs @@ -22,6 +22,8 @@ using System.Collections.Generic; using System.Globalization; using System.Text; +using CodeImp.DoomBuilder.Map; + #endregion namespace CodeImp.DoomBuilder.Rendering @@ -99,6 +101,32 @@ namespace CodeImp.DoomBuilder.Rendering return c.ToInt(); } + //mxd. This calculates wall brightness level with doom-style shading + public int CalculateBrightness(int level, Sidedef sd) { + if (!General.Map.Data.MapInfo.EvenLighting && sd != null) { + //all walls are shaded by their angle + if (General.Map.Data.MapInfo.SmoothLighting) { + float ammount = Math.Abs((float)Math.Sin(sd.Angle)); + int hAmmount = (int)((1.0f - ammount) * General.Map.Data.MapInfo.HorizWallShade); + int vAmmount = (int)(ammount * General.Map.Data.MapInfo.VertWallShade); + + level = General.Clamp(level - hAmmount - vAmmount, 0, 255); + + } else { //only horizontal/verticel walls are shaded + int angle = (int)(sd.Angle * 180.0f / Math.PI); + //horizontal wall + if (angle == 270 || angle == 90) { + level = General.Clamp(level + General.Map.Data.MapInfo.HorizWallShade, 0, 255); + //vertical wall + } else if (angle == 0 || angle == 180) { + level = General.Clamp(level + General.Map.Data.MapInfo.VertWallShade, 0, 255); + } + } + } + + return CalculateBrightness(level); + } + // This is called when the graphics need to be reset public virtual void Reset() { } diff --git a/Source/Core/Rendering/Renderer3D.cs b/Source/Core/Rendering/Renderer3D.cs index 41c80a5a..34b19030 100644 --- a/Source/Core/Rendering/Renderer3D.cs +++ b/Source/Core/Rendering/Renderer3D.cs @@ -685,6 +685,7 @@ namespace CodeImp.DoomBuilder.Rendering // This performs a single render pass private void RenderSinglePass(int pass) { + Color4 fogColor; int currentshaderpass = shaderpass; int highshaderpass = shaderpass + 2; @@ -779,14 +780,8 @@ namespace CodeImp.DoomBuilder.Rendering if (wantedshaderpass > 7) { graphics.Shaders.World3D.World = world; - bool sectorHasFogColor = true; - if(GZBuilder.GZGeneral.UDMF && sector.Sector.Fields.ContainsKey("fadecolor")){ - graphics.Shaders.World3D.LightColor = new Color4( (int)sector.Sector.Fields["fadecolor"].Value ); - }else{ - graphics.Shaders.World3D.LightColor = new Color4(); //black - sectorHasFogColor = false; - } - + bool sectorHasFogColor = getFogColor(sector.Sector, out fogColor); + graphics.Shaders.World3D.LightColor = fogColor; graphics.Shaders.World3D.CameraPosition = new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, getFogEnd(sector.Sector, sectorHasFogColor)); } @@ -850,12 +845,12 @@ namespace CodeImp.DoomBuilder.Rendering wantedshaderpass += 8; //mxd. if current thing is light - set it's color to light color - if (t.LightType != -1 && !fullbrightness) { + if (Array.IndexOf(GZBuilder.GZGeneral.GZ_LIGHTS, t.Thing.Type) != -1 && !fullbrightness) { wantedshaderpass += 4; //render using one of passes, which uses World3D.VertexColor graphics.Shaders.World3D.VertexColor = t.LightColor; //mxd. check if Thing is affected by dynamic lights and set color accordingly }else if (General.Settings.GZDrawLights && !fullbrightness && thingsWithLight.Count > 0) { - Color4 litColor = getLitColor(t.PositionV3); + Color4 litColor = getLitColorForThing(t); if (litColor.ToArgb() != 0) { wantedshaderpass += 4; //render using one of passes, which uses World3D.VertexColor graphics.Shaders.World3D.VertexColor = new Color4(t.VertexColor) + litColor; @@ -885,17 +880,11 @@ namespace CodeImp.DoomBuilder.Rendering //mxd. set variables for fog rendering if (wantedshaderpass > 7) { - Sector sector = t.Thing.Sector; graphics.Shaders.World3D.World = world; - bool sectorHasFogColor = true; - if (GZBuilder.GZGeneral.UDMF && sector.Fields.ContainsKey("fadecolor")) { - graphics.Shaders.World3D.LightColor = new Color4((int)sector.Fields["fadecolor"].Value); - } else { - graphics.Shaders.World3D.LightColor = new Color4(); //black - sectorHasFogColor = false; - } - graphics.Shaders.World3D.CameraPosition = new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, getFogEnd(sector, sectorHasFogColor)); + bool sectorHasFogColor = getFogColor(t.Thing.Sector, out fogColor); + graphics.Shaders.World3D.LightColor = fogColor; + graphics.Shaders.World3D.CameraPosition = new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, getFogEnd(t.Thing.Sector, sectorHasFogColor)); } graphics.Shaders.World3D.ApplySettings(); @@ -947,11 +936,12 @@ namespace CodeImp.DoomBuilder.Rendering for (i = 0; i < count; i++) { if (checkBBoxIntersection(g.BoundingBox, lights[i].BoundingBox)) { - lpr = lights[i].LightPositionAndRadius; + lpr = new Vector4(lights[i].Center,lights[i].LightRadius) ; if (lpr.W == 0) continue; graphics.Shaders.World3D.LightColor = lights[i].LightColor; - graphics.Shaders.World3D.LightPositionAndRadius = lights[i].LightPositionAndRadius; + //graphics.Shaders.World3D.LightPositionAndRadius = lights[i].LightPositionAndRadius; + graphics.Shaders.World3D.LightPositionAndRadius = lpr; graphics.Shaders.World3D.ApplySettings(); graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, g.VertexOffset, g.Triangles); } @@ -965,11 +955,13 @@ namespace CodeImp.DoomBuilder.Rendering for (i = lightOffsets[0]; i < count; i++) { if (checkBBoxIntersection(g.BoundingBox, lights[i].BoundingBox)) { - lpr = lights[i].LightPositionAndRadius; + //lpr = lights[i].LightPositionAndRadius; + lpr = new Vector4(lights[i].Center, lights[i].LightRadius); if (lpr.W == 0) continue; graphics.Shaders.World3D.LightColor = lights[i].LightColor; - graphics.Shaders.World3D.LightPositionAndRadius = lights[i].LightPositionAndRadius; + //graphics.Shaders.World3D.LightPositionAndRadius = lights[i].LightPositionAndRadius; + graphics.Shaders.World3D.LightPositionAndRadius = lpr; graphics.Shaders.World3D.ApplySettings(); graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, g.VertexOffset, g.Triangles); } @@ -983,12 +975,14 @@ namespace CodeImp.DoomBuilder.Rendering for (i = lightOffsets[0] + lightOffsets[1]; i < count; i++) { if (checkBBoxIntersection(g.BoundingBox, lights[i].BoundingBox)) { - lpr = lights[i].LightPositionAndRadius; + //lpr = lights[i].LightPositionAndRadius; + lpr = new Vector4(lights[i].Center, lights[i].LightRadius); if (lpr.W == 0) continue; Color4 lc = lights[i].LightColor; graphics.Shaders.World3D.LightColor = new Color4(lc.Alpha, (lc.Green + lc.Blue) / 2, (lc.Red + lc.Blue) / 2, (lc.Green + lc.Red) / 2); - graphics.Shaders.World3D.LightPositionAndRadius = lights[i].LightPositionAndRadius; + //graphics.Shaders.World3D.LightPositionAndRadius = lights[i].LightPositionAndRadius; + graphics.Shaders.World3D.LightPositionAndRadius = lpr; graphics.Shaders.World3D.ApplySettings(); graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, g.VertexOffset, g.Triangles); } @@ -1006,6 +1000,7 @@ namespace CodeImp.DoomBuilder.Rendering //mxd. render models private void RenderModels() { + Color4 fogColor; int shaderpass = fullbrightness ? 1 : 4; int currentshaderpass = shaderpass; int highshaderpass = shaderpass + 2; @@ -1019,7 +1014,7 @@ namespace CodeImp.DoomBuilder.Rendering vertexColor.Alpha = 1.0f; //check if model is affected by dynamic lights and set color accordingly if (General.Settings.GZDrawLights && !fullbrightness && thingsWithLight.Count > 0) { - Color4 litColor = getLitColor(t.PositionV3); + Color4 litColor = getLitColorForThing(t); graphics.Shaders.World3D.VertexColor = vertexColor + litColor; } else { graphics.Shaders.World3D.VertexColor = vertexColor; @@ -1054,22 +1049,13 @@ namespace CodeImp.DoomBuilder.Rendering //mxd. set variables for fog rendering if (wantedshaderpass > 7) { - Sector sector = t.Thing.Sector; graphics.Shaders.World3D.World = world; - bool sectorHasFogColor = true; - if (GZBuilder.GZGeneral.UDMF && sector.Fields.ContainsKey("fadecolor")) { - graphics.Shaders.World3D.LightColor = new Color4((int)sector.Fields["fadecolor"].Value); - } else { - graphics.Shaders.World3D.LightColor = new Color4(); //black - sectorHasFogColor = false; - } - graphics.Shaders.World3D.CameraPosition = new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, getFogEnd(sector, sectorHasFogColor)); + bool sectorHasFogColor = getFogColor(t.Thing.Sector, out fogColor); + graphics.Shaders.World3D.LightColor = fogColor; + graphics.Shaders.World3D.CameraPosition = new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, getFogEnd(t.Thing.Sector, sectorHasFogColor)); } - //dbg - //GZBuilder.GZGeneral.TraceInHeader("Using shader #"+wantedshaderpass); - for (int i = 0; i < group.Key.Model.NUM_MESHES; i++) { if (!graphics.Shaders.Enabled) graphics.Device.SetTexture(0, group.Key.Model.Textures[i]); graphics.Shaders.World3D.Texture1 = group.Key.Model.Textures[i]; @@ -1084,16 +1070,20 @@ namespace CodeImp.DoomBuilder.Rendering } //mxd. This gets color from dynamic lights based on distance to thing. - //WARNING: thing position must be in absolute cordinates + //thing position must be in absolute cordinates //(thing.Position.Z value is relative to floor of the sector the thing is in) - //so use visualThing.PositionV3 instead - private Color4 getLitColor(Vector3 thingPosition) { + private Color4 getLitColorForThing(VisualThing t) { Color4 litColor = new Color4(); float radius, radiusSquared, distSquared, scaler; int sign; for (int i = 0; i < thingsWithLight.Count; i++ ) { - distSquared = Vector3.DistanceSquared(thingsWithLight[i].Center, thingPosition); + //don't light self + if (General.Map.Data.GldefsEntries.ContainsKey(t.Thing.Type) && General.Map.Data.GldefsEntries[t.Thing.Type].DontLightSelf && t.Thing.Index == thingsWithLight[i].Thing.Index) { + continue; + } + + distSquared = Vector3.DistanceSquared(thingsWithLight[i].Center, t.PositionV3); radius = thingsWithLight[i].LightRadius; radiusSquared = radius * radius; if (distSquared < radiusSquared) { @@ -1109,12 +1099,27 @@ namespace CodeImp.DoomBuilder.Rendering //mxd. This returns distance, at which fog color completely replaces texture color for given sector private float getFogEnd(Sector s, bool sectorHasFogColor) { - //TODO: check if MapInfo has fog settings and apply them float brightness = (float)Math.Max(30, s.Brightness); if (sectorHasFogColor) { return brightness * 11.0f; } - return (float)Math.Pow(2.0f, brightness / 10.0f); + return (float)Math.Pow(2.0f, brightness / 11.0f); + } + + //mxd. returns true if sector has fog color + private bool getFogColor(Sector sector, out Color4 color) { + if (GZBuilder.GZGeneral.UDMF && sector.Fields.ContainsKey("fadecolor")) { + color = new Color4((int)sector.Fields["fadecolor"].Value); + return true; + } else if (General.Map.Data.MapInfo.HasOutsideFogColor && sector.CeilTexture == General.Map.Config.SkyFlatName) { + color = General.Map.Data.MapInfo.OutsideFogColor; + return true; + } else if (General.Map.Data.MapInfo.HasFadeColor) { + color = General.Map.Data.MapInfo.FadeColor; + return true; + } + color = new Color4(); //black + return false; } // This calculates the highlight/selection color diff --git a/Source/Core/Resources/Actions.cfg b/Source/Core/Resources/Actions.cfg index a6c34c2c..427f7164 100644 --- a/Source/Core/Resources/Actions.cfg +++ b/Source/Core/Resources/Actions.cfg @@ -832,7 +832,7 @@ gztogglemodels { title = "Toggle models rendering"; category = "gzdoombuilder"; - description = "Toggle MD3 models rendering."; + description = "Toggles models rendering."; allowkeys = true; allowmouse = true; allowscroll = false; @@ -886,4 +886,38 @@ gztogglefx allowkeys = true; allowmouse = true; allowscroll = false; +} + +//GZDOOMBUILDER MENU ACTIONS// +gzreloadmodeldef +{ + title = "Reload MODELDEF"; + category = "tools"; + description = "Reloads MODELDEF. Useful when resource files have been changed outside of Doom Builder."; + allowkeys = true; + allowmouse = false; + allowscroll = false; + default = 131188; +} + +gzreloadgldefs +{ + title = "Reload GLDEFS"; + category = "tools"; + description = "Reloads GLDEFS. Useful when resource files have been changed outside of Doom Builder."; + allowkeys = true; + allowmouse = false; + allowscroll = false; + default = 131189; +} + +gzreloadmapinfo +{ + title = "Reload (Z)MAPINFO"; + category = "tools"; + description = "Reloads (Z)MAPINFO. Useful when resource files have been changed outside of Doom Builder."; + allowkeys = true; + allowmouse = false; + allowscroll = false; + default = 131190; } \ No newline at end of file diff --git a/Source/Core/VisualModes/VisualGeometry.cs b/Source/Core/VisualModes/VisualGeometry.cs index 503784a5..25d0e0d1 100644 --- a/Source/Core/VisualModes/VisualGeometry.cs +++ b/Source/Core/VisualModes/VisualGeometry.cs @@ -84,7 +84,6 @@ namespace CodeImp.DoomBuilder.VisualModes //mxd private Vector3[] boundingBox; - //private Vector3D normal; #endregion @@ -167,14 +166,14 @@ namespace CodeImp.DoomBuilder.VisualModes triangles = vertices.Length / 3; //mxd - CalculateNormalsAndShading(); + CalculateNormals(); if(sector != null) sector.NeedsUpdateGeo = true; } - //mxd. Taken from OpenGl wiki - protected void CalculateNormalsAndShading() { - if (vertices.Length > 0) { + //mxd. Normals calculation algorithm taken from OpenGl wiki + protected void CalculateNormals() { + if (triangles > 0) { int startIndex; Vector3 U, V; @@ -193,21 +192,6 @@ namespace CodeImp.DoomBuilder.VisualModes p1.ny = p2.ny = p3.ny = -(U.Z * V.X - U.X * V.Z); p1.nz = p2.nz = p3.nz = -(U.X * V.Y - U.Y * V.X); - //doom-style walls shading - //not very apropriate place to put this, but most convinient :) - if (sidedef != null) { - float valMod = 1.0f - Math.Abs((float)Math.Sin(sidedef.Angle)) * 0.07f; //0.07 - PixelColor pc = PixelColor.FromInt(p1.c); - - pc.r = (byte)((float)pc.r * valMod); - pc.g = (byte)((float)pc.g * valMod); - pc.b = (byte)((float)pc.b * valMod); - - int c = pc.ToInt(); - p1.c = c; - p2.c = c; - p3.c = c; - } vertices[startIndex] = p1; vertices[startIndex + 1] = p2; vertices[startIndex + 2] = p3; diff --git a/Source/Core/VisualModes/VisualThing.cs b/Source/Core/VisualModes/VisualThing.cs index 8b9c5efc..dc4ec9ef 100644 --- a/Source/Core/VisualModes/VisualThing.cs +++ b/Source/Core/VisualModes/VisualThing.cs @@ -38,6 +38,7 @@ using CodeImp.DoomBuilder.Rendering; //mxd using CodeImp.DoomBuilder.GZBuilder.Data; +using CodeImp.DoomBuilder.GZBuilder.GZDoom; #endregion @@ -93,6 +94,10 @@ namespace CodeImp.DoomBuilder.VisualModes private Vector3 position_v3; private float lightDelta; //used in light animation private Vector3[] boundingBox; + //gldefs light + private Vector3 lightOffset; + private int lightInterval; + private bool isGldefsLight; #endregion @@ -110,7 +115,14 @@ namespace CodeImp.DoomBuilder.VisualModes //mxd internal int VertexColor { get { return vertices.Length > 0 ? vertices[0].c : 0;} } public int CameraDistance3D { get { return cameraDistance3D; } } - public Vector3 Center { get { return new Vector3(position_v3.X, position_v3.Y, position_v3.Z + thingHeight / 2); } } + public Vector3 Center { + get + { + if (isGldefsLight) + return position_v3 + lightOffset; + return new Vector3(position_v3.X, position_v3.Y, position_v3.Z + thingHeight / 2); + } + } public Vector3 PositionV3 { get { return position_v3; } } public Vector3[] BoundingBox { get { return boundingBox; } } //mxd. light properties @@ -118,7 +130,7 @@ namespace CodeImp.DoomBuilder.VisualModes public float LightRadius { get { return lightRadius; } } public int LightRenderStyle { get { return lightRenderStyle; } } public Color4 LightColor { get { return lightColor; } } - public Vector4 LightPositionAndRadius { get { return new Vector4(Center, lightRadius);} } + //public Vector4 LightPositionAndRadius { get { return new Vector4(Center, lightRadius);} } /// /// Set to True to use billboarding for this thing. When using billboarding, @@ -171,6 +183,7 @@ namespace CodeImp.DoomBuilder.VisualModes lightRenderStyle = -1; lightPrimaryRadius = -1; lightSecondaryRadius = -1; + lightInterval = -1; lightColor = new Color4(); boundingBox = new Vector3[9]; @@ -323,8 +336,16 @@ namespace CodeImp.DoomBuilder.VisualModes //mxd. Check if thing is light int light_id = Array.IndexOf(GZBuilder.GZGeneral.GZ_LIGHTS, thing.Type); if (light_id != -1) { + isGldefsLight = false; + lightInterval = -1; updateLight(light_id); UpdateBoundingBox(lightRadius, lightRadius * 2); + + //check if we have light from GLDEFS + } else if (General.Map.Data.GldefsEntries.ContainsKey(thing.Type)) { + isGldefsLight = true; + updateGldefsLight(); + UpdateBoundingBox(lightRadius, lightRadius * 2); } else { if (thing.IsModel) { updateBoundingBoxForModel(); @@ -336,6 +357,8 @@ namespace CodeImp.DoomBuilder.VisualModes lightPrimaryRadius = -1; lightSecondaryRadius = -1; lightRenderStyle = -1; + lightInterval = -1; + isGldefsLight = false; } // Done @@ -348,8 +371,6 @@ namespace CodeImp.DoomBuilder.VisualModes int light_id = Array.IndexOf(GZBuilder.GZGeneral.GZ_LIGHTS, thing.Type); if (light_id != -1) { updateLight(light_id); - - //if (Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, lightType) != -1) UpdateBoundingBox(lightRadius, lightRadius * 2); } } @@ -398,8 +419,37 @@ namespace CodeImp.DoomBuilder.VisualModes UpdateLightRadius(); } + //mxd + private void updateGldefsLight() { + GZDoomLight light = General.Map.Data.GldefsEntries[thing.Type]; + float intensity_mod = General.Settings.GZDynamicLightIntensity; + float scale_mod = General.Settings.GZDynamicLightRadius; + + //apply settings + lightRenderStyle = light.Subtractive ? (int)GZDoomLightRenderStyle.NEGATIVE : (int)GZDoomLightRenderStyle.NORMAL; + lightColor = new Color4((float)lightRenderStyle / 100.0f, light.Color.Red * intensity_mod, light.Color.Green * intensity_mod, light.Color.Blue * intensity_mod); + lightOffset = light.Offset; + lightType = light.Type; + + if (lightType == (int)GZDoomLightType.SECTOR) { + lightPrimaryRadius = light.Interval * thing.Sector.Brightness / 5; + } else { + lightPrimaryRadius = light.PrimaryRadius * scale_mod; + lightSecondaryRadius = light.SecondaryRadius * scale_mod; + } + + lightInterval = light.Interval; + + updateLightRadius(lightInterval); + } + //mxd public void UpdateLightRadius() { + updateLightRadius( (lightInterval != -1 ? lightInterval : thing.AngleDoom) ); + } + + //mxd + private void updateLightRadius(int interval) { if (lightType == -1) { General.ErrorLogger.Add(ErrorType.Error, "Please check that thing is light before accessing it's PositionAndRadius! You can use lightType, which is -1 if thing isn't light"); return; @@ -425,7 +475,7 @@ namespace CodeImp.DoomBuilder.VisualModes //pulse if (lightType == (int)GZDoomLightType.PULSE) { - lightDelta = ((float)Math.Sin(time / (thing.AngleDoom * 4.0f)) + 1.0f) / 2.0f; //just playing by the eye here... in [0.0 ... 1.0] interval + lightDelta = ((float)Math.Sin(time / (interval * 4.0f)) + 1.0f) / 2.0f; //just playing by the eye here... in [0.0 ... 1.0] interval lightRadius = rMin + diff * lightDelta; //flicker } else if (lightType == (int)GZDoomLightType.FLICKER) { @@ -433,7 +483,7 @@ namespace CodeImp.DoomBuilder.VisualModes float delta = (float)Math.Sin(time / 0.1f); //just playing by the eye here... if (Math.Sign(delta) != Math.Sign(lightDelta)) { lightDelta = delta; - if (new Random().Next(0, 359) < thing.AngleDoom) + if (new Random().Next(0, 359) < interval) lightRadius = rMax; else lightRadius = rMin; @@ -441,7 +491,7 @@ namespace CodeImp.DoomBuilder.VisualModes //random } else if (lightType == (int)GZDoomLightType.RANDOM) { //float delta = (float)Math.Sin(time / (thing.AngleDoom)); - float delta = (float)Math.Sin(time / (thing.AngleDoom * 9.0f)); //just playing by the eye here... + float delta = (float)Math.Sin(time / (interval * 9.0f)); //just playing by the eye here... if (Math.Sign(delta) != Math.Sign(lightDelta)) lightRadius = rMin + (float)(new Random().Next(0, (int)(diff * 10))) / 10.0f; lightDelta = delta; diff --git a/Source/Core/Windows/ErrorsForm.cs b/Source/Core/Windows/ErrorsForm.cs index cbe31f4e..3118481e 100644 --- a/Source/Core/Windows/ErrorsForm.cs +++ b/Source/Core/Windows/ErrorsForm.cs @@ -49,6 +49,8 @@ namespace CodeImp.DoomBuilder.Windows FillList(); checkerrors.Start(); checkshow.Checked = General.Settings.ShowErrorsWindow; + //mxd + grid.Focus(); } #endregion diff --git a/Source/Core/Windows/MainForm.Designer.cs b/Source/Core/Windows/MainForm.Designer.cs index 1886316d..e80521c8 100644 --- a/Source/Core/Windows/MainForm.Designer.cs +++ b/Source/Core/Windows/MainForm.Designer.cs @@ -34,6 +34,7 @@ namespace CodeImp.DoomBuilder.Windows System.Windows.Forms.ToolStripSeparator toolStripSeparator12; System.Windows.Forms.ToolStripSeparator toolStripMenuItem4; System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + System.Windows.Forms.ToolStripSeparator toolStripSeparator3; System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.seperatorfileopen = new System.Windows.Forms.ToolStripSeparator(); this.seperatorfilerecent = new System.Windows.Forms.ToolStripSeparator(); @@ -99,6 +100,9 @@ namespace CodeImp.DoomBuilder.Windows this.itemcreateprefab = new System.Windows.Forms.ToolStripMenuItem(); this.menutools = new System.Windows.Forms.ToolStripMenuItem(); this.itemreloadresources = new System.Windows.Forms.ToolStripMenuItem(); + this.itemReloadModedef = new System.Windows.Forms.ToolStripMenuItem(); + this.itemReloadGldefs = new System.Windows.Forms.ToolStripMenuItem(); + this.itemReloadMapinfo = new System.Windows.Forms.ToolStripMenuItem(); this.itemshowerrors = new System.Windows.Forms.ToolStripMenuItem(); this.seperatortoolsresources = new System.Windows.Forms.ToolStripSeparator(); this.configurationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -167,6 +171,7 @@ namespace CodeImp.DoomBuilder.Windows this.itemzoomfittoscreen = new System.Windows.Forms.ToolStripMenuItem(); this.xposlabel = new System.Windows.Forms.ToolStripStatusLabel(); this.yposlabel = new System.Windows.Forms.ToolStripStatusLabel(); + this.warnsLabel = new System.Windows.Forms.ToolStripStatusLabel(); this.panelinfo = new System.Windows.Forms.Panel(); this.heightpanel1 = new System.Windows.Forms.Panel(); this.vertexinfo = new CodeImp.DoomBuilder.Controls.VertexInfoPanel(); @@ -184,11 +189,13 @@ namespace CodeImp.DoomBuilder.Windows this.dockersspace = new System.Windows.Forms.Panel(); this.dockerspanel = new CodeImp.DoomBuilder.Controls.DockersControl(); this.dockerscollapser = new System.Windows.Forms.Timer(this.components); + this.warntimer = new System.Windows.Forms.Timer(this.components); toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator(); toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator(); toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator(); toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); this.menumain.SuspendLayout(); this.toolbar.SuspendLayout(); this.statusbar.SuspendLayout(); @@ -223,6 +230,12 @@ namespace CodeImp.DoomBuilder.Windows toolStripSeparator2.Name = "toolStripSeparator2"; toolStripSeparator2.Size = new System.Drawing.Size(153, 6); // + // toolStripSeparator3 + // + toolStripSeparator3.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); + toolStripSeparator3.Name = "toolStripSeparator3"; + toolStripSeparator3.Size = new System.Drawing.Size(6, 23); + // // seperatorfileopen // this.seperatorfileopen.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3); @@ -760,6 +773,9 @@ namespace CodeImp.DoomBuilder.Windows // this.menutools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.itemreloadresources, + this.itemReloadModedef, + this.itemReloadGldefs, + this.itemReloadMapinfo, this.itemshowerrors, this.seperatortoolsresources, this.configurationToolStripMenuItem, @@ -778,6 +794,30 @@ namespace CodeImp.DoomBuilder.Windows this.itemreloadresources.Text = "&Reload Resources"; this.itemreloadresources.Click += new System.EventHandler(this.InvokeTaggedAction); // + // itemReloadModedef + // + this.itemReloadModedef.Name = "itemReloadModedef"; + this.itemReloadModedef.Size = new System.Drawing.Size(196, 22); + this.itemReloadModedef.Tag = "builder_gzreloadmodeldef"; + this.itemReloadModedef.Text = "Reload MODELDEF"; + this.itemReloadModedef.Click += new System.EventHandler(this.InvokeTaggedAction); + // + // itemReloadGldefs + // + this.itemReloadGldefs.Name = "itemReloadGldefs"; + this.itemReloadGldefs.Size = new System.Drawing.Size(196, 22); + this.itemReloadGldefs.Tag = "builder_gzreloadgldefs"; + this.itemReloadGldefs.Text = "Reload GLDEFS"; + this.itemReloadGldefs.Click += new System.EventHandler(this.InvokeTaggedAction); + // + // itemReloadMapinfo + // + this.itemReloadMapinfo.Name = "itemReloadMapinfo"; + this.itemReloadMapinfo.Size = new System.Drawing.Size(196, 22); + this.itemReloadMapinfo.Tag = "builder_gzreloadmapinfo"; + this.itemReloadMapinfo.Text = "Reload (Z)MAPINFO"; + this.itemReloadMapinfo.Click += new System.EventHandler(this.InvokeTaggedAction); + // // itemshowerrors // this.itemshowerrors.Image = global::CodeImp.DoomBuilder.Properties.Resources.Warning; @@ -1259,10 +1299,12 @@ namespace CodeImp.DoomBuilder.Windows toolStripSeparator1, this.zoomlabel, this.buttonzoom, - toolStripSeparator9, + toolStripSeparator3, this.xposlabel, this.poscommalabel, - this.yposlabel}); + this.yposlabel, + toolStripSeparator9, + this.warnsLabel}); this.statusbar.Location = new System.Drawing.Point(0, 670); this.statusbar.Name = "statusbar"; this.statusbar.ShowItemToolTips = true; @@ -1275,7 +1317,7 @@ namespace CodeImp.DoomBuilder.Windows this.statuslabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; this.statuslabel.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None; this.statuslabel.Name = "statuslabel"; - this.statuslabel.Size = new System.Drawing.Size(396, 18); + this.statuslabel.Size = new System.Drawing.Size(309, 18); this.statuslabel.Spring = true; this.statuslabel.Text = "Initializing user interface..."; this.statuslabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; @@ -1507,6 +1549,20 @@ namespace CodeImp.DoomBuilder.Windows this.yposlabel.Text = "0"; this.yposlabel.ToolTipText = "Current X, Y coordinates on map"; // + // warnsLabel + // + this.warnsLabel.AutoSize = false; + this.warnsLabel.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.warnsLabel.Image = global::CodeImp.DoomBuilder.Properties.Resources.WarningOff; + this.warnsLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; + this.warnsLabel.Name = "warnsLabel"; + this.warnsLabel.Size = new System.Drawing.Size(44, 18); + this.warnsLabel.Text = "0"; + this.warnsLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.warnsLabel.TextImageRelation = System.Windows.Forms.TextImageRelation.TextBeforeImage; + this.warnsLabel.ToolTipText = "Click to open Errors and Warnings window"; + this.warnsLabel.Click += new System.EventHandler(this.warnsLabel_Click); + // // panelinfo // this.panelinfo.Controls.Add(this.heightpanel1); @@ -1682,6 +1738,11 @@ namespace CodeImp.DoomBuilder.Windows this.dockerscollapser.Interval = 200; this.dockerscollapser.Tick += new System.EventHandler(this.dockerscollapser_Tick); // + // warntimer + // + this.warntimer.Interval = 500; + this.warntimer.Tick += new System.EventHandler(this.warntimer_Tick); + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); @@ -1875,5 +1936,10 @@ namespace CodeImp.DoomBuilder.Windows private System.Windows.Forms.ToolStripButton buttontoggleanimatedlight; private System.Windows.Forms.ToolStripButton buttontogglefx; private System.Windows.Forms.ToolStripButton buttontogglefog; + private System.Windows.Forms.ToolStripStatusLabel warnsLabel; + private System.Windows.Forms.Timer warntimer; + private System.Windows.Forms.ToolStripMenuItem itemReloadModedef; + private System.Windows.Forms.ToolStripMenuItem itemReloadGldefs; + private System.Windows.Forms.ToolStripMenuItem itemReloadMapinfo; } } \ No newline at end of file diff --git a/Source/Core/Windows/MainForm.cs b/Source/Core/Windows/MainForm.cs index da8ff7b3..22dd6403 100644 --- a/Source/Core/Windows/MainForm.cs +++ b/Source/Core/Windows/MainForm.cs @@ -156,6 +156,9 @@ namespace CodeImp.DoomBuilder.Windows // Updating private int lockupdatecount; + + //mxd + private bool warnStatus; //status of warnings panel icon #endregion @@ -2281,7 +2284,13 @@ namespace CodeImp.DoomBuilder.Windows private void UpdateToolsMenu() { // Enable/disable items - itemreloadresources.Enabled = (General.Map != null); + bool enabled = (General.Map != null); + itemreloadresources.Enabled = enabled; + + //mxd + itemReloadGldefs.Enabled = enabled; + itemReloadMapinfo.Enabled = enabled; + itemReloadModedef.Enabled = enabled; } // Errors and Warnings @@ -2291,6 +2300,8 @@ namespace CodeImp.DoomBuilder.Windows ErrorsForm errform = new ErrorsForm(); errform.ShowDialog(this); errform.Dispose(); + //mxd + SetWarningsCount(0); } // Game Configuration action @@ -2670,6 +2681,39 @@ namespace CodeImp.DoomBuilder.Windows break; } } + + //mxd. Warnings panel + internal void SetWarningsCount(int count) { + if (count == 0) { + if (warnsLabel.Font.Bold) { + warnsLabel.Font = new Font(warnsLabel.Font, FontStyle.Regular); + warnsLabel.Image = global::CodeImp.DoomBuilder.Properties.Resources.WarningOff; + } + warntimer.Stop(); + warnStatus = false; + } else if (!warnsLabel.Font.Bold) { + warnsLabel.Font = new Font(warnsLabel.Font, FontStyle.Bold); + warnsLabel.Image = global::CodeImp.DoomBuilder.Properties.Resources.Warning; + warnStatus = true; + warntimer.Start(); + } + warnsLabel.Text = count.ToString(); + } + + //mxd + private void warnsLabel_Click(object sender, EventArgs e) { + ShowErrors(); + } + + //mxd + private void warntimer_Tick(object sender, EventArgs e) { + if (warnStatus) { + warnsLabel.Image = global::CodeImp.DoomBuilder.Properties.Resources.WarningOff; + } else { + warnsLabel.Image = global::CodeImp.DoomBuilder.Properties.Resources.Warning; + } + warnStatus = !warnStatus; + } #endregion diff --git a/Source/Core/Windows/MainForm.resx b/Source/Core/Windows/MainForm.resx index 638918d5..dcf53760 100644 --- a/Source/Core/Windows/MainForm.resx +++ b/Source/Core/Windows/MainForm.resx @@ -132,6 +132,9 @@ False + + False + True @@ -195,30 +198,6 @@ True - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - 319, 17 @@ -243,6 +222,9 @@ 781, 17 + + 17, 56 + True diff --git a/Source/Core/Windows/ThingEditForm.cs b/Source/Core/Windows/ThingEditForm.cs index 20373699..dd925c39 100644 --- a/Source/Core/Windows/ThingEditForm.cs +++ b/Source/Core/Windows/ThingEditForm.cs @@ -30,6 +30,7 @@ using CodeImp.DoomBuilder.Config; using CodeImp.DoomBuilder.Editing; using CodeImp.DoomBuilder.Geometry; using CodeImp.DoomBuilder.Controls; +using CodeImp.DoomBuilder.GZBuilder.Data; #endregion @@ -243,20 +244,31 @@ namespace CodeImp.DoomBuilder.Windows if(arg2label.Enabled) arg2.ForeColor = SystemColors.WindowText; else arg2.ForeColor = SystemColors.GrayText; if(arg3label.Enabled) arg3.ForeColor = SystemColors.WindowText; else arg3.ForeColor = SystemColors.GrayText; if(arg4label.Enabled) arg4.ForeColor = SystemColors.WindowText; else arg4.ForeColor = SystemColors.GrayText; - arg0.Setup(arginfo[0]); - arg1.Setup(arginfo[1]); - arg2.Setup(arginfo[2]); - arg3.Setup(arginfo[3]); - arg4.Setup(arginfo[4]); + + arg0.Setup(arginfo[0]); + arg1.Setup(arginfo[1]); + arg2.Setup(arginfo[2]); + arg3.Setup(arginfo[3]); + arg4.Setup(arginfo[4]); // Zero all arguments when linedef action 0 (normal) is chosen if(!preventchanges && (showaction == 0)) { - arg0.SetValue(0); - arg1.SetValue(0); - arg2.SetValue(0); - arg3.SetValue(0); - arg4.SetValue(0); + //mxd. If thing is light, set default light settings + int[] args = GZDoomLight.GetDefaultLightSettings(thingtype.GetResult(1)); + if (args != null) { + arg0.SetValue(args[0]); + arg1.SetValue(args[1]); + arg2.SetValue(args[2]); + arg3.SetValue(args[3]); + arg4.SetValue(args[4]); + } else { + arg0.SetValue(0); + arg1.SetValue(0); + arg2.SetValue(0); + arg3.SetValue(0); + arg4.SetValue(0); + } } } diff --git a/Source/Core/ZDoom/ZDTextParser.cs b/Source/Core/ZDoom/ZDTextParser.cs index 0e7a8a83..8cdddc1d 100644 --- a/Source/Core/ZDoom/ZDTextParser.cs +++ b/Source/Core/ZDoom/ZDTextParser.cs @@ -293,6 +293,36 @@ namespace CodeImp.DoomBuilder.ZDoom return token.Trim(); } + + //mxd + protected internal bool ReadSignedFloat(string token, ref float value) { + int sign = 1; + if (token == "-") { + sign = -1; + token = StripTokenQuotes(ReadToken()); + } + + float val; + bool success = float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out val); + if (success) + value = val * sign; + return success; + } + + //mxd + protected internal bool ReadSignedInt(string token, ref int value) { + int sign = 1; + if (token == "-") { + sign = -1; + token = StripTokenQuotes(ReadToken()); + } + + int val; + bool success = int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out val); + if (success) + value = val * sign; + return success; + } // This reports an error protected internal void ReportError(string message) diff --git a/Source/Plugins/ColorPicker/Resources/Actions.cfg b/Source/Plugins/ColorPicker/Resources/Actions.cfg index 8a318510..58021742 100644 --- a/Source/Plugins/ColorPicker/Resources/Actions.cfg +++ b/Source/Plugins/ColorPicker/Resources/Actions.cfg @@ -1,8 +1,8 @@ togglelightpannel { - title = "Toggle color picker"; + title = "Open color picker"; category = "tools"; - description = "Select dynamic light thing(s) or sectors, then use this pannel to set light properties quickly."; + description = "Select dynamic light thing(s) or sector(s), then use this panel to set light properties quickly."; allowkeys = true; allowmouse = true; allowscroll = false; diff --git a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualGeometrySidedef.cs b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualGeometrySidedef.cs index d72e2bcf..b9f774d6 100644 --- a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualGeometrySidedef.cs +++ b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualGeometrySidedef.cs @@ -162,14 +162,15 @@ namespace CodeImp.DoomBuilder.GZDoomEditing { List polygons = new List(poly); List verts = new List(); - + // Go for all levels to build geometry for(int i = sd.LightLevels.Count - 1; i >= 0; i--) { SectorLevel l = sd.LightLevels[i]; + if((l != sd.Floor) && (l != sd.Ceiling) && (l.type != SectorLevelType.Floor)) { - // Go for all polygons + // Go for all polygons int num = polygons.Count; for(int pi = 0; pi < num; pi++) { @@ -180,7 +181,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing { // Determine color int lightlevel = lightabsolute ? lightvalue : l.brightnessbelow + lightvalue; - PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel)); + //mxd + //PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel)); + PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef)); PixelColor wallcolor = PixelColor.Modulate(l.colorbelow, wallbrightness); np.color = wallcolor.WithAlpha(255).ToInt(); @@ -226,7 +229,6 @@ namespace CodeImp.DoomBuilder.GZDoomEditing return verts; } - // This splits a polygon with a plane and returns the other part as a new polygon // The polygon is expected to be convex and clockwise protected WallPolygon SplitPoly(ref WallPolygon poly, Plane p, bool keepfront) diff --git a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualMode.cs b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualMode.cs index 4c3e0381..d6c23c50 100644 --- a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualMode.cs +++ b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualMode.cs @@ -164,6 +164,11 @@ namespace CodeImp.DoomBuilder.GZDoomEditing { return renderer.CalculateBrightness(level); } + + //mxd. This calculates brightness level with doom-style shading + internal int CalculateBrightness(int level, Sidedef sd) { + return renderer.CalculateBrightness(level, sd); + } // This adds a selected object internal void AddSelectedObject(IVisualEventReceiver obj) diff --git a/Source/Plugins/GZDoomEditing/VisualModes/VisualLower.cs b/Source/Plugins/GZDoomEditing/VisualModes/VisualLower.cs index bd893fbe..ac9aaf45 100644 --- a/Source/Plugins/GZDoomEditing/VisualModes/VisualLower.cs +++ b/Source/Plugins/GZDoomEditing/VisualModes/VisualLower.cs @@ -168,7 +168,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing // Determine initial color int lightlevel = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue; - PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel)); + //mxd + //PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel)); + PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef)); PixelColor wallcolor = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness); poly.color = wallcolor.WithAlpha(255).ToInt(); diff --git a/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddle3D.cs b/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddle3D.cs index f491436b..c93cf530 100644 --- a/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddle3D.cs +++ b/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddle3D.cs @@ -187,7 +187,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing // Determine initial color int lightlevel = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue; - PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel)); + //mxd + //PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel)); + PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef)); PixelColor wallcolor = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness); poly.color = wallcolor.WithAlpha(255).ToInt(); diff --git a/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleDouble.cs b/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleDouble.cs index 8d516efe..1afbddc9 100644 --- a/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleDouble.cs +++ b/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleDouble.cs @@ -184,7 +184,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing // Determine initial color int lightlevel = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue; - PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel)); + //mxd + //PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel)); + PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef)); PixelColor wallcolor = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness); poly.color = wallcolor.WithAlpha(255).ToInt(); diff --git a/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleSingle.cs b/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleSingle.cs index 6cc008cd..a599cb9f 100644 --- a/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleSingle.cs +++ b/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleSingle.cs @@ -179,7 +179,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing // Determine initial color int lightlevel = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue; - PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel)); + //mxd + //PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel)); + PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef)); PixelColor wallcolor = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness); poly.color = wallcolor.WithAlpha(255).ToInt(); diff --git a/Source/Plugins/GZDoomEditing/VisualModes/VisualUpper.cs b/Source/Plugins/GZDoomEditing/VisualModes/VisualUpper.cs index 31feaa05..0f418081 100644 --- a/Source/Plugins/GZDoomEditing/VisualModes/VisualUpper.cs +++ b/Source/Plugins/GZDoomEditing/VisualModes/VisualUpper.cs @@ -169,7 +169,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing // Determine initial color int lightlevel = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue; - PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel)); + //mxd + //PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel)); + PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef)); PixelColor wallcolor = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness); poly.color = wallcolor.WithAlpha(255).ToInt();