Added GLDEFS and (Z)MAPINFO parsers.

Dynamic lights defined in GLDEFS are now rendered in Visual modes (currently only one light per Thing is supported).
Several values from (Z)MAPINFO are now used in Visual modes.
Added "Reload GLDEFS", "Reload (Z)MAPINFO" and "Reload MODELDEF" menu options (in "Tools" section).
MODELDEF parser now checks which model(s) is/are used in first frame.
Dynamic lights are now created with more meaningful default parameters.
Added errors and warnings indicator to main window.
This commit is contained in:
MaxED 2012-06-01 10:17:47 +00:00
parent 9b76183afd
commit 16b97e1c83
47 changed files with 3780 additions and 379 deletions

View file

@ -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

View file

@ -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";

2
Build/Gldefs/Readme.txt Normal file
View file

@ -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.

410
Build/Gldefs/doomdefs.txt Normal file
View file

@ -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 }
}

444
Build/Gldefs/hexndefs.txt Normal file
View file

@ -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 }
}

405
Build/Gldefs/hticdefs.txt Normal file
View file

@ -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 }
}

862
Build/Gldefs/strfdefs.txt Normal file
View file

@ -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 }
}

View file

@ -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" />

View file

@ -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

View file

@ -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", "");

View file

@ -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

View file

@ -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
}
}

View file

@ -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

View file

@ -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
}
}

View file

@ -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,
}
}

View file

@ -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" };
}
}

View file

@ -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;
}
}
}

View file

@ -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" };
}
}

View file

