diff --git a/Build/Configurations/Includes/Common.cfg b/Build/Configurations/Includes/Common.cfg index 981eefa4611a09ef13ffc45e0dd633d3de3d39e7..4f3877cc83e1494f1d870102e43908e5a87babd0 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 109e8c63695926c0a63ce7bdd31bdb8b86712611..1e3fb24b8047ad6d42090959866cfa2bbe66e3f1 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 0000000000000000000000000000000000000000..85399d699f2a65168c67cc4b1856b49f59faaddb --- /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 0000000000000000000000000000000000000000..2bb6351de971362a71ee6ae323f5d9f1ddc5c241 --- /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 0000000000000000000000000000000000000000..c8f433d58d047296f882085c4cfc606dcec0eebf --- /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 0000000000000000000000000000000000000000..c883a8ceaf1ba92a61283b3ef1140300c9d1955c --- /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 0000000000000000000000000000000000000000..a779fdea9f9bfa26eba304b00c4ec998c174d2d6 --- /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 0bdd93ea2d78f42c8a00c0c672073965d56f67e0..7dfd99b4ebbbdb404ca1e017ec725b6c644cd4f8 100644 --- a/Source/Core/Builder.csproj +++ b/Source/Core/Builder.csproj @@ -712,10 +712,14 @@ <DependentUpon>ConsoleDocker.cs</DependentUpon> </Compile> <Compile Include="GZBuilder\Data\BoundingBox.cs" /> + <Compile Include="GZBuilder\Data\GameType.cs" /> <Compile Include="GZBuilder\Data\GZDoomLight.cs" /> + <Compile Include="GZBuilder\Data\MapInfo.cs" /> <Compile Include="GZBuilder\Data\ModeldefEntry.cs" /> + <Compile Include="GZBuilder\Data\TextureData.cs" /> <Compile Include="GZBuilder\Data\ThingBoundingBox.cs" /> <Compile Include="GZBuilder\GZDoom\GldefsParser.cs" /> + <Compile Include="GZBuilder\GZDoom\MapinfoParser.cs" /> <Compile Include="GZBuilder\GZDoom\ModeldefParser.cs" /> <Compile Include="GZBuilder\GZDoom\ModeldefStructure.cs" /> <Compile Include="GZBuilder\GZGeneral.cs" /> diff --git a/Source/Core/Builder.sln b/Source/Core/Builder.sln index 9a59c636000acdd516a53194970da7805119c1a1..87f1bad790aa7a9770446c0015cc623722cdd512 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 b5912efc0b2d8a5381bb8755d65f5953f9faa520..5bf75cff136c29cc0c09485ccf7d4e58789f3ded 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<DefinedTextureSet> texturesets; private List<ThingsFilter> 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<DefinedTextureSet> TextureSets { get { return texturesets; } } public List<ThingsFilter> 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", "<unnamed 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 bca1ac74abd32b1eb97ed789293432956d3eeed2..85fe3f1bc5794553dbdf542750651a9eeb12e10c 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<ResourceTextureSet> resourcetextures; private AllTextureSet alltextures; - //mxd Folders - //private List<string> folders; - - //mxd modeldefs - private Dictionary<int, ModeldefEntry> modeldefEntries; + //mxd + private Dictionary<int, ModeldefEntry> modeldefEntries; //Thing.Type, Model entry + private Dictionary<int, GZDoomLight> gldefsEntries; //Thing.Type, Light entry + private MapInfo mapInfo; //mapinfo // Background loading private Queue<ImageData> imageque; @@ -114,8 +114,9 @@ namespace CodeImp.DoomBuilder.Data #region ================== Properties //mxd - //public List<string> Folders { get { return folders; } } public Dictionary<int, ModeldefEntry> ModeldefEntries { get { return modeldefEntries; } } + public Dictionary<int, GZDoomLight> 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<int, ModeldefEntry> 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<string, int> 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<long, ImageData> 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 <Actor Class, Thing.Type> dictionary. Should be called after all DECORATE actors are parsed + private Dictionary<string, int> createActorsByClassList() { + Dictionary<string, int> actors = new Dictionary<string, int>(); - Dictionary<string, int> Actors = new Dictionary<string, int>(); Dictionary<int, ThingTypeInfo> things = General.Map.Config.GetThingTypes(); //read our new shiny ClassNames for default game things foreach (KeyValuePair<int, ThingTypeInfo> 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<ActorStructure> ac = decorate.Actors; //General.Map.Data.Decorate.Actors; + ICollection<ActorStructure> 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<int, ModeldefEntry> 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<string, int> actorsByClass) { + modeldefEntries = new Dictionary<int, ModeldefEntry>(); //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<string, ModeldefEntry> modelDefEntriesByName = new Dictionary<string, ModeldefEntry>(); @@ -1424,7 +1502,6 @@ namespace CodeImp.DoomBuilder.Data Dictionary<string, Stream> streams = dr.GetModeldefData(); foreach (KeyValuePair<string, Stream> group in streams) { // Parse the data - group.Value.Seek(0, SeekOrigin.Begin); if (mdeParser.Parse(group.Value, currentreader.Location.location + "\\" + group.Key)) { foreach (KeyValuePair<string, ModeldefEntry> g in mdeParser.ModelDefEntries) { g.Value.Location = currentreader.Location.location; @@ -1435,14 +1512,153 @@ namespace CodeImp.DoomBuilder.Data } currentreader = null; - modeldefEntries = new Dictionary<int, ModeldefEntry>(); foreach (KeyValuePair<string, ModeldefEntry> 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<int, ModeldefEntry> 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<string, int> actorsByClass, bool loadDefaultDefinitions) { + gldefsEntries = new Dictionary<int, GZDoomLight>();//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<string, Stream> streams = dr.GetGldefsData(General.Map.Config.GameType); + + foreach (KeyValuePair<string, Stream> group in streams) + parser.Parse(group.Value, group.Key); + } + + //create gldefsEntries dictionary + foreach (KeyValuePair<string, string> 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<int, GZDoomLight> 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<string, Stream> streams = dr.GetMapinfoData(); + foreach (KeyValuePair<string, Stream> 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<string, Stream> streams = currentreader.GetGldefsData(location); + + foreach (KeyValuePair<string, Stream> 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 0cecb7b136783acf7a8ddd7d402604f4567f12bc..f8afb602cd19d13309bad86a3a75267fb95153e8 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<Stream> GetDecorateData(string pname) { return new List<Stream>(); } - //mxd. When implemented, this returns the modeldef lump + //mxd. When implemented, this returns the Modeldef lump public virtual Dictionary<string, Stream> GetModeldefData() { return new Dictionary<string, Stream>(); } + //mxd. When implemented, this returns the Mapinfo lump + public virtual Dictionary<string, Stream> GetMapinfoData() { return new Dictionary<string, Stream>(); } + + //mxd. When implemented, this returns the Gldefs lump + public virtual Dictionary<string, Stream> GetGldefsData(GameType gameType) { return new Dictionary<string, Stream>(); } + public virtual Dictionary<string, Stream> GetGldefsData(string location) { return new Dictionary<string, Stream>(); } + #endregion } } diff --git a/Source/Core/Data/PK3StructuredReader.cs b/Source/Core/Data/PK3StructuredReader.cs index af3cbcc11f36c84a5bbd7ca1f85593d4d95f79f6..8fdaebde38cf0dd7b46241ebdc058f5237ded412 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<string, Stream> GetMapinfoData() { + Dictionary<string, Stream> streams = new Dictionary<string, Stream>(); + // 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<string, Stream> GetGldefsData(GameType gameType) { + Dictionary<string, Stream> streams = new Dictionary<string, Stream>(); + // 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<string, Stream> GetGldefsData(string location) { + Dictionary<string, Stream> streams = new Dictionary<string, Stream>(); + // 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 80d77c219f0afa0206339882acda9a3cc8c0a6a2..b37aa74d0ae9a80e4a9d8015759f26a8cfad8577 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<Stream> GetDecorateData(string pname) @@ -816,6 +817,71 @@ namespace CodeImp.DoomBuilder.Data return streams; } + + //mxd + public override Dictionary<string, Stream> GetMapinfoData() { + if (issuspended) throw new Exception("Data reader is suspended"); + + Dictionary<string, Stream> streams = new Dictionary<string, Stream>(); + 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<string, Stream> GetGldefsData(GameType gameType) { + if (issuspended) throw new Exception("Data reader is suspended"); + + Dictionary<string, Stream> streams = new Dictionary<string, Stream>(); + 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<string, Stream> GetGldefsData(string location) { + if (issuspended) throw new Exception("Data reader is suspended"); + + Dictionary<string, Stream> streams = new Dictionary<string, Stream>(); + 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 c680c4ae6e476967006c37ab14dc4ee3ec80e0e4..9457554fb1ea7f522a2e13165e74c5477d88bb71 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 0000000000000000000000000000000000000000..2e086c5eac1f93b02741bc0d8fdf2e86e74a596a --- /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 0000000000000000000000000000000000000000..ee556f8ba795f2c4c91ad2b9b2ad522006275aa2 --- /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 0000000000000000000000000000000000000000..2cbd3e9bbbefa995bf078e20f3fe0d288c81afec --- /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 4cb07a72e9d502958af9a41478dab53cc49b8667..711d8b7bab3233f0b8a268bb92b849ce4fe5bf7a 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<string, GldefsLight> gldefsEntries; - public Dictionary<string, GldefsLight> GldefsEntries { get { return gldefsEntries; } } - public string Source { get { return sourcename; } } + + public delegate void IncludeDelegate(GldefsParser parser, string includefile); + public IncludeDelegate OnInclude; + + private Dictionary<string, GZDoomLight> lightsByName; //LightName, light definition + private Dictionary<string, string> objects; //ClassName, LightName + + public Dictionary<string, GZDoomLight> LightsByName { get { return lightsByName; } } + public Dictionary<string, string> Objects { get { return objects; } } + + private List<string> 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<string, int> GLDEFS_TO_GZDOOM_LIGHT_TYPE = new Dictionary<string, int>() { { POINT, 0 }, { PULSE, 1 }, { FLICKER, 2 }, { FLICKER2, 4 }, { SECTOR, 3 } }; + } + + public GldefsParser() { + parsedLumps = new List<string>(); + lightsByName = new Dictionary<string, GZDoomLight>(); //LightName, Light params + objects = new Dictionary<string, string>(); //ClassName, LightName + } public override bool Parse(Stream stream, string sourcefilename) { base.Parse(stream, sourcefilename); - gldefsEntries = new Dictionary<string, GldefsLight>(); - Dictionary<string, GldefsLight> lightsByName = new Dictionary<string, GldefsLight>(); - List<string> objects = new List<string>(); + 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 = 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; - 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 + "'"); + } 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 = 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; + } - 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 + "'"); + //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" && (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER || lightType == GldefsLightType.FLICKER2)) { - SkipWhitespace(true); +//secondarysize + } else if (token == "secondarysize") { + if (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 = 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; + } - 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 + "'"); + //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 = 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; + } - 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 + "'"); - 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; + } - 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); + //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; } + //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; + 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 (light.Size == 0) { - GZBuilder.GZGeneral.LogAndTraceWarning("'" + lightName + "' light Size is 0. It won't be shown in GZDoom!"); - valid = false; + + //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; + } } - if (valid) lightsByName.Add(lightName, light); + //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 0000000000000000000000000000000000000000..f60223dca79529b5f83eb48f331dc0f824e72d73 --- /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 e5ecbc1195339758da0847c727ff94886db86ffa..e7efe80a2ce3da61d373553a747ddf9bd913e633 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<string, ModeldefEntry> modelDefEntries; //classname, entry public Dictionary<string, ModeldefEntry> ModelDefEntries { get { return modelDefEntries; } } + private List<string> classNames; + public string Source { get { return sourcename; } } + public ModeldefParser() { + modelDefEntries = new Dictionary<string, ModeldefEntry>(); + classNames = new List<string>(); + } + //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 7296b762911a061b0722443e6def9efbd0ac8e88..cc161e246bf5c7b5f0b670997dc850325f0958be 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 e0b4b8eb84453b03e8e529e7c580e91038220857..d339cb6154231275d8687511487a7c2f34ad69c7 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 23c03004acb7cf8dce0085fc356bbfb15c05f315..d022d0e7c3d8c8de7f4ce4031a3f58a1a64c18f3 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 d8e224cce1213d070d49867d641bc871b3283ed8..b14450864a2749f96abaa5e160c0aea93b41a76b 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 920ecb74fc8a77c2ba93399d4a9392a6bac36867..43c71cb12c3be0ce0cade226feb4de1aece6ecf8 100644 --- a/Source/Core/Map/MapSet.cs +++ b/Source/Core/Map/MapSet.cs @@ -654,7 +654,7 @@ namespace CodeImp.DoomBuilder.Map /// <summary>This creates a new thing and returns it.</summary> 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 /// <summary>This creates a new thing and returns it.</summary> 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 061985f450451d61ef4a2c3e115ce8b40da3a0a2..e4eb08a45a7708914343d9af7c4c78a9655b62e3 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 f28a90f9786c7c54e4f3fe239509ad8ab7d325f5..ef4f6c5058980a669805665e9a028770dc147e3c 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 d42ed2e8c9da88d9e405c3ea561a09be549a521c..f5ef3394a7520526173e81599c0047888da5d696 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 41c80a5acf556d0216ad748f4bd2723b1298c53c..34b19030dcbffdeb28cb52c2d2a18594c1e87250 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 a6c34c2c1e2b5cf418fe8da7aba8a57d586acdc1..427f71640ea03f0763623f4b971a824f0602708d 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 503784a57dbad1cdcd17a9e924e3392212bf0b62..25d0e0d1982cedc255a25ad1660d1a5b644e513a 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 8b9c5efc41acc33b22a769f95642a8748617ae7c..dc4ec9ef3031b694fc024e58ba5ffa1cd5f7197e 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);} } /// <summary> /// 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 cbe31f4e2213774df330d73a42f3fd3e55240f5c..3118481e6ec6d0a454364ecc8fd8e47e91017212 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 1886316d797ac9de67b12a6f404710b9d924cce0..e80521c85dddd4a1225a73c289f98f6078080ff2 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 da8ff7b3ccacc28085530eda184d0e43ad653857..22dd640312f15370c4a3e07491a09e7e6dad1f4b 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 638918d509afea7953835961d1e32bbd8279107f..dcf537601d2b84b6814e424819a52c22c17195cc 100644 --- a/Source/Core/Windows/MainForm.resx +++ b/Source/Core/Windows/MainForm.resx @@ -132,6 +132,9 @@ <metadata name="toolStripSeparator2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <value>False</value> </metadata> + <metadata name="toolStripSeparator3.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>False</value> + </metadata> <metadata name="menumain.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <value>True</value> </metadata> @@ -195,30 +198,6 @@ <metadata name="sectorinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <value>True</value> </metadata> - <metadata name="heightpanel1.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> - <value>True</value> - </metadata> - <metadata name="vertexinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> - <value>True</value> - </metadata> - <metadata name="labelcollapsedinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> - <value>True</value> - </metadata> - <metadata name="buttontoggleinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> - <value>True</value> - </metadata> - <metadata name="modename.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> - <value>True</value> - </metadata> - <metadata name="linedefinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> - <value>True</value> - </metadata> - <metadata name="thinginfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> - <value>True</value> - </metadata> - <metadata name="sectorinfo.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> - <value>True</value> - </metadata> <metadata name="redrawtimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <value>319, 17</value> </metadata> @@ -243,6 +222,9 @@ <metadata name="dockerscollapser.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <value>781, 17</value> </metadata> + <metadata name="warntimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 56</value> + </metadata> <metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <value>True</value> </metadata> diff --git a/Source/Core/Windows/ThingEditForm.cs b/Source/Core/Windows/ThingEditForm.cs index 203736997b794530d10d9bdcf3d8c88e98ac55d0..dd925c396c6463723af01db7c90cf088b398fe21 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 0e7a8a839742d44c4b48d6b1ad21254ed5c0620c..8cdddc1d27b2b68f91625ae16c74638580c9bac0 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 8a3185103581243861d5ff7f0febb832dada73ee..58021742cfd441125d6a8d6098948fd521505321 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 d72e2bcf89481bfde900c0dcff843a7985ea6c46..b9f774d6233c048909f0d7b4d410333bc744fdae 100644 --- a/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualGeometrySidedef.cs +++ b/Source/Plugins/GZDoomEditing/VisualModes/BaseVisualGeometrySidedef.cs @@ -162,14 +162,15 @@ namespace CodeImp.DoomBuilder.GZDoomEditing { List<WallPolygon> polygons = new List<WallPolygon>(poly); List<WorldVertex> verts = new List<WorldVertex>(); - + // 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 4c3e0381d5e8ffad77fce0d0bc091896827b9887..d6c23c506916bce4dec31b658aa7f3dca0b1a2c0 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 bd893fbe7a7520e7bdc27444fd5fb4f76b92b3b5..ac9aaf4596ed86817be378f78af959163f9369f6 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 f491436b0713497075d504db74e36b23d883909c..c93cf53044b37015eba0614132aeb1b6f22e734f 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 8d516efeff9ad326c1cc97db3384c975ec2fda2d..1afbddc9c4909caa4cbc126beae6ed0acfb438c2 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 6cc008cd06d16e1c849d30cbab4688bd5db93544..a599cb9fa6d413c2e3a92b8b194ef1356a7323af 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 31feaa0543a35f9cd5c26b7b9f98fea32be30ccf..0f4180818235916a764993e8aa19497c3a4f8e0f 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();