@ -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 = ReadToken();
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.Size)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Size value, but got '" + token + "'");
token = StripTokenQuotes(ReadToken());
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.PrimaryRadius)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Size value, but got '" + token + "'");
gotErrors = true;
break;
}
light.PrimaryRadius *= 2;
} else {
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType);
gotErrors = true;
break;
}
//offset
//offset
} else if (token == "offset") {
SkipWhitespace(true);
token = ReadToken();
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Offset.X)) {
token = StripTokenQuotes(ReadToken());
if (!ReadSignedFloat(token, ref light.Offset.X)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset X value, but got '" + token + "'");
gotErrors = true;
@ -115,28 +151,28 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
SkipWhitespace(true);
token = ReadToken();
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Offset.Y)) {
token = StripTokenQuotes(ReadToken());
if (!ReadSignedFloat(token, ref light.Offset.Z)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset Y value, but got '" + token + "'");
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset X value, but got '" + token + "'");
gotErrors = true;
break;
}
SkipWhitespace(true);
token = ReadToken();
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Offset.Z)) {
token = StripTokenQuotes(ReadToken());
if (!ReadSignedFloat(token, ref light.Offset.Y)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset Z value, but got '" + token + "'");
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Offset X value, but got '" + token + "'");
gotErrors = true;
break;
}
//subtractive
//subtractive
} else if (token == "subtractive") {
SkipWhitespace(true);
token = ReadToken();
token = StripTokenQuotes(ReadToken());
int i;
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) {
// Not numeric!
@ -146,11 +182,11 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
}
light.Subtractive = i == 1;
//dontlightself
//dontlightself
} else if (token == "dontlightself") {
SkipWhitespace(true);
token = ReadToken();
token = StripTokenQuotes(ReadToken());
int i;
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) {
// Not numeric!
@ -159,74 +195,136 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
break;
}
light.DontLightSelf = i == 1;
//interval
} else if (token == "interval" && (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER2)) {
SkipWhitespace(true);
light.DontLightSelf = (i == 1);
//interval
} else if (token == "interval") {
if (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER2) {
SkipWhitespace(true);
token = ReadToken();
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Interval)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Interval value, but got '" + token + "'");
token = StripTokenQuotes(ReadToken());
float interval;
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out interval)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Interval value, but got '" + token + "'");
gotErrors = true;
break;
}
//I wrote logic for dynamic lights animation first, so here I modify gldefs settings to fit in existing logic
if (lightType == GldefsLightType.PULSE) {
light.Interval = (int)(interval * 35); //measured in tics (35 per second) in PointLightPulse, measured in seconds in gldefs' PulseLight
} else { //FLICKER2. Seems like PointLightFlickerRandom to me
light.Interval = (int)(interval * 350); //0.1 is one second for FlickerLight2
}
} else {
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '"+token+"' is not valid property for " + lightType);
gotErrors = true;
break;
}
//todo: modify Interval based on light type
//secondarysize
} else if (token == "secondarysize") {
if (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER || lightType == GldefsLightType.FLICKER2) {
SkipWhitespace(true);
//secondarysize
} else if (token == "secondarysize" && (lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER || lightType == GldefsLightType.FLICKER2)) {
SkipWhitespace(true);
token = StripTokenQuotes(ReadToken());
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.SecondaryRadius)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected SecondarySize value, but got '" + token + "'");
gotErrors = true;
break;
}
light.SecondaryRadius *= 2;
token = ReadToken();
if (!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.SecondarySize)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected SecondarySize value, but got '" + token + "'");
} else {
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType);
gotErrors = true;
break;
}
//chance
} else if (token == "chance" && lightType == GldefsLightType.FLICKER) {
SkipWhitespace(true);
//chance
} else if (token == "chance") {
if (lightType == GldefsLightType.FLICKER) {
SkipWhitespace(true);
token = ReadToken();
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Chance)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Chance value, but got '" + token + "'");
token = StripTokenQuotes(ReadToken());
float chance;
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out chance)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Chance value, but got '" + token + "'");
gotErrors = true;
break;
}
//transforming from 0.0 .. 1.0 to 0 .. 359 to fit in existing logic
light.Interval = (int)(chance * 359.0f);
} else {
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType);
gotErrors = true;
break;
}
//scale
} else if (token == "scale" && lightType == GldefsLightType.SECTOR) {
SkipWhitespace(true);
//scale
} else if (token == "scale") {
if (lightType == GldefsLightType.SECTOR) {
SkipWhitespace(true);
token = ReadToken();
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Scale)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Scale value, but got '" + token + "'");
token = StripTokenQuotes(ReadToken());
float scale;
if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale)) {
// Not numeric!
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected Scale value, but got '" + token + "'");
gotErrors = true;
break;
}
if (scale < 0.0f || scale > 1.0f) {
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": scale must be in 0.0 - 1.0 range, but is " + scale);
gotErrors = true;
break;
}
//sector light doesn't have animation, so we will store it's size in Interval
//transforming from 0.0 .. 1.0 to 0 .. 10 to preserve value.
light.Interval = (int)(scale * 10.0f);
} else {
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": '" + token + "' is not valid property for " + lightType);
gotErrors = true;
break;
}
if (light.Scale < 0 || light.Scale > 1) {
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": scale must be in 0.0 - 1.0 range, but is " + light.Scale);
gotErrors = true;
break;
}
//end of structure
} else if (token == "}") {
if (!gotErrors) {
//check light
bool valid = true;
//general checks
if (light.Color.Red == 0.0f && light.Color.Green == 0.0f && light.Color.Blue == 0.0f) {
GZBuilder.GZGeneral.LogAndTraceWarning("'" + lightName + "' light Color is 0,0,0. It won't be shown in GZDoom!");
valid = false;
}
if (light.Size == 0) {
GZBuilder.GZGeneral.LogAndTraceWarning("'" + lightName + "' light Size is 0. It won't be shown in GZDoom!");
valid = false;
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": light Color is " + light.Color.Red + "," + light.Color.Green + "," + light.Color.Blue + ". It won't be shown in GZDoom!");
gotErrors = true;
}
if (valid) lightsByName.Add(lightName, light);
//light-type specific checks
if (light.Type == (int)GZDoomLightType.NORMAL) {
if (light.PrimaryRadius == 0) {
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": light Size is 0. It won't be shown in GZDoom!");
gotErrors = true;
}
}
if (light.Type == (int)GZDoomLightType.FLICKER || light.Type == (int)GZDoomLightType.PULSE || light.Type == (int)GZDoomLightType.RANDOM) {
if (light.PrimaryRadius == 0 && light.SecondaryRadius == 0) {
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": 'Size' and 'SecondarySize' are 0. This light won't be shown in GZDoom!");
gotErrors = true;
}
}
//offset it slightly to avoid shading glitches
if (light.Offset.Y == 0)
light.Offset.Y = 0.1f;
if (!gotErrors) {
if (lightsByName.ContainsKey(lightName)) {
lightsByName[lightName] = light;
} else {
lightsByName.Add(lightName, light);
}
}
}
break; //break out of this parsing loop
}
@ -238,58 +336,68 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
SkipWhitespace(true);
//read object class
string objectClass = ReadToken().ToLowerInvariant();
string objectClass = StripTokenQuotes(ReadToken()).ToLowerInvariant();
if (!string.IsNullOrEmpty(objectClass)) {
if (objects.Contains(objectClass)) {
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": already got object '" + objectClass + "'; entry skipped");
continue; //already got this object; continue to next one
}
objects.Add(objectClass);
//now find opening brace
SkipWhitespace(true);
token = ReadToken();
if (token != "{") {
GZBuilder.GZGeneral.LogAndTraceWarning("Unexpected token found in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected '{', but got " + token);
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected '{', but got " + token);
continue;
}
int bracesCount = 1;
bool foundLight = false;
//read frames structure
while (SkipWhitespace(true)) {
token = ReadToken();
if (!string.IsNullOrEmpty(token)) {
token = token.ToLowerInvariant();
token = StripTokenQuotes(token).ToLowerInvariant();
if (token == "light") { //just use first light from first frame and be done with it
if (!foundLight && token == "light") { //just use first light from first frame and be done with it
SkipWhitespace(true);
token = ReadToken().ToLowerInvariant(); //should be light name
if (!string.IsNullOrEmpty(token)) {
if (lightsByName.ContainsKey(token)) {
gldefsEntries.Add(objectClass, lightsByName[token]);
if (objects.ContainsKey(objectClass))
objects[objectClass] = token;
else
objects.Add(objectClass, token);
foundLight = true;
} else {
GZBuilder.GZGeneral.LogAndTraceWarning("Light declaration not found for light '" + token + "' in '" + sourcefilename+"'");
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": light declaration not found for light '" + token + "'");
}
break;
}
} else if (token == "{") { //continue in this loop until object structure ends
bracesCount++;
} else if (token == "}") {
if (--bracesCount <= 0)
break; //This was Cave Johnson. And we are done here.
}
}
}
}
} else if (token == "#include") {
SkipWhitespace(true);
string includeLump = StripTokenQuotes(ReadToken()).ToLowerInvariant();
if (!string.IsNullOrEmpty(includeLump) && includeLump.IndexOf(".gl") != -1) {
//todo: load included file. check for recursive includes?
if (!string.IsNullOrEmpty(includeLump)) {
// Callback to parse this file
if (OnInclude != null)
OnInclude(this, includeLump.Replace("/", "\\"));
// Set our buffers back to continue parsing
datastream = localstream;
datareader = localreader;
sourcename = localsourcename;
} else {
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": got #include directive with missing or incorrect include path: '" + includeLump + "'");
GZBuilder.GZGeneral.LogAndTraceWarning("Error in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": got #include directive with missing or incorrect path: '" + includeLump + "'");
}
} else {
@ -314,35 +422,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom {
}
}
if (gldefsEntries.Count > 0)
if (objects.Count > 0)
return true;
return false;
}
}
public class GldefsLight {
public int Type;
public Color3 Color;
public int Size;
public int SecondarySize;
public float Interval;
public Vector3 Offset;
public float Chance;
public float Scale;
public bool Subtractive;
public bool DontLightSelf;
public GldefsLight() {
Color = new Color3();
Offset = new Vector3();
}
}
public struct GldefsLightType {
public const string POINT = "pointlight";
public const string PULSE = "pulselight";
public const string FLICKER = "flickerlight";
public const string FLICKER2 = "flickerlight2";
public const string SECTOR = "sectorlight";
}
}
}

View file

@ -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;
}
}
}

View file

@ -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);
}
}

View file

@ -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]);

View file

@ -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();
}
}
}

View file

@ -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 {

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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; } }

View file

@ -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);

View file

@ -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() { }

View file

@ -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

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -49,6 +49,8 @@ namespace CodeImp.DoomBuilder.Windows
FillList();
checkerrors.Start();
checkshow.Checked = General.Settings.ShowErrorsWindow;
//mxd
grid.Focus();
}
#endregion

View file

@ -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;
}
}

View file

@ -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

View file

@ -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>

View file

@ -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);
}
}
}

View file

@ -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)

View file

@ -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;

View file

@ -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)

View file

@ -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)

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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();